aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/acpi/Kconfig1
-rw-r--r--drivers/acpi/acpi_memhotplug.c17
-rw-r--r--drivers/acpi/asus_acpi.c35
-rw-r--r--drivers/acpi/dispatcher/dsfield.c37
-rw-r--r--drivers/acpi/dispatcher/dsinit.c51
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c360
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c37
-rw-r--r--drivers/acpi/dispatcher/dsobject.c106
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c58
-rw-r--r--drivers/acpi/dispatcher/dsutils.c33
-rw-r--r--drivers/acpi/dispatcher/dswexec.c80
-rw-r--r--drivers/acpi/dispatcher/dswload.c270
-rw-r--r--drivers/acpi/dispatcher/dswscope.c6
-rw-r--r--drivers/acpi/dispatcher/dswstate.c128
-rw-r--r--drivers/acpi/ec.c291
-rw-r--r--drivers/acpi/events/evevent.c63
-rw-r--r--drivers/acpi/events/evgpe.c54
-rw-r--r--drivers/acpi/events/evgpeblk.c215
-rw-r--r--drivers/acpi/events/evmisc.c26
-rw-r--r--drivers/acpi/events/evregion.c63
-rw-r--r--drivers/acpi/events/evrgnini.c8
-rw-r--r--drivers/acpi/events/evsci.c6
-rw-r--r--drivers/acpi/events/evxface.c19
-rw-r--r--drivers/acpi/events/evxfevnt.c34
-rw-r--r--drivers/acpi/events/evxfregn.c2
-rw-r--r--drivers/acpi/executer/exconfig.c8
-rw-r--r--drivers/acpi/executer/exconvrt.c36
-rw-r--r--drivers/acpi/executer/excreate.c6
-rw-r--r--drivers/acpi/executer/exdump.c671
-rw-r--r--drivers/acpi/executer/exfield.c11
-rw-r--r--drivers/acpi/executer/exfldio.c93
-rw-r--r--drivers/acpi/executer/exmisc.c113
-rw-r--r--drivers/acpi/executer/exmutex.c28
-rw-r--r--drivers/acpi/executer/exnames.c23
-rw-r--r--drivers/acpi/executer/exoparg1.c72
-rw-r--r--drivers/acpi/executer/exoparg2.c46
-rw-r--r--drivers/acpi/executer/exoparg3.c12
-rw-r--r--drivers/acpi/executer/exoparg6.c16
-rw-r--r--drivers/acpi/executer/exprep.c34
-rw-r--r--drivers/acpi/executer/exregion.c35
-rw-r--r--drivers/acpi/executer/exresnte.c51
-rw-r--r--drivers/acpi/executer/exresolv.c35
-rw-r--r--drivers/acpi/executer/exresop.c143
-rw-r--r--drivers/acpi/executer/exstore.c27
-rw-r--r--drivers/acpi/executer/exstoren.c24
-rw-r--r--drivers/acpi/executer/exstorob.c6
-rw-r--r--drivers/acpi/executer/exsystem.c6
-rw-r--r--drivers/acpi/executer/exutils.c20
-rw-r--r--drivers/acpi/glue.c8
-rw-r--r--drivers/acpi/hardware/hwacpi.c25
-rw-r--r--drivers/acpi/hardware/hwgpe.c2
-rw-r--r--drivers/acpi/hardware/hwregs.c59
-rw-r--r--drivers/acpi/hardware/hwsleep.c23
-rw-r--r--drivers/acpi/hardware/hwtimer.c2
-rw-r--r--drivers/acpi/motherboard.c30
-rw-r--r--drivers/acpi/namespace/nsaccess.c35
-rw-r--r--drivers/acpi/namespace/nsalloc.c11
-rw-r--r--drivers/acpi/namespace/nsdump.c13
-rw-r--r--drivers/acpi/namespace/nsdumpdv.c2
-rw-r--r--drivers/acpi/namespace/nseval.c5
-rw-r--r--drivers/acpi/namespace/nsinit.c105
-rw-r--r--drivers/acpi/namespace/nsload.c10
-rw-r--r--drivers/acpi/namespace/nsnames.c14
-rw-r--r--drivers/acpi/namespace/nsobject.c13
-rw-r--r--drivers/acpi/namespace/nsparse.c2
-rw-r--r--drivers/acpi/namespace/nssearch.c30
-rw-r--r--drivers/acpi/namespace/nsutils.c43
-rw-r--r--drivers/acpi/namespace/nswalk.c2
-rw-r--r--drivers/acpi/namespace/nsxfeval.c29
-rw-r--r--drivers/acpi/namespace/nsxfname.c5
-rw-r--r--drivers/acpi/namespace/nsxfobj.c2
-rw-r--r--drivers/acpi/osl.c10
-rw-r--r--drivers/acpi/parser/psargs.c358
-rw-r--r--drivers/acpi/parser/psloop.c39
-rw-r--r--drivers/acpi/parser/psopcode.c4
-rw-r--r--drivers/acpi/parser/psparse.c55
-rw-r--r--drivers/acpi/parser/psscope.c2
-rw-r--r--drivers/acpi/parser/pstree.c5
-rw-r--r--drivers/acpi/parser/psutils.c2
-rw-r--r--drivers/acpi/parser/pswalk.c2
-rw-r--r--drivers/acpi/parser/psxface.c144
-rw-r--r--drivers/acpi/pci_irq.c48
-rw-r--r--drivers/acpi/pci_link.c100
-rw-r--r--drivers/acpi/pci_root.c8
-rw-r--r--drivers/acpi/processor_core.c30
-rw-r--r--drivers/acpi/processor_idle.c139
-rw-r--r--drivers/acpi/processor_perflib.c4
-rw-r--r--drivers/acpi/processor_thermal.c7
-rw-r--r--drivers/acpi/processor_throttling.c7
-rw-r--r--drivers/acpi/resources/Makefile2
-rw-r--r--drivers/acpi/resources/rsaddr.c1164
-rw-r--r--drivers/acpi/resources/rscalc.c829
-rw-r--r--drivers/acpi/resources/rscreate.c231
-rw-r--r--drivers/acpi/resources/rsdump.c1399
-rw-r--r--drivers/acpi/resources/rsinfo.c204
-rw-r--r--drivers/acpi/resources/rsio.c544
-rw-r--r--drivers/acpi/resources/rsirq.c568
-rw-r--r--drivers/acpi/resources/rslist.c534
-rw-r--r--drivers/acpi/resources/rsmemory.c517
-rw-r--r--drivers/acpi/resources/rsmisc.c860
-rw-r--r--drivers/acpi/resources/rsutils.c390
-rw-r--r--drivers/acpi/resources/rsxface.c230
-rw-r--r--drivers/acpi/scan.c2
-rw-r--r--drivers/acpi/sleep/poweroff.c15
-rw-r--r--drivers/acpi/sleep/sleep.h2
-rw-r--r--drivers/acpi/sleep/wakeup.c6
-rw-r--r--drivers/acpi/tables/tbconvrt.c23
-rw-r--r--drivers/acpi/tables/tbget.c39
-rw-r--r--drivers/acpi/tables/tbgetall.c27
-rw-r--r--drivers/acpi/tables/tbinstal.c12
-rw-r--r--drivers/acpi/tables/tbrsdt.c30
-rw-r--r--drivers/acpi/tables/tbutils.c50
-rw-r--r--drivers/acpi/tables/tbxface.c18
-rw-r--r--drivers/acpi/tables/tbxfroot.c35
-rw-r--r--drivers/acpi/utilities/Makefile5
-rw-r--r--drivers/acpi/utilities/utalloc.c61
-rw-r--r--drivers/acpi/utilities/utcache.c2
-rw-r--r--drivers/acpi/utilities/utcopy.c27
-rw-r--r--drivers/acpi/utilities/utdebug.c2
-rw-r--r--drivers/acpi/utilities/utdelete.c15
-rw-r--r--drivers/acpi/utilities/uteval.c46
-rw-r--r--drivers/acpi/utilities/utglobal.c108
-rw-r--r--drivers/acpi/utilities/utinit.c13
-rw-r--r--drivers/acpi/utilities/utmath.c10
-rw-r--r--drivers/acpi/utilities/utmisc.c209
-rw-r--r--drivers/acpi/utilities/utmutex.c58
-rw-r--r--drivers/acpi/utilities/utobject.c33
-rw-r--r--drivers/acpi/utilities/utresrc.c554
-rw-r--r--drivers/acpi/utilities/utstate.c4
-rw-r--r--drivers/acpi/utilities/utxface.c69
-rw-r--r--drivers/acpi/video.c8
-rw-r--r--drivers/base/Makefile1
-rw-r--r--drivers/base/base.h4
-rw-r--r--drivers/base/bus.c3
-rw-r--r--drivers/base/memory.c2
-rw-r--r--drivers/base/power/resume.c3
-rw-r--r--drivers/base/power/shutdown.c2
-rw-r--r--drivers/base/power/suspend.c3
-rw-r--r--drivers/base/power/sysfs.c24
-rw-r--r--drivers/base/sys.c3
-rw-r--r--drivers/base/topology.c148
-rw-r--r--drivers/block/Kconfig8
-rw-r--r--drivers/block/cciss.c5
-rw-r--r--drivers/block/pktcdvd.c197
-rw-r--r--drivers/block/ub.c139
-rw-r--r--drivers/block/umem.c2
-rw-r--r--drivers/bluetooth/bt3c_cs.c17
-rw-r--r--drivers/cdrom/viocd.c2
-rw-r--r--drivers/char/Kconfig4
-rw-r--r--drivers/char/cyclades.c6
-rw-r--r--drivers/char/drm/ati_pcigart.c17
-rw-r--r--drivers/char/drm/drmP.h15
-rw-r--r--drivers/char/drm/drm_auth.c20
-rw-r--r--drivers/char/drm/drm_bufs.c80
-rw-r--r--drivers/char/drm/drm_context.c52
-rw-r--r--drivers/char/drm/drm_drv.c4
-rw-r--r--drivers/char/drm/drm_fops.c12
-rw-r--r--drivers/char/drm/drm_ioctl.c18
-rw-r--r--drivers/char/drm/drm_irq.c16
-rw-r--r--drivers/char/drm/drm_pciids.h3
-rw-r--r--drivers/char/drm/drm_proc.c28
-rw-r--r--drivers/char/drm/drm_stub.c6
-rw-r--r--drivers/char/drm/drm_sysfs.c131
-rw-r--r--drivers/char/drm/drm_vm.c12
-rw-r--r--drivers/char/drm/i810_dma.c2
-rw-r--r--drivers/char/drm/i810_drv.h2
-rw-r--r--drivers/char/drm/i830_dma.c2
-rw-r--r--drivers/char/drm/i830_drv.h3
-rw-r--r--drivers/char/drm/i915_dma.c42
-rw-r--r--drivers/char/drm/i915_drm.h33
-rw-r--r--drivers/char/drm/i915_drv.h6
-rw-r--r--drivers/char/drm/i915_mem.c31
-rw-r--r--drivers/char/drm/radeon_cp.c2
-rw-r--r--drivers/char/drm/savage_bci.c4
-rw-r--r--drivers/char/drm/savage_drv.h1
-rw-r--r--drivers/char/drm/via_dma.c10
-rw-r--r--drivers/char/drm/via_dmablit.c6
-rw-r--r--drivers/char/drm/via_drv.h7
-rw-r--r--drivers/char/drm/via_irq.c2
-rw-r--r--drivers/char/esp.c28
-rw-r--r--drivers/char/hangcheck-timer.c12
-rw-r--r--drivers/char/hpet.c40
-rw-r--r--drivers/char/ip2/i2cmd.c1
-rw-r--r--drivers/char/ip2main.c67
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c4
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c32
-rw-r--r--drivers/char/rio/brates.h106
-rw-r--r--drivers/char/rio/chan.h33
-rw-r--r--drivers/char/rio/cirrus.h142
-rw-r--r--drivers/char/rio/cmd.h83
-rw-r--r--drivers/char/rio/data.h40
-rw-r--r--drivers/char/rio/debug.h39
-rw-r--r--drivers/char/rio/defaults.h7
-rw-r--r--drivers/char/rio/eisa.h104
-rw-r--r--drivers/char/rio/enable.h48
-rw-r--r--drivers/char/rio/formpkt.h153
-rw-r--r--drivers/char/rio/hosthw.h55
-rw-r--r--drivers/char/rio/link.h34
-rw-r--r--drivers/char/rio/list.h140
-rw-r--r--drivers/char/rio/lrt.h52
-rw-r--r--drivers/char/rio/ltt.h52
-rw-r--r--drivers/char/rio/lttwake.h50
-rw-r--r--drivers/char/rio/mca.h73
-rw-r--r--drivers/char/rio/mesg.h41
-rw-r--r--drivers/char/rio/parmmap.h5
-rw-r--r--drivers/char/rio/phb.h133
-rw-r--r--drivers/char/rio/pkt.h27
-rw-r--r--drivers/char/rio/poll.h73
-rw-r--r--drivers/char/rio/proto.h244
-rw-r--r--drivers/char/rio/qbuf.h4
-rw-r--r--drivers/char/rio/rio_linux.c60
-rw-r--r--drivers/char/rio/rioboot.c61
-rw-r--r--drivers/char/rio/riocmd.c30
-rw-r--r--drivers/char/rio/rioctrl.c111
-rw-r--r--drivers/char/rio/rioinit.c1152
-rw-r--r--drivers/char/rio/riolocks.h43
-rw-r--r--drivers/char/rio/rioparam.c43
-rw-r--r--drivers/char/rio/rioroute.c24
-rw-r--r--drivers/char/rio/riotable.c8
-rw-r--r--drivers/char/rio/riotime.h63
-rw-r--r--drivers/char/rio/riotty.c583
-rw-r--r--drivers/char/rio/riotypes.h66
-rw-r--r--drivers/char/rio/riowinif.h1329
-rw-r--r--drivers/char/rio/riscos.h63
-rw-r--r--drivers/char/rio/rtahw.h75
-rw-r--r--drivers/char/rio/rup.h5
-rw-r--r--drivers/char/rio/rupstat.h50
-rw-r--r--drivers/char/rio/sam.h4
-rw-r--r--drivers/char/rio/selftest.h73
-rw-r--r--drivers/char/rio/sysmap.h62
-rw-r--r--drivers/char/rio/timeouts.h50
-rw-r--r--drivers/char/rocket.c2
-rw-r--r--drivers/char/ser_a2232.c1
-rw-r--r--drivers/char/sx.c6
-rw-r--r--drivers/char/synclink_gt.c2
-rw-r--r--drivers/char/sysrq.c2
-rw-r--r--drivers/char/tipar.c15
-rw-r--r--drivers/char/tlclk.c93
-rw-r--r--drivers/char/tpm/tpm_bios.c25
-rw-r--r--drivers/char/tpm/tpm_infineon.c50
-rw-r--r--drivers/char/tty_io.c104
-rw-r--r--drivers/char/vt.c1
-rw-r--r--drivers/char/watchdog/pcwd.c450
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c12
-rw-r--r--drivers/char/watchdog/sbc_epx_c3.c28
-rw-r--r--drivers/cpufreq/cpufreq.c174
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c52
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c41
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c78
-rw-r--r--drivers/edac/Kconfig101
-rw-r--r--drivers/edac/Makefile18
-rw-r--r--drivers/edac/amd76x_edac.c356
-rw-r--r--drivers/edac/e752x_edac.c1071
-rw-r--r--drivers/edac/e7xxx_edac.c558
-rw-r--r--drivers/edac/edac_mc.c2208
-rw-r--r--drivers/edac/edac_mc.h448
-rw-r--r--drivers/edac/i82860_edac.c299
-rw-r--r--drivers/edac/i82875p_edac.c532
-rw-r--r--drivers/edac/r82600_edac.c407
-rw-r--r--drivers/fc4/fc.c2
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/f71805f.c908
-rw-r--r--drivers/hwmon/it87.c11
-rw-r--r--drivers/hwmon/lm77.c8
-rw-r--r--drivers/hwmon/vt8231.c8
-rw-r--r--drivers/hwmon/w83781d.c43
-rw-r--r--drivers/hwmon/w83792d.c31
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c2
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-i801.c2
-rw-r--r--drivers/i2c/busses/i2c-isa.c12
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c9
-rw-r--r--drivers/i2c/busses/i2c-parport.c7
-rw-r--r--drivers/i2c/busses/i2c-pxa.c2
-rw-r--r--drivers/i2c/i2c-core.c15
-rw-r--r--drivers/ide/Kconfig25
-rw-r--r--drivers/ide/ide-disk.c14
-rw-r--r--drivers/ide/ide-io.c5
-rw-r--r--drivers/ide/ide-iops.c1
-rw-r--r--drivers/ide/ide-probe.c51
-rw-r--r--drivers/ide/ide-taskfile.c3
-rw-r--r--drivers/ide/ide.c1
-rw-r--r--drivers/ide/pci/aec62xx.c15
-rw-r--r--drivers/ide/pci/hpt366.c4
-rw-r--r--drivers/ide/pci/it821x.c2
-rw-r--r--drivers/ide/pci/pdc202xx_new.c6
-rw-r--r--drivers/ide/pci/pdc202xx_old.c15
-rw-r--r--drivers/ide/pci/piix.c4
-rw-r--r--drivers/ide/pci/sgiioc4.c14
-rw-r--r--drivers/infiniband/core/mad.c10
-rw-r--r--drivers/infiniband/core/sa_query.c2
-rw-r--r--drivers/infiniband/core/ucm.c13
-rw-r--r--drivers/infiniband/core/uverbs_main.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c51
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h12
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c10
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c20
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c36
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.h7
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c53
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c14
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h5
-rw-r--r--drivers/input/joystick/a3d.c88
-rw-r--r--drivers/input/joystick/db9.c85
-rw-r--r--drivers/input/joystick/gamecon.c361
-rw-r--r--drivers/input/joystick/grip.c11
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c4
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c1
-rw-r--r--drivers/input/joystick/sidewinder.c10
-rw-r--r--drivers/input/joystick/tmdc.c15
-rw-r--r--drivers/input/joystick/turbografx.c20
-rw-r--r--drivers/input/joystick/twidjoy.c4
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/misc/Kconfig12
-rw-r--r--drivers/input/misc/Makefile2
-rw-r--r--drivers/input/misc/ixp4xx-beeper.c184
-rw-r--r--drivers/input/mouse/logips2pp.c1
-rw-r--r--drivers/input/mouse/psmouse-base.c1
-rw-r--r--drivers/input/mouse/trackpoint.c20
-rw-r--r--drivers/input/mouse/trackpoint.h4
-rw-r--r--drivers/input/mousedev.c9
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/touchscreen/Kconfig2
-rw-r--r--drivers/input/touchscreen/ads7846.c156
-rw-r--r--drivers/input/touchscreen/mk712.c2
-rw-r--r--drivers/isdn/hisax/Kconfig2
-rw-r--r--drivers/isdn/hisax/hisax.h2
-rw-r--r--drivers/isdn/i4l/isdn_tty.c4
-rw-r--r--drivers/isdn/sc/ioctl.c4
-rw-r--r--drivers/macintosh/Kconfig8
-rw-r--r--drivers/macintosh/Makefile5
-rw-r--r--drivers/macintosh/macio_asic.c72
-rw-r--r--drivers/macintosh/windfarm.h3
-rw-r--r--drivers/macintosh/windfarm_core.c122
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c169
-rw-r--r--drivers/macintosh/windfarm_pid.c8
-rw-r--r--drivers/macintosh/windfarm_pid.h1
-rw-r--r--drivers/macintosh/windfarm_pm112.c698
-rw-r--r--drivers/macintosh/windfarm_pm81.c87
-rw-r--r--drivers/macintosh/windfarm_pm91.c95
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c69
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c419
-rw-r--r--drivers/macintosh/windfarm_smu_sensors.c43
-rw-r--r--drivers/md/dm-ioctl.c14
-rw-r--r--drivers/md/dm-log.c48
-rw-r--r--drivers/md/dm-snap.c29
-rw-r--r--drivers/md/dm-snap.h4
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--drivers/md/dm.c39
-rw-r--r--drivers/md/kcopyd.c1
-rw-r--r--drivers/md/md.c49
-rw-r--r--drivers/md/raid0.c2
-rw-r--r--drivers/md/raid10.c2
-rw-r--r--drivers/md/raid5.c3
-rw-r--r--drivers/md/raid6main.c152
-rw-r--r--drivers/media/dvb/b2c2/Kconfig2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-common.h2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-dma.c35
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c9
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c6
-rw-r--r--drivers/media/dvb/b2c2/flexcop-pci.c6
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h4
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c46
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h17
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c4
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c22
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig12
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c14
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c13
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h1
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c6
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.h2
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c6
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c2
-rw-r--r--drivers/media/dvb/frontends/Kconfig24
-rw-r--r--drivers/media/dvb/frontends/Makefile3
-rw-r--r--drivers/media/dvb/frontends/at76c651.c450
-rw-r--r--drivers/media/dvb/frontends/at76c651.h47
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c10
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h2
-rw-r--r--drivers/media/dvb/frontends/nxt2002.c706
-rw-r--r--drivers/media/dvb/frontends/nxt2002.h23
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c58
-rw-r--r--drivers/media/dvb/frontends/tda80xx.c734
-rw-r--r--drivers/media/dvb/frontends/tda80xx.h51
-rw-r--r--drivers/media/dvb/ttpci/av7110.c18
-rw-r--r--drivers/media/dvb/ttpci/av7110.h2
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c40
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h12
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c26
-rw-r--r--drivers/media/video/Makefile3
-rw-r--r--drivers/media/video/arv.c6
-rw-r--r--drivers/media/video/bt832.c2
-rw-r--r--drivers/media/video/btcx-risc.c2
-rw-r--r--drivers/media/video/bttv-cards.c6
-rw-r--r--drivers/media/video/bttv-driver.c89
-rw-r--r--drivers/media/video/bttv-i2c.c6
-rw-r--r--drivers/media/video/bttvp.h5
-rw-r--r--drivers/media/video/compat_ioctl32.c89
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c52
-rw-r--r--drivers/media/video/cx88/Kconfig15
-rw-r--r--drivers/media/video/cx88/Makefile6
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c15
-rw-r--r--drivers/media/video/cx88/cx88-cards.c6
-rw-r--r--drivers/media/video/cx88/cx88-core.c25
-rw-r--r--drivers/media/video/cx88/cx88-input.c1
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c8
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c4
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c17
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c8
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c77
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c10
-rw-r--r--drivers/media/video/hexium_orion.c2
-rw-r--r--drivers/media/video/msp3400-driver.c14
-rw-r--r--drivers/media/video/msp3400.h8
-rw-r--r--drivers/media/video/mt20xx.c12
-rw-r--r--drivers/media/video/planb.c4
-rw-r--r--drivers/media/video/saa6588.c10
-rw-r--r--drivers/media/video/saa711x.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c53
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c21
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c11
-rw-r--r--drivers/media/video/saa7134/saa7134.h2
-rw-r--r--drivers/media/video/stradis.c15
-rw-r--r--drivers/media/video/tda8290.c4
-rw-r--r--drivers/media/video/tda9887.c9
-rw-r--r--drivers/media/video/tea5767.c18
-rw-r--r--drivers/media/video/tuner-core.c93
-rw-r--r--drivers/media/video/tuner-simple.c794
-rw-r--r--drivers/media/video/tuner-types.c1406
-rw-r--r--drivers/media/video/tvaudio.c9
-rw-r--r--drivers/media/video/tveeprom.c2
-rw-r--r--drivers/media/video/tvp5150.c34
-rw-r--r--drivers/media/video/v4l2-common.c1
-rw-r--r--drivers/media/video/videodev.c25
-rw-r--r--drivers/message/fusion/Makefile2
-rw-r--r--drivers/message/fusion/mptbase.c299
-rw-r--r--drivers/message/fusion/mptbase.h18
-rw-r--r--drivers/message/fusion/mptctl.c241
-rw-r--r--drivers/message/fusion/mptctl.h4
-rw-r--r--drivers/message/fusion/mptfc.c203
-rw-r--r--drivers/message/fusion/mptsas.c241
-rw-r--r--drivers/message/fusion/mptscsih.c118
-rw-r--r--drivers/message/fusion/mptscsih.h1
-rw-r--r--drivers/message/fusion/mptspi.c10
-rw-r--r--drivers/message/i2o/core.h3
-rw-r--r--drivers/message/i2o/i2o_scsi.c2
-rw-r--r--drivers/message/i2o/pci.c47
-rw-r--r--drivers/misc/ibmasm/uart.c2
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mmc/au1xmmc.c59
-rw-r--r--drivers/mmc/mmc.c28
-rw-r--r--drivers/mmc/mmc_block.c8
-rw-r--r--drivers/mmc/mmci.c18
-rw-r--r--drivers/mmc/pxamci.c9
-rw-r--r--drivers/mmc/wbsd.c8
-rw-r--r--drivers/mtd/chips/Kconfig9
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c14
-rw-r--r--drivers/mtd/devices/Kconfig1
-rw-r--r--drivers/mtd/maps/dc21285.c9
-rw-r--r--drivers/mtd/maps/tsunami_flash.c2
-rw-r--r--drivers/net/3c59x.c33
-rw-r--r--drivers/net/8139too.c38
-rw-r--r--drivers/net/Kconfig50
-rw-r--r--drivers/net/acenic.c4
-rw-r--r--drivers/net/appletalk/cops.h2
-rw-r--r--drivers/net/b44.c7
-rw-r--r--drivers/net/bnx2.c308
-rw-r--r--drivers/net/bnx2.h34
-rw-r--r--drivers/net/bnx2_fw.h825
-rw-r--r--drivers/net/bonding/bond_main.c18
-rw-r--r--drivers/net/bonding/bond_sysfs.c6
-rw-r--r--drivers/net/cassini.c40
-rw-r--r--drivers/net/cs89x0.c3
-rw-r--r--drivers/net/e100.c144
-rw-r--r--drivers/net/e1000/e1000.h51
-rw-r--r--drivers/net/e1000/e1000_ethtool.c474
-rw-r--r--drivers/net/e1000/e1000_hw.c71
-rw-r--r--drivers/net/e1000/e1000_hw.h45
-rw-r--r--drivers/net/e1000/e1000_main.c1612
-rw-r--r--drivers/net/e1000/e1000_osdep.h2
-rw-r--r--drivers/net/e1000/e1000_param.c58
-rw-r--r--drivers/net/gianfar.c24
-rw-r--r--drivers/net/gianfar.h8
-rw-r--r--drivers/net/gianfar_ethtool.c8
-rw-r--r--drivers/net/gianfar_mii.c17
-rw-r--r--drivers/net/hamradio/baycom_par.c1
-rw-r--r--drivers/net/irda/irda-usb.c90
-rw-r--r--drivers/net/irda/irda-usb.h7
-rw-r--r--drivers/net/lp486e.c2
-rw-r--r--drivers/net/mv643xx_eth.c706
-rw-r--r--drivers/net/ppp_generic.c3
-rw-r--r--drivers/net/r8169.c13
-rw-r--r--drivers/net/s2io.c2
-rw-r--r--drivers/net/sis190.c4
-rw-r--r--drivers/net/sis900.h1
-rw-r--r--drivers/net/skge.c30
-rw-r--r--drivers/net/sky2.c434
-rw-r--r--drivers/net/sky2.h9
-rw-r--r--drivers/net/spider_net.c512
-rw-r--r--drivers/net/spider_net.h75
-rw-r--r--drivers/net/spider_net_ethtool.c19
-rw-r--r--drivers/net/tg3.c108
-rw-r--r--drivers/net/tg3.h2
-rw-r--r--drivers/net/tokenring/smctr.h2
-rw-r--r--drivers/net/tulip/uli526x.c2
-rw-r--r--drivers/net/wan/dscc4.c2
-rw-r--r--drivers/net/wan/pci200syn.c2
-rw-r--r--drivers/net/wan/wanxl.c2
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/airo.c21
-rw-r--r--drivers/net/wireless/atmel.c102
-rw-r--r--drivers/net/wireless/hostap/Kconfig24
-rw-r--r--drivers/net/wireless/hostap/Makefile3
-rw-r--r--drivers/net/wireless/hostap/hostap.h37
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h3
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c11
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c15
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c36
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_common.h3
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h13
-rw-r--r--drivers/net/wireless/hostap/hostap_info.c3
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c12
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c60
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c7
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h4
-rw-r--r--drivers/net/wireless/ipw2100.c483
-rw-r--r--drivers/net/wireless/ipw2200.c29
-rw-r--r--drivers/net/wireless/orinoco_cs.c5
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c2
-rw-r--r--drivers/net/wireless/ray_cs.c2
-rw-r--r--drivers/net/wireless/wavelan_cs.c18
-rw-r--r--drivers/parisc/ccio-dma.c167
-rw-r--r--drivers/parisc/dino.c4
-rw-r--r--drivers/parisc/hppb.c3
-rw-r--r--drivers/parisc/iosapic.c8
-rw-r--r--drivers/parisc/lasi.c5
-rw-r--r--drivers/parisc/lba_pci.c6
-rw-r--r--drivers/parisc/pdc_stable.c356
-rw-r--r--drivers/parisc/sba_iommu.c128
-rw-r--r--drivers/parisc/superio.c41
-rw-r--r--drivers/parisc/wax.c2
-rw-r--r--drivers/parport/Kconfig9
-rw-r--r--drivers/parport/Makefile1
-rw-r--r--drivers/parport/ieee1284.c10
-rw-r--r--drivers/parport/parport_gsc.c2
-rw-r--r--drivers/parport/parport_ip32.c2253
-rw-r--r--drivers/parport/parport_serial.c4
-rw-r--r--drivers/parport/probe.c4
-rw-r--r--drivers/pci/hotplug/Kconfig3
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c21
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c4
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c64
-rw-r--r--drivers/pci/hotplug/rpaphp.h14
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c114
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c267
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c17
-rw-r--r--drivers/pci/hotplug/shpchp.h94
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c12
-rw-r--r--drivers/pci/msi.c14
-rw-r--r--drivers/pci/msi.h6
-rw-r--r--drivers/pci/pci.c2
-rw-r--r--drivers/pci/quirks.c5
-rw-r--r--drivers/pci/setup-res.c1
-rw-r--r--drivers/pnp/card.c9
-rw-r--r--drivers/pnp/pnpacpi/core.c14
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c547
-rw-r--r--drivers/s390/Kconfig7
-rw-r--r--drivers/s390/block/dasd.c67
-rw-r--r--drivers/s390/block/dasd_3370_erp.c1
-rw-r--r--drivers/s390/block/dasd_3990_erp.c1
-rw-r--r--drivers/s390/block/dasd_9336_erp.c1
-rw-r--r--drivers/s390/block/dasd_9343_erp.c1
-rw-r--r--drivers/s390/block/dasd_cmb.c2
-rw-r--r--drivers/s390/block/dasd_devmap.c1
-rw-r--r--drivers/s390/block/dasd_diag.c1
-rw-r--r--drivers/s390/block/dasd_diag.h1
-rw-r--r--drivers/s390/block/dasd_eckd.c1
-rw-r--r--drivers/s390/block/dasd_eckd.h1
-rw-r--r--drivers/s390/block/dasd_erp.c1
-rw-r--r--drivers/s390/block/dasd_fba.c1
-rw-r--r--drivers/s390/block/dasd_fba.h1
-rw-r--r--drivers/s390/block/dasd_genhd.c1
-rw-r--r--drivers/s390/block/dasd_int.h2
-rw-r--r--drivers/s390/block/dasd_ioctl.c11
-rw-r--r--drivers/s390/block/dasd_proc.c1
-rw-r--r--drivers/s390/char/con3215.c3
-rw-r--r--drivers/s390/char/con3270.c3
-rw-r--r--drivers/s390/char/keyboard.c6
-rw-r--r--drivers/s390/char/sclp.c13
-rw-r--r--drivers/s390/char/tape_34xx.c5
-rw-r--r--drivers/s390/char/tape_class.c4
-rw-r--r--drivers/s390/char/tape_class.h2
-rw-r--r--drivers/s390/char/tape_core.c5
-rw-r--r--drivers/s390/cio/airq.c2
-rw-r--r--drivers/s390/cio/blacklist.c1
-rw-r--r--drivers/s390/cio/ccwgroup.c1
-rw-r--r--drivers/s390/cio/chsc.c11
-rw-r--r--drivers/s390/cio/chsc.h2
-rw-r--r--drivers/s390/cio/cio.c1
-rw-r--r--drivers/s390/cio/cmf.c2
-rw-r--r--drivers/s390/cio/css.c1
-rw-r--r--drivers/s390/cio/device.c7
-rw-r--r--drivers/s390/cio/device_ops.c2
-rw-r--r--drivers/s390/cio/device_pgid.c2
-rw-r--r--drivers/s390/cio/device_status.c1
-rw-r--r--drivers/s390/cio/qdio.c18
-rw-r--r--drivers/s390/cio/qdio.h2
-rw-r--r--drivers/s390/crypto/z90common.h2
-rw-r--r--drivers/s390/crypto/z90crypt.h2
-rw-r--r--drivers/s390/crypto/z90hardware.c6
-rw-r--r--drivers/s390/crypto/z90main.c10
-rw-r--r--drivers/s390/net/claw.c11
-rw-r--r--drivers/s390/net/claw.h2
-rw-r--r--drivers/s390/net/ctcdbug.c5
-rw-r--r--drivers/s390/net/ctcdbug.h4
-rw-r--r--drivers/s390/net/ctcmain.c19
-rw-r--r--drivers/s390/net/ctcmain.h4
-rw-r--r--drivers/s390/net/ctctty.c2
-rw-r--r--drivers/s390/net/ctctty.h2
-rw-r--r--drivers/s390/net/cu3088.c2
-rw-r--r--drivers/s390/net/fsm.c2
-rw-r--r--drivers/s390/net/fsm.h2
-rw-r--r--drivers/s390/net/iucv.c16
-rw-r--r--drivers/s390/net/lcs.c36
-rw-r--r--drivers/s390/net/lcs.h4
-rw-r--r--drivers/s390/net/netiucv.c15
-rw-r--r--drivers/s390/net/qeth.h114
-rw-r--r--drivers/s390/net/qeth_eddp.c16
-rw-r--r--drivers/s390/net/qeth_eddp.h6
-rw-r--r--drivers/s390/net/qeth_fs.h5
-rw-r--r--drivers/s390/net/qeth_main.c30
-rw-r--r--drivers/s390/net/qeth_mpc.c2
-rw-r--r--drivers/s390/net/qeth_mpc.h4
-rw-r--r--drivers/s390/net/qeth_proc.c4
-rw-r--r--drivers/s390/net/qeth_sys.c4
-rw-r--r--drivers/s390/net/qeth_tso.h4
-rw-r--r--drivers/s390/s390_rdev.c1
-rw-r--r--drivers/s390/s390mach.h17
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c2
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c78
-rw-r--r--drivers/s390/scsi/zfcp_def.h15
-rw-r--r--drivers/s390/scsi/zfcp_erp.c84
-rw-r--r--drivers/s390/scsi/zfcp_ext.h7
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c82
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c2
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c17
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c6
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_driver.c2
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c2
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_unit.c2
-rw-r--r--drivers/scsi/3w-9xxx.c7
-rw-r--r--drivers/scsi/aacraid/aachba.c217
-rw-r--r--drivers/scsi/aacraid/aacraid.h18
-rw-r--r--drivers/scsi/aacraid/commctrl.c22
-rw-r--r--drivers/scsi/aacraid/comminit.c12
-rw-r--r--drivers/scsi/aacraid/commsup.c52
-rw-r--r--drivers/scsi/aacraid/dpcsup.c2
-rw-r--r--drivers/scsi/aacraid/linit.c50
-rw-r--r--drivers/scsi/ahci.c29
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx4
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h3
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.reg29
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.seq143
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c286
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_inline.h7
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c43
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h10
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c17
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c11
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg.h_shipped27
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped21
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_seq.h_shipped881
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm.c23
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_gram.y19
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h88
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_scan.l27
-rw-r--r--drivers/scsi/ata_piix.c3
-rw-r--r--drivers/scsi/dc395x.c6
-rw-r--r--drivers/scsi/gdth.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c67
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h3
-rw-r--r--drivers/scsi/ibmvscsi/iseries_vscsi.c13
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c22
-rw-r--r--drivers/scsi/ide-scsi.c14
-rw-r--r--drivers/scsi/ipr.c49
-rw-r--r--drivers/scsi/ipr.h5
-rw-r--r--drivers/scsi/ips.c54
-rw-r--r--drivers/scsi/iscsi_tcp.c78
-rw-r--r--drivers/scsi/iscsi_tcp.h4
-rw-r--r--drivers/scsi/libata-core.c78
-rw-r--r--drivers/scsi/libata-scsi.c27
-rw-r--r--drivers/scsi/mac53c94.c4
-rw-r--r--drivers/scsi/megaraid.c2
-rw-r--r--drivers/scsi/megaraid.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c388
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h71
-rw-r--r--drivers/scsi/qla1280.c311
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c276
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h48
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h33
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c84
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c20
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c108
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c98
-rw-r--r--drivers/scsi/qla2xxx/qla_rscn.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c963
-rw-r--r--drivers/scsi/sata_mv.c12
-rw-r--r--drivers/scsi/sata_promise.c16
-rw-r--r--drivers/scsi/sata_sil.c10
-rw-r--r--drivers/scsi/sata_svw.c1
-rw-r--r--drivers/scsi/sata_vsc.c30
-rw-r--r--drivers/scsi/scsi.c2
-rw-r--r--drivers/scsi/scsi_error.c2
-rw-r--r--drivers/scsi/scsi_lib.c64
-rw-r--r--drivers/scsi/scsi_scan.c26
-rw-r--r--drivers/scsi/scsi_sysfs.c9
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c262
-rw-r--r--drivers/scsi/scsi_transport_sas.c6
-rw-r--r--drivers/scsi/sg.c4
-rw-r--r--drivers/scsi/st.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c2
-rw-r--r--drivers/serial/21285.c4
-rw-r--r--drivers/serial/68328serial.c4
-rw-r--r--drivers/serial/68360serial.c4
-rw-r--r--drivers/serial/8250.c35
-rw-r--r--drivers/serial/8250_acpi.c22
-rw-r--r--drivers/serial/8250_au1x00.c1
-rw-r--r--drivers/serial/8250_pci.c39
-rw-r--r--drivers/serial/Kconfig33
-rw-r--r--drivers/serial/amba-pl010.c8
-rw-r--r--drivers/serial/at91_serial.c2
-rw-r--r--drivers/serial/au1x00_uart.c12
-rw-r--r--drivers/serial/clps711x.c4
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c25
-rw-r--r--drivers/serial/dz.c3
-rw-r--r--drivers/serial/imx.c12
-rw-r--r--drivers/serial/ioc4_serial.c14
-rw-r--r--drivers/serial/ip22zilog.c8
-rw-r--r--drivers/serial/jsm/jsm.h1
-rw-r--r--drivers/serial/jsm/jsm_driver.c3
-rw-r--r--drivers/serial/jsm/jsm_neo.c85
-rw-r--r--drivers/serial/jsm/jsm_tty.c209
-rw-r--r--drivers/serial/m32r_sio.c2
-rw-r--r--drivers/serial/m32r_sio.h2
-rw-r--r--drivers/serial/mcfserial.c17
-rw-r--r--drivers/serial/mux.c2
-rw-r--r--drivers/serial/pmac_zilog.c2
-rw-r--r--drivers/serial/s3c2410.c6
-rw-r--r--drivers/serial/sa1100.c8
-rw-r--r--drivers/serial/serial_core.c18
-rw-r--r--drivers/serial/serial_lh7a40x.c12
-rw-r--r--drivers/serial/sh-sci.c317
-rw-r--r--drivers/serial/sh-sci.h114
-rw-r--r--drivers/serial/sn_console.c129
-rw-r--r--drivers/serial/suncore.c34
-rw-r--r--drivers/serial/sunsab.c9
-rw-r--r--drivers/serial/sunsu.c24
-rw-r--r--drivers/serial/sunzilog.c4
-rw-r--r--drivers/serial/v850e_uart.c2
-rw-r--r--drivers/sn/ioc3.c30
-rw-r--r--drivers/spi/Kconfig10
-rw-r--r--drivers/spi/spi.c5
-rw-r--r--drivers/spi/spi_butterfly.c36
-rw-r--r--drivers/tc/tc.c1
-rw-r--r--drivers/telephony/ixj.c14
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/atm/cxacru.c92
-rw-r--r--drivers/usb/atm/speedtch.c167
-rw-r--r--drivers/usb/atm/ueagle-atm.c96
-rw-r--r--drivers/usb/atm/usbatm.c574
-rw-r--r--drivers/usb/atm/usbatm.h59
-rw-r--r--drivers/usb/atm/xusbatm.c137
-rw-r--r--drivers/usb/class/cdc-acm.c9
-rw-r--r--drivers/usb/class/usblp.c71
-rw-r--r--drivers/usb/core/driver.c6
-rw-r--r--drivers/usb/core/message.c1
-rw-r--r--drivers/usb/core/urb.c1
-rw-r--r--drivers/usb/gadget/inode.c8
-rw-r--r--drivers/usb/gadget/net2280.c1
-rw-r--r--drivers/usb/gadget/zero.c8
-rw-r--r--drivers/usb/host/ehci-pci.c64
-rw-r--r--drivers/usb/host/ehci-sched.c4
-rw-r--r--drivers/usb/host/isp116x-hcd.c21
-rw-r--r--drivers/usb/host/ohci-au1xxx.c2
-rw-r--r--drivers/usb/host/pci-quirks.c122
-rw-r--r--drivers/usb/host/sl811_cs.c4
-rw-r--r--drivers/usb/host/uhci-q.c4
-rw-r--r--drivers/usb/input/hid-core.c59
-rw-r--r--drivers/usb/input/hiddev.c5
-rw-r--r--drivers/usb/input/touchkitusb.c3
-rw-r--r--drivers/usb/input/yealink.c48
-rw-r--r--drivers/usb/media/Kconfig17
-rw-r--r--drivers/usb/media/Makefile2
-rw-r--r--drivers/usb/media/et61x251.h220
-rw-r--r--drivers/usb/media/et61x251_core.c2605
-rw-r--r--drivers/usb/media/et61x251_sensor.h115
-rw-r--r--drivers/usb/media/et61x251_tas5130d1b.c137
-rw-r--r--drivers/usb/media/ov511.c196
-rw-r--r--drivers/usb/media/pwc/pwc-ctrl.c264
-rw-r--r--drivers/usb/media/sn9c102.h50
-rw-r--r--drivers/usb/media/sn9c102_core.c1681
-rw-r--r--drivers/usb/media/sn9c102_hv7131d.c2
-rw-r--r--drivers/usb/media/sn9c102_mi0343.c2
-rw-r--r--drivers/usb/media/sn9c102_ov7630.c8
-rw-r--r--drivers/usb/media/sn9c102_pas106b.c2
-rw-r--r--drivers/usb/media/sn9c102_sensor.h85
-rw-r--r--drivers/usb/media/sn9c102_tas5110c1b.c2
-rw-r--r--drivers/usb/media/sn9c102_tas5130d1b.c2
-rw-r--r--drivers/usb/media/w9968cf.c128
-rw-r--r--drivers/usb/media/w9968cf.h1
-rw-r--r--drivers/usb/media/w9968cf_vpp.h3
-rw-r--r--drivers/usb/misc/Kconfig2
-rw-r--r--drivers/usb/misc/auerswald.c2
-rw-r--r--drivers/usb/misc/ldusb.c59
-rw-r--r--drivers/usb/net/asix.c4
-rw-r--r--drivers/usb/serial/cp2101.c14
-rw-r--r--drivers/usb/serial/ftdi_sio.c6
-rw-r--r--drivers/usb/serial/ftdi_sio.h23
-rw-r--r--drivers/usb/serial/pl2303.c5
-rw-r--r--drivers/usb/serial/pl2303.h11
-rw-r--r--drivers/usb/storage/initializers.c73
-rw-r--r--drivers/usb/storage/initializers.h1
-rw-r--r--drivers/usb/storage/libusual.c2
-rw-r--r--drivers/usb/storage/unusual_devs.h67
-rw-r--r--drivers/usb/usb-skeleton.c2
-rw-r--r--drivers/video/Kconfig5
-rw-r--r--drivers/video/amba-clcd.c54
-rw-r--r--drivers/video/aty/radeon_pm.c19
-rw-r--r--drivers/video/backlight/Kconfig8
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/backlight.c1
-rw-r--r--drivers/video/backlight/hp680_bl.c189
-rw-r--r--drivers/video/backlight/lcd.c1
-rw-r--r--drivers/video/console/sticore.c45
-rw-r--r--drivers/video/cyblafb.c1
-rw-r--r--drivers/video/fbmem.c2
-rw-r--r--drivers/video/gbefb.c2
-rw-r--r--drivers/video/i810/i810-i2c.c6
-rw-r--r--drivers/video/i810/i810.h1
-rw-r--r--drivers/video/i810/i810_main.c13
-rw-r--r--drivers/video/neofb.c17
-rw-r--r--drivers/video/nvidia/nvidia.c2
-rw-r--r--drivers/video/pmag-ba-fb.c1
-rw-r--r--drivers/video/pmagb-b-fb.c1
-rw-r--r--drivers/video/s3c2410fb.c1
-rw-r--r--drivers/video/sbuslib.c25
-rw-r--r--drivers/video/sbuslib.h4
863 files changed, 38413 insertions, 27355 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 283c089537b..bddf431bbb7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -68,4 +68,6 @@ source "drivers/infiniband/Kconfig"
source "drivers/sn/Kconfig"
+source "drivers/edac/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 7c45050ecd0..5c69b86db62 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -63,12 +63,13 @@ obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
obj-$(CONFIG_BT) += bluetooth/
obj-$(CONFIG_ISDN) += isdn/
+obj-$(CONFIG_EDAC) += edac/
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_INFINIBAND) += infiniband/
-obj-$(CONFIG_SGI_IOC4) += sn/
+obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
obj-$(CONFIG_SUPERH) += sh/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 6d61945260a..0cce28c4025 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -267,7 +267,6 @@ config ACPI_DEBUG
config ACPI_EC
bool
- depends on X86
default y
help
This driver is required on some systems for the proper operation of
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 2143609d293..d882bf87fa9 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -71,8 +71,8 @@ static struct acpi_driver acpi_memory_device_driver = {
struct acpi_memory_device {
acpi_handle handle;
unsigned int state; /* State of the memory device */
- unsigned short cache_attribute; /* memory cache attribute */
- unsigned short read_write_attribute; /* memory read/write attribute */
+ unsigned short caching; /* memory cache attribute */
+ unsigned short write_protect; /* memory read/write attribute */
u64 start_addr; /* Memory Range start physical addr */
u64 end_addr; /* Memory Range end physical addr */
};
@@ -97,12 +97,12 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
if (ACPI_SUCCESS(status)) {
if (address64.resource_type == ACPI_MEMORY_RANGE) {
/* Populate the structure */
- mem_device->cache_attribute =
- address64.attribute.memory.cache_attribute;
- mem_device->read_write_attribute =
- address64.attribute.memory.read_write_attribute;
- mem_device->start_addr = address64.min_address_range;
- mem_device->end_addr = address64.max_address_range;
+ mem_device->caching =
+ address64.info.mem.caching;
+ mem_device->write_protect =
+ address64.info.mem.write_protect;
+ mem_device->start_addr = address64.minimum;
+ mem_device->end_addr = address64.maximum;
}
}
@@ -250,7 +250,6 @@ static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
int result;
u64 start = mem_device->start_addr;
u64 len = mem_device->end_addr - start + 1;
- unsigned long attr = mem_device->read_write_attribute;
ACPI_FUNCTION_TRACE("acpi_memory_disable_device");
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index fec895af6ae..f4c87750dbf 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -78,9 +78,9 @@ MODULE_LICENSE("GPL");
static uid_t asus_uid;
static gid_t asus_gid;
module_param(asus_uid, uint, 0);
-MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n");
+MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus.\n");
module_param(asus_gid, uint, 0);
-MODULE_PARM_DESC(gid, "GID for entries in /proc/acpi/asus.\n");
+MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus.\n");
/* For each model, all features implemented,
* those marked with R are relative to HOTK, A for absolute */
@@ -302,7 +302,7 @@ static struct model_data model_conf[END_MODEL] = {
.brightness_set = "SPLV",
.brightness_get = "GPLV",
.display_set = "SDSP",
- .display_get = "\\SSTE"},
+ .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
{
.name = "M6R",
.mt_mled = "MLED",
@@ -851,6 +851,8 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
mode = S_IFREG | S_IRUGO | S_IWUGO;
} else {
mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
+ printk(KERN_WARNING " asus_uid and asus_gid parameters are "
+ "deprecated, use chown and chmod instead!\n");
}
acpi_device_dir(device) = asus_proc_dir;
@@ -987,9 +989,21 @@ static int __init asus_hotk_get_info(void)
printk(KERN_NOTICE " BSTS called, 0x%02x returned\n",
bsts_result);
- /* Samsung P30 has a device with a valid _HID whose INIT does not
- * return anything. Catch this one and any similar here */
- if (buffer.pointer == NULL) {
+ /* This is unlikely with implicit return */
+ if (buffer.pointer == NULL)
+ return -EINVAL;
+
+ model = (union acpi_object *) buffer.pointer;
+ /*
+ * Samsung P30 has a device with a valid _HID whose INIT does not
+ * return anything. It used to be possible to catch this exception,
+ * but the implicit return code will now happily confuse the
+ * driver. We assume that every ACPI_TYPE_STRING is a valid model
+ * identifier but it's still possible to get completely bogus data.
+ */
+ if (model->type == ACPI_TYPE_STRING) {
+ printk(KERN_NOTICE " %s model detected, ", model->string.pointer);
+ } else {
if (asus_info && /* Samsung P30 */
strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
hotk->model = P30;
@@ -1002,13 +1016,10 @@ static int __init asus_hotk_get_info(void)
"the developers with your DSDT\n");
}
hotk->methods = &model_conf[hotk->model];
- return AE_OK;
- }
+
+ acpi_os_free(model);
- model = (union acpi_object *)buffer.pointer;
- if (model->type == ACPI_TYPE_STRING) {
- printk(KERN_NOTICE " %s model detected, ",
- model->string.pointer);
+ return AE_OK;
}
hotk->model = END_MODEL;
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
index 2022aeaecfb..76bc0463f6d 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -128,7 +128,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
ACPI_IMODE_LOAD_PASS1, flags, walk_state,
&(node));
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
}
@@ -232,7 +232,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
+ (acpi_integer) arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
- ACPI_REPORT_ERROR(("Bit offset within field too large (> 0xFFFFFFFF)\n"));
+ ACPI_ERROR((AE_INFO,
+ "Bit offset within field too large (> 0xFFFFFFFF)"));
return_ACPI_STATUS(AE_SUPPORT);
}
@@ -268,8 +269,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
ACPI_NS_DONT_OPEN_SCOPE,
walk_state, &info->field_node);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR((char *)&arg->named.name,
- status);
+ ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
+ status);
if (status != AE_ALREADY_EXISTS) {
return_ACPI_STATUS(status);
}
@@ -293,7 +294,11 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
+ (acpi_integer) arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
- ACPI_REPORT_ERROR(("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n", (char *)&info->field_node->name));
+ ACPI_ERROR((AE_INFO,
+ "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
+ ACPI_CAST_PTR(char,
+ &info->field_node->
+ name)));
return_ACPI_STATUS(AE_SUPPORT);
}
@@ -302,9 +307,9 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid opcode in field list: %X\n",
- arg->common.aml_opcode));
+ ACPI_ERROR((AE_INFO,
+ "Invalid opcode in field list: %X",
+ arg->common.aml_opcode));
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
@@ -349,7 +354,7 @@ acpi_ds_create_field(union acpi_parse_object *op,
ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
walk_state, &region_node);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(arg->common.value.name, status);
+ ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
return_ACPI_STATUS(status);
}
}
@@ -431,8 +436,8 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
ACPI_NS_ERROR_IF_FOUND,
walk_state, &node);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR((char *)&arg->named.name,
- status);
+ ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
+ status);
if (status != AE_ALREADY_EXISTS) {
return_ACPI_STATUS(status);
}
@@ -488,7 +493,7 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
walk_state, &region_node);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(arg->common.value.name, status);
+ ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
return_ACPI_STATUS(status);
}
}
@@ -502,7 +507,7 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
ACPI_NS_SEARCH_PARENT, walk_state,
&info.register_node);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
@@ -560,7 +565,7 @@ acpi_ds_create_index_field(union acpi_parse_object *op,
ACPI_NS_SEARCH_PARENT, walk_state,
&info.register_node);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
@@ -573,7 +578,7 @@ acpi_ds_create_index_field(union acpi_parse_object *op,
ACPI_NS_SEARCH_PARENT, walk_state,
&info.data_register_node);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
index 8693c704aea..e65a07ad242 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -84,7 +84,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
acpi_object_type type;
acpi_status status;
- ACPI_FUNCTION_NAME("ds_init_one_object");
+ ACPI_FUNCTION_ENTRY();
/*
* We are only interested in NS nodes owned by the table that
@@ -105,11 +105,10 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
status = acpi_ds_initialize_region(obj_handle);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Region %p [%4.4s] - Init failure, %s\n",
- obj_handle,
- acpi_ut_get_node_name(obj_handle),
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During Region initialization %p [%4.4s]",
+ obj_handle,
+ acpi_ut_get_node_name(obj_handle)));
}
info->op_region_count++;
@@ -118,14 +117,6 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
case ACPI_TYPE_METHOD:
/*
- * Print a dot for each method unless we are going to print
- * the entire pathname
- */
- if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
- ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
- }
-
- /*
* Set the execution data width (32 or 64) based upon the
* revision number of the parent ACPI table.
* TBD: This is really for possible future support of integer width
@@ -134,6 +125,21 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
if (info->table_desc->pointer->revision == 1) {
node->flags |= ANOBJ_DATA_WIDTH_32;
}
+#ifdef ACPI_INIT_PARSE_METHODS
+ /*
+ * Note 11/2005: Removed this code to parse all methods during table
+ * load because it causes problems if there are any errors during the
+ * parse. Also, it seems like overkill and we probably don't want to
+ * abort a table load because of an issue with a single method.
+ */
+
+ /*
+ * Print a dot for each method unless we are going to print
+ * the entire pathname
+ */
+ if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
+ }
/*
* Always parse methods to detect errors, we will delete
@@ -141,15 +147,15 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
*/
status = acpi_ds_parse_method(obj_handle);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "\n+Method %p [%4.4s] - parse failure, %s\n",
- obj_handle,
- acpi_ut_get_node_name(obj_handle),
- acpi_format_exception(status)));
+ ACPI_ERROR((AE_INFO,
+ "Method %p [%4.4s] - parse failure, %s",
+ obj_handle,
+ acpi_ut_get_node_name(obj_handle),
+ acpi_format_exception(status)));
/* This parse failed, but we will continue parsing more methods */
}
-
+#endif
info->method_count++;
break;
@@ -207,8 +213,7 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc,
status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
acpi_ds_init_one_object, &info, NULL);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 36c1ca0b9ad..c475546535b 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,135 +47,66 @@
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
+#include <acpi/acdisasm.h>
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsmethod")
/*******************************************************************************
*
- * FUNCTION: acpi_ds_parse_method
+ * FUNCTION: acpi_ds_method_error
*
- * PARAMETERS: Node - Method node
+ * PARAMETERS: Status - Execution status
+ * walk_state - Current state
*
* RETURN: Status
*
- * DESCRIPTION: Parse the AML that is associated with the method.
+ * DESCRIPTION: Called on method error. Invoke the global exception handler if
+ * present, dump the method data if the disassembler is configured
*
- * MUTEX: Assumes parser is locked
+ * Note: Allows the exception handler to change the status code
*
******************************************************************************/
-acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
+acpi_status
+acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- union acpi_parse_object *op;
- struct acpi_walk_state *walk_state;
-
- ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
+ ACPI_FUNCTION_ENTRY();
- /* Parameter Validation */
+ /* Ignore AE_OK and control exception codes */
- if (!node) {
- return_ACPI_STATUS(AE_NULL_ENTRY);
+ if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) {
+ return (status);
}
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "**** Parsing [%4.4s] **** named_obj=%p\n",
- acpi_ut_get_node_name(node), node));
-
- /* Extract the method object from the method Node */
+ /* Invoke the global exception handler */
- obj_desc = acpi_ns_get_attached_object(node);
- if (!obj_desc) {
- return_ACPI_STATUS(AE_NULL_OBJECT);
- }
+ if (acpi_gbl_exception_handler) {
+ /* Exit the interpreter, allow handler to execute methods */
- /* Create a mutex for the method if there is a concurrency limit */
+ acpi_ex_exit_interpreter();
- if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
- (!obj_desc->method.semaphore)) {
- status = acpi_os_create_semaphore(obj_desc->method.concurrency,
- obj_desc->method.concurrency,
- &obj_desc->method.semaphore);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
- /*
- * Allocate a new parser op to be the root of the parsed
- * method tree
- */
- op = acpi_ps_alloc_op(AML_METHOD_OP);
- if (!op) {
- return_ACPI_STATUS(AE_NO_MEMORY);
- }
-
- /* Init new op with the method name and pointer back to the Node */
-
- acpi_ps_set_name(op, node->name.integer);
- op->common.node = node;
-
- /*
- * Get a new owner_id for objects created by this method. Namespace
- * objects (such as Operation Regions) can be created during the
- * first pass parse.
- */
- status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
- if (ACPI_FAILURE(status)) {
- goto cleanup;
- }
-
- /* Create and initialize a new walk state */
-
- walk_state =
- acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
- NULL);
- if (!walk_state) {
- status = AE_NO_MEMORY;
- goto cleanup2;
+ /*
+ * Handler can map the exception code to anything it wants, including
+ * AE_OK, in which case the executing method will not be aborted.
+ */
+ status = acpi_gbl_exception_handler(status,
+ walk_state->method_node ?
+ walk_state->method_node->
+ name.integer : 0,
+ walk_state->opcode,
+ walk_state->aml_offset,
+ NULL);
+ (void)acpi_ex_enter_interpreter();
}
-
- status = acpi_ds_init_aml_walk(walk_state, op, node,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length, NULL, 1);
+#ifdef ACPI_DISASSEMBLER
if (ACPI_FAILURE(status)) {
- acpi_ds_delete_walk_state(walk_state);
- goto cleanup2;
- }
+ /* Display method locals/args if disassembler is present */
- /*
- * Parse the method, first pass
- *
- * The first pass load is where newly declared named objects are added into
- * the namespace. Actual evaluation of the named objects (what would be
- * called a "second pass") happens during the actual execution of the
- * method so that operands to the named objects can take on dynamic
- * run-time values.
- */
- status = acpi_ps_parse_aml(walk_state);
- if (ACPI_FAILURE(status)) {
- goto cleanup2;
+ acpi_dm_dump_method_info(status, walk_state, walk_state->op);
}
+#endif
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
- acpi_ut_get_node_name(node), node, op));
-
- /*
- * Delete the parse tree. We simply re-parse the method for every
- * execution since there isn't much overhead (compared to keeping lots
- * of parse trees around)
- */
- acpi_ns_delete_namespace_subtree(node);
- acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
-
- cleanup2:
- acpi_ut_release_owner_id(&obj_desc->method.owner_id);
-
- cleanup:
- acpi_ps_delete_parse_tree(op);
- return_ACPI_STATUS(status);
+ return (status);
}
/*******************************************************************************
@@ -195,9 +126,9 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
******************************************************************************/
acpi_status
-acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
- union acpi_operand_object *obj_desc,
- struct acpi_namespace_node *calling_method_node)
+acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
+ union acpi_operand_object * obj_desc,
+ struct acpi_namespace_node * calling_method_node)
{
acpi_status status = AE_OK;
@@ -210,7 +141,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
/* Prevent wraparound of thread count */
if (obj_desc->method.thread_count == ACPI_UINT8_MAX) {
- ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n"));
+ ACPI_ERROR((AE_INFO,
+ "Method reached maximum reentrancy limit (255)"));
return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
}
@@ -539,22 +471,61 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
acpi_os_signal_semaphore(walk_state->method_desc->method.
semaphore, 1);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not signal method semaphore\n"));
+ ACPI_ERROR((AE_INFO,
+ "Could not signal method semaphore"));
/* Ignore error and continue cleanup */
}
}
+ /*
+ * There are no more threads executing this method. Perform
+ * additional cleanup.
+ *
+ * The method Node is stored in the walk state
+ */
+ method_node = walk_state->method_node;
+
+ /* Lock namespace for possible update */
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /*
+ * Delete any namespace entries created immediately underneath
+ * the method
+ */
+ if (method_node->child) {
+ acpi_ns_delete_namespace_subtree(method_node);
+ }
+
+ /*
+ * Delete any namespace entries created anywhere else within
+ * the namespace by the execution of this method
+ */
+ acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method.
+ owner_id);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+ /* Are there any other threads currently executing this method? */
+
if (walk_state->method_desc->method.thread_count) {
+ /*
+ * Additional threads. Do not release the owner_id in this case,
+ * we immediately reuse it for the next thread executing this method
+ */
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "*** Not deleting method namespace, there are still %d threads\n",
+ "*** Completed execution of one thread, %d threads remaining\n",
walk_state->method_desc->method.
thread_count));
- } else { /* This is the last executing thread */
+ } else {
+ /* This is the only executing thread for this method */
/*
* Support to dynamically change a method from not_serialized to
- * Serialized if it appears that the method is written foolishly and
+ * Serialized if it appears that the method is incorrectly written and
* does not support multiple thread execution. The best example of this
* is if such a method creates namespace objects and blocks. A second
* thread will fail with an AE_ALREADY_EXISTS exception
@@ -570,34 +541,8 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
semaphore);
}
- /*
- * There are no more threads executing this method. Perform
- * additional cleanup.
- *
- * The method Node is stored in the walk state
- */
- method_node = walk_state->method_node;
-
- /*
- * Delete any namespace entries created immediately underneath
- * the method
- */
- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- if (method_node->child) {
- acpi_ns_delete_namespace_subtree(method_node);
- }
+ /* No more threads, we can free the owner_id */
- /*
- * Delete any namespace entries created anywhere else within
- * the namespace
- */
- acpi_ns_delete_namespace_by_owner(walk_state->method_desc->
- method.owner_id);
- status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_ut_release_owner_id(&walk_state->method_desc->method.
owner_id);
}
@@ -606,3 +551,140 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
(void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
return_VOID;
}
+
+#ifdef ACPI_INIT_PARSE_METHODS
+ /*
+ * Note 11/2005: Removed this code to parse all methods during table
+ * load because it causes problems if there are any errors during the
+ * parse. Also, it seems like overkill and we probably don't want to
+ * abort a table load because of an issue with a single method.
+ */
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_parse_method
+ *
+ * PARAMETERS: Node - Method node
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Parse the AML that is associated with the method.
+ *
+ * MUTEX: Assumes parser is locked
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
+{
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
+
+ ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
+
+ /* Parameter Validation */
+
+ if (!node) {
+ return_ACPI_STATUS(AE_NULL_ENTRY);
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Parsing [%4.4s] **** named_obj=%p\n",
+ acpi_ut_get_node_name(node), node));
+
+ /* Extract the method object from the method Node */
+
+ obj_desc = acpi_ns_get_attached_object(node);
+ if (!obj_desc) {
+ return_ACPI_STATUS(AE_NULL_OBJECT);
+ }
+
+ /* Create a mutex for the method if there is a concurrency limit */
+
+ if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
+ (!obj_desc->method.semaphore)) {
+ status = acpi_os_create_semaphore(obj_desc->method.concurrency,
+ obj_desc->method.concurrency,
+ &obj_desc->method.semaphore);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ /*
+ * Allocate a new parser op to be the root of the parsed
+ * method tree
+ */
+ op = acpi_ps_alloc_op(AML_METHOD_OP);
+ if (!op) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /* Init new op with the method name and pointer back to the Node */
+
+ acpi_ps_set_name(op, node->name.integer);
+ op->common.node = node;
+
+ /*
+ * Get a new owner_id for objects created by this method. Namespace
+ * objects (such as Operation Regions) can be created during the
+ * first pass parse.
+ */
+ status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
+ }
+
+ /* Create and initialize a new walk state */
+
+ walk_state =
+ acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
+ NULL);
+ if (!walk_state) {
+ status = AE_NO_MEMORY;
+ goto cleanup2;
+ }
+
+ status = acpi_ds_init_aml_walk(walk_state, op, node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length, NULL, 1);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup2;
+ }
+
+ /*
+ * Parse the method, first pass
+ *
+ * The first pass load is where newly declared named objects are added into
+ * the namespace. Actual evaluation of the named objects (what would be
+ * called a "second pass") happens during the actual execution of the
+ * method so that operands to the named objects can take on dynamic
+ * run-time values.
+ */
+ status = acpi_ps_parse_aml(walk_state);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup2;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
+ acpi_ut_get_node_name(node), node, op));
+
+ /*
+ * Delete the parse tree. We simply re-parse the method for every
+ * execution since there isn't much overhead (compared to keeping lots
+ * of parse trees around)
+ */
+ acpi_ns_delete_namespace_subtree(node);
+ acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
+
+ cleanup2:
+ acpi_ut_release_owner_id(&obj_desc->method.owner_id);
+
+ cleanup:
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(status);
+}
+#endif
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index 4095ce70982..c025674f938 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -260,9 +260,9 @@ acpi_ds_method_data_get_node(u16 opcode,
case AML_LOCAL_OP:
if (index > ACPI_METHOD_MAX_LOCAL) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Local index %d is invalid (max %d)\n",
- index, ACPI_METHOD_MAX_LOCAL));
+ ACPI_ERROR((AE_INFO,
+ "Local index %d is invalid (max %d)",
+ index, ACPI_METHOD_MAX_LOCAL));
return_ACPI_STATUS(AE_AML_INVALID_INDEX);
}
@@ -274,9 +274,9 @@ acpi_ds_method_data_get_node(u16 opcode,
case AML_ARG_OP:
if (index > ACPI_METHOD_MAX_ARG) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Arg index %d is invalid (max %d)\n",
- index, ACPI_METHOD_MAX_ARG));
+ ACPI_ERROR((AE_INFO,
+ "Arg index %d is invalid (max %d)",
+ index, ACPI_METHOD_MAX_ARG));
return_ACPI_STATUS(AE_AML_INVALID_INDEX);
}
@@ -286,8 +286,7 @@ acpi_ds_method_data_get_node(u16 opcode,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Opcode %d is invalid\n",
- opcode));
+ ACPI_ERROR((AE_INFO, "Opcode %d is invalid", opcode));
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
@@ -378,8 +377,7 @@ acpi_ds_method_data_get_value(u16 opcode,
/* Validate the object descriptor */
if (!dest_desc) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Null object descriptor pointer\n"));
+ ACPI_ERROR((AE_INFO, "Null object descriptor pointer"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -424,23 +422,24 @@ acpi_ds_method_data_get_value(u16 opcode,
switch (opcode) {
case AML_ARG_OP:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Uninitialized Arg[%d] at node %p\n",
- index, node));
+ ACPI_ERROR((AE_INFO,
+ "Uninitialized Arg[%d] at node %p",
+ index, node));
return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
case AML_LOCAL_OP:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Uninitialized Local[%d] at node %p\n",
- index, node));
+ ACPI_ERROR((AE_INFO,
+ "Uninitialized Local[%d] at node %p",
+ index, node));
return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
default:
- ACPI_REPORT_ERROR(("Not Arg/Local opcode: %X\n",
- opcode));
+ ACPI_ERROR((AE_INFO,
+ "Not a Arg/Local opcode: %X",
+ opcode));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
}
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index 8ac0cd93adb..8b21f0f9e51 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,7 @@
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsobject")
+/* Local prototypes */
static acpi_status
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
@@ -85,7 +86,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
*obj_desc_ptr = NULL;
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
/*
- * This is an named object reference. If this name was
+ * This is a named object reference. If this name was
* previously looked up in the namespace, it was stored in this op.
* Otherwise, go ahead and look it up now
*/
@@ -96,18 +97,48 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT |
ACPI_NS_DONT_OPEN_SCOPE, NULL,
- (struct acpi_namespace_node **)
- &(op->common.node));
-
+ ACPI_CAST_INDIRECT_PTR(struct
+ acpi_namespace_node,
+ &(op->
+ common.
+ node)));
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(op->common.value.string,
- status);
+ /* Check if we are resolving a named reference within a package */
+
+ if ((status == AE_NOT_FOUND)
+ && (acpi_gbl_enable_interpreter_slack)
+ &&
+ ((op->common.parent->common.aml_opcode ==
+ AML_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP))) {
+ /*
+ * We didn't find the target and we are populating elements
+ * of a package - ignore if slack enabled. Some ASL code
+ * contains dangling invalid references in packages and
+ * expects that no exception will be issued. Leave the
+ * element as a null element. It cannot be used, but it
+ * can be overwritten by subsequent ASL code - this is
+ * typically the case.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Ignoring unresolved reference in package [%4.4s]\n",
+ walk_state->
+ scope_info->scope.
+ node->name.ascii));
+
+ return_ACPI_STATUS(AE_OK);
+ } else {
+ ACPI_ERROR_NAMESPACE(op->common.value.
+ string, status);
+ }
+
return_ACPI_STATUS(status);
}
}
}
- /* Create and init the internal ACPI object */
+ /* Create and init a new internal ACPI object */
obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
(op->common.aml_opcode))->
@@ -157,13 +188,13 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
+ /*
+ * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
+ * The buffer object already exists (from the NS node), otherwise it must
+ * be created.
+ */
obj_desc = *obj_desc_ptr;
- if (obj_desc) {
- /*
- * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
- * The buffer object already exists (from the NS node)
- */
- } else {
+ if (!obj_desc) {
/* Create a new buffer object */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
@@ -183,10 +214,9 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
byte_list = arg->named.next;
if (byte_list) {
if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Expecting bytelist, got AML opcode %X in op %p\n",
- byte_list->common.aml_opcode,
- byte_list));
+ ACPI_ERROR((AE_INFO,
+ "Expecting bytelist, got AML opcode %X in op %p",
+ byte_list->common.aml_opcode, byte_list));
acpi_ut_remove_reference(obj_desc);
return (AE_TYPE);
@@ -259,7 +289,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
union acpi_operand_object *obj_desc = NULL;
u32 package_list_length;
acpi_status status = AE_OK;
- u32 i;
+ acpi_native_uint i;
ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
@@ -271,13 +301,12 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
parent = parent->common.parent;
}
+ /*
+ * If we are evaluating a Named package object "Name (xxxx, Package)",
+ * the package object already exists, otherwise it must be created.
+ */
obj_desc = *obj_desc_ptr;
- if (obj_desc) {
- /*
- * We are evaluating a Named package object "Name (xxxx, Package)".
- * Get the existing package object from the NS node
- */
- } else {
+ if (!obj_desc) {
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
*obj_desc_ptr = obj_desc;
if (!obj_desc) {
@@ -291,11 +320,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
/* Count the number of items in the package list */
- package_list_length = 0;
arg = op->common.value.arg;
arg = arg->common.next;
- while (arg) {
- package_list_length++;
+ for (package_list_length = 0; arg; package_list_length++) {
arg = arg->common.next;
}
@@ -322,12 +349,11 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
}
/*
- * Now init the elements of the package
+ * Initialize all elements of the package
*/
- i = 0;
arg = op->common.value.arg;
arg = arg->common.next;
- while (arg) {
+ for (i = 0; arg; i++) {
if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
/* Object (package or buffer) is already built */
@@ -340,8 +366,6 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
package.
elements[i]);
}
-
- i++;
arg = arg->common.next;
}
@@ -518,9 +542,9 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown constant opcode %X\n",
- opcode));
+ ACPI_ERROR((AE_INFO,
+ "Unknown constant opcode %X",
+ opcode));
status = AE_AML_OPERAND_TYPE;
break;
}
@@ -535,9 +559,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown Integer type %X\n",
- op_info->type));
+ ACPI_ERROR((AE_INFO, "Unknown Integer type %X",
+ op_info->type));
status = AE_AML_OPERAND_TYPE;
break;
}
@@ -615,9 +638,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unimplemented data type: %X\n",
- ACPI_GET_OBJECT_TYPE(obj_desc)));
+ ACPI_ERROR((AE_INFO, "Unimplemented data type: %X",
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_OPERAND_TYPE;
break;
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 939d167bf87..6229c10674e 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -245,7 +245,9 @@ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
node = obj_desc->buffer.node;
if (!node) {
- ACPI_REPORT_ERROR(("No pointer back to NS node in buffer obj %p\n", obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "No pointer back to NS node in buffer obj %p",
+ obj_desc));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -287,8 +289,9 @@ acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
node = obj_desc->package.node;
if (!node) {
- ACPI_REPORT_ERROR(("No pointer back to NS node in package %p\n",
- obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "No pointer back to NS node in package %p",
+ obj_desc));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -413,9 +416,9 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
/* Host object must be a Buffer */
if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Target of Create Field is not a Buffer object - %s\n",
- acpi_ut_get_object_type_name(buffer_desc)));
+ ACPI_ERROR((AE_INFO,
+ "Target of Create Field is not a Buffer object - %s",
+ acpi_ut_get_object_type_name(buffer_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -427,10 +430,10 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
* after resolution in acpi_ex_resolve_operands().
*/
if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "(%s) destination not a NS Node [%s]\n",
- acpi_ps_get_opcode_name(aml_opcode),
- acpi_ut_get_descriptor_name(result_desc)));
+ ACPI_ERROR((AE_INFO,
+ "(%s) destination not a NS Node [%s]",
+ acpi_ps_get_opcode_name(aml_opcode),
+ acpi_ut_get_descriptor_name(result_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -453,8 +456,8 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
/* Must have a valid (>0) bit count */
if (bit_count == 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Attempt to create_field of length 0\n"));
+ ACPI_ERROR((AE_INFO,
+ "Attempt to create_field of length zero"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
@@ -507,9 +510,8 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown field creation opcode %02x\n",
- aml_opcode));
+ ACPI_ERROR((AE_INFO,
+ "Unknown field creation opcode %02x", aml_opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
@@ -517,13 +519,12 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
/* Entire field must fit within the current length of the buffer */
if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
- acpi_ut_get_node_name(result_desc),
- bit_offset + bit_count,
- acpi_ut_get_node_name(buffer_desc->buffer.
- node),
- 8 * (u32) buffer_desc->buffer.length));
+ ACPI_ERROR((AE_INFO,
+ "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)",
+ acpi_ut_get_node_name(result_desc),
+ bit_offset + bit_count,
+ acpi_ut_get_node_name(buffer_desc->buffer.node),
+ 8 * (u32) buffer_desc->buffer.length));
status = AE_AML_BUFFER_LIMIT;
goto cleanup;
}
@@ -629,9 +630,9 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
"after acpi_ex_resolve_operands");
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n",
- acpi_ps_get_opcode_name(op->common.
- aml_opcode), status));
+ ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ status));
return_ACPI_STATUS(status);
}
@@ -1155,9 +1156,8 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown control opcode=%X Op=%p\n",
- op->common.aml_opcode, op));
+ ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p",
+ op->common.aml_opcode, op));
status = AE_AML_BAD_OPCODE;
break;
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 83ae1c1aa28..53356a591ac 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -176,8 +176,8 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
/* Must have both an Op and a Result Object */
if (!op) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n"));
- return_VALUE(TRUE);
+ ACPI_ERROR((AE_INFO, "Null Op"));
+ return_UINT8(TRUE);
}
/*
@@ -208,7 +208,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
"At Method level, result of [%s] not used\n",
acpi_ps_get_opcode_name(op->common.
aml_opcode)));
- return_VALUE(FALSE);
+ return_UINT8(FALSE);
}
/* Get info on the parent. The root_op is AML_SCOPE */
@@ -216,9 +216,8 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
parent_info =
acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
if (parent_info->class == AML_CLASS_UNKNOWN) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown parent opcode. Op=%p\n", op));
- return_VALUE(FALSE);
+ ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
+ return_UINT8(FALSE);
}
/*
@@ -304,7 +303,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
acpi_ps_get_opcode_name(op->common.parent->common.
aml_opcode), op));
- return_VALUE(TRUE);
+ return_UINT8(TRUE);
result_not_used:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
@@ -313,7 +312,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
acpi_ps_get_opcode_name(op->common.parent->common.
aml_opcode), op));
- return_VALUE(FALSE);
+ return_UINT8(FALSE);
}
/*******************************************************************************
@@ -344,7 +343,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj);
if (!op) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n"));
+ ACPI_ERROR((AE_INFO, "Null Op"));
return_VOID;
}
@@ -567,7 +566,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
}
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(name_string, status);
+ ACPI_ERROR_NAMESPACE(name_string, status);
}
}
@@ -616,7 +615,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
if (op_info->flags & AML_HAS_RETVAL) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "Argument previously created, already stacked \n"));
+ "Argument previously created, already stacked\n"));
ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
(walk_state->
@@ -635,10 +634,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
* Only error is underflow, and this indicates
* a missing or null operand!
*/
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Missing or null operand, %s\n",
- acpi_format_exception
- (status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Missing or null operand"));
return_ACPI_STATUS(status);
}
} else {
@@ -730,7 +727,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
*/
(void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
- (arg_count + 1), acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d",
+ (arg_count + 1)));
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index e522763bb69..f1af655ff11 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -100,9 +100,8 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
if (result_obj) {
status = acpi_ds_result_pop(&obj_desc, walk_state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not get result from predicate evaluation, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not get result from predicate evaluation"));
return_ACPI_STATUS(status);
}
@@ -123,9 +122,9 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
}
if (!obj_desc) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No predicate obj_desc=%p State=%p\n",
- obj_desc, walk_state));
+ ACPI_ERROR((AE_INFO,
+ "No predicate obj_desc=%p State=%p",
+ obj_desc, walk_state));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
@@ -140,10 +139,10 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
}
if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
- obj_desc, walk_state,
- ACPI_GET_OBJECT_TYPE(obj_desc)));
+ ACPI_ERROR((AE_INFO,
+ "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X",
+ obj_desc, walk_state,
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -314,12 +313,13 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
-
/*
* Most operators with arguments.
* Start a new result/operand state
*/
- status = acpi_ds_result_stack_push(walk_state);
+ if (walk_state->opcode != AML_CREATE_FIELD_OP) {
+ status = acpi_ds_result_stack_push(walk_state);
+ }
break;
default:
@@ -361,8 +361,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
op_class = walk_state->op_info->class;
if (op_class == AML_CLASS_UNKNOWN) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown opcode %X\n",
- op->common.aml_opcode));
+ ACPI_ERROR((AE_INFO, "Unknown opcode %X",
+ op->common.aml_opcode));
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
@@ -452,12 +452,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
walk_state->operands[1]->reference.offset)) {
status = AE_OK;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "[%s]: Could not resolve operands, %s\n",
- acpi_ps_get_opcode_name
- (walk_state->opcode),
- acpi_format_exception
- (status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While resolving operands for [%s]",
+ acpi_ps_get_opcode_name
+ (walk_state->opcode)));
}
}
@@ -676,8 +674,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
case AML_TYPE_UNDEFINED:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Undefined opcode type Op=%p\n", op));
+ ACPI_ERROR((AE_INFO,
+ "Undefined opcode type Op=%p", op));
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
case AML_TYPE_BOGUS:
@@ -689,10 +687,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n",
- op_class, op_type,
- op->common.aml_opcode, op));
+ ACPI_ERROR((AE_INFO,
+ "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p",
+ op_class, op_type, op->common.aml_opcode,
+ op));
status = AE_NOT_IMPLEMENTED;
break;
@@ -723,20 +721,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
cleanup:
- /* Invoke exception handler on error */
-
- if (ACPI_FAILURE(status) &&
- acpi_gbl_exception_handler && !(status & AE_CODE_CONTROL)) {
- acpi_ex_exit_interpreter();
- status = acpi_gbl_exception_handler(status,
- walk_state->method_node->
- name.integer,
- walk_state->opcode,
- walk_state->aml_offset,
- NULL);
- (void)acpi_ex_enter_interpreter();
- }
-
if (walk_state->result_obj) {
/* Break to debugger to display result */
@@ -758,18 +742,14 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
}
#endif
- /* Always clear the object stack */
-
- walk_state->num_operands = 0;
-
-#ifdef ACPI_DISASSEMBLER
-
- /* On error, display method locals/args */
+ /* Invoke exception handler on error */
if (ACPI_FAILURE(status)) {
- acpi_dm_dump_method_info(status, walk_state, op);
+ status = acpi_ds_method_error(status, walk_state);
}
-#endif
+ /* Always clear the object stack */
+
+ walk_state->num_operands = 0;
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index 411731261c2..d3d24da31c8 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -127,7 +127,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
char *path;
u32 flags;
- ACPI_FUNCTION_NAME("ds_load1_begin_op");
+ ACPI_FUNCTION_TRACE("ds_load1_begin_op");
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -138,14 +138,14 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
if (op) {
if (!(walk_state->op_info->flags & AML_NAMED)) {
*out_op = op;
- return (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Check if this object has already been installed in the namespace */
if (op->common.node) {
*out_op = op;
- return (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
}
@@ -187,8 +187,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
}
#endif
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(path, status);
- return (status);
+ ACPI_ERROR_NAMESPACE(path, status);
+ return_ACPI_STATUS(status);
}
/*
@@ -233,9 +233,11 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
/* All other types are an error */
- ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n", acpi_ut_get_type_name(node->type), path));
+ ACPI_ERROR((AE_INFO,
+ "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)",
+ acpi_ut_get_type_name(node->type), path));
- return (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
@@ -257,6 +259,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
* buffer_field, or Package), the name of the object is already
* in the namespace.
*/
+
if (walk_state->deferred_node) {
/* This name is already in the namespace, get the node */
@@ -265,6 +268,16 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
break;
}
+ /*
+ * If we are executing a method, do not create any namespace objects
+ * during the load phase, only during execution.
+ */
+ if (walk_state->method_node) {
+ node = NULL;
+ status = AE_OK;
+ break;
+ }
+
flags = ACPI_NS_NO_UPSEARCH;
if ((walk_state->opcode != AML_SCOPE_OP) &&
(!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
@@ -289,8 +302,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
ACPI_IMODE_LOAD_PASS1, flags, walk_state,
&(node));
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(path, status);
- return (status);
+ ACPI_ERROR_NAMESPACE(path, status);
+ return_ACPI_STATUS(status);
}
break;
}
@@ -302,28 +315,29 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
op = acpi_ps_alloc_op(walk_state->opcode);
if (!op) {
- return (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
}
- /* Initialize */
-
- op->named.name = node->name.integer;
+ /* Initialize the op */
#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
- op->named.path = (u8 *) path;
+ op->named.path = ACPI_CAST_PTR(u8, path);
#endif
- /*
- * Put the Node in the "op" object that the parser uses, so we
- * can get it again quickly when this scope is closed
- */
- op->common.node = node;
+ if (node) {
+ /*
+ * Put the Node in the "op" object that the parser uses, so we
+ * can get it again quickly when this scope is closed
+ */
+ op->common.node = node;
+ op->named.name = node->name.integer;
+ }
+
acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
op);
-
*out_op = op;
- return (status);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -339,13 +353,13 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
*
******************************************************************************/
-acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
+acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
{
union acpi_parse_object *op;
acpi_object_type object_type;
acpi_status status = AE_OK;
- ACPI_FUNCTION_NAME("ds_load1_end_op");
+ ACPI_FUNCTION_TRACE("ds_load1_end_op");
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -354,7 +368,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
/* We are only interested in opcodes that have an associated name */
if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
- return (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the object type to determine if we should pop the scope */
@@ -363,21 +377,37 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
#ifndef ACPI_NO_METHOD_EXECUTION
if (walk_state->op_info->flags & AML_FIELD) {
- if (walk_state->opcode == AML_FIELD_OP ||
- walk_state->opcode == AML_BANK_FIELD_OP ||
- walk_state->opcode == AML_INDEX_FIELD_OP) {
- status = acpi_ds_init_field_objects(op, walk_state);
+ /*
+ * If we are executing a method, do not create any namespace objects
+ * during the load phase, only during execution.
+ */
+ if (!walk_state->method_node) {
+ if (walk_state->opcode == AML_FIELD_OP ||
+ walk_state->opcode == AML_BANK_FIELD_OP ||
+ walk_state->opcode == AML_INDEX_FIELD_OP) {
+ status =
+ acpi_ds_init_field_objects(op, walk_state);
+ }
}
- return (status);
+ return_ACPI_STATUS(status);
}
- if (op->common.aml_opcode == AML_REGION_OP) {
- status = acpi_ex_create_region(op->named.data, op->named.length,
- (acpi_adr_space_type)
- ((op->common.value.arg)->common.
- value.integer), walk_state);
- if (ACPI_FAILURE(status)) {
- return (status);
+ /*
+ * If we are executing a method, do not create any namespace objects
+ * during the load phase, only during execution.
+ */
+ if (!walk_state->method_node) {
+ if (op->common.aml_opcode == AML_REGION_OP) {
+ status =
+ acpi_ex_create_region(op->named.data,
+ op->named.length,
+ (acpi_adr_space_type)
+ ((op->common.value.arg)->
+ common.value.integer),
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
}
}
#endif
@@ -391,47 +421,63 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
common.
aml_opcode))->
object_type;
- op->common.node->type = (u8) object_type;
+
+ /* Set node type if we have a namespace node */
+
+ if (op->common.node) {
+ op->common.node->type = (u8) object_type;
+ }
}
}
- if (op->common.aml_opcode == AML_METHOD_OP) {
- /*
- * method_op pkg_length name_string method_flags term_list
- *
- * Note: We must create the method node/object pair as soon as we
- * see the method declaration. This allows later pass1 parsing
- * of invocations of the method (need to know the number of
- * arguments.)
- */
- ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "LOADING-Method: State=%p Op=%p named_obj=%p\n",
- walk_state, op, op->named.node));
+ /*
+ * If we are executing a method, do not create any namespace objects
+ * during the load phase, only during execution.
+ */
+ if (!walk_state->method_node) {
+ if (op->common.aml_opcode == AML_METHOD_OP) {
+ /*
+ * method_op pkg_length name_string method_flags term_list
+ *
+ * Note: We must create the method node/object pair as soon as we
+ * see the method declaration. This allows later pass1 parsing
+ * of invocations of the method (need to know the number of
+ * arguments.)
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+ walk_state, op, op->named.node));
- if (!acpi_ns_get_attached_object(op->named.node)) {
- walk_state->operands[0] = (void *)op->named.node;
- walk_state->num_operands = 1;
+ if (!acpi_ns_get_attached_object(op->named.node)) {
+ walk_state->operands[0] =
+ ACPI_CAST_PTR(void, op->named.node);
+ walk_state->num_operands = 1;
- status =
- acpi_ds_create_operands(walk_state,
- op->common.value.arg);
- if (ACPI_SUCCESS(status)) {
- status = acpi_ex_create_method(op->named.data,
- op->named.length,
- walk_state);
- }
- walk_state->operands[0] = NULL;
- walk_state->num_operands = 0;
+ status =
+ acpi_ds_create_operands(walk_state,
+ op->common.value.
+ arg);
+ if (ACPI_SUCCESS(status)) {
+ status =
+ acpi_ex_create_method(op->named.
+ data,
+ op->named.
+ length,
+ walk_state);
+ }
+ walk_state->operands[0] = NULL;
+ walk_state->num_operands = 0;
- if (ACPI_FAILURE(status)) {
- return (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
}
}
}
- /* Pop the scope stack */
+ /* Pop the scope stack (only if loading a table) */
- if (acpi_ns_opens_scope(object_type)) {
+ if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"(%s): Popping scope for Op %p\n",
acpi_ut_get_type_name(object_type), op));
@@ -439,7 +485,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
status = acpi_ds_scope_stack_pop(walk_state);
}
- return (status);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -456,8 +502,8 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
******************************************************************************/
acpi_status
-acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state,
- union acpi_parse_object ** out_op)
+acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op)
{
union acpi_parse_object *op;
struct acpi_namespace_node *node;
@@ -574,10 +620,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state,
if (status == AE_NOT_FOUND) {
status = AE_OK;
} else {
- ACPI_REPORT_NSERROR(buffer_ptr, status);
+ ACPI_ERROR_NAMESPACE(buffer_ptr, status);
}
#else
- ACPI_REPORT_NSERROR(buffer_ptr, status);
+ ACPI_ERROR_NAMESPACE(buffer_ptr, status);
#endif
return_ACPI_STATUS(status);
}
@@ -607,7 +653,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state,
* Scope (DEB) { ... }
*/
- ACPI_REPORT_WARNING(("Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", buffer_ptr, acpi_ut_get_type_name(node->type)));
+ ACPI_WARNING((AE_INFO,
+ "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)",
+ buffer_ptr,
+ acpi_ut_get_type_name(node->type)));
node->type = ACPI_TYPE_ANY;
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
@@ -617,7 +666,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state,
/* All other types are an error */
- ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s]\n", acpi_ut_get_type_name(node->type), buffer_ptr));
+ ACPI_ERROR((AE_INFO,
+ "Invalid type (%s) for target of Scope operator [%4.4s]",
+ acpi_ut_get_type_name(node->type),
+ buffer_ptr));
return (AE_AML_OPERAND_TYPE);
}
@@ -670,7 +722,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state,
}
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_NSERROR(buffer_ptr, status);
+ ACPI_ERROR_NAMESPACE(buffer_ptr, status);
return_ACPI_STATUS(status);
}
@@ -840,6 +892,13 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
case AML_TYPE_NAMED_FIELD:
+ /*
+ * If we are executing a method, initialize the field
+ */
+ if (walk_state->method_node) {
+ status = acpi_ds_init_field_objects(op, walk_state);
+ }
+
switch (op->common.aml_opcode) {
case AML_INDEX_FIELD_OP:
@@ -929,6 +988,24 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
switch (op->common.aml_opcode) {
#ifndef ACPI_NO_METHOD_EXECUTION
case AML_REGION_OP:
+
+ /*
+ * If we are executing a method, initialize the region
+ */
+ if (walk_state->method_node) {
+ status =
+ acpi_ex_create_region(op->named.data,
+ op->named.length,
+ (acpi_adr_space_type)
+ ((op->common.value.
+ arg)->common.value.
+ integer),
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ }
+
/*
* The op_region is not fully parsed at this time. Only valid
* argument is the space_id. (We must save the address of the
@@ -957,11 +1034,50 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
status = acpi_ds_create_node(walk_state, node, op);
break;
+
+ case AML_METHOD_OP:
+ /*
+ * method_op pkg_length name_string method_flags term_list
+ *
+ * Note: We must create the method node/object pair as soon as we
+ * see the method declaration. This allows later pass1 parsing
+ * of invocations of the method (need to know the number of
+ * arguments.)
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+ walk_state, op, op->named.node));
+
+ if (!acpi_ns_get_attached_object(op->named.node)) {
+ walk_state->operands[0] =
+ ACPI_CAST_PTR(void, op->named.node);
+ walk_state->num_operands = 1;
+
+ status =
+ acpi_ds_create_operands(walk_state,
+ op->common.value.
+ arg);
+ if (ACPI_SUCCESS(status)) {
+ status =
+ acpi_ex_create_method(op->named.
+ data,
+ op->named.
+ length,
+ walk_state);
+ }
+ walk_state->operands[0] = NULL;
+ walk_state->num_operands = 0;
+
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+ break;
+
#endif /* ACPI_NO_METHOD_EXECUTION */
default:
/* All NAMED_COMPLEX opcodes must be handled above */
- /* Note: Method objects were already created in Pass 1 */
break;
}
break;
@@ -1004,7 +1120,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
*/
op->common.node = new_node;
} else {
- ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
}
break;
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
index defe956ef75..ada21ef4a17 100644
--- a/drivers/acpi/dispatcher/dswscope.c
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -107,14 +107,14 @@ acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
if (!node) {
/* Invalid scope */
- ACPI_REPORT_ERROR(("ds_scope_stack_push: null scope passed\n"));
+ ACPI_ERROR((AE_INFO, "Null scope parameter"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Make sure object type is valid */
if (!acpi_ut_valid_object_type(type)) {
- ACPI_REPORT_WARNING(("ds_scope_stack_push: Invalid object type: 0x%X\n", type));
+ ACPI_WARNING((AE_INFO, "Invalid object type: 0x%X", type));
}
/* Allocate a new scope object */
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 7d68a5aaf3c..fa78cb74ee3 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -92,26 +92,23 @@ acpi_ds_result_remove(union acpi_operand_object **object,
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No result object pushed! State=%p\n",
- walk_state));
+ ACPI_ERROR((AE_INFO, "No result object pushed! State=%p",
+ walk_state));
return (AE_NOT_EXIST);
}
if (index >= ACPI_OBJ_MAX_OPERAND) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Index out of range: %X State=%p Num=%X\n",
- index, walk_state,
- state->results.num_results));
+ ACPI_ERROR((AE_INFO,
+ "Index out of range: %X State=%p Num=%X",
+ index, walk_state, state->results.num_results));
}
/* Check for a valid result object */
if (!state->results.obj_desc[index]) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X, Index=%X\n",
- walk_state, state->results.num_results,
- index));
+ ACPI_ERROR((AE_INFO,
+ "Null operand! State=%p #Ops=%X, Index=%X",
+ walk_state, state->results.num_results, index));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -163,9 +160,8 @@ acpi_ds_result_pop(union acpi_operand_object ** object,
}
if (!state->results.num_results) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Result stack is empty! State=%p\n",
- walk_state));
+ ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p",
+ walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -192,8 +188,7 @@ acpi_ds_result_pop(union acpi_operand_object ** object,
}
}
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No result objects! State=%p\n", walk_state));
+ ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -222,15 +217,14 @@ acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object,
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Warning: No result object pushed! State=%p\n",
- walk_state));
+ ACPI_ERROR((AE_INFO,
+ "No result object pushed! State=%p", walk_state));
return (AE_NOT_EXIST);
}
if (!state->results.num_results) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No result objects! State=%p\n", walk_state));
+ ACPI_ERROR((AE_INFO, "No result objects! State=%p",
+ walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -250,10 +244,10 @@ acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object,
/* Check for a valid result object */
if (!*object) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X Index=%X\n",
- walk_state, state->results.num_results,
- (u32) index));
+ ACPI_ERROR((AE_INFO,
+ "Null operand! State=%p #Ops=%X Index=%X",
+ walk_state, state->results.num_results,
+ (u32) index));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -288,23 +282,21 @@ acpi_ds_result_push(union acpi_operand_object * object,
state = walk_state->results;
if (!state) {
- ACPI_REPORT_ERROR(("No result stack frame during push\n"));
+ ACPI_ERROR((AE_INFO, "No result stack frame during push"));
return (AE_AML_INTERNAL);
}
if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Result stack overflow: Obj=%p State=%p Num=%X\n",
- object, walk_state,
- state->results.num_results));
+ ACPI_ERROR((AE_INFO,
+ "Result stack overflow: Obj=%p State=%p Num=%X",
+ object, walk_state, state->results.num_results));
return (AE_STACK_OVERFLOW);
}
if (!object) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Null Object! Obj=%p State=%p Num=%X\n",
- object, walk_state,
- state->results.num_results));
+ ACPI_ERROR((AE_INFO,
+ "Null Object! Obj=%p State=%p Num=%X",
+ object, walk_state, state->results.num_results));
return (AE_BAD_PARAMETER);
}
@@ -413,10 +405,9 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
/* Check for stack overflow */
if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "overflow! Obj=%p State=%p #Ops=%X\n",
- object, walk_state,
- walk_state->num_operands));
+ ACPI_ERROR((AE_INFO,
+ "Object stack overflow! Obj=%p State=%p #Ops=%X",
+ object, walk_state, walk_state->num_operands));
return (AE_STACK_OVERFLOW);
}
@@ -460,10 +451,10 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state)
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Underflow! Count=%X State=%p #Ops=%X\n",
- pop_count, walk_state,
- walk_state->num_operands));
+ ACPI_ERROR((AE_INFO,
+ "Object stack underflow! Count=%X State=%p #Ops=%X",
+ pop_count, walk_state,
+ walk_state->num_operands));
return (AE_STACK_UNDERFLOW);
}
@@ -506,10 +497,10 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Underflow! Count=%X State=%p #Ops=%X\n",
- pop_count, walk_state,
- walk_state->num_operands));
+ ACPI_ERROR((AE_INFO,
+ "Object stack underflow! Count=%X State=%p #Ops=%X",
+ pop_count, walk_state,
+ walk_state->num_operands));
return (AE_STACK_UNDERFLOW);
}
@@ -826,16 +817,14 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
}
if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%p is not a valid walk state\n",
- walk_state));
+ ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
+ walk_state));
return;
}
if (walk_state->parser_state.scope) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%p walk still has a scope list\n",
- walk_state));
+ ACPI_ERROR((AE_INFO, "%p walk still has a scope list",
+ walk_state));
}
/* Always must free any linked control states */
@@ -894,25 +883,24 @@ acpi_ds_result_insert(void *object,
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No result object pushed! State=%p\n",
- walk_state));
+ ACPI_ERROR((AE_INFO, "No result object pushed! State=%p",
+ walk_state));
return (AE_NOT_EXIST);
}
if (index >= ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Index out of range: %X Obj=%p State=%p Num=%X\n",
- index, object, walk_state,
- state->results.num_results));
+ ACPI_ERROR((AE_INFO,
+ "Index out of range: %X Obj=%p State=%p Num=%X",
+ index, object, walk_state,
+ state->results.num_results));
return (AE_BAD_PARAMETER);
}
if (!object) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
- index, object, walk_state,
- state->results.num_results));
+ ACPI_ERROR((AE_INFO,
+ "Null Object! Index=%X Obj=%p State=%p Num=%X",
+ index, object, walk_state,
+ state->results.num_results));
return (AE_BAD_PARAMETER);
}
@@ -986,9 +974,9 @@ acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Missing operand/stack empty! State=%p #Ops=%X\n",
- walk_state, walk_state->num_operands));
+ ACPI_ERROR((AE_INFO,
+ "Missing operand/stack empty! State=%p #Ops=%X",
+ walk_state, walk_state->num_operands));
*object = NULL;
return (AE_AML_NO_OPERAND);
}
@@ -1000,9 +988,9 @@ acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
/* Check for a valid operand */
if (!walk_state->operands[walk_state->num_operands]) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X\n",
- walk_state, walk_state->num_operands));
+ ACPI_ERROR((AE_INFO,
+ "Null operand! State=%p #Ops=%X",
+ walk_state, walk_state->num_operands));
*object = NULL;
return (AE_AML_NO_OPERAND);
}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 3758b558d2b..79b09d76c18 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -60,20 +60,20 @@ ACPI_MODULE_NAME("acpi_ec")
#define ACPI_EC_BURST_ENABLE 0x82
#define ACPI_EC_BURST_DISABLE 0x83
#define ACPI_EC_COMMAND_QUERY 0x84
-#define EC_POLLING 0xFF
-#define EC_BURST 0x00
+#define EC_POLL 0xFF
+#define EC_INTR 0x00
static int acpi_ec_remove(struct acpi_device *device, int type);
static int acpi_ec_start(struct acpi_device *device);
static int acpi_ec_stop(struct acpi_device *device, int type);
-static int acpi_ec_burst_add(struct acpi_device *device);
-static int acpi_ec_polling_add(struct acpi_device *device);
+static int acpi_ec_intr_add(struct acpi_device *device);
+static int acpi_ec_poll_add(struct acpi_device *device);
static struct acpi_driver acpi_ec_driver = {
.name = ACPI_EC_DRIVER_NAME,
.class = ACPI_EC_CLASS,
.ids = ACPI_EC_HID,
.ops = {
- .add = acpi_ec_polling_add,
+ .add = acpi_ec_intr_add,
.remove = acpi_ec_remove,
.start = acpi_ec_start,
.stop = acpi_ec_stop,
@@ -105,7 +105,7 @@ union acpi_ec {
atomic_t pending_gpe;
struct semaphore sem;
wait_queue_head_t wait;
- } burst;
+ } intr;
struct {
u32 mode;
@@ -117,37 +117,37 @@ union acpi_ec {
struct acpi_generic_address data_addr;
unsigned long global_lock;
spinlock_t lock;
- } polling;
+ } poll;
};
-static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event);
-static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event);
-static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data);
-static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data);
-static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data);
-static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data);
-static void acpi_ec_gpe_polling_query(void *ec_cxt);
-static void acpi_ec_gpe_burst_query(void *ec_cxt);
-static u32 acpi_ec_gpe_polling_handler(void *data);
-static u32 acpi_ec_gpe_burst_handler(void *data);
+static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event);
+static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event);
+static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data);
+static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data);
+static void acpi_ec_gpe_poll_query(void *ec_cxt);
+static void acpi_ec_gpe_intr_query(void *ec_cxt);
+static u32 acpi_ec_gpe_poll_handler(void *data);
+static u32 acpi_ec_gpe_intr_handler(void *data);
static acpi_status __init
-acpi_fake_ecdt_polling_callback(acpi_handle handle,
+acpi_fake_ecdt_poll_callback(acpi_handle handle,
u32 Level, void *context, void **retval);
static acpi_status __init
-acpi_fake_ecdt_burst_callback(acpi_handle handle,
+acpi_fake_ecdt_intr_callback(acpi_handle handle,
u32 Level, void *context, void **retval);
-static int __init acpi_ec_polling_get_real_ecdt(void);
-static int __init acpi_ec_burst_get_real_ecdt(void);
+static int __init acpi_ec_poll_get_real_ecdt(void);
+static int __init acpi_ec_intr_get_real_ecdt(void);
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
static union acpi_ec *ec_ecdt;
/* External interfaces use first EC only, so remember */
static struct acpi_device *first_ec;
-static int acpi_ec_polling_mode = EC_POLLING;
+static int acpi_ec_poll_mode = EC_INTR;
/* --------------------------------------------------------------------------
Transaction Management
@@ -163,13 +163,13 @@ static u32 acpi_ec_read_status(union acpi_ec *ec)
static int acpi_ec_wait(union acpi_ec *ec, u8 event)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_wait(ec, event);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_wait(ec, event);
else
- return acpi_ec_burst_wait(ec, event);
+ return acpi_ec_intr_wait(ec, event);
}
-static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event)
+static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event)
{
u32 acpi_ec_status = 0;
u32 i = ACPI_EC_UDELAY_COUNT;
@@ -203,36 +203,31 @@ static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event)
return -ETIME;
}
-static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
+static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event)
{
int result = 0;
ACPI_FUNCTION_TRACE("acpi_ec_wait");
- ec->burst.expect_event = event;
+ ec->intr.expect_event = event;
smp_mb();
switch (event) {
- case ACPI_EC_EVENT_OBF:
- if (acpi_ec_read_status(ec) & event) {
- ec->burst.expect_event = 0;
- return_VALUE(0);
- }
- break;
-
case ACPI_EC_EVENT_IBE:
if (~acpi_ec_read_status(ec) & event) {
- ec->burst.expect_event = 0;
+ ec->intr.expect_event = 0;
return_VALUE(0);
}
break;
+ default:
+ break;
}
- result = wait_event_timeout(ec->burst.wait,
- !ec->burst.expect_event,
+ result = wait_event_timeout(ec->intr.wait,
+ !ec->intr.expect_event,
msecs_to_jiffies(ACPI_EC_DELAY));
- ec->burst.expect_event = 0;
+ ec->intr.expect_event = 0;
smp_mb();
/*
@@ -255,7 +250,12 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
return_VALUE(-ETIME);
}
-static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
+#ifdef ACPI_FUTURE_USAGE
+/*
+ * Note: samsung nv5000 doesn't work with ec burst mode.
+ * http://bugzilla.kernel.org/show_bug.cgi?id=4980
+ */
+int acpi_ec_enter_burst_mode(union acpi_ec *ec)
{
u32 tmp = 0;
int status = 0;
@@ -270,45 +270,56 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE,
&ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status)
- return_VALUE(-EINVAL);
acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
if (tmp != 0x90) { /* Burst ACK byte */
return_VALUE(-EINVAL);
}
}
- atomic_set(&ec->burst.leaving_burst, 0);
+ atomic_set(&ec->intr.leaving_burst, 0);
return_VALUE(0);
end:
- printk("Error in acpi_ec_wait\n");
+ printk(KERN_WARNING PREFIX "Error in acpi_ec_wait\n");
return_VALUE(-1);
}
-static int acpi_ec_leave_burst_mode(union acpi_ec *ec)
+int acpi_ec_leave_burst_mode(union acpi_ec *ec)
{
+ int status = 0;
ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode");
- atomic_set(&ec->burst.leaving_burst, 1);
+ status = acpi_ec_read_status(ec);
+ if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){
+ status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+ if(status)
+ goto end;
+ acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
+ acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+ }
+ atomic_set(&ec->intr.leaving_burst, 1);
return_VALUE(0);
+end:
+ printk(KERN_WARNING PREFIX "leave burst_mode:error\n");
+ return_VALUE(-1);
}
+#endif /* ACPI_FUTURE_USAGE */
static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_read(ec, address, data);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_read(ec, address, data);
else
- return acpi_ec_burst_read(ec, address, data);
+ return acpi_ec_intr_read(ec, address, data);
}
static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_write(ec, address, data);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_write(ec, address, data);
else
- return acpi_ec_burst_write(ec, address, data);
+ return acpi_ec_intr_write(ec, address, data);
}
-static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data)
{
acpi_status status = AE_OK;
int result = 0;
@@ -328,7 +339,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
return_VALUE(-ENODEV);
}
- spin_lock_irqsave(&ec->polling.lock, flags);
+ spin_lock_irqsave(&ec->poll.lock, flags);
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
&ec->common.command_addr);
@@ -347,7 +358,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
*data, address));
end:
- spin_unlock_irqrestore(&ec->polling.lock, flags);
+ spin_unlock_irqrestore(&ec->poll.lock, flags);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -355,7 +366,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
return_VALUE(result);
}
-static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data)
{
int result = 0;
acpi_status status = AE_OK;
@@ -373,7 +384,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
return_VALUE(-ENODEV);
}
- spin_lock_irqsave(&ec->polling.lock, flags);
+ spin_lock_irqsave(&ec->poll.lock, flags);
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
&ec->common.command_addr);
@@ -395,7 +406,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
data, address));
end:
- spin_unlock_irqrestore(&ec->polling.lock, flags);
+ spin_unlock_irqrestore(&ec->poll.lock, flags);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -403,7 +414,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
return_VALUE(result);
}
-static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data)
{
int status = 0;
u32 glk;
@@ -422,25 +433,24 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
}
WARN_ON(in_interrupt());
- down(&ec->burst.sem);
+ down(&ec->intr.sem);
- acpi_ec_enter_burst_mode(ec);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("read EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
goto end;
}
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
&ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("read EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
}
acpi_hw_low_level_write(8, address, &ec->common.data_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (status) {
- printk("read EC, OB not full\n");
+ printk(KERN_DEBUG PREFIX "read EC, OB not full\n");
goto end;
}
acpi_hw_low_level_read(8, data, &ec->common.data_addr);
@@ -448,8 +458,7 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
*data, address));
end:
- acpi_ec_leave_burst_mode(ec);
- up(&ec->burst.sem);
+ up(&ec->intr.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -457,7 +466,7 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
return_VALUE(status);
}
-static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data)
{
int status = 0;
u32 glk;
@@ -474,25 +483,23 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
}
WARN_ON(in_interrupt());
- down(&ec->burst.sem);
-
- acpi_ec_enter_burst_mode(ec);
+ down(&ec->intr.sem);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("write EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
&ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("write EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, address, &ec->common.data_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("write EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, data, &ec->common.data_addr);
@@ -500,8 +507,7 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
data, address));
- acpi_ec_leave_burst_mode(ec);
- up(&ec->burst.sem);
+ up(&ec->intr.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -553,12 +559,12 @@ EXPORT_SYMBOL(ec_write);
static int acpi_ec_query(union acpi_ec *ec, u32 * data)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_query(ec, data);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_query(ec, data);
else
- return acpi_ec_burst_query(ec, data);
+ return acpi_ec_intr_query(ec, data);
}
-static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
+static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data)
{
int result = 0;
acpi_status status = AE_OK;
@@ -583,7 +589,7 @@ static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
* Note that successful completion of the query causes the ACPI_EC_SCI
* bit to be cleared (and thus clearing the interrupt source).
*/
- spin_lock_irqsave(&ec->polling.lock, flags);
+ spin_lock_irqsave(&ec->poll.lock, flags);
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
&ec->common.command_addr);
@@ -596,14 +602,14 @@ static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
result = -ENODATA;
end:
- spin_unlock_irqrestore(&ec->polling.lock, flags);
+ spin_unlock_irqrestore(&ec->poll.lock, flags);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
return_VALUE(result);
}
-static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
+static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data)
{
int status = 0;
u32 glk;
@@ -620,11 +626,11 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
return_VALUE(-ENODEV);
}
- down(&ec->burst.sem);
+ down(&ec->intr.sem);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("query EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "query EC, IB not empty\n");
goto end;
}
/*
@@ -636,7 +642,7 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
&ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (status) {
- printk("query EC, OB not full\n");
+ printk(KERN_DEBUG PREFIX "query EC, OB not full\n");
goto end;
}
@@ -645,7 +651,7 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
status = -ENODATA;
end:
- up(&ec->burst.sem);
+ up(&ec->intr.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -664,13 +670,13 @@ union acpi_ec_query_data {
static void acpi_ec_gpe_query(void *ec_cxt)
{
- if (acpi_ec_polling_mode)
- acpi_ec_gpe_polling_query(ec_cxt);
+ if (acpi_ec_poll_mode)
+ acpi_ec_gpe_poll_query(ec_cxt);
else
- acpi_ec_gpe_burst_query(ec_cxt);
+ acpi_ec_gpe_intr_query(ec_cxt);
}
-static void acpi_ec_gpe_polling_query(void *ec_cxt)
+static void acpi_ec_gpe_poll_query(void *ec_cxt)
{
union acpi_ec *ec = (union acpi_ec *)ec_cxt;
u32 value = 0;
@@ -685,9 +691,9 @@ static void acpi_ec_gpe_polling_query(void *ec_cxt)
if (!ec_cxt)
goto end;
- spin_lock_irqsave(&ec->polling.lock, flags);
+ spin_lock_irqsave(&ec->poll.lock, flags);
acpi_hw_low_level_read(8, &value, &ec->common.command_addr);
- spin_unlock_irqrestore(&ec->polling.lock, flags);
+ spin_unlock_irqrestore(&ec->poll.lock, flags);
/* TBD: Implement asynch events!
* NOTE: All we care about are EC-SCI's. Other EC events are
@@ -711,7 +717,7 @@ static void acpi_ec_gpe_polling_query(void *ec_cxt)
end:
acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
}
-static void acpi_ec_gpe_burst_query(void *ec_cxt)
+static void acpi_ec_gpe_intr_query(void *ec_cxt)
{
union acpi_ec *ec = (union acpi_ec *)ec_cxt;
u32 value;
@@ -736,18 +742,18 @@ static void acpi_ec_gpe_burst_query(void *ec_cxt)
acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
end:
- atomic_dec(&ec->burst.pending_gpe);
+ atomic_dec(&ec->intr.pending_gpe);
return;
}
static u32 acpi_ec_gpe_handler(void *data)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_gpe_polling_handler(data);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_gpe_poll_handler(data);
else
- return acpi_ec_gpe_burst_handler(data);
+ return acpi_ec_gpe_intr_handler(data);
}
-static u32 acpi_ec_gpe_polling_handler(void *data)
+static u32 acpi_ec_gpe_poll_handler(void *data)
{
acpi_status status = AE_OK;
union acpi_ec *ec = (union acpi_ec *)data;
@@ -765,7 +771,7 @@ static u32 acpi_ec_gpe_polling_handler(void *data)
else
return ACPI_INTERRUPT_NOT_HANDLED;
}
-static u32 acpi_ec_gpe_burst_handler(void *data)
+static u32 acpi_ec_gpe_intr_handler(void *data)
{
acpi_status status = AE_OK;
u32 value;
@@ -777,22 +783,22 @@ static u32 acpi_ec_gpe_burst_handler(void *data)
acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
value = acpi_ec_read_status(ec);
- switch (ec->burst.expect_event) {
+ switch (ec->intr.expect_event) {
case ACPI_EC_EVENT_OBF:
if (!(value & ACPI_EC_FLAG_OBF))
break;
case ACPI_EC_EVENT_IBE:
if ((value & ACPI_EC_FLAG_IBF))
break;
- ec->burst.expect_event = 0;
- wake_up(&ec->burst.wait);
+ ec->intr.expect_event = 0;
+ wake_up(&ec->intr.wait);
return ACPI_INTERRUPT_HANDLED;
default:
break;
}
if (value & ACPI_EC_FLAG_SCI) {
- atomic_add(1, &ec->burst.pending_gpe);
+ atomic_add(1, &ec->intr.pending_gpe);
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
acpi_ec_gpe_query, ec);
return status == AE_OK ?
@@ -980,7 +986,7 @@ static int acpi_ec_remove_fs(struct acpi_device *device)
Driver Interface
-------------------------------------------------------------------------- */
-static int acpi_ec_polling_add(struct acpi_device *device)
+static int acpi_ec_poll_add(struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
@@ -999,7 +1005,7 @@ static int acpi_ec_polling_add(struct acpi_device *device)
ec->common.handle = device->handle;
ec->common.uid = -1;
- spin_lock_init(&ec->polling.lock);
+ spin_lock_init(&ec->poll.lock);
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
acpi_driver_data(device) = ec;
@@ -1038,7 +1044,7 @@ static int acpi_ec_polling_add(struct acpi_device *device)
if (result)
goto end;
- printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
+ printk(KERN_INFO PREFIX "%s [%s] (gpe %d) polling mode.\n",
acpi_device_name(device), acpi_device_bid(device),
(u32) ec->common.gpe_bit);
@@ -1051,7 +1057,7 @@ static int acpi_ec_polling_add(struct acpi_device *device)
return_VALUE(result);
}
-static int acpi_ec_burst_add(struct acpi_device *device)
+static int acpi_ec_intr_add(struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
@@ -1070,10 +1076,10 @@ static int acpi_ec_burst_add(struct acpi_device *device)
ec->common.handle = device->handle;
ec->common.uid = -1;
- atomic_set(&ec->burst.pending_gpe, 0);
- atomic_set(&ec->burst.leaving_burst, 1);
- init_MUTEX(&ec->burst.sem);
- init_waitqueue_head(&ec->burst.wait);
+ atomic_set(&ec->intr.pending_gpe, 0);
+ atomic_set(&ec->intr.leaving_burst, 1);
+ init_MUTEX(&ec->intr.sem);
+ init_waitqueue_head(&ec->intr.wait);
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
acpi_driver_data(device) = ec;
@@ -1112,8 +1118,7 @@ static int acpi_ec_burst_add(struct acpi_device *device)
if (result)
goto end;
- printk("burst-mode-ec-10-Aug\n");
- printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
+ printk(KERN_INFO PREFIX "%s [%s] (gpe %d) interrupt mode.\n",
acpi_device_name(device), acpi_device_bid(device),
(u32) ec->common.gpe_bit);
@@ -1151,7 +1156,7 @@ acpi_ec_io_ports(struct acpi_resource *resource, void *context)
union acpi_ec *ec = (union acpi_ec *)context;
struct acpi_generic_address *addr;
- if (resource->id != ACPI_RSTYPE_IO) {
+ if (resource->type != ACPI_RESOURCE_TYPE_IO) {
return AE_OK;
}
@@ -1171,7 +1176,7 @@ acpi_ec_io_ports(struct acpi_resource *resource, void *context)
addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
addr->register_bit_width = 8;
addr->register_bit_offset = 0;
- addr->address = resource->data.io.min_base_address;
+ addr->address = resource->data.io.minimum;
return AE_OK;
}
@@ -1267,16 +1272,16 @@ acpi_fake_ecdt_callback(acpi_handle handle,
u32 Level, void *context, void **retval)
{
- if (acpi_ec_polling_mode)
- return acpi_fake_ecdt_polling_callback(handle,
+ if (acpi_ec_poll_mode)
+ return acpi_fake_ecdt_poll_callback(handle,
Level, context, retval);
else
- return acpi_fake_ecdt_burst_callback(handle,
+ return acpi_fake_ecdt_intr_callback(handle,
Level, context, retval);
}
static acpi_status __init
-acpi_fake_ecdt_polling_callback(acpi_handle handle,
+acpi_fake_ecdt_poll_callback(acpi_handle handle,
u32 Level, void *context, void **retval)
{
acpi_status status;
@@ -1295,7 +1300,7 @@ acpi_fake_ecdt_polling_callback(acpi_handle handle,
&ec_ecdt->common.gpe_bit);
if (ACPI_FAILURE(status))
return status;
- spin_lock_init(&ec_ecdt->polling.lock);
+ spin_lock_init(&ec_ecdt->poll.lock);
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.handle = handle;
@@ -1308,13 +1313,13 @@ acpi_fake_ecdt_polling_callback(acpi_handle handle,
}
static acpi_status __init
-acpi_fake_ecdt_burst_callback(acpi_handle handle,
+acpi_fake_ecdt_intr_callback(acpi_handle handle,
u32 Level, void *context, void **retval)
{
acpi_status status;
- init_MUTEX(&ec_ecdt->burst.sem);
- init_waitqueue_head(&ec_ecdt->burst.wait);
+ init_MUTEX(&ec_ecdt->intr.sem);
+ init_waitqueue_head(&ec_ecdt->intr.wait);
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
acpi_ec_io_ports, ec_ecdt);
if (ACPI_FAILURE(status))
@@ -1380,13 +1385,13 @@ static int __init acpi_ec_fake_ecdt(void)
static int __init acpi_ec_get_real_ecdt(void)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_get_real_ecdt();
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_get_real_ecdt();
else
- return acpi_ec_burst_get_real_ecdt();
+ return acpi_ec_intr_get_real_ecdt();
}
-static int __init acpi_ec_polling_get_real_ecdt(void)
+static int __init acpi_ec_poll_get_real_ecdt(void)
{
acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
@@ -1411,7 +1416,7 @@ static int __init acpi_ec_polling_get_real_ecdt(void)
ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
- spin_lock_init(&ec_ecdt->polling.lock);
+ spin_lock_init(&ec_ecdt->poll.lock);
/* use the GL just to be safe */
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.uid = ecdt_ptr->uid;
@@ -1431,7 +1436,7 @@ static int __init acpi_ec_polling_get_real_ecdt(void)
return -ENODEV;
}
-static int __init acpi_ec_burst_get_real_ecdt(void)
+static int __init acpi_ec_intr_get_real_ecdt(void)
{
acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
@@ -1452,8 +1457,8 @@ static int __init acpi_ec_burst_get_real_ecdt(void)
return -ENOMEM;
memset(ec_ecdt, 0, sizeof(union acpi_ec));
- init_MUTEX(&ec_ecdt->burst.sem);
- init_waitqueue_head(&ec_ecdt->burst.wait);
+ init_MUTEX(&ec_ecdt->intr.sem);
+ init_waitqueue_head(&ec_ecdt->intr.wait);
ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
@@ -1571,22 +1576,22 @@ static int __init acpi_fake_ecdt_setup(char *str)
}
__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
-static int __init acpi_ec_set_polling_mode(char *str)
+static int __init acpi_ec_set_intr_mode(char *str)
{
- int burst;
+ int intr;
- if (!get_option(&str, &burst))
+ if (!get_option(&str, &intr))
return 0;
- if (burst) {
- acpi_ec_polling_mode = EC_BURST;
- acpi_ec_driver.ops.add = acpi_ec_burst_add;
+ if (intr) {
+ acpi_ec_poll_mode = EC_INTR;
+ acpi_ec_driver.ops.add = acpi_ec_intr_add;
} else {
- acpi_ec_polling_mode = EC_POLLING;
- acpi_ec_driver.ops.add = acpi_ec_polling_add;
+ acpi_ec_poll_mode = EC_POLL;
+ acpi_ec_driver.ops.add = acpi_ec_poll_add;
}
- printk(KERN_INFO PREFIX "EC %s mode.\n", burst ? "burst" : "polling");
+ printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling");
return 0;
}
-__setup("ec_burst=", acpi_ec_set_polling_mode);
+__setup("ec_intr=", acpi_ec_set_intr_mode);
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index 842d1e3fb37..c9ac05c4685 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,7 +73,7 @@ acpi_status acpi_ev_initialize_events(void)
/* Make sure we have ACPI tables */
if (!acpi_gbl_DSDT) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No ACPI tables present!\n"));
+ ACPI_WARNING((AE_INFO, "No ACPI tables present!"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
@@ -84,14 +84,15 @@ acpi_status acpi_ev_initialize_events(void)
*/
status = acpi_ev_fixed_event_initialize();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Unable to initialize fixed events, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to initialize fixed events"));
return_ACPI_STATUS(status);
}
status = acpi_ev_gpe_initialize();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Unable to initialize general purpose events, %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to initialize general purpose events"));
return_ACPI_STATUS(status);
}
@@ -100,6 +101,48 @@ acpi_status acpi_ev_initialize_events(void)
/*******************************************************************************
*
+ * FUNCTION: acpi_ev_install_fadt_gpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks
+ * (0 and 1). This causes the _PRW methods to be run, so the HW
+ * must be fully initialized at this point, including global lock
+ * support.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ev_install_fadt_gpes(void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("ev_install_fadt_gpes");
+
+ /* Namespace must be locked */
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* FADT GPE Block 0 */
+
+ (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
+ acpi_gbl_gpe_fadt_blocks[0]);
+
+ /* FADT GPE Block 1 */
+
+ (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
+ acpi_gbl_gpe_fadt_blocks[1]);
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ev_install_xrupt_handlers
*
* PARAMETERS: None
@@ -120,7 +163,8 @@ acpi_status acpi_ev_install_xrupt_handlers(void)
status = acpi_ev_install_sci_handler();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Unable to install System Control Interrupt Handler, %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to install System Control Interrupt handler"));
return_ACPI_STATUS(status);
}
@@ -128,7 +172,8 @@ acpi_status acpi_ev_install_xrupt_handlers(void)
status = acpi_ev_init_global_lock_handler();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Unable to initialize Global Lock handler, %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to initialize Global Lock handler"));
return_ACPI_STATUS(status);
}
@@ -262,7 +307,9 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
enable_register_id, 0,
ACPI_MTX_DO_NOT_LOCK);
- ACPI_REPORT_ERROR(("No installed handler for fixed event [%08X]\n", event));
+ ACPI_ERROR((AE_INFO,
+ "No installed handler for fixed event [%08X]",
+ event));
return (ACPI_INTERRUPT_NOT_HANDLED);
}
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index b2f232df13d..f64f977dd3d 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -372,14 +372,14 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
{
+ acpi_status status;
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_register_info *gpe_register_info;
u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
u8 enabled_status_byte;
- struct acpi_gpe_register_info *gpe_register_info;
u32 status_reg;
u32 enable_reg;
- u32 flags;
- acpi_status status;
- struct acpi_gpe_block_info *gpe_block;
+ acpi_cpu_flags flags;
acpi_native_uint i;
acpi_native_uint j;
@@ -546,7 +546,11 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
status = acpi_ns_evaluate_by_handle(&info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("%s while evaluating method [%4.4s] for GPE[%2X]\n", acpi_format_exception(status), acpi_ut_get_node_name(local_gpe_event_info.dispatch.method_node), gpe_number));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While evaluating method [%4.4s] for GPE[%2X]",
+ acpi_ut_get_node_name
+ (local_gpe_event_info.dispatch.
+ method_node), gpe_number));
}
}
@@ -599,8 +603,10 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
ACPI_GPE_EDGE_TRIGGERED) {
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
- return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to clear GPE[%2X]",
+ gpe_number));
+ return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
}
}
@@ -637,8 +643,10 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
ACPI_GPE_LEVEL_TRIGGERED) {
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
- return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to clear GPE[%2X]",
+ gpe_number));
+ return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
}
}
break;
@@ -651,8 +659,10 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
*/
status = acpi_ev_disable_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
- return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to disable GPE[%2X]",
+ gpe_number));
+ return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
}
/*
@@ -663,7 +673,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
acpi_ev_asynch_execute_gpe_method,
gpe_event_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n", acpi_format_exception(status), gpe_number));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to queue handler for GPE[%2X] - event disabled",
+ gpe_number));
}
break;
@@ -671,7 +683,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
/* No handler or method to run! */
- ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n", gpe_number));
+ ACPI_ERROR((AE_INFO,
+ "No handler or method for GPE[%2X], disabling event",
+ gpe_number));
/*
* Disable the GPE. The GPE will remain disabled until the ACPI
@@ -679,13 +693,15 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
*/
status = acpi_ev_disable_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
- return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to disable GPE[%2X]",
+ gpe_number));
+ return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
}
break;
}
- return_VALUE(ACPI_INTERRUPT_HANDLED);
+ return_UINT32(ACPI_INTERRUPT_HANDLED);
}
#ifdef ACPI_GPE_NOTIFY_CHECK
@@ -722,7 +738,9 @@ acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info)
acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
- ACPI_REPORT_INFO(("GPE %p was updated from wake/run to wake-only\n", gpe_event_info));
+ ACPI_INFO((AE_INFO,
+ "GPE %p was updated from wake/run to wake-only",
+ gpe_event_info));
/* This was a wake-only GPE */
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index b312eb33c43..0fd00b5ad65 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -78,7 +78,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
*
* RETURN: TRUE if the gpe_event is valid
*
- * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
+ * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
* Should be called only when the GPE lists are semaphore locked
* and not subject to change.
*
@@ -136,7 +136,7 @@ acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback)
struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
acpi_status status = AE_OK;
- u32 flags;
+ acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE("ev_walk_gpe_list");
@@ -264,7 +264,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
* 2) Edge/Level determination is based on the 2nd character
* of the method name
*
- * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
+ * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
* if a _PRW object is found that points to this GPE.
*/
switch (name[1]) {
@@ -279,9 +279,9 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
default:
/* Unknown method type, just ignore it! */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
- name));
+ ACPI_ERROR((AE_INFO,
+ "Unknown GPE method type: %s (name not of form _Lxx or _Exx)",
+ name));
return_ACPI_STATUS(AE_OK);
}
@@ -291,9 +291,9 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
if (gpe_number == ACPI_UINT32_MAX) {
/* Conversion failed; invalid method, just ignore it */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
- name));
+ ACPI_ERROR((AE_INFO,
+ "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)",
+ name));
return_ACPI_STATUS(AE_OK);
}
@@ -313,14 +313,14 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
/*
* Now we can add this information to the gpe_event_info block
- * for use during dispatch of this GPE. Default type is RUNTIME, although
+ * for use during dispatch of this GPE. Default type is RUNTIME, although
* this may change when the _PRW methods are executed later.
*/
gpe_event_info =
&gpe_block->event_info[gpe_number - gpe_block->block_base_number];
- gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
- ACPI_GPE_TYPE_RUNTIME);
+ gpe_event_info->flags = (u8)
+ (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
gpe_event_info->dispatch.method_node =
(struct acpi_namespace_node *)obj_handle;
@@ -341,11 +341,11 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
*
* PARAMETERS: Callback from walk_namespace
*
- * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
+ * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
* not aborted on a single _PRW failure.
*
* DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
- * Device. Run the _PRW method. If present, extract the GPE
+ * Device. Run the _PRW method. If present, extract the GPE
* number and mark the GPE as a WAKE GPE.
*
******************************************************************************/
@@ -443,6 +443,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
gpe_event_info->flags &=
~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
+
status =
acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
if (ACPI_FAILURE(status)) {
@@ -466,7 +467,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
*
* RETURN: A GPE interrupt block
*
- * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
+ * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
* block per unique interrupt level used for GPEs.
* Should be called only when the GPE lists are semaphore locked
* and not subject to change.
@@ -479,7 +480,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
struct acpi_gpe_xrupt_info *next_gpe_xrupt;
struct acpi_gpe_xrupt_info *gpe_xrupt;
acpi_status status;
- u32 flags;
+ acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block");
@@ -526,9 +527,9 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
acpi_ev_gpe_xrupt_handler,
gpe_xrupt);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not install GPE interrupt handler at level 0x%X\n",
- interrupt_number));
+ ACPI_ERROR((AE_INFO,
+ "Could not install GPE interrupt handler at level 0x%X",
+ interrupt_number));
return_PTR(NULL);
}
}
@@ -553,7 +554,7 @@ static acpi_status
acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
{
acpi_status status;
- u32 flags;
+ acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt");
@@ -566,8 +567,9 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
/* Disable this interrupt */
- status = acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
- acpi_ev_gpe_xrupt_handler);
+ status =
+ acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
+ acpi_ev_gpe_xrupt_handler);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -610,7 +612,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
struct acpi_gpe_block_info *next_gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_block;
acpi_status status;
- u32 flags;
+ acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE("ev_install_gpe_block");
@@ -663,7 +665,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
{
acpi_status status;
- u32 flags;
+ acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE("ev_install_gpe_block");
@@ -743,22 +745,22 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
sizeof(struct
acpi_gpe_register_info));
if (!gpe_register_info) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not allocate the gpe_register_info table\n"));
+ ACPI_ERROR((AE_INFO,
+ "Could not allocate the gpe_register_info table"));
return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Allocate the GPE event_info block. There are eight distinct GPEs
- * per register. Initialization to zeros is sufficient.
+ * per register. Initialization to zeros is sufficient.
*/
gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block->
register_count *
ACPI_GPE_REGISTER_WIDTH) *
sizeof(struct acpi_gpe_event_info));
if (!gpe_event_info) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not allocate the gpe_event_info table\n"));
+ ACPI_ERROR((AE_INFO,
+ "Could not allocate the gpe_event_info table"));
status = AE_NO_MEMORY;
goto error_exit;
}
@@ -769,9 +771,9 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
gpe_block->event_info = gpe_event_info;
/*
- * Initialize the GPE Register and Event structures. A goal of these
+ * Initialize the GPE Register and Event structures. A goal of these
* tables is to hide the fact that there are two separate GPE register sets
- * in a given gpe hardware block, the status registers occupy the first half,
+ * in a given GPE hardware block, the status registers occupy the first half,
* and the enable registers occupy the second half.
*/
this_register = gpe_register_info;
@@ -812,11 +814,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
this_event++;
}
- /*
- * Clear the status/enable registers. Note that status registers
- * are cleared by writing a '1', while enable registers are cleared
- * by writing a '0'.
- */
+ /* Disable all GPEs within this register */
+
status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00,
&this_register->
enable_address);
@@ -824,6 +823,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
goto error_exit;
}
+ /* Clear any pending GPE events within this register */
+
status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF,
&this_register->
status_address);
@@ -860,7 +861,9 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
*
* RETURN: Status
*
- * DESCRIPTION: Create and Install a block of GPE registers
+ * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
+ * the block are disabled at exit.
+ * Note: Assumes namespace is locked.
*
******************************************************************************/
@@ -872,14 +875,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
u32 interrupt_number,
struct acpi_gpe_block_info **return_gpe_block)
{
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_gpe_event_info *gpe_event_info;
- acpi_native_uint i;
- acpi_native_uint j;
- u32 wake_gpe_count;
- u32 gpe_enabled_count;
acpi_status status;
- struct acpi_gpe_walk_info gpe_info;
+ struct acpi_gpe_block_info *gpe_block;
ACPI_FUNCTION_TRACE("ev_create_gpe_block");
@@ -896,22 +893,24 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
/* Initialize the new GPE block */
+ gpe_block->node = gpe_device;
gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number;
- gpe_block->node = gpe_device;
ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
sizeof(struct acpi_generic_address));
- /* Create the register_info and event_info sub-structures */
-
+ /*
+ * Create the register_info and event_info sub-structures
+ * Note: disables and clears all GPEs in the block
+ */
status = acpi_ev_create_gpe_info_blocks(gpe_block);
if (ACPI_FAILURE(status)) {
ACPI_MEM_FREE(gpe_block);
return_ACPI_STATUS(status);
}
- /* Install the new block in the global list(s) */
+ /* Install the new block in the global lists */
status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
if (ACPI_FAILURE(status)) {
@@ -926,16 +925,70 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
acpi_ev_save_method_info, gpe_block,
NULL);
+ /* Return the new block */
+
+ if (return_gpe_block) {
+ (*return_gpe_block) = gpe_block;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
+ (u32) gpe_block->block_base_number,
+ (u32) (gpe_block->block_base_number +
+ ((gpe_block->register_count *
+ ACPI_GPE_REGISTER_WIDTH) - 1)),
+ gpe_device->name.ascii, gpe_block->register_count,
+ interrupt_number));
+
+ return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ev_initialize_gpe_block
+ *
+ * PARAMETERS: gpe_device - Handle to the parent GPE block
+ * gpe_block - Gpe Block info
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize and enable a GPE block. First find and run any
+ * _PRT methods associated with the block, then enable the
+ * appropriate GPEs.
+ * Note: Assumes namespace is locked.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
+ struct acpi_gpe_block_info *gpe_block)
+{
+ acpi_status status;
+ struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_gpe_walk_info gpe_info;
+ u32 wake_gpe_count;
+ u32 gpe_enabled_count;
+ acpi_native_uint i;
+ acpi_native_uint j;
+
+ ACPI_FUNCTION_TRACE("ev_initialize_gpe_block");
+
+ /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
+
+ if (!gpe_block) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
/*
- * Runtime option: Should Wake GPEs be enabled at runtime? The default
- * is No, they should only be enabled just as the machine goes to sleep.
+ * Runtime option: Should wake GPEs be enabled at runtime? The default
+ * is no, they should only be enabled just as the machine goes to sleep.
*/
if (acpi_gbl_leave_wake_gpes_disabled) {
/*
- * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
- * (Each GPE that has one or more _PRWs that reference it is by
- * definition a WAKE GPE and will not be enabled while the machine
- * is running.)
+ * Differentiate runtime vs wake GPEs, via the _PRW control methods.
+ * Each GPE that has one or more _PRWs that reference it is by
+ * definition a wake GPE and will not be enabled while the machine
+ * is running.
*/
gpe_info.gpe_block = gpe_block;
gpe_info.gpe_device = gpe_device;
@@ -948,9 +1001,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
}
/*
- * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
- * and 2) have a corresponding _Lxx or _Exx method. All other GPEs must
- * be enabled via the acpi_enable_gpe() external interface.
+ * Enable all GPEs in this block that have these attributes:
+ * 1) are "runtime" or "run/wake" GPEs, and
+ * 2) have a corresponding _Lxx or _Exx method
+ *
+ * Any other GPEs within this block must be enabled via the acpi_enable_gpe()
+ * external interface.
*/
wake_gpe_count = 0;
gpe_enabled_count = 0;
@@ -976,32 +1032,19 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
}
}
- /* Dump info about this GPE block */
-
- ACPI_DEBUG_PRINT((ACPI_DB_INIT,
- "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
- (u32) gpe_block->block_base_number,
- (u32) (gpe_block->block_base_number +
- ((gpe_block->register_count *
- ACPI_GPE_REGISTER_WIDTH) - 1)),
- gpe_device->name.ascii, gpe_block->register_count,
- interrupt_number));
-
- /* Enable all valid GPEs found above */
-
- status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
-
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"Found %u Wake, Enabled %u Runtime GPEs in this block\n",
wake_gpe_count, gpe_enabled_count));
- /* Return the new block */
+ /* Enable all valid runtime GPEs found above */
- if (return_gpe_block) {
- (*return_gpe_block) = gpe_block;
+ status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR((AE_INFO, "Could not enable GPEs in gpe_block %p",
+ gpe_block));
}
- return_ACPI_STATUS(AE_OK);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -1072,8 +1115,8 @@ acpi_status acpi_ev_gpe_initialize(void)
&acpi_gbl_gpe_fadt_blocks[0]);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not create GPE Block 0, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not create GPE Block 0"));
}
}
@@ -1086,7 +1129,12 @@ acpi_status acpi_ev_gpe_initialize(void)
if ((register_count0) &&
(gpe_number_max >= acpi_gbl_FADT->gpe1_base)) {
- ACPI_REPORT_ERROR(("GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n", gpe_number_max, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
+ ACPI_ERROR((AE_INFO,
+ "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1",
+ gpe_number_max, acpi_gbl_FADT->gpe1_base,
+ acpi_gbl_FADT->gpe1_base +
+ ((register_count1 *
+ ACPI_GPE_REGISTER_WIDTH) - 1)));
/* Ignore GPE1 block by setting the register count to zero */
@@ -1104,7 +1152,8 @@ acpi_status acpi_ev_gpe_initialize(void)
[1]);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not create GPE Block 1, %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not create GPE Block 1"));
}
/*
@@ -1130,7 +1179,9 @@ acpi_status acpi_ev_gpe_initialize(void)
/* Check for Max GPE number out-of-range */
if (gpe_number_max > ACPI_GPE_MAX) {
- ACPI_REPORT_ERROR(("Maximum GPE number from FADT is too large: 0x%X\n", gpe_number_max));
+ ACPI_ERROR((AE_INFO,
+ "Maximum GPE number from FADT is too large: 0x%X",
+ gpe_number_max));
status = AE_BAD_VALUE;
goto cleanup;
}
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 7e57b8470f5..0909ba69577 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -303,7 +303,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore,
acpi_gbl_global_lock_thread_count);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not signal Global Lock semaphore\n"));
+ ACPI_ERROR((AE_INFO,
+ "Could not signal Global Lock semaphore"));
}
}
}
@@ -344,7 +345,8 @@ static u32 acpi_ev_global_lock_handler(void *context)
acpi_ev_global_lock_thread,
context);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not queue Global Lock thread, %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not queue Global Lock thread"));
return (ACPI_INTERRUPT_NOT_HANDLED);
}
@@ -384,7 +386,8 @@ acpi_status acpi_ev_init_global_lock_handler(void)
* with an error.
*/
if (status == AE_NO_HARDWARE_RESPONSE) {
- ACPI_REPORT_ERROR(("No response from Global Lock hardware, disabling lock\n"));
+ ACPI_ERROR((AE_INFO,
+ "No response from Global Lock hardware, disabling lock"));
acpi_gbl_global_lock_present = FALSE;
status = AE_OK;
@@ -480,7 +483,8 @@ acpi_status acpi_ev_release_global_lock(void)
ACPI_FUNCTION_TRACE("ev_release_global_lock");
if (!acpi_gbl_global_lock_thread_count) {
- ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n"));
+ ACPI_WARNING((AE_INFO,
+ "Cannot release HW Global Lock, it has not been acquired"));
return_ACPI_STATUS(AE_NOT_ACQUIRED);
}
@@ -542,9 +546,9 @@ void acpi_ev_terminate(void)
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
status = acpi_disable_event((u32) i, 0);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not disable fixed event %d\n",
- (u32) i));
+ ACPI_ERROR((AE_INFO,
+ "Could not disable fixed event %d",
+ (u32) i));
}
}
@@ -556,8 +560,7 @@ void acpi_ev_terminate(void)
status = acpi_ev_remove_sci_handler();
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not remove SCI handler\n"));
+ ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
}
}
@@ -570,8 +573,7 @@ void acpi_ev_terminate(void)
if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
status = acpi_disable();
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "acpi_disable failed\n"));
+ ACPI_WARNING((AE_INFO, "acpi_disable failed"));
}
}
return_VOID;
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index 84fad082d80..6da58e77641 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -295,12 +295,12 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
handler_desc = region_obj->region.handler;
if (!handler_desc) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No handler for Region [%4.4s] (%p) [%s]\n",
- acpi_ut_get_node_name(region_obj->region.
- node), region_obj,
- acpi_ut_get_region_name(region_obj->region.
- space_id)));
+ ACPI_ERROR((AE_INFO,
+ "No handler for Region [%4.4s] (%p) [%s]",
+ acpi_ut_get_node_name(region_obj->region.node),
+ region_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
@@ -317,12 +317,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
if (!region_setup) {
/* No initialization routine, exit with error */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No init routine for region(%p) [%s]\n",
- region_obj,
- acpi_ut_get_region_name(region_obj->
- region.
- space_id)));
+ ACPI_ERROR((AE_INFO,
+ "No init routine for region(%p) [%s]",
+ region_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
@@ -347,12 +346,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
/* Check for failure of the Region Setup */
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Region Init: %s [%s]\n",
- acpi_format_exception(status),
- acpi_ut_get_region_name(region_obj->
- region.
- space_id)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During region initialization: [%s]",
+ acpi_ut_get_region_name(region_obj->
+ region.
+ space_id)));
return_ACPI_STATUS(status);
}
@@ -406,10 +404,9 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
region_obj2->extra.region_context);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Handler for [%s] returned %s\n",
- acpi_ut_get_region_name(region_obj->region.
- space_id),
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
}
if (!
@@ -501,12 +498,10 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
status = acpi_ev_execute_reg_method(region_obj, 0);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%s from region _REG, [%s]\n",
- acpi_format_exception(status),
- acpi_ut_get_region_name
- (region_obj->region.
- space_id)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "from region _REG, [%s]",
+ acpi_ut_get_region_name
+ (region_obj->region.space_id)));
}
if (acpi_ns_is_locked) {
@@ -528,12 +523,10 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
/* Init routine may fail, Just ignore errors */
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%s from region init, [%s]\n",
- acpi_format_exception(status),
- acpi_ut_get_region_name
- (region_obj->region.
- space_id)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "from region init, [%s]",
+ acpi_ut_get_region_name
+ (region_obj->region.space_id)));
}
region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index a1bd2da27c4..baed8c1a1b9 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -233,7 +233,11 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
*/
status = AE_OK;
} else {
- ACPI_REPORT_ERROR(("Could not install pci_config handler for Root Bridge %4.4s, %s\n", acpi_ut_get_node_name(pci_root_node), acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO,
+ status,
+ "Could not install pci_config handler for Root Bridge %4.4s",
+ acpi_ut_get_node_name
+ (pci_root_node)));
}
}
break;
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
index 14183597700..9a622169008 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/events/evsci.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -88,7 +88,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
*/
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
- return_VALUE(interrupt_handled);
+ return_UINT32(interrupt_handled);
}
/*******************************************************************************
@@ -121,7 +121,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
*/
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
- return_VALUE(interrupt_handled);
+ return_UINT32(interrupt_handled);
}
/******************************************************************************
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index 43b33d19cdf..b38b39dde54 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -143,8 +143,8 @@ acpi_install_fixed_event_handler(u32 event,
if (ACPI_SUCCESS(status))
status = acpi_enable_event(event, 0);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Could not enable fixed event.\n"));
+ ACPI_WARNING((AE_INFO, "Could not enable fixed event %X",
+ event));
/* Remove the handler */
@@ -204,10 +204,11 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
acpi_gbl_fixed_event_handlers[event].context = NULL;
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Could not write to fixed event enable register.\n"));
+ ACPI_WARNING((AE_INFO,
+ "Could not write to fixed event enable register %X",
+ event));
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X.\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
event));
}
@@ -434,7 +435,7 @@ acpi_remove_notify_handler(acpi_handle device,
if (device == ACPI_ROOT_OBJECT) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Removing notify handler for ROOT object.\n"));
+ "Removing notify handler for namespace root object\n"));
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
!acpi_gbl_system_notify.handler) ||
@@ -562,7 +563,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_handler_info *handler;
acpi_status status;
- u32 flags;
+ acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE("acpi_install_gpe_handler");
@@ -653,7 +654,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_handler_info *handler;
acpi_status status;
- u32 flags;
+ acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler");
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index 887ff9f28a0..ec9ce8429f1 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,8 +70,7 @@ acpi_status acpi_enable(void)
/* Make sure we have the FADT */
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "No FADT information present!\n"));
+ ACPI_WARNING((AE_INFO, "No FADT information present!"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
@@ -83,7 +82,8 @@ acpi_status acpi_enable(void)
status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not transition to ACPI mode.\n"));
+ ACPI_ERROR((AE_INFO,
+ "Could not transition to ACPI mode"));
return_ACPI_STATUS(status);
}
@@ -113,8 +113,7 @@ acpi_status acpi_disable(void)
ACPI_FUNCTION_TRACE("acpi_disable");
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "No FADT information present!\n"));
+ ACPI_WARNING((AE_INFO, "No FADT information present!"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
@@ -127,8 +126,8 @@ acpi_status acpi_disable(void)
status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not exit ACPI mode to legacy mode"));
+ ACPI_ERROR((AE_INFO,
+ "Could not exit ACPI mode to legacy mode"));
return_ACPI_STATUS(status);
}
@@ -185,9 +184,9 @@ acpi_status acpi_enable_event(u32 event, u32 flags)
}
if (value != 1) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not enable %s event\n",
- acpi_ut_get_event_name(event)));
+ ACPI_ERROR((AE_INFO,
+ "Could not enable %s event",
+ acpi_ut_get_event_name(event)));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
@@ -384,9 +383,9 @@ acpi_status acpi_disable_event(u32 event, u32 flags)
}
if (value != 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not disable %s events\n",
- acpi_ut_get_event_name(event)));
+ ACPI_ERROR((AE_INFO,
+ "Could not disable %s events",
+ acpi_ut_get_event_name(event)));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
@@ -626,6 +625,13 @@ acpi_install_gpe_block(acpi_handle gpe_device,
goto unlock_and_exit;
}
+ /* Run the _PRW methods and enable the GPEs */
+
+ status = acpi_ev_initialize_gpe_block(node, gpe_block);
+ if (ACPI_FAILURE(status)) {
+ goto unlock_and_exit;
+ }
+
/* Get the device_object attached to the node */
obj_desc = acpi_ns_get_attached_object(node);
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index 6f28ea2db5b..abf5caca9ae 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 1ce365d651d..a29782fe3ec 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -413,9 +413,9 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
(!ACPI_STRNCMP(table_ptr->signature,
acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
- table_ptr->signature));
+ ACPI_ERROR((AE_INFO,
+ "Table has invalid signature [%4.4s], must be SSDT or PSDT",
+ table_ptr->signature));
status = AE_BAD_SIGNATURE;
goto cleanup;
}
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index 04e5194989a..e6d52e12d77 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -504,18 +504,12 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
}
/*
- * Perform the conversion.
+ * Create a new string object and string buffer
* (-1 because of extra separator included in string_length from above)
*/
- string_length--;
- if (string_length > ACPI_MAX_STRING_CONVERSION) { /* ACPI limit */
- return_ACPI_STATUS(AE_AML_STRING_LIMIT);
- }
-
- /* Create a new string object and string buffer */
-
return_desc =
- acpi_ut_create_string_object((acpi_size) string_length);
+ acpi_ut_create_string_object((acpi_size)
+ (string_length - 1));
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -647,7 +641,9 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
break;
default:
- ACPI_REPORT_ERROR(("Bad destination type during conversion: %X\n", destination_type));
+ ACPI_ERROR((AE_INFO,
+ "Bad destination type during conversion: %X",
+ destination_type));
status = AE_AML_INTERNAL;
break;
}
@@ -660,17 +656,13 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown Target type ID 0x%X Op %s dest_type %s\n",
- GET_CURRENT_ARG_TYPE(walk_state->op_info->
- runtime_args),
- walk_state->op_info->name,
- acpi_ut_get_type_name(destination_type)));
-
- ACPI_REPORT_ERROR(("Bad Target Type (ARGI): %X\n",
- GET_CURRENT_ARG_TYPE(walk_state->op_info->
- runtime_args)))
- status = AE_AML_INTERNAL;
+ ACPI_ERROR((AE_INFO,
+ "Unknown Target type ID 0x%X aml_opcode %X dest_type %s",
+ GET_CURRENT_ARG_TYPE(walk_state->op_info->
+ runtime_args),
+ walk_state->opcode,
+ acpi_ut_get_type_name(destination_type)));
+ status = AE_AML_INTERNAL;
}
/*
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 91c49188fb0..68057540283 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -300,8 +300,8 @@ acpi_ex_create_region(u8 * aml_start,
*/
if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
(region_space < ACPI_USER_REGION_BEGIN)) {
- ACPI_REPORT_ERROR(("Invalid address_space type %X\n",
- region_space));
+ ACPI_ERROR((AE_INFO, "Invalid address_space type %X",
+ region_space));
return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
}
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index bc2fa996047..a7cca8d4f85 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,20 +55,386 @@ ACPI_MODULE_NAME("exdump")
*/
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/* Local prototypes */
-#ifdef ACPI_FUTURE_USAGE
static void acpi_ex_out_string(char *title, char *value);
static void acpi_ex_out_pointer(char *title, void *value);
-static void acpi_ex_out_integer(char *title, u32 value);
-
static void acpi_ex_out_address(char *title, acpi_physical_address value);
-static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc);
+static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc);
static void
-acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
+ u32 level, u32 index);
+
+/*******************************************************************************
+ *
+ * Object Descriptor info tables
+ *
+ * Note: The first table entry must be an INIT opcode and must contain
+ * the table length (number of table entries)
+ *
+ ******************************************************************************/
+
+static struct acpi_exdump_info acpi_ex_dump_integer[2] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_integer), NULL},
+ {ACPI_EXD_UINT64, ACPI_EXD_OFFSET(integer.value), "Value"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_string[4] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_string), NULL},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(string.length), "Length"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(string.pointer), "Pointer"},
+ {ACPI_EXD_STRING, 0, NULL}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_buffer[4] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer), NULL},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(buffer.length), "Length"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.pointer), "Pointer"},
+ {ACPI_EXD_BUFFER, 0, NULL}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_package[5] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Elements"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"},
+ {ACPI_EXD_PACKAGE, 0, NULL}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_device[4] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.system_notify),
+ "System Notify"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.device_notify),
+ "Device Notify"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_event[2] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_event), NULL},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(event.semaphore), "Semaphore"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_method[8] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "param_count"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.concurrency), "Concurrency"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.semaphore), "Semaphore"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.thread_count), "Thread Count"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(method.aml_length), "Aml Length"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_mutex[5] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
+ {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
+ "Acquire Depth"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.semaphore), "Semaphore"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_region[7] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region), NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.space_id), "Space Id"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.flags), "Flags"},
+ {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(region.address), "Address"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(region.length), "Length"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.handler), "Handler"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.next), "Next"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_power[5] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_power), NULL},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.system_level),
+ "System Level"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order),
+ "Resource Order"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.system_notify),
+ "System Notify"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.device_notify),
+ "Device Notify"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_processor[7] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_processor), NULL},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(processor.length), "Length"},
+ {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify),
+ "System Notify"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.device_notify),
+ "Device Notify"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_thermal[4] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.system_notify),
+ "System Notify"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.device_notify),
+ "Device Notify"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer_field), NULL},
+ {ACPI_EXD_FIELD, 0, NULL},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer_field.buffer_obj),
+ "Buffer Object"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_region_field[3] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL},
+ {ACPI_EXD_FIELD, 0, NULL},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL},
+ {ACPI_EXD_FIELD, 0, NULL},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(bank_field.value), "Value"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.region_obj),
+ "Region Object"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.bank_obj), "Bank Object"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_index_field[5] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL},
+ {ACPI_EXD_FIELD, 0, NULL},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(index_field.value), "Value"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.index_obj),
+ "Index Object"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_reference[7] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.offset), "Offset"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"},
+ {ACPI_EXD_REFERENCE, 0, NULL}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_address_handler),
+ NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(address_space.space_id), "Space Id"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.next), "Next"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.region_list),
+ "Region List"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.node), "Node"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_notify[3] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"}
+};
+
+/* Miscellaneous tables */
+
+static struct acpi_exdump_info acpi_ex_dump_common[4] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_common), NULL},
+ {ACPI_EXD_TYPE, 0, NULL},
+ {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(common.reference_count),
+ "Reference Count"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_field_common[7] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_field_common), NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.field_flags),
+ "Field Flags"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.access_byte_width),
+ "Access Byte Width"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.bit_length),
+ "Bit Length"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.start_field_bit_offset),
+ "Field Bit Offset"},
+ {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.base_byte_offset),
+ "Base Byte Offset"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"}
+};
+
+static struct acpi_exdump_info acpi_ex_dump_node[6] = {
+ {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL},
+ {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"},
+ {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"},
+ {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(reference_count),
+ "Reference Count"},
+ {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"},
+ {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"}
+};
+
+/* Dispatch table, indexed by object type */
+
+static struct acpi_exdump_info *acpi_ex_dump_info[] = {
+ NULL,
+ acpi_ex_dump_integer,
+ acpi_ex_dump_string,
+ acpi_ex_dump_buffer,
+ acpi_ex_dump_package,
+ NULL,
+ acpi_ex_dump_device,
+ acpi_ex_dump_event,
+ acpi_ex_dump_method,
+ acpi_ex_dump_mutex,
+ acpi_ex_dump_region,
+ acpi_ex_dump_power,
+ acpi_ex_dump_processor,
+ acpi_ex_dump_thermal,
+ acpi_ex_dump_buffer_field,
+ NULL,
+ NULL,
+ acpi_ex_dump_region_field,
+ acpi_ex_dump_bank_field,
+ acpi_ex_dump_index_field,
+ acpi_ex_dump_reference,
+ NULL,
+ NULL,
+ acpi_ex_dump_notify,
+ acpi_ex_dump_address_handler,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ex_dump_object
+ *
+ * PARAMETERS: obj_desc - Descriptor to dump
+ * Info - Info table corresponding to this object
+ * type
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Walk the info table for this object
+ *
+ ******************************************************************************/
+
+static void
+acpi_ex_dump_object(union acpi_operand_object *obj_desc,
+ struct acpi_exdump_info *info)
+{
+ u8 *target;
+ char *name;
+ u8 count;
+
+ if (!info) {
+ acpi_os_printf
+ ("ex_dump_object: Display not implemented for object type %s\n",
+ acpi_ut_get_object_type_name(obj_desc));
+ return;
+ }
+
+ /* First table entry must contain the table length (# of table entries) */
+
+ count = info->offset;
+
+ while (count) {
+ target = ACPI_ADD_PTR(u8, obj_desc, info->offset);
+ name = info->name;
+
+ switch (info->opcode) {
+ case ACPI_EXD_INIT:
+ break;
+
+ case ACPI_EXD_TYPE:
+ acpi_ex_out_string("Type",
+ acpi_ut_get_object_type_name
+ (obj_desc));
+ break;
+
+ case ACPI_EXD_UINT8:
+
+ acpi_os_printf("%20s : %2.2X\n", name, *target);
+ break;
+
+ case ACPI_EXD_UINT16:
+
+ acpi_os_printf("%20s : %4.4X\n", name,
+ ACPI_GET16(target));
+ break;
+
+ case ACPI_EXD_UINT32:
+
+ acpi_os_printf("%20s : %8.8X\n", name,
+ ACPI_GET32(target));
+ break;
+
+ case ACPI_EXD_UINT64:
+
+ acpi_os_printf("%20s : %8.8X%8.8X\n", "Value",
+ ACPI_FORMAT_UINT64(ACPI_GET64(target)));
+ break;
+
+ case ACPI_EXD_POINTER:
+
+ acpi_ex_out_pointer(name,
+ *ACPI_CAST_PTR(void *, target));
+ break;
+
+ case ACPI_EXD_ADDRESS:
+
+ acpi_ex_out_address(name,
+ *ACPI_CAST_PTR
+ (acpi_physical_address, target));
+ break;
+
+ case ACPI_EXD_STRING:
+
+ acpi_ut_print_string(obj_desc->string.pointer,
+ ACPI_UINT8_MAX);
+ acpi_os_printf("\n");
+ break;
+
+ case ACPI_EXD_BUFFER:
+
+ ACPI_DUMP_BUFFER(obj_desc->buffer.pointer,
+ obj_desc->buffer.length);
+ break;
+
+ case ACPI_EXD_PACKAGE:
+
+ /* Dump the package contents */
+
+ acpi_os_printf("\nPackage Contents:\n");
+ acpi_ex_dump_package_obj(obj_desc, 0, 0);
+ break;
+
+ case ACPI_EXD_FIELD:
+
+ acpi_ex_dump_object(obj_desc,
+ acpi_ex_dump_field_common);
+ break;
+
+ case ACPI_EXD_REFERENCE:
+
+ acpi_ex_out_string("Opcode",
+ (acpi_ps_get_opcode_info
+ (obj_desc->reference.opcode))->
+ name);
+ acpi_ex_dump_reference_obj(obj_desc);
+ break;
+
+ default:
+ acpi_os_printf("**** Invalid table opcode [%X] ****\n",
+ info->opcode);
+ return;
+ }
+
+ info++;
+ count--;
+ }
+}
/*******************************************************************************
*
@@ -214,7 +580,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
case ACPI_TYPE_BUFFER:
- acpi_os_printf("Buffer len %X @ %p \n",
+ acpi_os_printf("Buffer len %X @ %p\n",
obj_desc->buffer.length,
obj_desc->buffer.pointer);
@@ -320,17 +686,17 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
case ACPI_TYPE_BUFFER_FIELD:
- acpi_os_printf("buffer_field: %X bits at byte %X bit %X of \n",
+ acpi_os_printf("buffer_field: %X bits at byte %X bit %X of\n",
obj_desc->buffer_field.bit_length,
obj_desc->buffer_field.base_byte_offset,
obj_desc->buffer_field.start_field_bit_offset);
if (!obj_desc->buffer_field.buffer_obj) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL* \n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n"));
} else
if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj)
!= ACPI_TYPE_BUFFER) {
- acpi_os_printf("*not a Buffer* \n");
+ acpi_os_printf("*not a Buffer*\n");
} else {
acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj,
depth + 1);
@@ -441,7 +807,6 @@ acpi_ex_dump_operands(union acpi_operand_object **operands,
return;
}
-#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
* FUNCTION: acpi_ex_out* functions
@@ -465,11 +830,6 @@ static void acpi_ex_out_pointer(char *title, void *value)
acpi_os_printf("%20s : %p\n", title, value);
}
-static void acpi_ex_out_integer(char *title, u32 value)
-{
- acpi_os_printf("%20s : %.2X\n", title, value);
-}
-
static void acpi_ex_out_address(char *title, acpi_physical_address value)
{
@@ -482,16 +842,16 @@ static void acpi_ex_out_address(char *title, acpi_physical_address value)
/*******************************************************************************
*
- * FUNCTION: acpi_ex_dump_node
+ * FUNCTION: acpi_ex_dump_namespace_node
*
- * PARAMETERS: *Node - Descriptor to dump
+ * PARAMETERS: Node - Descriptor to dump
* Flags - Force display if TRUE
*
* DESCRIPTION: Dumps the members of the given.Node
*
******************************************************************************/
-void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags)
+void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags)
{
ACPI_FUNCTION_ENTRY();
@@ -506,19 +866,17 @@ void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags)
acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node));
acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type));
- acpi_ex_out_integer("Flags", node->flags);
- acpi_ex_out_integer("Owner Id", node->owner_id);
- acpi_ex_out_integer("Reference Count", node->reference_count);
acpi_ex_out_pointer("Attached Object",
acpi_ns_get_attached_object(node));
- acpi_ex_out_pointer("child_list", node->child);
- acpi_ex_out_pointer("next_peer", node->peer);
acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node));
+
+ acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node),
+ acpi_ex_dump_node);
}
/*******************************************************************************
*
- * FUNCTION: acpi_ex_dump_reference
+ * FUNCTION: acpi_ex_dump_reference_obj
*
* PARAMETERS: Object - Descriptor to dump
*
@@ -526,14 +884,16 @@ void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags)
*
******************************************************************************/
-static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc)
+static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
{
struct acpi_buffer ret_buf;
acpi_status status;
+ ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+
if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) {
acpi_os_printf("Named Object %p ", obj_desc->reference.node);
- ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+
status =
acpi_ns_handle_to_pathname(obj_desc->reference.node,
&ret_buf);
@@ -551,9 +911,9 @@ static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc)
/*******************************************************************************
*
- * FUNCTION: acpi_ex_dump_package
+ * FUNCTION: acpi_ex_dump_package_obj
*
- * PARAMETERS: Object - Descriptor to dump
+ * PARAMETERS: obj_desc - Descriptor to dump
* Level - Indentation Level
* Index - Package index for this object
*
@@ -562,7 +922,8 @@ static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc)
******************************************************************************/
static void
-acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index)
+acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
+ u32 level, u32 index)
{
u32 i;
@@ -608,7 +969,8 @@ acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index)
acpi_os_printf("[Buffer] Length %.2X = ",
obj_desc->buffer.length);
if (obj_desc->buffer.length) {
- acpi_ut_dump_buffer((u8 *) obj_desc->buffer.pointer,
+ acpi_ut_dump_buffer(ACPI_CAST_PTR
+ (u8, obj_desc->buffer.pointer),
obj_desc->buffer.length,
DB_DWORD_DISPLAY, _COMPONENT);
} else {
@@ -618,19 +980,19 @@ acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index)
case ACPI_TYPE_PACKAGE:
- acpi_os_printf("[Package] Contains %d Elements: \n",
+ acpi_os_printf("[Package] Contains %d Elements:\n",
obj_desc->package.count);
for (i = 0; i < obj_desc->package.count; i++) {
- acpi_ex_dump_package(obj_desc->package.elements[i],
- level + 1, i);
+ acpi_ex_dump_package_obj(obj_desc->package.elements[i],
+ level + 1, i);
}
break;
case ACPI_TYPE_LOCAL_REFERENCE:
acpi_os_printf("[Object Reference] ");
- acpi_ex_dump_reference(obj_desc);
+ acpi_ex_dump_reference_obj(obj_desc);
break;
default:
@@ -645,7 +1007,7 @@ acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index)
*
* FUNCTION: acpi_ex_dump_object_descriptor
*
- * PARAMETERS: Object - Descriptor to dump
+ * PARAMETERS: obj_desc - Descriptor to dump
* Flags - Force display if TRUE
*
* DESCRIPTION: Dumps the members of the object descriptor given.
@@ -670,11 +1032,13 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
}
if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) {
- acpi_ex_dump_node((struct acpi_namespace_node *)obj_desc,
- flags);
+ acpi_ex_dump_namespace_node((struct acpi_namespace_node *)
+ obj_desc, flags);
+
acpi_os_printf("\nAttached Object (%p):\n",
((struct acpi_namespace_node *)obj_desc)->
object);
+
acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *)
obj_desc)->object, flags);
return_VOID;
@@ -687,233 +1051,18 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
return_VOID;
}
- /* Common Fields */
-
- acpi_ex_out_string("Type", acpi_ut_get_object_type_name(obj_desc));
- acpi_ex_out_integer("Reference Count",
- obj_desc->common.reference_count);
- acpi_ex_out_integer("Flags", obj_desc->common.flags);
-
- /* Object-specific Fields */
-
- switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
- case ACPI_TYPE_INTEGER:
-
- acpi_os_printf("%20s : %8.8X%8.8X\n", "Value",
- ACPI_FORMAT_UINT64(obj_desc->integer.value));
- break;
-
- case ACPI_TYPE_STRING:
-
- acpi_ex_out_integer("Length", obj_desc->string.length);
-
- acpi_os_printf("%20s : %p ", "Pointer",
- obj_desc->string.pointer);
- acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
- acpi_os_printf("\n");
- break;
-
- case ACPI_TYPE_BUFFER:
-
- acpi_ex_out_integer("Length", obj_desc->buffer.length);
- acpi_ex_out_pointer("Pointer", obj_desc->buffer.pointer);
- ACPI_DUMP_BUFFER(obj_desc->buffer.pointer,
- obj_desc->buffer.length);
- break;
-
- case ACPI_TYPE_PACKAGE:
-
- acpi_ex_out_integer("Flags", obj_desc->package.flags);
- acpi_ex_out_integer("Elements", obj_desc->package.count);
- acpi_ex_out_pointer("Element List", obj_desc->package.elements);
-
- /* Dump the package contents */
-
- acpi_os_printf("\nPackage Contents:\n");
- acpi_ex_dump_package(obj_desc, 0, 0);
- break;
-
- case ACPI_TYPE_DEVICE:
-
- acpi_ex_out_pointer("Handler", obj_desc->device.handler);
- acpi_ex_out_pointer("system_notify",
- obj_desc->device.system_notify);
- acpi_ex_out_pointer("device_notify",
- obj_desc->device.device_notify);
- break;
-
- case ACPI_TYPE_EVENT:
-
- acpi_ex_out_pointer("Semaphore", obj_desc->event.semaphore);
- break;
-
- case ACPI_TYPE_METHOD:
-
- acpi_ex_out_integer("param_count",
- obj_desc->method.param_count);
- acpi_ex_out_integer("Concurrency",
- obj_desc->method.concurrency);
- acpi_ex_out_pointer("Semaphore", obj_desc->method.semaphore);
- acpi_ex_out_integer("owner_id", obj_desc->method.owner_id);
- acpi_ex_out_integer("aml_length", obj_desc->method.aml_length);
- acpi_ex_out_pointer("aml_start", obj_desc->method.aml_start);
- break;
-
- case ACPI_TYPE_MUTEX:
-
- acpi_ex_out_integer("sync_level", obj_desc->mutex.sync_level);
- acpi_ex_out_pointer("owner_thread",
- obj_desc->mutex.owner_thread);
- acpi_ex_out_integer("acquire_depth",
- obj_desc->mutex.acquisition_depth);
- acpi_ex_out_pointer("Semaphore", obj_desc->mutex.semaphore);
- break;
-
- case ACPI_TYPE_REGION:
-
- acpi_ex_out_integer("space_id", obj_desc->region.space_id);
- acpi_ex_out_integer("Flags", obj_desc->region.flags);
- acpi_ex_out_address("Address", obj_desc->region.address);
- acpi_ex_out_integer("Length", obj_desc->region.length);
- acpi_ex_out_pointer("Handler", obj_desc->region.handler);
- acpi_ex_out_pointer("Next", obj_desc->region.next);
- break;
-
- case ACPI_TYPE_POWER:
-
- acpi_ex_out_integer("system_level",
- obj_desc->power_resource.system_level);
- acpi_ex_out_integer("resource_order",
- obj_desc->power_resource.resource_order);
- acpi_ex_out_pointer("system_notify",
- obj_desc->power_resource.system_notify);
- acpi_ex_out_pointer("device_notify",
- obj_desc->power_resource.device_notify);
- break;
-
- case ACPI_TYPE_PROCESSOR:
-
- acpi_ex_out_integer("Processor ID",
- obj_desc->processor.proc_id);
- acpi_ex_out_integer("Length", obj_desc->processor.length);
- acpi_ex_out_address("Address",
- (acpi_physical_address) obj_desc->processor.
- address);
- acpi_ex_out_pointer("system_notify",
- obj_desc->processor.system_notify);
- acpi_ex_out_pointer("device_notify",
- obj_desc->processor.device_notify);
- acpi_ex_out_pointer("Handler", obj_desc->processor.handler);
- break;
-
- case ACPI_TYPE_THERMAL:
-
- acpi_ex_out_pointer("system_notify",
- obj_desc->thermal_zone.system_notify);
- acpi_ex_out_pointer("device_notify",
- obj_desc->thermal_zone.device_notify);
- acpi_ex_out_pointer("Handler", obj_desc->thermal_zone.handler);
- break;
-
- case ACPI_TYPE_BUFFER_FIELD:
- case ACPI_TYPE_LOCAL_REGION_FIELD:
- case ACPI_TYPE_LOCAL_BANK_FIELD:
- case ACPI_TYPE_LOCAL_INDEX_FIELD:
-
- acpi_ex_out_integer("field_flags",
- obj_desc->common_field.field_flags);
- acpi_ex_out_integer("access_byte_width",
- obj_desc->common_field.access_byte_width);
- acpi_ex_out_integer("bit_length",
- obj_desc->common_field.bit_length);
- acpi_ex_out_integer("fld_bit_offset",
- obj_desc->common_field.
- start_field_bit_offset);
- acpi_ex_out_integer("base_byte_offset",
- obj_desc->common_field.base_byte_offset);
- acpi_ex_out_pointer("parent_node", obj_desc->common_field.node);
-
- switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
- case ACPI_TYPE_BUFFER_FIELD:
- acpi_ex_out_pointer("buffer_obj",
- obj_desc->buffer_field.buffer_obj);
- break;
-
- case ACPI_TYPE_LOCAL_REGION_FIELD:
- acpi_ex_out_pointer("region_obj",
- obj_desc->field.region_obj);
- break;
-
- case ACPI_TYPE_LOCAL_BANK_FIELD:
- acpi_ex_out_integer("Value",
- obj_desc->bank_field.value);
- acpi_ex_out_pointer("region_obj",
- obj_desc->bank_field.region_obj);
- acpi_ex_out_pointer("bank_obj",
- obj_desc->bank_field.bank_obj);
- break;
-
- case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_ex_out_integer("Value",
- obj_desc->index_field.value);
- acpi_ex_out_pointer("Index",
- obj_desc->index_field.index_obj);
- acpi_ex_out_pointer("Data",
- obj_desc->index_field.data_obj);
- break;
-
- default:
- /* All object types covered above */
- break;
- }
- break;
-
- case ACPI_TYPE_LOCAL_REFERENCE:
-
- acpi_ex_out_integer("target_type",
- obj_desc->reference.target_type);
- acpi_ex_out_string("Opcode",
- (acpi_ps_get_opcode_info
- (obj_desc->reference.opcode))->name);
- acpi_ex_out_integer("Offset", obj_desc->reference.offset);
- acpi_ex_out_pointer("obj_desc", obj_desc->reference.object);
- acpi_ex_out_pointer("Node", obj_desc->reference.node);
- acpi_ex_out_pointer("Where", obj_desc->reference.where);
-
- acpi_ex_dump_reference(obj_desc);
- break;
-
- case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
-
- acpi_ex_out_integer("space_id",
- obj_desc->address_space.space_id);
- acpi_ex_out_pointer("Next", obj_desc->address_space.next);
- acpi_ex_out_pointer("region_list",
- obj_desc->address_space.region_list);
- acpi_ex_out_pointer("Node", obj_desc->address_space.node);
- acpi_ex_out_pointer("Context", obj_desc->address_space.context);
- break;
+ if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) {
+ return_VOID;
+ }
- case ACPI_TYPE_LOCAL_NOTIFY:
+ /* Common Fields */
- acpi_ex_out_pointer("Node", obj_desc->notify.node);
- acpi_ex_out_pointer("Context", obj_desc->notify.context);
- break;
+ acpi_ex_dump_object(obj_desc, acpi_ex_dump_common);
- case ACPI_TYPE_LOCAL_ALIAS:
- case ACPI_TYPE_LOCAL_METHOD_ALIAS:
- case ACPI_TYPE_LOCAL_EXTRA:
- case ACPI_TYPE_LOCAL_DATA:
- default:
-
- acpi_os_printf
- ("ex_dump_object_descriptor: Display not implemented for object type %s\n",
- acpi_ut_get_object_type_name(obj_desc));
- break;
- }
+ /* Object-specific fields */
+ acpi_ex_dump_object(obj_desc, acpi_ex_dump_info[obj_desc->common.type]);
return_VOID;
}
-#endif /* ACPI_FUTURE_USAGE */
#endif
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
index ab1ba399aa2..e259201ce9a 100644
--- a/drivers/acpi/executer/exfield.c
+++ b/drivers/acpi/executer/exfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -249,13 +249,18 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
* Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
*/
if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
- ACPI_REPORT_ERROR(("SMBus write requires Buffer, found type %s\n", acpi_ut_get_object_type_name(source_desc)));
+ ACPI_ERROR((AE_INFO,
+ "SMBus write requires Buffer, found type %s",
+ acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
- ACPI_REPORT_ERROR(("SMBus write requires Buffer of length %X, found length %X\n", ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
+ ACPI_ERROR((AE_INFO,
+ "SMBus write requires Buffer of length %X, found length %X",
+ ACPI_SMBUS_BUFFER_SIZE,
+ source_desc->buffer.length));
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index ba6e08843c2..bd1af35f7fc 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -94,10 +94,9 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
/* We must have a valid region */
if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed Region, found type %X (%s)\n",
- ACPI_GET_OBJECT_TYPE(rgn_desc),
- acpi_ut_get_object_type_name(rgn_desc)));
+ ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)",
+ ACPI_GET_OBJECT_TYPE(rgn_desc),
+ acpi_ut_get_object_type_name(rgn_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -162,31 +161,28 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
* than the region itself. For example, a region of length one
* byte, and a field with Dword access specified.
*/
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
- acpi_ut_get_node_name(obj_desc->
- common_field.
- node),
- obj_desc->common_field.
- access_byte_width,
- acpi_ut_get_node_name(rgn_desc->
- region.node),
- rgn_desc->region.length));
+ ACPI_ERROR((AE_INFO,
+ "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)",
+ acpi_ut_get_node_name(obj_desc->
+ common_field.node),
+ obj_desc->common_field.access_byte_width,
+ acpi_ut_get_node_name(rgn_desc->region.
+ node),
+ rgn_desc->region.length));
}
/*
* Offset rounded up to next multiple of field width
* exceeds region length, indicate an error
*/
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
- acpi_ut_get_node_name(obj_desc->common_field.
- node),
- obj_desc->common_field.base_byte_offset,
- field_datum_byte_offset,
- obj_desc->common_field.access_byte_width,
- acpi_ut_get_node_name(rgn_desc->region.node),
- rgn_desc->region.length));
+ ACPI_ERROR((AE_INFO,
+ "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)",
+ acpi_ut_get_node_name(obj_desc->common_field.node),
+ obj_desc->common_field.base_byte_offset,
+ field_datum_byte_offset,
+ obj_desc->common_field.access_byte_width,
+ acpi_ut_get_node_name(rgn_desc->region.node),
+ rgn_desc->region.length));
return_ACPI_STATUS(AE_AML_REGION_LIMIT);
}
@@ -270,18 +266,17 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
if (ACPI_FAILURE(status)) {
if (status == AE_NOT_IMPLEMENTED) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Region %s(%X) not implemented\n",
- acpi_ut_get_region_name(rgn_desc->
- region.
- space_id),
- rgn_desc->region.space_id));
+ ACPI_ERROR((AE_INFO,
+ "Region %s(%X) not implemented",
+ acpi_ut_get_region_name(rgn_desc->region.
+ space_id),
+ rgn_desc->region.space_id));
} else if (status == AE_NOT_EXIST) {
- ACPI_REPORT_ERROR(("Region %s(%X) has no handler\n",
- acpi_ut_get_region_name(rgn_desc->
- region.
- space_id),
- rgn_desc->region.space_id));
+ ACPI_ERROR((AE_INFO,
+ "Region %s(%X) has no handler",
+ acpi_ut_get_region_name(rgn_desc->region.
+ space_id),
+ rgn_desc->region.space_id));
}
}
@@ -514,8 +509,8 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
default:
- ACPI_REPORT_ERROR(("Wrong object type in field I/O %X\n",
- ACPI_GET_OBJECT_TYPE(obj_desc)));
+ ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X",
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_INTERNAL;
break;
}
@@ -618,11 +613,11 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "write_with_update_rule: Unknown update_rule setting: %X\n",
- (obj_desc->common_field.
- field_flags &
- AML_FIELD_UPDATE_RULE_MASK)));
+ ACPI_ERROR((AE_INFO,
+ "Unknown update_rule value: %X",
+ (obj_desc->common_field.
+ field_flags &
+ AML_FIELD_UPDATE_RULE_MASK)));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
}
@@ -677,10 +672,9 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
if (buffer_length <
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Field size %X (bits) is too large for buffer (%X)\n",
- obj_desc->common_field.bit_length,
- buffer_length));
+ ACPI_ERROR((AE_INFO,
+ "Field size %X (bits) is too large for buffer (%X)",
+ obj_desc->common_field.bit_length, buffer_length));
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
@@ -792,10 +786,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
if (buffer_length <
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Field size %X (bits) is too large for buffer (%X)\n",
- obj_desc->common_field.bit_length,
- buffer_length));
+ ACPI_ERROR((AE_INFO,
+ "Field size %X (bits) is too large for buffer (%X)",
+ obj_desc->common_field.bit_length, buffer_length));
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index a3f4d72bedc..48c18d29222 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
+#include <acpi/amlresrc.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exmisc")
@@ -97,7 +98,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
default:
- ACPI_REPORT_ERROR(("Unknown Reference opcode in get_reference %X\n", obj_desc->reference.opcode));
+ ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
+ obj_desc->reference.opcode));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
break;
@@ -112,7 +114,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
default:
- ACPI_REPORT_ERROR(("Invalid descriptor type in get_reference: %X\n", ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
+ ACPI_ERROR((AE_INFO, "Invalid descriptor type %X",
+ ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
return_ACPI_STATUS(AE_TYPE);
}
@@ -157,48 +160,65 @@ acpi_ex_concat_template(union acpi_operand_object *operand0,
union acpi_operand_object **actual_return_desc,
struct acpi_walk_state *walk_state)
{
+ acpi_status status;
union acpi_operand_object *return_desc;
u8 *new_buf;
- u8 *end_tag1;
- u8 *end_tag2;
+ u8 *end_tag;
+ acpi_size length0;
acpi_size length1;
- acpi_size length2;
+ acpi_size new_length;
ACPI_FUNCTION_TRACE("ex_concat_template");
- /* Find the end_tags in each resource template */
+ /*
+ * Find the end_tag descriptor in each resource template.
+ * Note1: returned pointers point TO the end_tag, not past it.
+ * Note2: zero-length buffers are allowed; treated like one end_tag
+ */
+
+ /* Get the length of the first resource template */
- end_tag1 = acpi_ut_get_resource_end_tag(operand0);
- end_tag2 = acpi_ut_get_resource_end_tag(operand1);
- if (!end_tag1 || !end_tag2) {
- return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+ status = acpi_ut_get_resource_end_tag(operand0, &end_tag);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- /* Compute the length of each part */
+ length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer);
+
+ /* Get the length of the second resource template */
+
+ status = acpi_ut_get_resource_end_tag(operand1, &end_tag);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
- length1 = ACPI_PTR_DIFF(end_tag1, operand0->buffer.pointer);
- length2 = ACPI_PTR_DIFF(end_tag2, operand1->buffer.pointer) + 2; /* Size of END_TAG */
+ length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer);
- /* Create a new buffer object for the result */
+ /* Combine both lengths, minimum size will be 2 for end_tag */
- return_desc = acpi_ut_create_buffer_object(length1 + length2);
+ new_length = length0 + length1 + sizeof(struct aml_resource_end_tag);
+
+ /* Create a new buffer object for the result (with one end_tag) */
+
+ return_desc = acpi_ut_create_buffer_object(new_length);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- /* Copy the templates to the new descriptor */
-
+ /*
+ * Copy the templates to the new buffer, 0 first, then 1 follows. One
+ * end_tag descriptor is copied from Operand1.
+ */
new_buf = return_desc->buffer.pointer;
- ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length1);
- ACPI_MEMCPY(new_buf + length1, operand1->buffer.pointer, length2);
+ ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length0);
+ ACPI_MEMCPY(new_buf + length0, operand1->buffer.pointer, length1);
- /* Compute the new checksum */
+ /* Insert end_tag and set the checksum to zero, means "ignore checksum" */
- new_buf[return_desc->buffer.length - 1] =
- acpi_ut_generate_checksum(return_desc->buffer.pointer,
- (return_desc->buffer.length - 1));
+ new_buf[new_length - 1] = 0;
+ new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
- /* Return the completed template descriptor */
+ /* Return the completed resource template */
*actual_return_desc = return_desc;
return_ACPI_STATUS(AE_OK);
@@ -229,7 +249,6 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
union acpi_operand_object *return_desc;
char *new_buf;
acpi_status status;
- acpi_size new_length;
ACPI_FUNCTION_TRACE("ex_do_concatenate");
@@ -256,8 +275,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
break;
default:
- ACPI_REPORT_ERROR(("Concat - invalid obj type: %X\n",
- ACPI_GET_OBJECT_TYPE(operand0)));
+ ACPI_ERROR((AE_INFO, "Invalid object type: %X",
+ ACPI_GET_OBJECT_TYPE(operand0)));
status = AE_AML_INTERNAL;
}
@@ -296,8 +315,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
/* Copy the first integer, LSB first */
- ACPI_MEMCPY(new_buf,
- &operand0->integer.value,
+ ACPI_MEMCPY(new_buf, &operand0->integer.value,
acpi_gbl_integer_byte_width);
/* Copy the second integer (LSB first) after the first */
@@ -311,14 +329,11 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
/* Result of two Strings is a String */
- new_length = (acpi_size) operand0->string.length +
- (acpi_size) local_operand1->string.length;
- if (new_length > ACPI_MAX_STRING_CONVERSION) {
- status = AE_AML_STRING_LIMIT;
- goto cleanup;
- }
-
- return_desc = acpi_ut_create_string_object(new_length);
+ return_desc = acpi_ut_create_string_object((acpi_size)
+ (operand0->string.
+ length +
+ local_operand1->
+ string.length));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -338,11 +353,10 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
/* Result of two Buffers is a Buffer */
return_desc = acpi_ut_create_buffer_object((acpi_size)
- operand0->buffer.
- length +
- (acpi_size)
- local_operand1->
- buffer.length);
+ (operand0->buffer.
+ length +
+ local_operand1->
+ buffer.length));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -352,8 +366,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
/* Concatenate the buffers */
- ACPI_MEMCPY(new_buf,
- operand0->buffer.pointer, operand0->buffer.length);
+ ACPI_MEMCPY(new_buf, operand0->buffer.pointer,
+ operand0->buffer.length);
ACPI_MEMCPY(new_buf + operand0->buffer.length,
local_operand1->buffer.pointer,
local_operand1->buffer.length);
@@ -363,8 +377,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
/* Invalid object type, should not happen here */
- ACPI_REPORT_ERROR(("Concatenate - Invalid object type: %X\n",
- ACPI_GET_OBJECT_TYPE(operand0)));
+ ACPI_ERROR((AE_INFO, "Invalid object type: %X",
+ ACPI_GET_OBJECT_TYPE(operand0)));
status = AE_AML_INTERNAL;
goto cleanup;
}
@@ -625,9 +639,8 @@ acpi_ex_do_logical_op(u16 opcode,
/* Lexicographic compare: compare the data bytes */
- compare = ACPI_MEMCMP((const char *)operand0->buffer.pointer,
- (const char *)local_operand1->buffer.
- pointer,
+ compare = ACPI_MEMCMP(operand0->buffer.pointer,
+ local_operand1->buffer.pointer,
(length0 > length1) ? length1 : length0);
switch (opcode) {
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index ab47f6d8b5c..f843b22e20b 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -153,7 +153,9 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
/* Sanity check -- we must have a valid thread ID */
if (!walk_state->thread) {
- ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ ACPI_ERROR((AE_INFO,
+ "Cannot acquire Mutex [%4.4s], null thread info",
+ acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -162,7 +164,9 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
* mutex. This mechanism provides some deadlock prevention
*/
if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
- ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ ACPI_ERROR((AE_INFO,
+ "Cannot acquire Mutex [%4.4s], incorrect sync_level",
+ acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
@@ -237,14 +241,18 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
/* The mutex must have been previously acquired in order to release it */
if (!obj_desc->mutex.owner_thread) {
- ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], not acquired\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ ACPI_ERROR((AE_INFO,
+ "Cannot release Mutex [%4.4s], not acquired",
+ acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
}
/* Sanity check -- we must have a valid thread ID */
if (!walk_state->thread) {
- ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ ACPI_ERROR((AE_INFO,
+ "Cannot release Mutex [%4.4s], null thread info",
+ acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -255,7 +263,11 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
if ((obj_desc->mutex.owner_thread->thread_id !=
walk_state->thread->thread_id)
&& (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
- ACPI_REPORT_ERROR(("Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", walk_state->thread->thread_id, acpi_ut_get_node_name(obj_desc->mutex.node), obj_desc->mutex.owner_thread->thread_id));
+ ACPI_ERROR((AE_INFO,
+ "Thread %X cannot release Mutex [%4.4s] acquired by thread %X",
+ walk_state->thread->thread_id,
+ acpi_ut_get_node_name(obj_desc->mutex.node),
+ obj_desc->mutex.owner_thread->thread_id));
return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
@@ -264,7 +276,9 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
* equal to the current sync level
*/
if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
- ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ ACPI_ERROR((AE_INFO,
+ "Cannot release Mutex [%4.4s], incorrect sync_level",
+ acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
index 239d8473e9a..054fe5e1a31 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/executer/exnames.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -99,7 +99,8 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
*/
name_string = ACPI_MEM_ALLOCATE(size_needed);
if (!name_string) {
- ACPI_REPORT_ERROR(("ex_allocate_name_string: Could not allocate size %d\n", size_needed));
+ ACPI_ERROR((AE_INFO,
+ "Could not allocate size %d", size_needed));
return_PTR(NULL);
}
@@ -167,8 +168,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
char_buf[0] = *aml_address;
if ('0' <= char_buf[0] && char_buf[0] <= '9') {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "leading digit: %c\n",
- char_buf[0]));
+ ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0]));
return_ACPI_STATUS(AE_CTRL_PENDING);
}
@@ -191,10 +191,10 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
if (name_string) {
ACPI_STRCAT(name_string, char_buf);
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
- "Appended to - %s \n", name_string));
+ "Appended to - %s\n", name_string));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
- "No Name string - %s \n", char_buf));
+ "No Name string - %s\n", char_buf));
}
} else if (index == 0) {
/*
@@ -211,12 +211,12 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
* the required 4
*/
status = AE_AML_BAD_NAME;
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Bad character %02x in name, at %p\n",
- *aml_address, aml_address));
+ ACPI_ERROR((AE_INFO,
+ "Bad character %02x in name, at %p",
+ *aml_address, aml_address));
}
- *in_aml_address = (u8 *) aml_address;
+ *in_aml_address = ACPI_CAST_PTR(u8, aml_address);
return_ACPI_STATUS(status);
}
@@ -412,8 +412,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
if (AE_CTRL_PENDING == status && has_prefix) {
/* Ran out of segments after processing a prefix */
- ACPI_REPORT_ERROR(("ex_do_name: Malformed Name at %p\n",
- name_string));
+ ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
status = AE_AML_BAD_NAME;
}
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index 97e34542f5e..23d0823bcd5 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -111,7 +111,8 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
default: /* Unknown opcode */
- ACPI_REPORT_ERROR(("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
@@ -188,7 +189,8 @@ acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state)
default: /* Unknown opcode */
- ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
@@ -227,7 +229,8 @@ acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)
default: /* Unknown opcode */
- ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
@@ -346,9 +349,9 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
/* Check the range of the digit */
if (temp32 > 9) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "BCD digit too large (not decimal): 0x%X\n",
- temp32));
+ ACPI_ERROR((AE_INFO,
+ "BCD digit too large (not decimal): 0x%X",
+ temp32));
status = AE_AML_NUMERIC_OVERFLOW;
goto cleanup;
@@ -393,12 +396,10 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
/* Overflow if there is any data left in Digit */
if (digit > 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Integer too large to convert to BCD: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64(operand
- [0]->
- integer.
- value)));
+ ACPI_ERROR((AE_INFO,
+ "Integer too large to convert to BCD: %8.8X%8.8X",
+ ACPI_FORMAT_UINT64(operand[0]->
+ integer.value)));
status = AE_AML_NUMERIC_OVERFLOW;
goto cleanup;
}
@@ -525,15 +526,16 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
/* These are two obsolete opcodes */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%s is obsolete and not implemented\n",
- acpi_ps_get_opcode_name(walk_state->opcode)));
+ ACPI_ERROR((AE_INFO,
+ "%s is obsolete and not implemented",
+ acpi_ps_get_opcode_name(walk_state->opcode)));
status = AE_SUPPORT;
goto cleanup;
default: /* Unknown opcode */
- ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
@@ -639,11 +641,10 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc,
walk_state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%s: bad operand(s) %s\n",
- acpi_ps_get_opcode_name(walk_state->
- opcode),
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While resolving operands for [%s]",
+ acpi_ps_get_opcode_name(walk_state->
+ opcode)));
goto cleanup;
}
@@ -742,9 +743,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n",
- acpi_ut_get_type_name(type)));
+ ACPI_ERROR((AE_INFO,
+ "Operand is not Buf/Int/Str/Pkg - found type %s",
+ acpi_ut_get_type_name(type)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
@@ -941,11 +942,10 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown Index target_type %X in obj %p\n",
- operand[0]->reference.
- target_type,
- operand[0]));
+ ACPI_ERROR((AE_INFO,
+ "Unknown Index target_type %X in obj %p",
+ operand[0]->reference.
+ target_type, operand[0]));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
@@ -971,11 +971,10 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown opcode in ref(%p) - %X\n",
- operand[0],
- operand[0]->reference.
- opcode));
+ ACPI_ERROR((AE_INFO,
+ "Unknown opcode in ref(%p) - %X",
+ operand[0],
+ operand[0]->reference.opcode));
status = AE_TYPE;
goto cleanup;
@@ -985,7 +984,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
default:
- ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index 8d70c6beef0..e263a5ddd40 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -111,9 +111,9 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
/* Are notifies allowed on this object? */
if (!acpi_ev_is_notify_object(node)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unexpected notify object type [%s]\n",
- acpi_ut_get_type_name(node->type)));
+ ACPI_ERROR((AE_INFO,
+ "Unexpected notify object type [%s]",
+ acpi_ut_get_type_name(node->type)));
status = AE_AML_OPERAND_TYPE;
break;
@@ -157,7 +157,8 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
default:
- ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
}
@@ -221,7 +222,8 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
default:
- ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
@@ -344,10 +346,6 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
(length < operand[1]->integer.value) &&
(operand[0]->buffer.pointer[length])) {
length++;
- if (length > ACPI_MAX_STRING_CONVERSION) {
- status = AE_AML_STRING_LIMIT;
- goto cleanup;
- }
}
/* Allocate a new string object */
@@ -358,8 +356,10 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
goto cleanup;
}
- /* Copy the raw buffer data with no transform. NULL terminated already */
-
+ /*
+ * Copy the raw buffer data with no transform.
+ * (NULL terminated already)
+ */
ACPI_MEMCPY(return_desc->string.pointer,
operand[0]->buffer.pointer, length);
break;
@@ -391,10 +391,10 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
/* Object to be indexed is a Package */
if (index >= operand[0]->package.count) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Index value (%X%8.8X) beyond package end (%X)\n",
- ACPI_FORMAT_UINT64(index),
- operand[0]->package.count));
+ ACPI_ERROR((AE_INFO,
+ "Index value (%X%8.8X) beyond package end (%X)",
+ ACPI_FORMAT_UINT64(index),
+ operand[0]->package.count));
status = AE_AML_PACKAGE_LIMIT;
goto cleanup;
}
@@ -407,10 +407,10 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
/* Object to be indexed is a Buffer/String */
if (index >= operand[0]->buffer.length) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Index value (%X%8.8X) beyond end of buffer (%X)\n",
- ACPI_FORMAT_UINT64(index),
- operand[0]->buffer.length));
+ ACPI_ERROR((AE_INFO,
+ "Index value (%X%8.8X) beyond end of buffer (%X)",
+ ACPI_FORMAT_UINT64(index),
+ operand[0]->buffer.length));
status = AE_AML_BUFFER_LIMIT;
goto cleanup;
}
@@ -442,7 +442,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
default:
- ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
@@ -546,7 +547,8 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
default:
- ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
index 48336577767..6a3a883cb8a 100644
--- a/drivers/acpi/executer/exoparg3.c
+++ b/drivers/acpi/executer/exoparg3.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -119,7 +119,8 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
default:
- ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
@@ -223,8 +224,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
goto cleanup;
}
- if (length > 0) {
- /* Copy the portion requested */
+ if (buffer) {
+ /* We have a buffer, copy the portion requested */
ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
length);
@@ -242,7 +243,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
default:
- ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c
index 5dee7713957..e043d924444 100644
--- a/drivers/acpi/executer/exoparg6.c
+++ b/drivers/acpi/executer/exoparg6.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -234,8 +234,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
(operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Match operator out of range\n"));
+ ACPI_ERROR((AE_INFO, "Match operator out of range"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
@@ -244,10 +243,10 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
index = operand[5]->integer.value;
if (index >= operand[0]->package.count) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Index (%X%8.8X) beyond package end (%X)\n",
- ACPI_FORMAT_UINT64(index),
- operand[0]->package.count));
+ ACPI_ERROR((AE_INFO,
+ "Index (%X%8.8X) beyond package end (%X)",
+ ACPI_FORMAT_UINT64(index),
+ operand[0]->package.count));
status = AE_AML_PACKAGE_LIMIT;
goto cleanup;
}
@@ -316,7 +315,8 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
default:
- ACPI_REPORT_ERROR(("acpi_ex_opcode_6A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
+ walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index 7476c363e40..7719ae5d4f1 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/executer/exprep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -274,9 +274,8 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
default:
/* Invalid field access type */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown field access type %X\n", access));
- return_VALUE(0);
+ ACPI_ERROR((AE_INFO, "Unknown field access type %X", access));
+ return_UINT32(0);
}
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
@@ -289,7 +288,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
}
*return_byte_alignment = byte_alignment;
- return_VALUE(bit_length);
+ return_UINT32(bit_length);
}
/*******************************************************************************
@@ -422,15 +421,15 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
if (!info->region_node) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null region_node\n"));
+ ACPI_ERROR((AE_INFO, "Null region_node"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
type = acpi_ns_get_type(info->region_node);
if (type != ACPI_TYPE_REGION) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed Region, found type %X (%s)\n",
- type, acpi_ut_get_type_name(type)));
+ ACPI_ERROR((AE_INFO,
+ "Needed Region, found type %X (%s)",
+ type, acpi_ut_get_type_name(type)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -499,17 +498,17 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
case ACPI_TYPE_LOCAL_INDEX_FIELD:
+ /* Get the Index and Data registers */
+
obj_desc->index_field.index_obj =
acpi_ns_get_attached_object(info->register_node);
obj_desc->index_field.data_obj =
acpi_ns_get_attached_object(info->data_register_node);
- obj_desc->index_field.value = (u32)
- (info->field_bit_position /
- ACPI_MUL_8(obj_desc->field.access_byte_width));
if (!obj_desc->index_field.data_obj
|| !obj_desc->index_field.index_obj) {
- ACPI_REPORT_ERROR(("Null Index Object during field prep\n"));
+ ACPI_ERROR((AE_INFO,
+ "Null Index Object during field prep"));
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -519,6 +518,15 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
acpi_ut_add_reference(obj_desc->index_field.data_obj);
acpi_ut_add_reference(obj_desc->index_field.index_obj);
+ /*
+ * The value written to the Index register is the byte offset of the
+ * target field
+ * Note: may change code to: ACPI_DIV_8 (Info->field_bit_position)
+ */
+ obj_desc->index_field.value = (u32)
+ (info->field_bit_position /
+ ACPI_MUL_8(obj_desc->field.access_byte_width));
+
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
obj_desc->index_field.start_field_bit_offset,
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
index 9a2f5bea3af..6a4cfdff606 100644
--- a/drivers/acpi/executer/exregion.c
+++ b/drivers/acpi/executer/exregion.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -77,7 +77,7 @@ acpi_ex_system_memory_space_handler(u32 function,
struct acpi_mem_space_context *mem_info = region_context;
u32 length;
acpi_size window_size;
-#ifndef ACPI_MISALIGNED_TRANSFERS
+#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
u32 remainder;
#endif
@@ -103,13 +103,12 @@ acpi_ex_system_memory_space_handler(u32 function,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid system_memory width %d\n",
- bit_width));
+ ACPI_ERROR((AE_INFO, "Invalid system_memory width %d",
+ bit_width));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
-#ifndef ACPI_MISALIGNED_TRANSFERS
+#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
/*
* Hardware does not support non-aligned data transfers, we must verify
* the request.
@@ -159,10 +158,10 @@ acpi_ex_system_memory_space_handler(u32 function,
(void **)&mem_info->
mapped_logical_address);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not map memory at %8.8X%8.8X, size %X\n",
- ACPI_FORMAT_UINT64(address),
- (u32) window_size));
+ ACPI_ERROR((AE_INFO,
+ "Could not map memory at %8.8X%8.8X, size %X",
+ ACPI_FORMAT_UINT64(address),
+ (u32) window_size));
mem_info->mapped_length = 0;
return_ACPI_STATUS(status);
}
@@ -199,20 +198,20 @@ acpi_ex_system_memory_space_handler(u32 function,
*value = 0;
switch (bit_width) {
case 8:
- *value = (acpi_integer) * ((u8 *) logical_addr_ptr);
+ *value = (acpi_integer) ACPI_GET8(logical_addr_ptr);
break;
case 16:
- *value = (acpi_integer) * ((u16 *) logical_addr_ptr);
+ *value = (acpi_integer) ACPI_GET16(logical_addr_ptr);
break;
case 32:
- *value = (acpi_integer) * ((u32 *) logical_addr_ptr);
+ *value = (acpi_integer) ACPI_GET32(logical_addr_ptr);
break;
#if ACPI_MACHINE_WIDTH != 16
case 64:
- *value = (acpi_integer) * ((u64 *) logical_addr_ptr);
+ *value = (acpi_integer) ACPI_GET64(logical_addr_ptr);
break;
#endif
default:
@@ -225,20 +224,20 @@ acpi_ex_system_memory_space_handler(u32 function,
switch (bit_width) {
case 8:
- *(u8 *) logical_addr_ptr = (u8) * value;
+ ACPI_SET8(logical_addr_ptr) = (u8) * value;
break;
case 16:
- *(u16 *) logical_addr_ptr = (u16) * value;
+ ACPI_SET16(logical_addr_ptr) = (u16) * value;
break;
case 32:
- *(u32 *) logical_addr_ptr = (u32) * value;
+ ACPI_SET32(logical_addr_ptr) = (u32) * value;
break;
#if ACPI_MACHINE_WIDTH != 16
case 64:
- *(u64 *) logical_addr_ptr = (u64) * value;
+ ACPI_SET64(logical_addr_ptr) = (u64) * value;
break;
#endif
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
index ff5d8f97e8e..01b26c80d22 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/executer/exresnte.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -122,8 +122,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
}
if (!source_desc) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No object attached to node %p\n", node));
+ ACPI_ERROR((AE_INFO, "No object attached to node %p", node));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
@@ -135,10 +134,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_PACKAGE:
if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Object not a Package, type %s\n",
- acpi_ut_get_object_type_name
- (source_desc)));
+ ACPI_ERROR((AE_INFO, "Object not a Package, type %s",
+ acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -154,10 +151,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_BUFFER:
if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Object not a Buffer, type %s\n",
- acpi_ut_get_object_type_name
- (source_desc)));
+ ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s",
+ acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -173,10 +168,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_STRING:
if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Object not a String, type %s\n",
- acpi_ut_get_object_type_name
- (source_desc)));
+ ACPI_ERROR((AE_INFO, "Object not a String, type %s",
+ acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -189,10 +182,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_INTEGER:
if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Object not a Integer, type %s\n",
- acpi_ut_get_object_type_name
- (source_desc)));
+ ACPI_ERROR((AE_INFO, "Object not a Integer, type %s",
+ acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -236,9 +227,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_ANY:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Untyped entry %p, no attached object!\n",
- node));
+ ACPI_ERROR((AE_INFO,
+ "Untyped entry %p, no attached object!", node));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */
@@ -257,12 +247,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
default:
/* No named references are allowed here */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unsupported Reference opcode %X (%s)\n",
- source_desc->reference.opcode,
- acpi_ps_get_opcode_name(source_desc->
- reference.
- opcode)));
+ ACPI_ERROR((AE_INFO,
+ "Unsupported Reference opcode %X (%s)",
+ source_desc->reference.opcode,
+ acpi_ps_get_opcode_name(source_desc->
+ reference.opcode)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -272,9 +261,9 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
/* Default case is for unknown types */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Node %p - Unknown object type %X\n",
- node, entry_type));
+ ACPI_ERROR((AE_INFO,
+ "Node %p - Unknown object type %X",
+ node, entry_type));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 97eecbd3242..1deed492fe8 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,7 @@ acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr);
if (!stack_ptr || !*stack_ptr) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Internal - null pointer\n"));
+ ACPI_ERROR((AE_INFO, "Internal - null pointer"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
@@ -97,8 +97,7 @@ acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
}
if (!*stack_ptr) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Internal - null pointer\n"));
+ ACPI_ERROR((AE_INFO, "Internal - null pointer"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
}
@@ -228,9 +227,9 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
* A NULL object descriptor means an unitialized element of
* the package, can't dereference it
*/
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Attempt to deref an Index to NULL pkg element Idx=%p\n",
- stack_desc));
+ ACPI_ERROR((AE_INFO,
+ "Attempt to deref an Index to NULL pkg element Idx=%p",
+ stack_desc));
status = AE_AML_UNINITIALIZED_ELEMENT;
}
break;
@@ -239,7 +238,10 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
/* Invalid reference object */
- ACPI_REPORT_ERROR(("During resolve, Unknown target_type %X in Index/Reference obj %p\n", stack_desc->reference.target_type, stack_desc));
+ ACPI_ERROR((AE_INFO,
+ "Unknown target_type %X in Index/Reference obj %p",
+ stack_desc->reference.target_type,
+ stack_desc));
status = AE_AML_INTERNAL;
break;
}
@@ -264,7 +266,10 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
default:
- ACPI_REPORT_ERROR(("During resolve, Unknown Reference opcode %X (%s) in %p\n", opcode, acpi_ps_get_opcode_name(opcode), stack_desc));
+ ACPI_ERROR((AE_INFO,
+ "Unknown Reference opcode %X (%s) in %p",
+ opcode, acpi_ps_get_opcode_name(opcode),
+ stack_desc));
status = AE_AML_INTERNAL;
break;
}
@@ -386,7 +391,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", node, acpi_ut_get_descriptor_name(node)));
+ ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]",
+ node,
+ acpi_ut_get_descriptor_name(node)));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -442,7 +449,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", node, acpi_ut_get_descriptor_name(node)));
+ ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]",
+ node,
+ acpi_ut_get_descriptor_name(node)));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -511,7 +520,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
default:
- ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Unknown Reference subtype %X\n", obj_desc->reference.opcode));
+ ACPI_ERROR((AE_INFO,
+ "Unknown Reference subtype %X",
+ obj_desc->reference.opcode));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
}
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index ff064e79ab9..a1c000f5a41 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
#include <acpi/amlcode.h>
#include <acpi/acparser.h>
#include <acpi/acinterp.h>
+#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresop")
@@ -73,7 +74,7 @@ static acpi_status
acpi_ex_check_object_type(acpi_object_type type_needed,
acpi_object_type this_type, void *object)
{
- ACPI_FUNCTION_NAME("ex_check_object_type");
+ ACPI_FUNCTION_ENTRY();
if (type_needed == ACPI_TYPE_ANY) {
/* All types OK, so we don't perform any typechecks */
@@ -95,10 +96,10 @@ acpi_ex_check_object_type(acpi_object_type type_needed,
}
if (type_needed != this_type) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [%s], found [%s] %p\n",
- acpi_ut_get_type_name(type_needed),
- acpi_ut_get_type_name(this_type), object));
+ ACPI_ERROR((AE_INFO,
+ "Needed type [%s], found [%s] %p",
+ acpi_ut_get_type_name(type_needed),
+ acpi_ut_get_type_name(this_type), object));
return (AE_AML_OPERAND_TYPE);
}
@@ -151,13 +152,13 @@ acpi_ex_resolve_operands(u16 opcode,
arg_types = op_info->runtime_args;
if (arg_types == ARGI_INVALID_OPCODE) {
- ACPI_REPORT_ERROR(("resolve_operands: %X is not a valid AML opcode\n", opcode));
+ ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", opcode));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Opcode %X [%s] required_operand_types=%8.8X \n",
+ "Opcode %X [%s] required_operand_types=%8.8X\n",
opcode, op_info->name, arg_types));
/*
@@ -169,7 +170,8 @@ acpi_ex_resolve_operands(u16 opcode,
*/
while (GET_CURRENT_ARG_TYPE(arg_types)) {
if (!stack_ptr || !*stack_ptr) {
- ACPI_REPORT_ERROR(("resolve_operands: Null stack entry at %p\n", stack_ptr));
+ ACPI_ERROR((AE_INFO, "Null stack entry at %p",
+ stack_ptr));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -187,6 +189,22 @@ acpi_ex_resolve_operands(u16 opcode,
object_type =
((struct acpi_namespace_node *)obj_desc)->type;
+
+ /*
+ * Resolve an alias object. The construction of these objects
+ * guarantees that there is only one level of alias indirection;
+ * thus, the attached object is always the aliased namespace node
+ */
+ if (object_type == ACPI_TYPE_LOCAL_ALIAS) {
+ obj_desc =
+ acpi_ns_get_attached_object((struct
+ acpi_namespace_node
+ *)obj_desc);
+ *stack_ptr = obj_desc;
+ object_type =
+ ((struct acpi_namespace_node *)obj_desc)->
+ type;
+ }
break;
case ACPI_DESC_TYPE_OPERAND:
@@ -198,9 +216,9 @@ acpi_ex_resolve_operands(u16 opcode,
/* Check for bad acpi_object_type */
if (!acpi_ut_valid_object_type(object_type)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Bad operand object type [%X]\n",
- object_type));
+ ACPI_ERROR((AE_INFO,
+ "Bad operand object type [%X]",
+ object_type));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -238,13 +256,10 @@ acpi_ex_resolve_operands(u16 opcode,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Operand is a Reference, Unknown Reference Opcode %X [%s]\n",
- obj_desc->reference.
- opcode,
- (acpi_ps_get_opcode_info
- (obj_desc->reference.
- opcode))->name));
+ ACPI_ERROR((AE_INFO,
+ "Operand is a Reference, Unknown Reference Opcode: %X",
+ obj_desc->reference.
+ opcode));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -255,11 +270,10 @@ acpi_ex_resolve_operands(u16 opcode,
/* Invalid descriptor */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid descriptor %p [%s]\n",
- obj_desc,
- acpi_ut_get_descriptor_name
- (obj_desc)));
+ ACPI_ERROR((AE_INFO,
+ "Invalid descriptor %p [%s]",
+ obj_desc,
+ acpi_ut_get_descriptor_name(obj_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -417,11 +431,10 @@ acpi_ex_resolve_operands(u16 opcode,
acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16);
if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc),
- obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed [Integer/String/Buffer], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -444,11 +457,10 @@ acpi_ex_resolve_operands(u16 opcode,
status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr);
if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc),
- obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed [Integer/String/Buffer], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -472,11 +484,10 @@ acpi_ex_resolve_operands(u16 opcode,
ACPI_IMPLICIT_CONVERT_HEX);
if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc),
- obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed [Integer/String/Buffer], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -502,10 +513,10 @@ acpi_ex_resolve_operands(u16 opcode,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc), obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed [Integer/String/Buffer], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -539,10 +550,10 @@ acpi_ex_resolve_operands(u16 opcode,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc), obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed [Integer/String/Buffer], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -566,10 +577,10 @@ acpi_ex_resolve_operands(u16 opcode,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [Buffer/String/Package/Reference], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc), obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed [Buffer/String/Package/Reference], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -588,10 +599,10 @@ acpi_ex_resolve_operands(u16 opcode,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [Buffer/String/Package], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc), obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed [Buffer/String/Package], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -611,10 +622,10 @@ acpi_ex_resolve_operands(u16 opcode,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed [Region/region_field], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc), obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed [Region/region_field], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -656,10 +667,10 @@ acpi_ex_resolve_operands(u16 opcode,
break;
}
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n",
- acpi_ut_get_object_type_name
- (obj_desc), obj_desc));
+ ACPI_ERROR((AE_INFO,
+ "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -669,9 +680,9 @@ acpi_ex_resolve_operands(u16 opcode,
/* Unknown type */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Internal - Unknown ARGI (required operand) type %X\n",
- this_arg_type));
+ ACPI_ERROR((AE_INFO,
+ "Internal - Unknown ARGI (required operand) type %X",
+ this_arg_type));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index a7d8eea305c..3f020c0e2b9 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -250,7 +250,7 @@ acpi_ex_store(union acpi_operand_object *source_desc,
/* Validate parameters */
if (!source_desc || !dest_desc) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null parameter\n"));
+ ACPI_ERROR((AE_INFO, "Null parameter"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
@@ -290,10 +290,10 @@ acpi_ex_store(union acpi_operand_object *source_desc,
/* Destination is not a Reference object */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Target is not a Reference or Constant object - %s [%p]\n",
- acpi_ut_get_object_type_name(dest_desc),
- dest_desc));
+ ACPI_ERROR((AE_INFO,
+ "Target is not a Reference or Constant object - %s [%p]",
+ acpi_ut_get_object_type_name(dest_desc),
+ dest_desc));
ACPI_DUMP_STACK_ENTRY(source_desc);
ACPI_DUMP_STACK_ENTRY(dest_desc);
@@ -360,8 +360,8 @@ acpi_ex_store(union acpi_operand_object *source_desc,
default:
- ACPI_REPORT_ERROR(("ex_store: Unknown Reference opcode %X\n",
- ref_desc->reference.opcode));
+ ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
+ ref_desc->reference.opcode));
ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR);
status = AE_AML_INTERNAL;
@@ -490,10 +490,9 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
/* All other types are invalid */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Source must be Integer/Buffer/String type, not %s\n",
- acpi_ut_get_object_type_name
- (source_desc)));
+ ACPI_ERROR((AE_INFO,
+ "Source must be Integer/Buffer/String type, not %s",
+ acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
@@ -503,8 +502,8 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Target is not a Package or buffer_field\n"));
+ ACPI_ERROR((AE_INFO,
+ "Target is not a Package or buffer_field"));
status = AE_AML_OPERAND_TYPE;
break;
}
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index 382f63c14ea..42967baf760 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -7,7 +7,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -123,11 +123,10 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
&& (source_desc->reference.opcode == AML_LOAD_OP))) {
/* Conversion successful but still not a valid type */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Cannot assign type %s to %s (must be type Int/Str/Buf)\n",
- acpi_ut_get_object_type_name
- (source_desc),
- acpi_ut_get_type_name(target_type)));
+ ACPI_ERROR((AE_INFO,
+ "Cannot assign type %s to %s (must be type Int/Str/Buf)",
+ acpi_ut_get_object_type_name(source_desc),
+ acpi_ut_get_type_name(target_type)));
status = AE_AML_OPERAND_TYPE;
}
break;
@@ -135,9 +134,11 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
- /* Aliases are resolved by acpi_ex_prep_operands */
-
- ACPI_REPORT_ERROR(("Store into Alias - should never happen\n"));
+ /*
+ * All aliases should have been resolved earlier, during the
+ * operand resolution phase.
+ */
+ ACPI_ERROR((AE_INFO, "Store into an unresolved Alias object"));
status = AE_AML_INTERNAL;
break;
@@ -280,9 +281,8 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
/*
* All other types come here.
*/
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Store into type %s not implemented\n",
- acpi_ut_get_object_type_name(dest_desc)));
+ ACPI_WARNING((AE_INFO, "Store into type %s not implemented",
+ acpi_ut_get_object_type_name(dest_desc)));
status = AE_NOT_IMPLEMENTED;
break;
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
index c4ff654a669..6ab70708775 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/executer/exstorob.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
/* We know that source_desc is a buffer by now */
- buffer = (u8 *) source_desc->buffer.pointer;
+ buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
length = source_desc->buffer.length;
/*
@@ -160,7 +160,7 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
/* We know that source_desc is a string by now */
- buffer = (u8 *) source_desc->string.pointer;
+ buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer);
length = source_desc->string.length;
/*
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index 8a88b841237..ea9144f42e1 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -129,8 +129,8 @@ acpi_status acpi_ex_system_do_stall(u32 how_long)
* (ACPI specifies 100 usec as max, but this gives some slack in
* order to support existing BIOSs)
*/
- ACPI_REPORT_ERROR(("Stall: Time parameter is too large (%d)\n",
- how_long));
+ ACPI_ERROR((AE_INFO, "Time parameter is too large (%d)",
+ how_long));
status = AE_AML_OPERAND_VALUE;
} else {
acpi_os_stall(how_long);
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index 1ee79d8c8f8..f73a61aeb7e 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -91,7 +91,7 @@ acpi_status acpi_ex_enter_interpreter(void)
status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not acquire interpreter mutex\n"));
+ ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex"));
}
return_ACPI_STATUS(status);
@@ -127,7 +127,7 @@ void acpi_ex_exit_interpreter(void)
status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not release interpreter mutex\n"));
+ ACPI_ERROR((AE_INFO, "Could not release interpreter mutex"));
}
return_VOID;
@@ -200,13 +200,12 @@ u8 acpi_ex_acquire_global_lock(u32 field_flags)
if (ACPI_SUCCESS(status)) {
locked = TRUE;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not acquire Global Lock, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not acquire Global Lock"));
}
}
- return_VALUE(locked);
+ return_UINT8(locked);
}
/*******************************************************************************
@@ -237,7 +236,8 @@ void acpi_ex_release_global_lock(u8 locked_by_me)
if (ACPI_FAILURE(status)) {
/* Report the error, but there isn't much else we can do */
- ACPI_REPORT_ERROR(("Could not release ACPI Global Lock, %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not release ACPI Global Lock"));
}
}
@@ -268,7 +268,7 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base)
/* acpi_integer is unsigned, so we don't worry about a '-' prefix */
if (value == 0) {
- return_VALUE(1);
+ return_UINT32(1);
}
current_value = value;
@@ -282,7 +282,7 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base)
num_digits++;
}
- return_VALUE(num_digits);
+ return_UINT32(num_digits);
}
/*******************************************************************************
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index aa993715d64..8daef57b994 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -99,15 +99,15 @@ do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
unsigned long *busnr = (unsigned long *)data;
struct acpi_resource_address64 address;
- if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
- resource->id != ACPI_RSTYPE_ADDRESS32 &&
- resource->id != ACPI_RSTYPE_ADDRESS64)
+ if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
+ resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
+ resource->type != ACPI_RESOURCE_TYPE_ADDRESS64)
return AE_OK;
acpi_resource_to_address64(resource, &address);
if ((address.address_length > 0) &&
(address.resource_type == ACPI_BUS_NUMBER_RANGE))
- *busnr = address.min_address_range;
+ *busnr = address.minimum;
return AE_OK;
}
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
index 1bb3463d704..ea2f13271ff 100644
--- a/drivers/acpi/hardware/hwacpi.c
+++ b/drivers/acpi/hardware/hwacpi.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -68,8 +68,7 @@ acpi_status acpi_hw_initialize(void)
/* We must have the ACPI tables by the time we get here */
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No FADT is present\n"));
-
+ ACPI_ERROR((AE_INFO, "No FADT is present"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
@@ -108,7 +107,8 @@ acpi_status acpi_hw_set_mode(u32 mode)
* system does not support mode transition.
*/
if (!acpi_gbl_FADT->smi_cmd) {
- ACPI_REPORT_ERROR(("No SMI_CMD in FADT, mode transition failed.\n"));
+ ACPI_ERROR((AE_INFO,
+ "No SMI_CMD in FADT, mode transition failed"));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
@@ -120,7 +120,8 @@ acpi_status acpi_hw_set_mode(u32 mode)
* transitions are not supported.
*/
if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) {
- ACPI_REPORT_ERROR(("No ACPI mode transition supported in this system (enable/disable both zero)\n"));
+ ACPI_ERROR((AE_INFO,
+ "No ACPI mode transition supported in this system (enable/disable both zero)"));
return_ACPI_STATUS(AE_OK);
}
@@ -154,8 +155,8 @@ acpi_status acpi_hw_set_mode(u32 mode)
}
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not write mode change, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not write ACPI mode change"));
return_ACPI_STATUS(status);
}
@@ -175,7 +176,7 @@ acpi_status acpi_hw_set_mode(u32 mode)
retry--;
}
- ACPI_REPORT_ERROR(("Hardware never changed modes\n"));
+ ACPI_ERROR((AE_INFO, "Hardware did not change modes"));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
@@ -204,18 +205,18 @@ u32 acpi_hw_get_mode(void)
* system does not support mode transition.
*/
if (!acpi_gbl_FADT->smi_cmd) {
- return_VALUE(ACPI_SYS_MODE_ACPI);
+ return_UINT32(ACPI_SYS_MODE_ACPI);
}
status =
acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK);
if (ACPI_FAILURE(status)) {
- return_VALUE(ACPI_SYS_MODE_LEGACY);
+ return_UINT32(ACPI_SYS_MODE_LEGACY);
}
if (value) {
- return_VALUE(ACPI_SYS_MODE_ACPI);
+ return_UINT32(ACPI_SYS_MODE_ACPI);
} else {
- return_VALUE(ACPI_SYS_MODE_LEGACY);
+ return_UINT32(ACPI_SYS_MODE_LEGACY);
}
}
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index 5c8e5dfd024..d84942d22dd 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index 536a7aea80c..e1fe7549841 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -7,7 +7,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -144,7 +144,8 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
info.parameters = NULL;
info.return_object = NULL;
- sleep_state_name = (char *)acpi_gbl_sleep_state_names[sleep_state];
+ sleep_state_name =
+ ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
status = acpi_ns_evaluate_by_name(sleep_state_name, &info);
if (ACPI_FAILURE(status)) {
@@ -159,15 +160,16 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
/* Must have a return object */
if (!info.return_object) {
- ACPI_REPORT_ERROR(("No Sleep State object returned from [%s]\n",
- sleep_state_name));
+ ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
+ sleep_state_name));
status = AE_NOT_EXIST;
}
/* It must be of type Package */
else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) {
- ACPI_REPORT_ERROR(("Sleep State return object is not a Package\n"));
+ ACPI_ERROR((AE_INFO,
+ "Sleep State return object is not a Package"));
status = AE_AML_OPERAND_TYPE;
}
@@ -179,7 +181,8 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
* one per sleep type (A/B).
*/
else if (info.return_object->package.count < 2) {
- ACPI_REPORT_ERROR(("Sleep State return package does not have at least two elements\n"));
+ ACPI_ERROR((AE_INFO,
+ "Sleep State return package does not have at least two elements"));
status = AE_AML_NO_OPERAND;
}
@@ -189,7 +192,12 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
!= ACPI_TYPE_INTEGER) ||
(ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1])
!= ACPI_TYPE_INTEGER)) {
- ACPI_REPORT_ERROR(("Sleep State return package elements are not both Integers (%s, %s)\n", acpi_ut_get_object_type_name(info.return_object->package.elements[0]), acpi_ut_get_object_type_name(info.return_object->package.elements[1])));
+ ACPI_ERROR((AE_INFO,
+ "Sleep State return package elements are not both Integers (%s, %s)",
+ acpi_ut_get_object_type_name(info.return_object->
+ package.elements[0]),
+ acpi_ut_get_object_type_name(info.return_object->
+ package.elements[1])));
status = AE_AML_OPERAND_TYPE;
} else {
/* Valid _Sx_ package size, type, and value */
@@ -201,12 +209,11 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
}
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%s While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
- acpi_format_exception(status),
- sleep_state_name, info.return_object,
- acpi_ut_get_object_type_name(info.
- return_object)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While evaluating sleep_state [%s], bad Sleep object %p type %s",
+ sleep_state_name, info.return_object,
+ acpi_ut_get_object_type_name(info.
+ return_object)));
}
acpi_ut_remove_reference(info.return_object);
@@ -229,12 +236,11 @@ EXPORT_SYMBOL(acpi_get_sleep_type_data);
struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
{
- ACPI_FUNCTION_NAME("hw_get_bit_register_info");
+ ACPI_FUNCTION_ENTRY();
if (register_id > ACPI_BITREG_MAX) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid bit_register ID: %X\n",
- register_id));
+ ACPI_ERROR((AE_INFO, "Invalid bit_register ID: %X",
+ register_id));
return (NULL);
}
@@ -334,8 +340,8 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
bit_reg_info = acpi_hw_get_bit_register_info(register_id);
if (!bit_reg_info) {
- ACPI_REPORT_ERROR(("Bad ACPI HW register_id: %X\n",
- register_id));
+ ACPI_ERROR((AE_INFO, "Bad ACPI HW register_id: %X",
+ register_id));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -569,8 +575,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
- register_id));
+ ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
status = AE_BAD_PARAMETER;
break;
}
@@ -765,9 +770,9 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unsupported address space: %X\n",
- reg->address_space_id));
+ ACPI_ERROR((AE_INFO,
+ "Unsupported address space: %X",
+ reg->address_space_id));
return (AE_BAD_PARAMETER);
}
@@ -836,9 +841,9 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unsupported address space: %X\n",
- reg->address_space_id));
+ ACPI_ERROR((AE_INFO,
+ "Unsupported address space: %X",
+ reg->address_space_id));
return (AE_BAD_PARAMETER);
}
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 34519069050..89269272fd6 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -199,8 +199,8 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While executing method _SST"));
}
return_ACPI_STATUS(AE_OK);
@@ -232,9 +232,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
(acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
- ACPI_REPORT_ERROR(("Sleep values out of range: A=%X B=%X\n",
- acpi_gbl_sleep_type_a,
- acpi_gbl_sleep_type_b));
+ ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X",
+ acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
@@ -533,21 +532,18 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
arg.integer.value = ACPI_SST_WAKING;
status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
}
arg.integer.value = sleep_state;
status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR(("Method _BFS failed, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
}
status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR(("Method _WAK failed, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK"));
}
/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
@@ -582,8 +578,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
arg.integer.value = ACPI_SST_WORKING;
status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
}
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
index aff6dc14178..fc10b7cb456 100644
--- a/drivers/acpi/hardware/hwtimer.c
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
index e928e8c2c6e..468244147ec 100644
--- a/drivers/acpi/motherboard.c
+++ b/drivers/acpi/motherboard.c
@@ -54,36 +54,36 @@ static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
ACPI_FUNCTION_TRACE("acpi_reserve_io_ranges");
- if (res->id == ACPI_RSTYPE_IO) {
+ if (res->type == ACPI_RESOURCE_TYPE_IO) {
struct acpi_resource_io *io_res = &res->data.io;
- if (io_res->min_base_address != io_res->max_base_address)
+ if (io_res->minimum != io_res->maximum)
return_VALUE(AE_OK);
if (IS_RESERVED_ADDR
- (io_res->min_base_address, io_res->range_length)) {
+ (io_res->minimum, io_res->address_length)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Motherboard resources 0x%08x - 0x%08x\n",
- io_res->min_base_address,
- io_res->min_base_address +
- io_res->range_length));
+ io_res->minimum,
+ io_res->minimum +
+ io_res->address_length));
requested_res =
- request_region(io_res->min_base_address,
- io_res->range_length, "motherboard");
+ request_region(io_res->minimum,
+ io_res->address_length, "motherboard");
}
- } else if (res->id == ACPI_RSTYPE_FIXED_IO) {
+ } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_IO) {
struct acpi_resource_fixed_io *fixed_io_res =
&res->data.fixed_io;
if (IS_RESERVED_ADDR
- (fixed_io_res->base_address, fixed_io_res->range_length)) {
+ (fixed_io_res->address, fixed_io_res->address_length)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Motherboard resources 0x%08x - 0x%08x\n",
- fixed_io_res->base_address,
- fixed_io_res->base_address +
- fixed_io_res->range_length));
+ fixed_io_res->address,
+ fixed_io_res->address +
+ fixed_io_res->address_length));
requested_res =
- request_region(fixed_io_res->base_address,
- fixed_io_res->range_length,
+ request_region(fixed_io_res->address,
+ fixed_io_res->address_length,
"motherboard");
}
} else {
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index edfbe34600f..1149bc18fb3 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -110,10 +110,9 @@ acpi_status acpi_ns_root_initialize(void)
ACPI_NS_NO_UPSEARCH, NULL, &new_node);
if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not create predefined name %s, %s\n",
- init_val->name,
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not create predefined name %s",
+ init_val->name));
}
/*
@@ -124,9 +123,9 @@ acpi_status acpi_ns_root_initialize(void)
if (init_val->val) {
status = acpi_os_predefined_override(init_val, &val);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not override predefined %s\n",
- init_val->name));
+ ACPI_ERROR((AE_INFO,
+ "Could not override predefined %s",
+ init_val->name));
}
if (!val) {
@@ -233,7 +232,9 @@ acpi_status acpi_ns_root_initialize(void)
default:
- ACPI_REPORT_ERROR(("Unsupported initial type value %X\n", init_val->type));
+ ACPI_ERROR((AE_INFO,
+ "Unsupported initial type value %X",
+ init_val->type));
acpi_ut_remove_reference(obj_desc);
obj_desc = NULL;
continue;
@@ -339,7 +340,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
prefix_node = scope_info->scope.node;
if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) !=
ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR(("ns_lookup: %p is not a namespace node [%s]\n", prefix_node, acpi_ut_get_descriptor_name(prefix_node)));
+ ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]",
+ prefix_node,
+ acpi_ut_get_descriptor_name(prefix_node)));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
@@ -429,7 +432,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
if (!this_node) {
/* Current scope has no parent scope */
- ACPI_REPORT_ERROR(("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
+ ACPI_ERROR((AE_INFO,
+ "ACPI path has too many parent prefixes (^) - reached beyond root node"));
return_ACPI_STATUS(AE_NOT_FOUND);
}
}
@@ -498,7 +502,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
path++;
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
- "Multi Pathname (%d Segments, Flags=%X) \n",
+ "Multi Pathname (%d Segments, Flags=%X)\n",
num_segments, flags));
break;
@@ -600,7 +604,12 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
(this_node->type != type_to_check_for)) {
/* Complain about a type mismatch */
- ACPI_REPORT_WARNING(("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n", (char *)&simple_name, acpi_ut_get_type_name(this_node->type), acpi_ut_get_type_name(type_to_check_for)));
+ ACPI_WARNING((AE_INFO,
+ "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)",
+ ACPI_CAST_PTR(char, &simple_name),
+ acpi_ut_get_type_name(this_node->type),
+ acpi_ut_get_type_name
+ (type_to_check_for)));
}
/*
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index cc7a85f8cfe..9b871f38b61 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -272,9 +272,8 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
/* Grandchildren should have all been deleted already */
if (child_node->child) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Found a grandchild! P=%p C=%p\n",
- parent_node, child_node));
+ ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p",
+ parent_node, child_node));
}
/* Now we can free this child object */
@@ -302,7 +301,9 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
/* There should be only one reference remaining on this node */
if (child_node->reference_count != 1) {
- ACPI_REPORT_WARNING(("Existing references (%d) on node being deleted (%p)\n", child_node->reference_count, child_node));
+ ACPI_WARNING((AE_INFO,
+ "Existing references (%d) on node being deleted (%p)",
+ child_node->reference_count, child_node));
}
/* Now we can delete the node */
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index 9faf1d5c86e..a2807317a84 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/namespace/nsdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -198,12 +198,13 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
/* Check the node type and name */
if (type > ACPI_TYPE_LOCAL_MAX) {
- ACPI_REPORT_WARNING(("Invalid ACPI Type %08X\n", type));
+ ACPI_WARNING((AE_INFO, "Invalid ACPI Object Type %08X",
+ type));
}
if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
- ACPI_REPORT_WARNING(("Invalid ACPI Name %08X\n",
- this_node->name.integer));
+ ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
+ this_node->name.integer));
}
acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
@@ -212,7 +213,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
/*
* Now we can print out the pertinent information
*/
- acpi_os_printf(" %-12s %p ", acpi_ut_get_type_name(type), this_node);
+ acpi_os_printf(" %-12s %p %2.2X ",
+ acpi_ut_get_type_name(type), this_node,
+ this_node->owner_id);
dbg_level = acpi_dbg_level;
acpi_dbg_level = 0;
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
index 55de883943d..aff899a935e 100644
--- a/drivers/acpi/namespace/nsdumpdv.c
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 0191c7d9282..19d7b94d40c 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -373,8 +373,7 @@ acpi_ns_execute_control_method(struct acpi_parameter_info *info)
info->obj_desc = acpi_ns_get_attached_object(info->node);
if (!info->obj_desc) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No attached method object\n"));
+ ACPI_ERROR((AE_INFO, "No attached method object"));
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(AE_NULL_OBJECT);
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 0a08d2f04a0..9f929e479fd 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -93,8 +93,7 @@ acpi_status acpi_ns_initialize_objects(void)
ACPI_UINT32_MAX, acpi_ns_init_one_object,
&info, NULL);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
@@ -159,12 +158,11 @@ acpi_status acpi_ns_initialize_devices(void)
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
- "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
+ "\n%hd Devices found - executed %hd _STA, %hd _INI methods\n",
info.device_count, info.num_STA, info.num_INI));
return_ACPI_STATUS(status);
@@ -289,12 +287,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
}
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR, "\n"));
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not execute arguments for [%4.4s] (%s), %s\n",
- acpi_ut_get_node_name(node),
- acpi_ut_get_type_name(type),
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not execute arguments for [%4.4s] (%s)",
+ acpi_ut_get_node_name(node),
+ acpi_ut_get_type_name(type)));
}
/*
@@ -336,23 +332,22 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
struct acpi_parameter_info pinfo;
u32 flags;
acpi_status status;
+ struct acpi_namespace_node *ini_node;
+ struct acpi_namespace_node *device_node;
ACPI_FUNCTION_TRACE("ns_init_one_device");
- pinfo.parameters = NULL;
- pinfo.parameter_type = ACPI_PARAM_ARGS;
-
- pinfo.node = acpi_ns_map_handle_to_node(obj_handle);
- if (!pinfo.node) {
+ device_node = acpi_ns_map_handle_to_node(obj_handle);
+ if (!device_node) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* We will run _STA/_INI on Devices, Processors and thermal_zones only
*/
- if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
- (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
- (pinfo.node->type != ACPI_TYPE_THERMAL)) {
+ if ((device_node->type != ACPI_TYPE_DEVICE) &&
+ (device_node->type != ACPI_TYPE_PROCESSOR) &&
+ (device_node->type != ACPI_TYPE_THERMAL)) {
return_ACPI_STATUS(AE_OK);
}
@@ -364,57 +359,69 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
info->device_count++;
/*
- * Run _STA to determine if we can run _INI on the device.
+ * Check if the _INI method exists for this device -
+ * if _INI does not exist, there is no need to run _STA
+ * No _INI means device requires no initialization
+ */
+ status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI),
+ device_node, ACPI_TYPE_METHOD, &ini_node);
+ if (ACPI_FAILURE(status)) {
+ /* No _INI method found - move on to next device */
+
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ /*
+ * Run _STA to determine if we can run _INI on the device -
+ * the device must be present before _INI can be run.
+ * However, _STA is not required - assume device present if no _STA
*/
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
- pinfo.node,
+ device_node,
METHOD_NAME__STA));
- status = acpi_ut_execute_STA(pinfo.node, &flags);
+ pinfo.node = device_node;
+ pinfo.parameters = NULL;
+ pinfo.parameter_type = ACPI_PARAM_ARGS;
+
+ status = acpi_ut_execute_STA(pinfo.node, &flags);
if (ACPI_FAILURE(status)) {
- if (pinfo.node->type == ACPI_TYPE_DEVICE) {
- /* Ignore error and move on to next device */
+ /* Ignore error and move on to next device */
- return_ACPI_STATUS(AE_OK);
- }
+ return_ACPI_STATUS(AE_OK);
+ }
- /* _STA is not required for Processor or thermal_zone objects */
- } else {
+ if (flags != ACPI_UINT32_MAX) {
info->num_STA++;
+ }
- if (!(flags & 0x01)) {
- /* Don't look at children of a not present device */
+ if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
+ /* Don't look at children of a not present device */
- return_ACPI_STATUS(AE_CTRL_DEPTH);
- }
+ return_ACPI_STATUS(AE_CTRL_DEPTH);
}
/*
- * The device is present. Run _INI.
+ * The device is present and _INI exists. Run the _INI method.
+ * (We already have the _INI node from above)
*/
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
pinfo.node,
METHOD_NAME__INI));
- status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo);
- if (ACPI_FAILURE(status)) {
- /* No _INI (AE_NOT_FOUND) means device requires no initialization */
- if (status != AE_NOT_FOUND) {
- /* Ignore error and move on to next device */
+ pinfo.node = ini_node;
+ status = acpi_ns_evaluate_by_handle(&pinfo);
+ if (ACPI_FAILURE(status)) {
+ /* Ignore error and move on to next device */
#ifdef ACPI_DEBUG_OUTPUT
- char *scope_name =
- acpi_ns_get_external_pathname(pinfo.node);
+ char *scope_name = acpi_ns_get_external_pathname(ini_node);
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "%s._INI failed: %s\n",
- scope_name,
- acpi_format_exception(status)));
+ ACPI_WARNING((AE_INFO, "%s._INI failed: %s",
+ scope_name, acpi_format_exception(status)));
- ACPI_MEM_FREE(scope_name);
+ ACPI_MEM_FREE(scope_name);
#endif
- }
-
- status = AE_OK;
} else {
/* Delete any return object (especially if implicit_return is enabled) */
@@ -434,5 +441,5 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI);
}
- return_ACPI_STATUS(status);
+ return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index c28849de465..4e0b0524c18 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -92,7 +92,7 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc,
/* Check validity of the AML start and length */
if (!table_desc->aml_start) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null AML pointer\n"));
+ ACPI_ERROR((AE_INFO, "Null AML pointer"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -102,8 +102,8 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc,
/* Ignore table if there is no AML contained within */
if (!table_desc->aml_length) {
- ACPI_REPORT_WARNING(("Zero-length AML block in table [%4.4s]\n",
- table_desc->pointer->signature));
+ ACPI_WARNING((AE_INFO, "Zero-length AML block in table [%4.4s]",
+ table_desc->pointer->signature));
return_ACPI_STATUS(AE_OK);
}
@@ -263,7 +263,7 @@ acpi_status acpi_ns_load_namespace(void)
/* There must be at least a DSDT installed */
if (acpi_gbl_DSDT == NULL) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "DSDT is not in memory\n"));
+ ACPI_ERROR((AE_INFO, "DSDT is not in memory"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index d5e8dea61c2..639f653b4b6 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -75,7 +75,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
acpi_size index;
struct acpi_namespace_node *parent_node;
- ACPI_FUNCTION_NAME("ns_build_external_path");
+ ACPI_FUNCTION_ENTRY();
/* Special case for root */
@@ -110,9 +110,9 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
name_buffer[index] = AML_ROOT_PREFIX;
if (index != 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not construct pathname; index=%X, size=%X, Path=%s\n",
- (u32) index, (u32) size, &name_buffer[size]));
+ ACPI_ERROR((AE_INFO,
+ "Could not construct pathname; index=%X, size=%X, Path=%s",
+ (u32) index, (u32) size, &name_buffer[size]));
}
return;
@@ -148,7 +148,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
name_buffer = ACPI_MEM_CALLOCATE(size);
if (!name_buffer) {
- ACPI_REPORT_ERROR(("ns_get_table_pathname: allocation failure\n"));
+ ACPI_ERROR((AE_INFO, "Allocation failure"));
return_PTR(NULL);
}
@@ -241,7 +241,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
acpi_ns_build_external_path(node, required_size, buffer->pointer);
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X] \n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",
(char *)buffer->pointer, (u32) required_size));
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
index fc9be946ebe..10ae6292bca 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/namespace/nsobject.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -84,22 +84,23 @@ acpi_ns_attach_object(struct acpi_namespace_node *node,
if (!node) {
/* Invalid handle */
- ACPI_REPORT_ERROR(("ns_attach_object: Null named_obj handle\n"));
+ ACPI_ERROR((AE_INFO, "Null named_obj handle"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (!object && (ACPI_TYPE_ANY != type)) {
/* Null object */
- ACPI_REPORT_ERROR(("ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
+ ACPI_ERROR((AE_INFO,
+ "Null object, but type not ACPI_TYPE_ANY"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
/* Not a name handle */
- ACPI_REPORT_ERROR(("ns_attach_object: Invalid handle %p [%s]\n",
- node, acpi_ut_get_descriptor_name(node)));
+ ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
+ node, acpi_ut_get_descriptor_name(node)));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -254,7 +255,7 @@ union acpi_operand_object *acpi_ns_get_attached_object(struct
ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node);
if (!node) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Null Node ptr\n"));
+ ACPI_WARNING((AE_INFO, "Null Node ptr"));
return_PTR(NULL);
}
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index 433442a9ec7..232be430365 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index 50a3ca5470e..d64b78952f2 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -99,8 +99,8 @@ acpi_ns_search_node(u32 target_name,
if (scope_name) {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Searching %s (%p) For [%4.4s] (%s)\n",
- scope_name, node,
- (char *)&target_name,
+ scope_name, node, ACPI_CAST_PTR(char,
+ &target_name),
acpi_ut_get_type_name(type)));
ACPI_MEM_FREE(scope_name);
@@ -131,7 +131,7 @@ acpi_ns_search_node(u32 target_name,
*/
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
- (char *)&target_name,
+ ACPI_CAST_PTR(char, &target_name),
acpi_ut_get_type_name(next_node->
type),
next_node,
@@ -160,7 +160,8 @@ acpi_ns_search_node(u32 target_name,
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
- (char *)&target_name, acpi_ut_get_type_name(type),
+ ACPI_CAST_PTR(char, &target_name),
+ acpi_ut_get_type_name(type),
acpi_ut_get_node_name(node), node, node->child));
return_ACPI_STATUS(AE_NOT_FOUND);
@@ -210,14 +211,14 @@ acpi_ns_search_parent_tree(u32 target_name,
*/
if (!parent_node) {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[%4.4s] has no parent\n",
- (char *)&target_name));
+ ACPI_CAST_PTR(char, &target_name)));
return_ACPI_STATUS(AE_NOT_FOUND);
}
if (acpi_ns_local(type)) {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"[%4.4s] type [%s] must be local to this scope (no parent search)\n",
- (char *)&target_name,
+ ACPI_CAST_PTR(char, &target_name),
acpi_ut_get_type_name(type)));
return_ACPI_STATUS(AE_NOT_FOUND);
}
@@ -227,7 +228,7 @@ acpi_ns_search_parent_tree(u32 target_name,
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Searching parent [%4.4s] for [%4.4s]\n",
acpi_ut_get_node_name(parent_node),
- (char *)&target_name));
+ ACPI_CAST_PTR(char, &target_name)));
/*
* Search parents until target is found or we have backed up to the root
@@ -297,18 +298,17 @@ acpi_ns_search_and_enter(u32 target_name,
/* Parameter validation */
if (!node || !target_name || !return_node) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Null param: Node %p Name %X return_node %p\n",
- node, target_name, return_node));
-
- ACPI_REPORT_ERROR(("ns_search_and_enter: Null parameter\n"));
+ ACPI_ERROR((AE_INFO,
+ "Null param: Node %p Name %X return_node %p",
+ node, target_name, return_node));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Name must consist of printable characters */
if (!acpi_ut_valid_acpi_name(target_name)) {
- ACPI_REPORT_ERROR(("ns_search_and_enter: Bad character in ACPI Name: %X\n", target_name));
+ ACPI_ERROR((AE_INFO, "Bad character in ACPI Name: %X",
+ target_name));
return_ACPI_STATUS(AE_BAD_CHARACTER);
}
@@ -360,7 +360,7 @@ acpi_ns_search_and_enter(u32 target_name,
if (interpreter_mode == ACPI_IMODE_EXECUTE) {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"%4.4s Not found in %p [Not adding]\n",
- (char *)&target_name, node));
+ ACPI_CAST_PTR(char, &target_name), node));
return_ACPI_STATUS(AE_NOT_FOUND);
}
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index ebec036423c..3e7cad549a3 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/namespace/nsutils.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,6 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
- * component_id - Caller's component ID (for error output)
* internal_name - Name or path of the namespace node
* lookup_status - Exception code from NS lookup
*
@@ -76,19 +75,17 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
void
acpi_ns_report_error(char *module_name,
u32 line_number,
- u32 component_id,
char *internal_name, acpi_status lookup_status)
{
acpi_status status;
char *name = NULL;
- acpi_os_printf("%8s-%04d: *** Error: Looking up ",
- module_name, line_number);
+ acpi_ut_report_error(module_name, line_number);
if (lookup_status == AE_BAD_CHARACTER) {
/* There is a non-ascii character in the name */
- acpi_os_printf("[0x%4.4X] (NON-ASCII)\n",
+ acpi_os_printf("[0x%4.4X] (NON-ASCII)",
*(ACPI_CAST_PTR(u32, internal_name)));
} else {
/* Convert path to external format */
@@ -109,7 +106,7 @@ acpi_ns_report_error(char *module_name,
}
}
- acpi_os_printf(" in namespace, %s\n",
+ acpi_os_printf(" Namespace lookup failure, %s\n",
acpi_format_exception(lookup_status));
}
@@ -119,10 +116,9 @@ acpi_ns_report_error(char *module_name,
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
- * component_id - Caller's component ID (for error output)
* Message - Error message to use on failure
* prefix_node - Prefix relative to the path
- * Path - Path to the node
+ * Path - Path to the node (optional)
* method_status - Execution status
*
* RETURN: None
@@ -134,7 +130,6 @@ acpi_ns_report_error(char *module_name,
void
acpi_ns_report_method_error(char *module_name,
u32 line_number,
- u32 component_id,
char *message,
struct acpi_namespace_node *prefix_node,
char *path, acpi_status method_status)
@@ -142,17 +137,16 @@ acpi_ns_report_method_error(char *module_name,
acpi_status status;
struct acpi_namespace_node *node = prefix_node;
+ acpi_ut_report_error(module_name, line_number);
+
if (path) {
status = acpi_ns_get_node_by_path(path, prefix_node,
ACPI_NS_NO_UPSEARCH, &node);
if (ACPI_FAILURE(status)) {
- acpi_os_printf
- ("report_method_error: Could not get node\n");
- return;
+ acpi_os_printf("[Could not get node by pathname]");
}
}
- acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
acpi_ns_print_node_pathname(node, message);
acpi_os_printf(", %s\n", acpi_format_exception(method_status));
}
@@ -248,11 +242,11 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
ACPI_FUNCTION_TRACE("ns_get_type");
if (!node) {
- ACPI_REPORT_WARNING(("ns_get_type: Null Node input pointer\n"));
- return_VALUE(ACPI_TYPE_ANY);
+ ACPI_WARNING((AE_INFO, "Null Node parameter"));
+ return_UINT32(ACPI_TYPE_ANY);
}
- return_VALUE((acpi_object_type) node->type);
+ return_UINT32((acpi_object_type) node->type);
}
/*******************************************************************************
@@ -275,11 +269,11 @@ u32 acpi_ns_local(acpi_object_type type)
if (!acpi_ut_valid_object_type(type)) {
/* Type code out of range */
- ACPI_REPORT_WARNING(("ns_local: Invalid Object Type\n"));
- return_VALUE(ACPI_NS_NORMAL);
+ ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
+ return_UINT32(ACPI_NS_NORMAL);
}
- return_VALUE((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
+ return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
}
/*******************************************************************************
@@ -627,7 +621,7 @@ acpi_ns_externalize_name(u32 internal_name_length,
* with internal_name (invalid format).
*/
if (required_length > internal_name_length) {
- ACPI_REPORT_ERROR(("ns_externalize_name: Invalid internal name\n"));
+ ACPI_ERROR((AE_INFO, "Invalid internal name"));
return_ACPI_STATUS(AE_BAD_PATHNAME);
}
@@ -803,12 +797,11 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
if (!acpi_ut_valid_object_type(type)) {
/* type code out of range */
- ACPI_REPORT_WARNING(("ns_opens_scope: Invalid Object Type %X\n",
- type));
- return_VALUE(ACPI_NS_NORMAL);
+ ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
+ return_UINT32(ACPI_NS_NORMAL);
}
- return_VALUE(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
+ return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
}
/*******************************************************************************
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
index 5f164c0df33..fcab1e784b8 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/namespace/nswalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index c07b046659f..a95f636dc35 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -112,8 +112,7 @@ acpi_evaluate_object_typed(acpi_handle handle,
if (return_buffer->length == 0) {
/* Error because caller specifically asked for a return value */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No return value\n"));
-
+ ACPI_ERROR((AE_INFO, "No return value"));
return_ACPI_STATUS(AE_NULL_OBJECT);
}
@@ -125,11 +124,11 @@ acpi_evaluate_object_typed(acpi_handle handle,
/* Return object type does not match requested type */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Incorrect return type [%s] requested [%s]\n",
- acpi_ut_get_type_name(((union acpi_object *)
- return_buffer->pointer)->type),
- acpi_ut_get_type_name(return_type)));
+ ACPI_ERROR((AE_INFO,
+ "Incorrect return type [%s] requested [%s]",
+ acpi_ut_get_type_name(((union acpi_object *)return_buffer->
+ pointer)->type),
+ acpi_ut_get_type_name(return_type)));
if (must_free) {
/* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
@@ -236,11 +235,11 @@ acpi_evaluate_object(acpi_handle handle,
* qualified names above, this is an error
*/
if (!pathname) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Both Handle and Pathname are NULL\n"));
+ ACPI_ERROR((AE_INFO,
+ "Both Handle and Pathname are NULL"));
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Handle is NULL and Pathname is relative\n"));
+ ACPI_ERROR((AE_INFO,
+ "Handle is NULL and Pathname is relative"));
}
status = AE_BAD_PARAMETER;
@@ -399,7 +398,7 @@ acpi_walk_namespace(acpi_object_type type,
/* Parameter validation */
- if ((type > ACPI_TYPE_EXTERNAL_MAX) || (!max_depth) || (!user_function)) {
+ if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -473,8 +472,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
return (AE_CTRL_DEPTH);
}
- if (!(flags & 0x01)) {
- /* Don't return at the device or children of the device if not there */
+ if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
+ /* Don't examine children of the device if not present */
return (AE_CTRL_DEPTH);
}
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index 6b5f8d4481d..8cd8675a47c 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -300,8 +300,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
status = acpi_ut_execute_CID(node, &cid_list);
if (ACPI_SUCCESS(status)) {
- size += ((acpi_size) cid_list->count - 1) *
- sizeof(struct acpi_compatible_id);
+ size += cid_list->size;
info->valid |= ACPI_VALID_CID;
}
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index 0856d42e690..a0332595677 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 20c9a37643c..ac5bbaedac1 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -838,7 +838,7 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
static const int quantum_ms = 1000 / HZ;
ret = down_trylock(sem);
- for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
+ for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
schedule_timeout_interruptible(1);
ret = down_trylock(sem);
}
@@ -1060,13 +1060,11 @@ EXPORT_SYMBOL(max_cstate);
* Acquire a spinlock.
*
* handle is a pointer to the spinlock_t.
- * flags is *not* the result of save_flags - it is an ACPI-specific flag variable
- * that indicates whether we are at interrupt level.
*/
-unsigned long acpi_os_acquire_lock(acpi_handle handle)
+acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle)
{
- unsigned long flags;
+ acpi_cpu_flags flags;
spin_lock_irqsave((spinlock_t *) handle, flags);
return flags;
}
@@ -1075,7 +1073,7 @@ unsigned long acpi_os_acquire_lock(acpi_handle handle)
* Release a spinlock. See above.
*/
-void acpi_os_release_lock(acpi_handle handle, unsigned long flags)
+void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags)
{
spin_unlock_irqrestore((spinlock_t *) handle, flags);
}
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index 5858188f94a..de573be5271 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
+#include <acpi/acdispat.h>
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psargs")
@@ -62,61 +63,51 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
*
* PARAMETERS: parser_state - Current parser state object
*
- * RETURN: Decoded package length. On completion, the AML pointer points
+ * RETURN: Decoded package length. On completion, the AML pointer points
* past the length byte or bytes.
*
- * DESCRIPTION: Decode and return a package length field
+ * DESCRIPTION: Decode and return a package length field.
+ * Note: Largest package length is 28 bits, from ACPI specification
*
******************************************************************************/
static u32
acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
{
- u32 encoded_length;
- u32 length = 0;
+ u8 *aml = parser_state->aml;
+ u32 package_length = 0;
+ acpi_native_uint byte_count;
+ u8 byte_zero_mask = 0x3F; /* Default [0:5] */
ACPI_FUNCTION_TRACE("ps_get_next_package_length");
- encoded_length = (u32) ACPI_GET8(parser_state->aml);
- parser_state->aml++;
-
- switch (encoded_length >> 6) { /* bits 6-7 contain encoding scheme */
- case 0: /* 1-byte encoding (bits 0-5) */
-
- length = (encoded_length & 0x3F);
- break;
-
- case 1: /* 2-byte encoding (next byte + bits 0-3) */
-
- length = ((ACPI_GET8(parser_state->aml) << 04) |
- (encoded_length & 0x0F));
- parser_state->aml++;
- break;
-
- case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
-
- length = ((ACPI_GET8(parser_state->aml + 1) << 12) |
- (ACPI_GET8(parser_state->aml) << 04) |
- (encoded_length & 0x0F));
- parser_state->aml += 2;
- break;
+ /*
+ * Byte 0 bits [6:7] contain the number of additional bytes
+ * used to encode the package length, either 0,1,2, or 3
+ */
+ byte_count = (aml[0] >> 6);
+ parser_state->aml += (byte_count + 1);
- case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
+ /* Get bytes 3, 2, 1 as needed */
- length = ((ACPI_GET8(parser_state->aml + 2) << 20) |
- (ACPI_GET8(parser_state->aml + 1) << 12) |
- (ACPI_GET8(parser_state->aml) << 04) |
- (encoded_length & 0x0F));
- parser_state->aml += 3;
- break;
-
- default:
+ while (byte_count) {
+ /*
+ * Final bit positions for the package length bytes:
+ * Byte3->[20:27]
+ * Byte2->[12:19]
+ * Byte1->[04:11]
+ * Byte0->[00:03]
+ */
+ package_length |= (aml[byte_count] << ((byte_count << 3) - 4));
- /* Can't get here, only 2 bits / 4 cases */
- break;
+ byte_zero_mask = 0x0F; /* Use bits [0:3] of byte 0 */
+ byte_count--;
}
- return_VALUE(length);
+ /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
+
+ package_length |= (aml[0] & byte_zero_mask);
+ return_UINT32(package_length);
}
/*******************************************************************************
@@ -135,16 +126,15 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
{
u8 *start = parser_state->aml;
- acpi_native_uint length;
+ u32 package_length;
ACPI_FUNCTION_TRACE("ps_get_next_package_end");
- /* Function below changes parser_state->Aml */
+ /* Function below updates parser_state->Aml */
- length =
- (acpi_native_uint) acpi_ps_get_next_package_length(parser_state);
+ package_length = acpi_ps_get_next_package_length(parser_state);
- return_PTR(start + length); /* end of package */
+ return_PTR(start + package_length); /* end of package */
}
/*******************************************************************************
@@ -169,17 +159,15 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
ACPI_FUNCTION_TRACE("ps_get_next_namestring");
- /* Handle multiple prefix characters */
-
- while (acpi_ps_is_prefix_char(ACPI_GET8(end))) {
- /* Include prefix '\\' or '^' */
+ /* Point past any namestring prefix characters (backslash or carat) */
+ while (acpi_ps_is_prefix_char(*end)) {
end++;
}
- /* Decode the path */
+ /* Decode the path prefix character */
- switch (ACPI_GET8(end)) {
+ switch (*end) {
case 0:
/* null_name */
@@ -199,9 +187,9 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
case AML_MULTI_NAME_PREFIX_OP:
- /* Multiple name segments, 4 chars each */
+ /* Multiple name segments, 4 chars each, count in next byte */
- end += 2 + ((acpi_size) ACPI_GET8(end + 1) * ACPI_NAME_SIZE);
+ end += 2 + (*(end + 1) * ACPI_NAME_SIZE);
break;
default:
@@ -212,7 +200,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
break;
}
- parser_state->aml = (u8 *) end;
+ parser_state->aml = end;
return_PTR((char *)start);
}
@@ -224,7 +212,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
* Arg - Where the namepath will be stored
* arg_count - If the namepath points to a control method
* the method's argument is returned here.
- * method_call - Whether the namepath can possibly be the
+ * possible_method_call - Whether the namepath can possibly be the
* start of a method call
*
* RETURN: Status
@@ -240,11 +228,11 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
acpi_status
acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
struct acpi_parse_state *parser_state,
- union acpi_parse_object *arg, u8 method_call)
+ union acpi_parse_object *arg, u8 possible_method_call)
{
char *path;
union acpi_parse_object *name_op;
- acpi_status status = AE_OK;
+ acpi_status status;
union acpi_operand_object *method_desc;
struct acpi_namespace_node *node;
union acpi_generic_state scope_info;
@@ -252,115 +240,129 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
ACPI_FUNCTION_TRACE("ps_get_next_namepath");
path = acpi_ps_get_next_namestring(parser_state);
+ acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
- /* Null path case is allowed */
+ /* Null path case is allowed, just exit */
- if (path) {
- /*
- * Lookup the name in the internal namespace
- */
- scope_info.scope.node = NULL;
- node = parser_state->start_node;
- if (node) {
- scope_info.scope.node = node;
- }
+ if (!path) {
+ arg->common.value.name = path;
+ return_ACPI_STATUS(AE_OK);
+ }
- /*
- * Lookup object. We don't want to add anything new to the namespace
- * here, however. So we use MODE_EXECUTE. Allow searching of the
- * parent tree, but don't open a new scope -- we just want to lookup the
- * object (MUST BE mode EXECUTE to perform upsearch)
- */
- status = acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY,
- ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT |
- ACPI_NS_DONT_OPEN_SCOPE, NULL, &node);
- if (ACPI_SUCCESS(status) && method_call) {
- if (node->type == ACPI_TYPE_METHOD) {
- /* This name is actually a control method invocation */
-
- method_desc = acpi_ns_get_attached_object(node);
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "Control Method - %p Desc %p Path=%p\n",
- node, method_desc, path));
-
- name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
- if (!name_op) {
- return_ACPI_STATUS(AE_NO_MEMORY);
- }
+ /* Setup search scope info */
- /* Change arg into a METHOD CALL and attach name to it */
+ scope_info.scope.node = NULL;
+ node = parser_state->start_node;
+ if (node) {
+ scope_info.scope.node = node;
+ }
- acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
- name_op->common.value.name = path;
+ /*
+ * Lookup the name in the internal namespace. We don't want to add
+ * anything new to the namespace here, however, so we use MODE_EXECUTE.
+ * Allow searching of the parent tree, but don't open a new scope -
+ * we just want to lookup the object (must be mode EXECUTE to perform
+ * the upsearch)
+ */
+ status =
+ acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
+ NULL, &node);
- /* Point METHODCALL/NAME to the METHOD Node */
+ /*
+ * If this name is a control method invocation, we must
+ * setup the method call
+ */
+ if (ACPI_SUCCESS(status) &&
+ possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
+ /* This name is actually a control method invocation */
- name_op->common.node = node;
- acpi_ps_append_arg(arg, name_op);
+ method_desc = acpi_ns_get_attached_object(node);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Control Method - %p Desc %p Path=%p\n", node,
+ method_desc, path));
- if (!method_desc) {
- ACPI_REPORT_ERROR(("ps_get_next_namepath: Control Method %p has no attached object\n", node));
- return_ACPI_STATUS(AE_AML_INTERNAL);
- }
+ name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
+ if (!name_op) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "Control Method - %p Args %X\n",
- node,
- method_desc->method.
- param_count));
+ /* Change Arg into a METHOD CALL and attach name to it */
- /* Get the number of arguments to expect */
+ acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
+ name_op->common.value.name = path;
- walk_state->arg_count =
- method_desc->method.param_count;
- return_ACPI_STATUS(AE_OK);
- }
+ /* Point METHODCALL/NAME to the METHOD Node */
- /*
- * Else this is normal named object reference.
- * Just init the NAMEPATH object with the pathname.
- * (See code below)
- */
- }
+ name_op->common.node = node;
+ acpi_ps_append_arg(arg, name_op);
- if (ACPI_FAILURE(status)) {
- /*
- * 1) Any error other than NOT_FOUND is always severe
- * 2) NOT_FOUND is only important if we are executing a method.
- * 3) If executing a cond_ref_of opcode, NOT_FOUND is ok.
- */
- if ((((walk_state->
- parse_flags & ACPI_PARSE_MODE_MASK) ==
- ACPI_PARSE_EXECUTE) && (status == AE_NOT_FOUND)
- && (walk_state->op->common.aml_opcode !=
- AML_COND_REF_OF_OP))
- || (status != AE_NOT_FOUND)) {
- ACPI_REPORT_NSERROR(path, status);
-
- acpi_os_printf
- ("search_node %p start_node %p return_node %p\n",
- scope_info.scope.node,
- parser_state->start_node, node);
-
- } else {
- /*
- * We got a NOT_FOUND during table load or we encountered
- * a cond_ref_of(x) where the target does not exist.
- * Either case is ok
- */
- status = AE_OK;
- }
+ if (!method_desc) {
+ ACPI_ERROR((AE_INFO,
+ "Control Method %p has no attached object",
+ node));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
+
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Control Method - %p Args %X\n",
+ node, method_desc->method.param_count));
+
+ /* Get the number of arguments to expect */
+
+ walk_state->arg_count = method_desc->method.param_count;
+ return_ACPI_STATUS(AE_OK);
}
/*
- * Regardless of success/failure above,
- * Just initialize the Op with the pathname.
+ * Special handling if the name was not found during the lookup -
+ * some not_found cases are allowed
*/
- acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
- arg->common.value.name = path;
+ if (status == AE_NOT_FOUND) {
+ /* 1) not_found is ok during load pass 1/2 (allow forward references) */
+
+ if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) !=
+ ACPI_PARSE_EXECUTE) {
+ status = AE_OK;
+ }
+
+ /* 2) not_found during a cond_ref_of(x) is ok by definition */
+
+ else if (walk_state->op->common.aml_opcode ==
+ AML_COND_REF_OF_OP) {
+ status = AE_OK;
+ }
+
+ /*
+ * 3) not_found while building a Package is ok at this point, we
+ * may flag as an error later if slack mode is not enabled.
+ * (Some ASL code depends on allowing this behavior)
+ */
+ else if ((arg->common.parent) &&
+ ((arg->common.parent->common.aml_opcode ==
+ AML_PACKAGE_OP)
+ || (arg->common.parent->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP))) {
+ status = AE_OK;
+ }
+ }
+
+ /* Final exception check (may have been changed from code above) */
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR_NAMESPACE(path, status);
+
+ if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
+ ACPI_PARSE_EXECUTE) {
+ /* Report a control method execution error */
+
+ status = acpi_ds_method_error(status, walk_state);
+ }
+ }
+
+ /* Save the namepath */
+
+ arg->common.value.name = path;
return_ACPI_STATUS(status);
}
@@ -382,59 +384,63 @@ void
acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
u32 arg_type, union acpi_parse_object *arg)
{
+ u32 length;
+ u16 opcode;
+ u8 *aml = parser_state->aml;
ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type);
switch (arg_type) {
case ARGP_BYTEDATA:
- acpi_ps_init_op(arg, AML_BYTE_OP);
- arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml);
- parser_state->aml++;
+ /* Get 1 byte from the AML stream */
+
+ opcode = AML_BYTE_OP;
+ arg->common.value.integer = (acpi_integer) * aml;
+ length = 1;
break;
case ARGP_WORDDATA:
- acpi_ps_init_op(arg, AML_WORD_OP);
-
/* Get 2 bytes from the AML stream */
- ACPI_MOVE_16_TO_32(&arg->common.value.integer,
- parser_state->aml);
- parser_state->aml += 2;
+ opcode = AML_WORD_OP;
+ ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml);
+ length = 2;
break;
case ARGP_DWORDDATA:
- acpi_ps_init_op(arg, AML_DWORD_OP);
-
/* Get 4 bytes from the AML stream */
- ACPI_MOVE_32_TO_32(&arg->common.value.integer,
- parser_state->aml);
- parser_state->aml += 4;
+ opcode = AML_DWORD_OP;
+ ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml);
+ length = 4;
break;
case ARGP_QWORDDATA:
- acpi_ps_init_op(arg, AML_QWORD_OP);
-
/* Get 8 bytes from the AML stream */
- ACPI_MOVE_64_TO_64(&arg->common.value.integer,
- parser_state->aml);
- parser_state->aml += 8;
+ opcode = AML_QWORD_OP;
+ ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml);
+ length = 8;
break;
case ARGP_CHARLIST:
- acpi_ps_init_op(arg, AML_STRING_OP);
- arg->common.value.string = (char *)parser_state->aml;
+ /* Get a pointer to the string, point past the string */
+
+ opcode = AML_STRING_OP;
+ arg->common.value.string = ACPI_CAST_PTR(char, aml);
- while (ACPI_GET8(parser_state->aml) != '\0') {
- parser_state->aml++;
+ /* Find the null terminator */
+
+ length = 0;
+ while (aml[length]) {
+ length++;
}
- parser_state->aml++;
+ length++;
break;
case ARGP_NAME:
@@ -443,14 +449,16 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
arg->common.value.name =
acpi_ps_get_next_namestring(parser_state);
- break;
+ return_VOID;
default:
- ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type));
- break;
+ ACPI_ERROR((AE_INFO, "Invalid arg_type %X", arg_type));
+ return_VOID;
}
+ acpi_ps_init_op(arg, opcode);
+ parser_state->aml += length;
return_VOID;
}
@@ -540,7 +548,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
* access_type is first operand, access_attribute is second
*/
field->common.value.integer =
- (ACPI_GET8(parser_state->aml) << 8);
+ (((u32) ACPI_GET8(parser_state->aml) << 8));
parser_state->aml++;
field->common.value.integer |= ACPI_GET8(parser_state->aml);
parser_state->aml++;
@@ -703,7 +711,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
default:
- ACPI_REPORT_ERROR(("Invalid arg_type: %X\n", arg_type));
+ ACPI_ERROR((AE_INFO, "Invalid arg_type: %X", arg_type));
status = AE_AML_OPERAND_TYPE;
break;
}
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
index 088d33999d9..00b072e15d1 100644
--- a/drivers/acpi/parser/psloop.c
+++ b/drivers/acpi/parser/psloop.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -123,16 +123,12 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
&& ((status & AE_CODE_MASK) !=
AE_CODE_CONTROL)) {
if (status == AE_AML_NO_RETURN_VALUE) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invoked method did not return a value, %s\n",
- acpi_format_exception
- (status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Invoked method did not return a value"));
}
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "get_predicate Failed, %s\n",
- acpi_format_exception
- (status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "get_predicate Failed"));
return_ACPI_STATUS(status);
}
@@ -190,11 +186,11 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
/* The opcode is unrecognized. Just skip unknown opcodes */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
- walk_state->opcode,
- parser_state->aml,
- walk_state->aml_offset));
+ ACPI_ERROR((AE_INFO,
+ "Found unknown opcode %X at AML address %p offset %X, ignoring",
+ walk_state->opcode,
+ parser_state->aml,
+ walk_state->aml_offset));
ACPI_DUMP_BUFFER(parser_state->aml, 128);
@@ -281,10 +277,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
walk_state->descending_callback(walk_state,
&op);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "During name lookup/catalog, %s\n",
- acpi_format_exception
- (status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During name lookup/catalog"));
goto close_this_op;
}
@@ -704,6 +698,15 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
acpi_ps_pop_scope(parser_state, &op,
&walk_state->arg_types,
&walk_state->arg_count);
+
+ if (op->common.aml_opcode != AML_WHILE_OP) {
+ status2 =
+ acpi_ds_result_stack_pop
+ (walk_state);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ }
}
/* Close this iteration of the While loop */
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 229ae86afe8..11d6351ab8b 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -747,7 +747,7 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode)
/* Unknown AML opcode */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Unknown AML opcode [%4.4X]\n", opcode));
return (&acpi_gbl_aml_op_info[_UNK]);
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index 76d4d640d83..a9f3229f410 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -333,7 +333,6 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
switch (callback_status) {
case AE_CTRL_TERMINATE:
-
/*
* A control method was terminated via a RETURN statement.
* The walk of this method is complete.
@@ -346,13 +345,19 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
parser_state->aml = walk_state->aml_last_while;
walk_state->control_state->common.value = FALSE;
- status = AE_CTRL_BREAK;
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_SUCCESS(status)) {
+ status = AE_CTRL_BREAK;
+ }
break;
case AE_CTRL_CONTINUE:
parser_state->aml = walk_state->aml_last_while;
- status = AE_CTRL_CONTINUE;
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_SUCCESS(status)) {
+ status = AE_CTRL_CONTINUE;
+ }
break;
case AE_CTRL_PENDING:
@@ -369,16 +374,18 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
#endif
case AE_CTRL_TRUE:
-
/*
* Predicate of an IF was true, and we are at the matching ELSE.
* Just close out this package
*/
parser_state->aml = acpi_ps_get_next_package_end(parser_state);
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_SUCCESS(status)) {
+ status = AE_CTRL_PENDING;
+ }
break;
case AE_CTRL_FALSE:
-
/*
* Either an IF/WHILE Predicate was false or we encountered a BREAK
* opcode. In both cases, we do not execute the rest of the
@@ -503,22 +510,23 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
} else if (status == AE_CTRL_TERMINATE) {
status = AE_OK;
} else if ((status != AE_OK) && (walk_state->method_desc)) {
- ACPI_REPORT_METHOD_ERROR("Method execution failed",
- walk_state->method_node, NULL,
- status);
-
- /* Ensure proper cleanup */
+ /* Either the method parse or actual execution failed */
- walk_state->parse_flags |= ACPI_PARSE_EXECUTE;
+ ACPI_ERROR_METHOD("Method parse/execution failed",
+ walk_state->method_node, NULL,
+ status);
/* Check for possible multi-thread reentrancy problem */
if ((status == AE_ALREADY_EXISTS) &&
(!walk_state->method_desc->method.semaphore)) {
/*
- * This method is marked not_serialized, but it tried to create
+ * Method tried to create an object twice. The probable cause is
+ * that the method cannot handle reentrancy.
+ *
+ * The method is marked not_serialized, but it tried to create
* a named object, causing the second thread entrance to fail.
- * We will workaround this by marking the method permanently
+ * Workaround this problem by marking the method permanently
* as Serialized.
*/
walk_state->method_desc->method.method_flags |=
@@ -536,15 +544,23 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
acpi_ds_scope_stack_clear(walk_state);
/*
- * If we just returned from the execution of a control method,
- * there's lots of cleanup to do
+ * If we just returned from the execution of a control method or if we
+ * encountered an error during the method parse phase, there's lots of
+ * cleanup to do
*/
- if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
- ACPI_PARSE_EXECUTE) {
+ if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
+ ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) {
if (walk_state->method_desc) {
/* Decrement the thread count on the method parse tree */
- walk_state->method_desc->method.thread_count--;
+ if (walk_state->method_desc->method.
+ thread_count) {
+ walk_state->method_desc->method.
+ thread_count--;
+ } else {
+ ACPI_ERROR((AE_INFO,
+ "Invalid zero thread count in method"));
+ }
}
acpi_ds_terminate_control_method(walk_state);
@@ -553,7 +569,6 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
/* Delete this walk state and all linked control states */
acpi_ps_cleanup_scope(&walk_state->parser_state);
-
previous_walk_state = walk_state;
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
index 1c953b6f1af..bc6047caccd 100644
--- a/drivers/acpi/parser/psscope.c
+++ b/drivers/acpi/parser/psscope.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
index f0e755884ee..dd6f16726fc 100644
--- a/drivers/acpi/parser/pstree.c
+++ b/drivers/acpi/parser/pstree.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -132,7 +132,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
if (op_info->class == AML_CLASS_UNKNOWN) {
/* Invalid opcode */
- ACPI_REPORT_ERROR(("ps_append_arg: Invalid AML Opcode: 0x%2.2X\n", op->common.aml_opcode));
+ ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X",
+ op->common.aml_opcode));
return;
}
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index 2075efbb432..3e07cb9cb74 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index 08f2321b6de..06f05bfd761 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index 4dcbd443160..2dd48cbb7c0 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,10 @@
ACPI_MODULE_NAME("psxface")
/* Local Prototypes */
+static void acpi_ps_start_trace(struct acpi_parameter_info *info);
+
+static void acpi_ps_stop_trace(struct acpi_parameter_info *info);
+
static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info);
static void
@@ -57,6 +61,136 @@ acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action);
/*******************************************************************************
*
+ * FUNCTION: acpi_debug_trace
+ *
+ * PARAMETERS: method_name - Valid ACPI name string
+ * debug_level - Optional level mask. 0 to use default
+ * debug_layer - Optional layer mask. 0 to use default
+ * Flags - bit 1: one shot(1) or persistent(0)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: External interface to enable debug tracing during control
+ * method execution
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags)
+{
+ acpi_status status;
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* TBDs: Validate name, allow full path or just nameseg */
+
+ acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name);
+ acpi_gbl_trace_flags = flags;
+
+ if (debug_level) {
+ acpi_gbl_trace_dbg_level = debug_level;
+ }
+ if (debug_layer) {
+ acpi_gbl_trace_dbg_layer = debug_layer;
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_start_trace
+ *
+ * PARAMETERS: Info - Method info struct
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Start control method execution trace
+ *
+ ******************************************************************************/
+
+static void acpi_ps_start_trace(struct acpi_parameter_info *info)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return;
+ }
+
+ if ((!acpi_gbl_trace_method_name) ||
+ (acpi_gbl_trace_method_name != info->node->name.integer)) {
+ goto exit;
+ }
+
+ acpi_gbl_original_dbg_level = acpi_dbg_level;
+ acpi_gbl_original_dbg_layer = acpi_dbg_layer;
+
+ acpi_dbg_level = 0x00FFFFFF;
+ acpi_dbg_layer = ACPI_UINT32_MAX;
+
+ if (acpi_gbl_trace_dbg_level) {
+ acpi_dbg_level = acpi_gbl_trace_dbg_level;
+ }
+ if (acpi_gbl_trace_dbg_layer) {
+ acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
+ }
+
+ exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_stop_trace
+ *
+ * PARAMETERS: Info - Method info struct
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Stop control method execution trace
+ *
+ ******************************************************************************/
+
+static void acpi_ps_stop_trace(struct acpi_parameter_info *info)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return;
+ }
+
+ if ((!acpi_gbl_trace_method_name) ||
+ (acpi_gbl_trace_method_name != info->node->name.integer)) {
+ goto exit;
+ }
+
+ /* Disable further tracing if type is one-shot */
+
+ if (acpi_gbl_trace_flags & 1) {
+ acpi_gbl_trace_method_name = 0;
+ acpi_gbl_trace_dbg_level = 0;
+ acpi_gbl_trace_dbg_layer = 0;
+ }
+
+ acpi_dbg_level = acpi_gbl_original_dbg_level;
+ acpi_dbg_layer = acpi_gbl_original_dbg_layer;
+
+ exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ps_execute_method
*
* PARAMETERS: Info - Method info block, contains:
@@ -104,6 +238,10 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
*/
acpi_ps_update_parameter_list(info, REF_INCREMENT);
+ /* Begin tracing if requested */
+
+ acpi_ps_start_trace(info);
+
/*
* 1) Perform the first pass parse of the method to enter any
* named objects that it creates into the namespace
@@ -129,6 +267,10 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
status = acpi_ps_execute_pass(info);
cleanup:
+ /* End optional tracing */
+
+ acpi_ps_stop_trace(info);
+
/* Take away the extra reference that we gave the parameters above */
acpi_ps_update_parameter_list(info, REF_DECREMENT);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index e567c03b238..65aee79b397 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -258,7 +258,7 @@ typedef int (*irq_lookup_func) (struct acpi_prt_entry *, int *, int *, char **);
static int
acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
- int *edge_level, int *active_high_low, char **link)
+ int *triggering, int *polarity, char **link)
{
int irq;
@@ -266,8 +266,8 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
if (entry->link.handle) {
irq = acpi_pci_link_allocate_irq(entry->link.handle,
- entry->link.index, edge_level,
- active_high_low, link);
+ entry->link.index, triggering,
+ polarity, link);
if (irq < 0) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid IRQ link routing entry\n"));
@@ -275,8 +275,8 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
}
} else {
irq = entry->link.index;
- *edge_level = ACPI_LEVEL_SENSITIVE;
- *active_high_low = ACPI_ACTIVE_LOW;
+ *triggering = ACPI_LEVEL_SENSITIVE;
+ *polarity = ACPI_ACTIVE_LOW;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
@@ -285,7 +285,7 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
static int
acpi_pci_free_irq(struct acpi_prt_entry *entry,
- int *edge_level, int *active_high_low, char **link)
+ int *triggering, int *polarity, char **link)
{
int irq;
@@ -307,8 +307,8 @@ static int
acpi_pci_irq_lookup(struct pci_bus *bus,
int device,
int pin,
- int *edge_level,
- int *active_high_low, char **link, irq_lookup_func func)
+ int *triggering,
+ int *polarity, char **link, irq_lookup_func func)
{
struct acpi_prt_entry *entry = NULL;
int segment = pci_domain_nr(bus);
@@ -327,7 +327,7 @@ acpi_pci_irq_lookup(struct pci_bus *bus,
return_VALUE(-1);
}
- ret = func(entry, edge_level, active_high_low, link);
+ ret = func(entry, triggering, polarity, link);
return_VALUE(ret);
}
@@ -339,8 +339,8 @@ acpi_pci_irq_lookup(struct pci_bus *bus,
static int
acpi_pci_irq_derive(struct pci_dev *dev,
int pin,
- int *edge_level,
- int *active_high_low, char **link, irq_lookup_func func)
+ int *triggering,
+ int *polarity, char **link, irq_lookup_func func)
{
struct pci_dev *bridge = dev;
int irq = -1;
@@ -374,7 +374,7 @@ acpi_pci_irq_derive(struct pci_dev *dev,
}
irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
- pin, edge_level, active_high_low,
+ pin, triggering, polarity,
link, func);
}
@@ -401,8 +401,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
{
int irq = 0;
u8 pin = 0;
- int edge_level = ACPI_LEVEL_SENSITIVE;
- int active_high_low = ACPI_ACTIVE_LOW;
+ int triggering = ACPI_LEVEL_SENSITIVE;
+ int polarity = ACPI_ACTIVE_LOW;
char *link = NULL;
int rc;
@@ -431,7 +431,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
* values override any BIOS-assigned IRQs set during boot.
*/
irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low, &link,
+ &triggering, &polarity, &link,
acpi_pci_allocate_irq);
/*
@@ -439,8 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
* device's parent bridge.
*/
if (irq < 0)
- irq = acpi_pci_irq_derive(dev, pin, &edge_level,
- &active_high_low, &link,
+ irq = acpi_pci_irq_derive(dev, pin, &triggering,
+ &polarity, &link,
acpi_pci_allocate_irq);
/*
@@ -462,7 +462,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
}
}
- rc = acpi_register_gsi(irq, edge_level, active_high_low);
+ rc = acpi_register_gsi(irq, triggering, polarity);
if (rc < 0) {
printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed "
"to register GSI\n", pci_name(dev), ('A' + pin));
@@ -477,8 +477,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
printk("Link [%s] -> ", link);
printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
- (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
- (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
+ (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
return_VALUE(0);
}
@@ -494,8 +494,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
{
int gsi = 0;
u8 pin = 0;
- int edge_level = ACPI_LEVEL_SENSITIVE;
- int active_high_low = ACPI_ACTIVE_LOW;
+ int triggering = ACPI_LEVEL_SENSITIVE;
+ int polarity = ACPI_ACTIVE_LOW;
ACPI_FUNCTION_TRACE("acpi_pci_irq_disable");
@@ -511,7 +511,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
* First we check the PCI IRQ routing table (PRT) for an IRQ.
*/
gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low, NULL,
+ &triggering, &polarity, NULL,
acpi_pci_free_irq);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
@@ -519,7 +519,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
*/
if (gsi < 0)
gsi = acpi_pci_irq_derive(dev, pin,
- &edge_level, &active_high_low, NULL,
+ &triggering, &polarity, NULL,
acpi_pci_free_irq);
if (gsi < 0)
return_VOID;
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 78927c0f155..07bc6dfe662 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -70,8 +70,8 @@ static struct acpi_driver acpi_pci_link_driver = {
*/
struct acpi_pci_link_irq {
u8 active; /* Current IRQ */
- u8 edge_level; /* All IRQs */
- u8 active_high_low; /* All IRQs */
+ u8 triggering; /* All IRQs */
+ u8 polarity; /* All IRQs */
u8 resource_type;
u8 possible_count;
u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
@@ -108,19 +108,19 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
- switch (resource->id) {
- case ACPI_RSTYPE_START_DPF:
+ switch (resource->type) {
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
return_ACPI_STATUS(AE_OK);
- case ACPI_RSTYPE_IRQ:
+ case ACPI_RESOURCE_TYPE_IRQ:
{
struct acpi_resource_irq *p = &resource->data.irq;
- if (!p || !p->number_of_interrupts) {
+ if (!p || !p->interrupt_count) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Blank IRQ resource\n"));
return_ACPI_STATUS(AE_OK);
}
for (i = 0;
- (i < p->number_of_interrupts
+ (i < p->interrupt_count
&& i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
if (!p->interrupts[i]) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
@@ -131,22 +131,22 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
link->irq.possible[i] = p->interrupts[i];
link->irq.possible_count++;
}
- link->irq.edge_level = p->edge_level;
- link->irq.active_high_low = p->active_high_low;
- link->irq.resource_type = ACPI_RSTYPE_IRQ;
+ link->irq.triggering = p->triggering;
+ link->irq.polarity = p->polarity;
+ link->irq.resource_type = ACPI_RESOURCE_TYPE_IRQ;
break;
}
- case ACPI_RSTYPE_EXT_IRQ:
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
{
- struct acpi_resource_ext_irq *p =
+ struct acpi_resource_extended_irq *p =
&resource->data.extended_irq;
- if (!p || !p->number_of_interrupts) {
+ if (!p || !p->interrupt_count) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Blank EXT IRQ resource\n"));
return_ACPI_STATUS(AE_OK);
}
for (i = 0;
- (i < p->number_of_interrupts
+ (i < p->interrupt_count
&& i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
if (!p->interrupts[i]) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
@@ -157,9 +157,9 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
link->irq.possible[i] = p->interrupts[i];
link->irq.possible_count++;
}
- link->irq.edge_level = p->edge_level;
- link->irq.active_high_low = p->active_high_low;
- link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
+ link->irq.triggering = p->triggering;
+ link->irq.polarity = p->polarity;
+ link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
break;
}
default:
@@ -201,11 +201,11 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
ACPI_FUNCTION_TRACE("acpi_pci_link_check_current");
- switch (resource->id) {
- case ACPI_RSTYPE_IRQ:
+ switch (resource->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
{
struct acpi_resource_irq *p = &resource->data.irq;
- if (!p || !p->number_of_interrupts) {
+ if (!p || !p->interrupt_count) {
/*
* IRQ descriptors may have no IRQ# bits set,
* particularly those those w/ _STA disabled
@@ -217,11 +217,11 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
*irq = p->interrupts[0];
break;
}
- case ACPI_RSTYPE_EXT_IRQ:
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
{
- struct acpi_resource_ext_irq *p =
+ struct acpi_resource_extended_irq *p =
&resource->data.extended_irq;
- if (!p || !p->number_of_interrupts) {
+ if (!p || !p->interrupt_count) {
/*
* extended IRQ descriptors must
* return at least 1 IRQ
@@ -233,8 +233,10 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
*irq = p->interrupts[0];
break;
}
+ break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource isn't an IRQ\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource %d isn't an IRQ\n", resource->type));
+ case ACPI_RESOURCE_TYPE_END_TAG:
return_ACPI_STATUS(AE_OK);
}
return_ACPI_STATUS(AE_CTRL_TERMINATE);
@@ -325,36 +327,36 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
buffer.pointer = resource;
switch (link->irq.resource_type) {
- case ACPI_RSTYPE_IRQ:
- resource->res.id = ACPI_RSTYPE_IRQ;
+ case ACPI_RESOURCE_TYPE_IRQ:
+ resource->res.type = ACPI_RESOURCE_TYPE_IRQ;
resource->res.length = sizeof(struct acpi_resource);
- resource->res.data.irq.edge_level = link->irq.edge_level;
- resource->res.data.irq.active_high_low =
- link->irq.active_high_low;
- if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
- resource->res.data.irq.shared_exclusive =
+ resource->res.data.irq.triggering = link->irq.triggering;
+ resource->res.data.irq.polarity =
+ link->irq.polarity;
+ if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
+ resource->res.data.irq.sharable =
ACPI_EXCLUSIVE;
else
- resource->res.data.irq.shared_exclusive = ACPI_SHARED;
- resource->res.data.irq.number_of_interrupts = 1;
+ resource->res.data.irq.sharable = ACPI_SHARED;
+ resource->res.data.irq.interrupt_count = 1;
resource->res.data.irq.interrupts[0] = irq;
break;
- case ACPI_RSTYPE_EXT_IRQ:
- resource->res.id = ACPI_RSTYPE_EXT_IRQ;
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ resource->res.type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
resource->res.length = sizeof(struct acpi_resource);
resource->res.data.extended_irq.producer_consumer =
ACPI_CONSUMER;
- resource->res.data.extended_irq.edge_level =
- link->irq.edge_level;
- resource->res.data.extended_irq.active_high_low =
- link->irq.active_high_low;
- if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
- resource->res.data.irq.shared_exclusive =
+ resource->res.data.extended_irq.triggering =
+ link->irq.triggering;
+ resource->res.data.extended_irq.polarity =
+ link->irq.polarity;
+ if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
+ resource->res.data.irq.sharable =
ACPI_EXCLUSIVE;
else
- resource->res.data.irq.shared_exclusive = ACPI_SHARED;
- resource->res.data.extended_irq.number_of_interrupts = 1;
+ resource->res.data.irq.sharable = ACPI_SHARED;
+ resource->res.data.extended_irq.interrupt_count = 1;
resource->res.data.extended_irq.interrupts[0] = irq;
/* ignore resource_source, it's optional */
break;
@@ -364,7 +366,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
goto end;
}
- resource->end.id = ACPI_RSTYPE_END_TAG;
+ resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
/* Attempt to set the resource */
status = acpi_set_current_resources(link->handle, &buffer);
@@ -613,7 +615,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
int
acpi_pci_link_allocate_irq(acpi_handle handle,
int index,
- int *edge_level, int *active_high_low, char **name)
+ int *triggering, int *polarity, char **name)
{
int result = 0;
struct acpi_device *device = NULL;
@@ -653,10 +655,10 @@ acpi_pci_link_allocate_irq(acpi_handle handle,
link->refcnt++;
up(&acpi_link_lock);
- if (edge_level)
- *edge_level = link->irq.edge_level;
- if (active_high_low)
- *active_high_low = link->irq.active_high_low;
+ if (triggering)
+ *triggering = link->irq.triggering;
+ if (polarity)
+ *polarity = link->irq.polarity;
if (name)
*name = acpi_device_bid(link->device);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 0fd9988c283..4c313eab631 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -122,15 +122,15 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
int *busnr = (int *)data;
struct acpi_resource_address64 address;
- if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
- resource->id != ACPI_RSTYPE_ADDRESS32 &&
- resource->id != ACPI_RSTYPE_ADDRESS64)
+ if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
+ resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
+ resource->type != ACPI_RESOURCE_TYPE_ADDRESS64)
return AE_OK;
acpi_resource_to_address64(resource, &address);
if ((address.address_length > 0) &&
(address.resource_type == ACPI_BUS_NUMBER_RANGE))
- *busnr = address.min_address_range;
+ *busnr = address.minimum;
return AE_OK;
}
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 1278aca96fe..99a3a28594d 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -253,31 +253,21 @@ static int acpi_processor_errata(struct acpi_processor *pr)
* _PDC is required for a BIOS-OS handshake for most of the newer
* ACPI processor features.
*/
-
-int acpi_processor_set_pdc(struct acpi_processor *pr,
- struct acpi_object_list *pdc_in)
+static int acpi_processor_set_pdc(struct acpi_processor *pr)
{
+ struct acpi_object_list *pdc_in = pr->pdc;
acpi_status status = AE_OK;
- u32 arg0_buf[3];
- union acpi_object arg0 = { ACPI_TYPE_BUFFER };
- struct acpi_object_list no_object = { 1, &arg0 };
- struct acpi_object_list *pdc;
ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
- arg0.buffer.length = 12;
- arg0.buffer.pointer = (u8 *) arg0_buf;
- arg0_buf[0] = ACPI_PDC_REVISION_ID;
- arg0_buf[1] = 0;
- arg0_buf[2] = 0;
-
- pdc = (pdc_in) ? pdc_in : &no_object;
+ if (!pdc_in)
+ return_VALUE(status);
- status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
+ status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
- if ((ACPI_FAILURE(status)) && (pdc_in))
+ if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Error evaluating _PDC, using legacy perf. control...\n"));
+ "Could not evaluate _PDC, using legacy perf. control...\n"));
return_VALUE(status);
}
@@ -357,7 +347,6 @@ static int acpi_processor_add_fs(struct acpi_device *device)
ACPI_PROCESSOR_FILE_THROTTLING));
else {
entry->proc_fops = &acpi_processor_throttling_fops;
- entry->proc_fops->write = acpi_processor_write_throttling;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -372,7 +361,6 @@ static int acpi_processor_add_fs(struct acpi_device *device)
ACPI_PROCESSOR_FILE_LIMIT));
else {
entry->proc_fops = &acpi_processor_limit_fops;
- entry->proc_fops->write = acpi_processor_write_limit;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -589,6 +577,10 @@ static int acpi_processor_start(struct acpi_device *device)
"Error installing device notify handler\n"));
}
+ /* _PDC call should be done before doing anything else (if reqd.). */
+ arch_acpi_processor_init_pdc(pr);
+ acpi_processor_set_pdc(pr);
+
acpi_processor_power_init(pr, device);
if (pr->flags.throttling) {
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index cc049338e41..eb730a80952 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -94,23 +94,60 @@ static int set_max_cstate(struct dmi_system_id *id)
return 0;
}
-static struct dmi_system_id __initdata processor_power_dmi_table[] = {
- {set_max_cstate, "IBM ThinkPad R40e", {
- DMI_MATCH(DMI_BIOS_VENDOR,
- "IBM"),
- DMI_MATCH(DMI_BIOS_VERSION,
- "1SET60WW")},
- (void *)1},
- {set_max_cstate, "Medion 41700", {
- DMI_MATCH(DMI_BIOS_VENDOR,
- "Phoenix Technologies LTD"),
- DMI_MATCH(DMI_BIOS_VERSION,
- "R01-A1J")}, (void *)1},
- {set_max_cstate, "Clevo 5600D", {
- DMI_MATCH(DMI_BIOS_VENDOR,
- "Phoenix Technologies LTD"),
- DMI_MATCH(DMI_BIOS_VERSION,
- "SHE845M0.86C.0013.D.0302131307")},
+/* Actually this shouldn't be __cpuinitdata, would be better to fix the
+ callers to only run once -AK */
+static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = {
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET43WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET45WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET47WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET50WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET52WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET55WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET56WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET59WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET61WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET62WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET64WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET65WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET68WW") }, (void*)1},
+ { set_max_cstate, "Medion 41700", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J")}, (void *)1},
+ { set_max_cstate, "Clevo 5600D", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")},
(void *)2},
{},
};
@@ -550,18 +587,10 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
if (!pr->pblk)
return_VALUE(-ENODEV);
- memset(pr->power.states, 0, sizeof(pr->power.states));
-
/* if info is obtained from pblk/fadt, type equals state */
- pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3;
- /* the C0 state only exists as a filler in our array,
- * and all processors need to support C1 */
- pr->power.states[ACPI_STATE_C0].valid = 1;
- pr->power.states[ACPI_STATE_C1].valid = 1;
-
#ifndef CONFIG_HOTPLUG_CPU
/*
* Check for P_LVL2_UP flag before entering C2 and above on
@@ -591,12 +620,11 @@ static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr)
{
ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1");
+ /* Zero initialize all the C-states info. */
memset(pr->power.states, 0, sizeof(pr->power.states));
- /* if info is obtained from pblk/fadt, type equals state */
+ /* set the first C-State to C1 */
pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
- pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
- pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3;
/* the C0 state only exists as a filler in our array,
* and all processors need to support C1 */
@@ -610,6 +638,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
{
acpi_status status = 0;
acpi_integer count;
+ int current_count;
int i;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *cst;
@@ -619,10 +648,12 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
if (nocst)
return_VALUE(-ENODEV);
- pr->power.count = 0;
- for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
- memset(&(pr->power.states[i]), 0,
- sizeof(struct acpi_processor_cx));
+ current_count = 1;
+
+ /* Zero initialize C2 onwards and prepare for fresh CST lookup */
+ for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++)
+ memset(&(pr->power.states[i]), 0,
+ sizeof(struct acpi_processor_cx));
status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
if (ACPI_FAILURE(status)) {
@@ -650,16 +681,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
goto end;
}
- /* We support up to ACPI_PROCESSOR_MAX_POWER. */
- if (count > ACPI_PROCESSOR_MAX_POWER) {
- printk(KERN_WARNING
- "Limiting number of power states to max (%d)\n",
- ACPI_PROCESSOR_MAX_POWER);
- printk(KERN_WARNING
- "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
- count = ACPI_PROCESSOR_MAX_POWER;
- }
-
/* Tell driver that at least _CST is supported. */
pr->flags.has_cst = 1;
@@ -703,7 +724,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
(reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
continue;
- if ((cx.type < ACPI_STATE_C1) || (cx.type > ACPI_STATE_C3))
+ if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3))
continue;
obj = (union acpi_object *)&(element->package.elements[2]);
@@ -718,15 +739,28 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
cx.power = obj->integer.value;
- (pr->power.count)++;
- memcpy(&(pr->power.states[pr->power.count]), &cx, sizeof(cx));
+ current_count++;
+ memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
+
+ /*
+ * We support total ACPI_PROCESSOR_MAX_POWER - 1
+ * (From 1 through ACPI_PROCESSOR_MAX_POWER - 1)
+ */
+ if (current_count >= (ACPI_PROCESSOR_MAX_POWER - 1)) {
+ printk(KERN_WARNING
+ "Limiting number of power states to max (%d)\n",
+ ACPI_PROCESSOR_MAX_POWER);
+ printk(KERN_WARNING
+ "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
+ break;
+ }
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n",
- pr->power.count));
+ current_count));
/* Validate number of power states discovered */
- if (pr->power.count < 2)
+ if (current_count < 2)
status = -EFAULT;
end:
@@ -867,7 +901,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
case ACPI_STATE_C3:
acpi_processor_power_verify_c3(pr, cx);
#ifdef ARCH_APICTIMER_STOPS_ON_C3
- if (c->x86_vendor == X86_VENDOR_INTEL) {
+ if (cx->valid && c->x86_vendor == X86_VENDOR_INTEL) {
on_each_cpu(switch_APIC_timer_to_ipi,
&mask, 1, 1);
}
@@ -892,12 +926,13 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
/* NOTE: the idle thread may not be running while calling
* this function */
+ /* Adding C1 state */
+ acpi_processor_get_power_info_default_c1(pr);
result = acpi_processor_get_power_info_cst(pr);
if (result == -ENODEV)
- result = acpi_processor_get_power_info_fadt(pr);
+ acpi_processor_get_power_info_fadt(pr);
- if ((result) || (acpi_processor_power_verify(pr) < 2))
- result = acpi_processor_get_power_info_default_c1(pr);
+ pr->power.count = acpi_processor_power_verify(pr);
/*
* Set Default Policy
@@ -1066,8 +1101,6 @@ int acpi_processor_power_init(struct acpi_processor *pr,
}
}
- acpi_processor_power_init_pdc(&(pr->power), pr->id);
- acpi_processor_set_pdc(pr, pr->power.pdc);
acpi_processor_get_power_info(pr);
/*
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 22c7bb66c20..abbdb37a7f5 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -315,8 +315,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
if (!pr || !pr->performance || !pr->handle)
return_VALUE(-EINVAL);
- acpi_processor_set_pdc(pr, pr->performance->pdc);
-
status = acpi_get_handle(pr->handle, "_PCT", &handle);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -520,8 +518,8 @@ static void acpi_cpufreq_add_file(struct acpi_processor *pr)
"Unable to create '%s' fs entry\n",
ACPI_PROCESSOR_FILE_PERFORMANCE));
else {
+ acpi_processor_perf_fops.write = acpi_processor_write_performance;
entry->proc_fops = &acpi_processor_perf_fops;
- entry->proc_fops->write = acpi_processor_write_performance;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index dc9817cfb88..f99ad05cd6a 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -348,9 +348,9 @@ static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
PDE(inode)->data);
}
-ssize_t acpi_processor_write_limit(struct file * file,
- const char __user * buffer,
- size_t count, loff_t * data)
+static ssize_t acpi_processor_write_limit(struct file * file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
int result = 0;
struct seq_file *m = (struct seq_file *)file->private_data;
@@ -394,6 +394,7 @@ ssize_t acpi_processor_write_limit(struct file * file,
struct file_operations acpi_processor_limit_fops = {
.open = acpi_processor_limit_open_fs,
.read = seq_read,
+ .write = acpi_processor_write_limit,
.llseek = seq_lseek,
.release = single_release,
};
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 74a52d4e79a..b966549ec00 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -306,9 +306,9 @@ static int acpi_processor_throttling_open_fs(struct inode *inode,
PDE(inode)->data);
}
-ssize_t acpi_processor_write_throttling(struct file * file,
- const char __user * buffer,
- size_t count, loff_t * data)
+static ssize_t acpi_processor_write_throttling(struct file * file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
int result = 0;
struct seq_file *m = (struct seq_file *)file->private_data;
@@ -337,6 +337,7 @@ ssize_t acpi_processor_write_throttling(struct file * file,
struct file_operations acpi_processor_throttling_fops = {
.open = acpi_processor_throttling_open_fs,
.read = seq_read,
+ .write = acpi_processor_write_throttling,
.llseek = seq_lseek,
.release = single_release,
};
diff --git a/drivers/acpi/resources/Makefile b/drivers/acpi/resources/Makefile
index 2130b74170c..8de4f69dfa0 100644
--- a/drivers/acpi/resources/Makefile
+++ b/drivers/acpi/resources/Makefile
@@ -2,7 +2,7 @@
# Makefile for all Linux ACPI interpreter subdirectories
#
-obj-y := rsaddr.o rscreate.o rsio.o rslist.o rsmisc.o rsxface.o \
+obj-y := rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \
rscalc.o rsirq.o rsmemory.o rsutils.o
obj-$(ACPI_FUTURE_USAGE) += rsdump.o
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
index 23b54baa0cb..8fa3213ce00 100644
--- a/drivers/acpi/resources/rsaddr.c
+++ b/drivers/acpi/resources/rsaddr.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,1072 +47,334 @@
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsaddr")
-/* Local prototypes */
-static void
-acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags);
-
-static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource);
-
-static void
-acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags);
-
-static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource);
-
/*******************************************************************************
*
- * FUNCTION: acpi_rs_decode_general_flags
- *
- * PARAMETERS: Resource - Address resource data struct
- * Flags - Actual flag byte
- *
- * RETURN: Decoded flag bits in resource struct
- *
- * DESCRIPTION: Decode a general flag byte to an address resource struct
+ * acpi_rs_convert_address16 - All WORD (16-bit) address resources
*
******************************************************************************/
+struct acpi_rsconvert_info acpi_rs_convert_address16[5] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16,
+ ACPI_RS_SIZE(struct acpi_resource_address16),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address16)},
-static void
-acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags)
-{
- ACPI_FUNCTION_ENTRY();
-
- /* Producer / Consumer - flag bit[0] */
-
- resource->address.producer_consumer = (u32) (flags & 0x01);
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16,
+ sizeof(struct aml_resource_address16),
+ 0},
- /* Decode (_DEC) - flag bit[1] */
+ /* Resource Type, General Flags, and Type-Specific Flags */
- resource->address.decode = (u32) ((flags >> 1) & 0x01);
+ {ACPI_RSC_ADDRESS, 0, 0, 0},
- /* Min Address Fixed (_MIF) - flag bit[2] */
+ /*
+ * These fields are contiguous in both the source and destination:
+ * Address Granularity
+ * Address Range Minimum
+ * Address Range Maximum
+ * Address Translation Offset
+ * Address Length
+ */
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.granularity),
+ AML_OFFSET(address16.granularity),
+ 5},
- resource->address.min_address_fixed = (u32) ((flags >> 2) & 0x01);
+ /* Optional resource_source (Index and String) */
- /* Max Address Fixed (_MAF) - flag bit[3] */
-
- resource->address.max_address_fixed = (u32) ((flags >> 3) & 0x01);
-}
+ {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address16.resource_source),
+ 0,
+ sizeof(struct aml_resource_address16)}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_encode_general_flags
- *
- * PARAMETERS: Resource - Address resource data struct
- *
- * RETURN: Encoded general flag byte
- *
- * DESCRIPTION: Construct a general flag byte from an address resource struct
+ * acpi_rs_convert_address32 - All DWORD (32-bit) address resources
*
******************************************************************************/
-static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource)
-{
- u8 flags;
-
- ACPI_FUNCTION_ENTRY();
-
- /* Producer / Consumer - flag bit[0] */
-
- flags = (u8) (resource->address.producer_consumer & 0x01);
-
- /* Decode (_DEC) - flag bit[1] */
-
- flags |= (u8) ((resource->address.decode & 0x01) << 1);
-
- /* Min Address Fixed (_MIF) - flag bit[2] */
-
- flags |= (u8) ((resource->address.min_address_fixed & 0x01) << 2);
+struct acpi_rsconvert_info acpi_rs_convert_address32[5] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32,
+ ACPI_RS_SIZE(struct acpi_resource_address32),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address32)},
- /* Max Address Fixed (_MAF) - flag bit[3] */
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32,
+ sizeof(struct aml_resource_address32),
+ 0},
- flags |= (u8) ((resource->address.max_address_fixed & 0x01) << 3);
+ /* Resource Type, General Flags, and Type-Specific Flags */
- return (flags);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_decode_specific_flags
- *
- * PARAMETERS: Resource - Address resource data struct
- * Flags - Actual flag byte
- *
- * RETURN: Decoded flag bits in attribute struct
- *
- * DESCRIPTION: Decode a type-specific flag byte to an attribute struct.
- * Type-specific flags are only defined for the Memory and IO
- * resource types.
- *
- ******************************************************************************/
+ {ACPI_RSC_ADDRESS, 0, 0, 0},
-static void
-acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags)
-{
- ACPI_FUNCTION_ENTRY();
-
- if (resource->address.resource_type == ACPI_MEMORY_RANGE) {
- /* Write Status (_RW) - flag bit[0] */
-
- resource->address.attribute.memory.read_write_attribute =
- (u16) (flags & 0x01);
-
- /* Memory Attributes (_MEM) - flag bits[2:1] */
-
- resource->address.attribute.memory.cache_attribute =
- (u16) ((flags >> 1) & 0x03);
- } else if (resource->address.resource_type == ACPI_IO_RANGE) {
- /* Ranges (_RNG) - flag bits[1:0] */
-
- resource->address.attribute.io.range_attribute =
- (u16) (flags & 0x03);
+ /*
+ * These fields are contiguous in both the source and destination:
+ * Address Granularity
+ * Address Range Minimum
+ * Address Range Maximum
+ * Address Translation Offset
+ * Address Length
+ */
+ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.granularity),
+ AML_OFFSET(address32.granularity),
+ 5},
- /* Translations (_TTP and _TRS) - flag bits[5:4] */
+ /* Optional resource_source (Index and String) */
- resource->address.attribute.io.translation_attribute =
- (u16) ((flags >> 4) & 0x03);
- }
-}
+ {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address32.resource_source),
+ 0,
+ sizeof(struct aml_resource_address32)}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_encode_specific_flags
- *
- * PARAMETERS: Resource - Address resource data struct
- *
- * RETURN: Encoded type-specific flag byte
- *
- * DESCRIPTION: Construct a type-specific flag byte from an attribute struct.
- * Type-specific flags are only defined for the Memory and IO
- * resource types.
+ * acpi_rs_convert_address64 - All QWORD (64-bit) address resources
*
******************************************************************************/
-static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource)
-{
- u8 flags = 0;
-
- ACPI_FUNCTION_ENTRY();
-
- if (resource->address.resource_type == ACPI_MEMORY_RANGE) {
- /* Write Status (_RW) - flag bit[0] */
+struct acpi_rsconvert_info acpi_rs_convert_address64[5] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64,
+ ACPI_RS_SIZE(struct acpi_resource_address64),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address64)},
- flags = (u8)
- (resource->address.attribute.memory.
- read_write_attribute & 0x01);
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64,
+ sizeof(struct aml_resource_address64),
+ 0},
- /* Memory Attributes (_MEM) - flag bits[2:1] */
+ /* Resource Type, General Flags, and Type-Specific Flags */
- flags |= (u8)
- ((resource->address.attribute.memory.
- cache_attribute & 0x03) << 1);
- } else if (resource->address.resource_type == ACPI_IO_RANGE) {
- /* Ranges (_RNG) - flag bits[1:0] */
+ {ACPI_RSC_ADDRESS, 0, 0, 0},
- flags = (u8)
- (resource->address.attribute.io.range_attribute & 0x03);
+ /*
+ * These fields are contiguous in both the source and destination:
+ * Address Granularity
+ * Address Range Minimum
+ * Address Range Maximum
+ * Address Translation Offset
+ * Address Length
+ */
+ {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.granularity),
+ AML_OFFSET(address64.granularity),
+ 5},
- /* Translations (_TTP and _TRS) - flag bits[5:4] */
+ /* Optional resource_source (Index and String) */
- flags |= (u8)
- ((resource->address.attribute.io.
- translation_attribute & 0x03) << 4);
- }
-
- return (flags);
-}
+ {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address64.resource_source),
+ 0,
+ sizeof(struct aml_resource_address64)}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_address16_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_convert_ext_address64 - All Extended (64-bit) address resources
*
******************************************************************************/
-acpi_status
-acpi_rs_address16_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u32 index;
- u16 temp16;
- u8 temp8;
- u8 *temp_ptr;
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16);
-
- ACPI_FUNCTION_TRACE("rs_address16_resource");
-
- /* Get the Descriptor Length field */
-
- buffer += 1;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- /* Validate minimum descriptor length */
-
- if (temp16 < 13) {
- return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
- }
-
- *bytes_consumed = temp16 + 3;
- output_struct->id = ACPI_RSTYPE_ADDRESS16;
-
- /* Get the Resource Type (Byte3) */
+struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64,
+ ACPI_RS_SIZE(struct acpi_resource_extended_address64),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_address64)},
- buffer += 2;
- temp8 = *buffer;
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64,
+ sizeof(struct aml_resource_extended_address64),
+ 0},
- /* Values 0-2 and 0xC0-0xFF are valid */
+ /* Resource Type, General Flags, and Type-Specific Flags */
- if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
- }
-
- output_struct->data.address16.resource_type = temp8;
-
- /* Get the General Flags (Byte4) */
-
- buffer += 1;
- acpi_rs_decode_general_flags(&output_struct->data, *buffer);
-
- /* Get the Type Specific Flags (Byte5) */
-
- buffer += 1;
- acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
-
- /* Get Granularity (Bytes 6-7) */
-
- buffer += 1;
- ACPI_MOVE_16_TO_32(&output_struct->data.address16.granularity, buffer);
-
- /* Get min_address_range (Bytes 8-9) */
+ {ACPI_RSC_ADDRESS, 0, 0, 0},
- buffer += 2;
- ACPI_MOVE_16_TO_32(&output_struct->data.address16.min_address_range,
- buffer);
-
- /* Get max_address_range (Bytes 10-11) */
-
- buffer += 2;
- ACPI_MOVE_16_TO_32(&output_struct->data.address16.max_address_range,
- buffer);
-
- /* Get address_translation_offset (Bytes 12-13) */
-
- buffer += 2;
- ACPI_MOVE_16_TO_32(&output_struct->data.address16.
- address_translation_offset, buffer);
-
- /* Get address_length (Bytes 14-15) */
-
- buffer += 2;
- ACPI_MOVE_16_TO_32(&output_struct->data.address16.address_length,
- buffer);
-
- /* Resource Source Index (if present) */
-
- buffer += 2;
+ /* Revision ID */
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_iD),
+ AML_OFFSET(ext_address64.revision_iD),
+ 1},
/*
- * This will leave us pointing to the Resource Source Index
- * If it is present, then save it off and calculate the
- * pointer to where the null terminated string goes:
- * Each Interrupt takes 32-bits + the 5 bytes of the
- * stream that are default.
- *
- * Note: Some resource descriptors will have an additional null, so
- * we add 1 to the length.
+ * These fields are contiguous in both the source and destination:
+ * Address Granularity
+ * Address Range Minimum
+ * Address Range Maximum
+ * Address Translation Offset
+ * Address Length
+ * Type-Specific Attribute
*/
- if (*bytes_consumed > (16 + 1)) {
- /* Dereference the Index */
-
- output_struct->data.address16.resource_source.index =
- (u32) * buffer;
-
- /* Point to the String */
-
- buffer += 1;
-
- /* Point the String pointer to the end of this structure */
-
- output_struct->data.address16.resource_source.string_ptr =
- (char *)((u8 *) output_struct + struct_size);
-
- temp_ptr = (u8 *)
- output_struct->data.address16.resource_source.string_ptr;
-
- /* Copy the resource_source string into the buffer */
-
- index = 0;
- while (*buffer) {
- *temp_ptr = *buffer;
-
- temp_ptr++;
- buffer++;
- index++;
- }
-
- /* Add the terminating null and set the string length */
-
- *temp_ptr = 0;
- output_struct->data.address16.resource_source.string_length =
- index + 1;
-
- /*
- * In order for the struct_size to fall on a 32-bit boundary,
- * calculate the length of the string and expand the
- * struct_size to the next 32-bit boundary.
- */
- temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
- } else {
- output_struct->data.address16.resource_source.index = 0;
- output_struct->data.address16.resource_source.string_length = 0;
- output_struct->data.address16.resource_source.string_ptr = NULL;
- }
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.ext_address64.granularity),
+ AML_OFFSET(ext_address64.granularity),
+ 6}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_address16_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_convert_general_flags - Flags common to all address descriptors
*
******************************************************************************/
-acpi_status
-acpi_rs_address16_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u8 *length_field;
- acpi_size actual_bytes;
-
- ACPI_FUNCTION_TRACE("rs_address16_stream");
-
- /* Set the Descriptor Type field */
-
- *buffer = ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE;
- buffer += 1;
-
- /* Save a pointer to the Length field - to be filled in later */
-
- length_field = buffer;
- buffer += 2;
-
- /* Set the Resource Type (Memory, Io, bus_number) */
-
- *buffer = (u8) (linked_list->data.address16.resource_type & 0x03);
- buffer += 1;
-
- /* Set the general flags */
-
- *buffer = acpi_rs_encode_general_flags(&linked_list->data);
- buffer += 1;
-
- /* Set the type specific flags */
-
- *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
- buffer += 1;
-
- /* Set the address space granularity */
-
- ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.granularity);
- buffer += 2;
-
- /* Set the address range minimum */
+static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = {
+ {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.flags),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_general_flags)},
- ACPI_MOVE_32_TO_16(buffer,
- &linked_list->data.address16.min_address_range);
- buffer += 2;
+ /* Resource Type (Memory, Io, bus_number, etc.) */
- /* Set the address range maximum */
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.address.resource_type),
+ AML_OFFSET(address.resource_type),
+ 1},
- ACPI_MOVE_32_TO_16(buffer,
- &linked_list->data.address16.max_address_range);
- buffer += 2;
+ /* General Flags - Consume, Decode, min_fixed, max_fixed */
- /* Set the address translation offset */
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer),
+ AML_OFFSET(address.flags),
+ 0},
- ACPI_MOVE_32_TO_16(buffer,
- &linked_list->data.address16.
- address_translation_offset);
- buffer += 2;
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.decode),
+ AML_OFFSET(address.flags),
+ 1},
- /* Set the address length */
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.min_address_fixed),
+ AML_OFFSET(address.flags),
+ 2},
- ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.address_length);
- buffer += 2;
-
- /* Resource Source Index and Resource Source are optional */
-
- if (linked_list->data.address16.resource_source.string_length) {
- *buffer =
- (u8) linked_list->data.address16.resource_source.index;
- buffer += 1;
-
- /* Copy the resource_source string */
-
- ACPI_STRCPY((char *)buffer,
- linked_list->data.address16.resource_source.
- string_ptr);
-
- /*
- * Buffer needs to be set to the length of the string + one for the
- * terminating null
- */
- buffer +=
- (acpi_size) (ACPI_STRLEN
- (linked_list->data.address16.resource_source.
- string_ptr) + 1);
- }
-
- /* Return the number of bytes consumed in this operation */
-
- actual_bytes = ACPI_PTR_DIFF(buffer, *output_buffer);
- *bytes_consumed = actual_bytes;
-
- /*
- * Set the length field to the number of bytes consumed
- * minus the header size (3 bytes)
- */
- actual_bytes -= 3;
- ACPI_MOVE_SIZE_TO_16(length_field, &actual_bytes);
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.max_address_fixed),
+ AML_OFFSET(address.flags),
+ 3}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_address32_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_convert_mem_flags - Flags common to Memory address descriptors
*
******************************************************************************/
-acpi_status
-acpi_rs_address32_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u16 temp16;
- u8 temp8;
- u8 *temp_ptr;
- u32 index;
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32);
+static struct acpi_rsconvert_info acpi_rs_convert_mem_flags[5] = {
+ {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_mem_flags)},
- ACPI_FUNCTION_TRACE("rs_address32_resource");
+ /* Memory-specific flags */
- /* Get the Descriptor Length field */
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.write_protect),
+ AML_OFFSET(address.specific_flags),
+ 0},
- buffer += 1;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.caching),
+ AML_OFFSET(address.specific_flags),
+ 1},
- /* Validate minimum descriptor length */
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.range_type),
+ AML_OFFSET(address.specific_flags),
+ 3},
- if (temp16 < 23) {
- return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
- }
-
- *bytes_consumed = temp16 + 3;
- output_struct->id = ACPI_RSTYPE_ADDRESS32;
-
- /* Get the Resource Type (Byte3) */
-
- buffer += 2;
- temp8 = *buffer;
-
- /* Values 0-2 and 0xC0-0xFF are valid */
-
- if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
- }
-
- output_struct->data.address32.resource_type = temp8;
-
- /* Get the General Flags (Byte4) */
-
- buffer += 1;
- acpi_rs_decode_general_flags(&output_struct->data, *buffer);
-
- /* Get the Type Specific Flags (Byte5) */
-
- buffer += 1;
- acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
-
- /* Get Granularity (Bytes 6-9) */
-
- buffer += 1;
- ACPI_MOVE_32_TO_32(&output_struct->data.address32.granularity, buffer);
-
- /* Get min_address_range (Bytes 10-13) */
-
- buffer += 4;
- ACPI_MOVE_32_TO_32(&output_struct->data.address32.min_address_range,
- buffer);
-
- /* Get max_address_range (Bytes 14-17) */
-
- buffer += 4;
- ACPI_MOVE_32_TO_32(&output_struct->data.address32.max_address_range,
- buffer);
-
- /* Get address_translation_offset (Bytes 18-21) */
-
- buffer += 4;
- ACPI_MOVE_32_TO_32(&output_struct->data.address32.
- address_translation_offset, buffer);
-
- /* Get address_length (Bytes 22-25) */
-
- buffer += 4;
- ACPI_MOVE_32_TO_32(&output_struct->data.address32.address_length,
- buffer);
-
- /* Resource Source Index (if present) */
-
- buffer += 4;
-
- /*
- * This will leave us pointing to the Resource Source Index
- * If it is present, then save it off and calculate the
- * pointer to where the null terminated string goes:
- *
- * Note: Some resource descriptors will have an additional null, so
- * we add 1 to the length.
- */
- if (*bytes_consumed > (26 + 1)) {
- /* Dereference the Index */
-
- output_struct->data.address32.resource_source.index =
- (u32) * buffer;
-
- /* Point to the String */
-
- buffer += 1;
-
- /* Point the String pointer to the end of this structure */
-
- output_struct->data.address32.resource_source.string_ptr =
- (char *)((u8 *) output_struct + struct_size);
-
- temp_ptr = (u8 *)
- output_struct->data.address32.resource_source.string_ptr;
-
- /* Copy the resource_source string into the buffer */
-
- index = 0;
- while (*buffer) {
- *temp_ptr = *buffer;
-
- temp_ptr++;
- buffer++;
- index++;
- }
-
- /* Add the terminating null and set the string length */
-
- *temp_ptr = 0;
- output_struct->data.address32.resource_source.string_length =
- index + 1;
-
- /*
- * In order for the struct_size to fall on a 32-bit boundary,
- * calculate the length of the string and expand the
- * struct_size to the next 32-bit boundary.
- */
- temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
- } else {
- output_struct->data.address32.resource_source.index = 0;
- output_struct->data.address32.resource_source.string_length = 0;
- output_struct->data.address32.resource_source.string_ptr = NULL;
- }
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.translation),
+ AML_OFFSET(address.specific_flags),
+ 5}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_address32_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_convert_io_flags - Flags common to I/O address descriptors
*
******************************************************************************/
-acpi_status
-acpi_rs_address32_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer;
- u16 *length_field;
-
- ACPI_FUNCTION_TRACE("rs_address32_stream");
-
- buffer = *output_buffer;
-
- /* Set the Descriptor Type field */
-
- *buffer = ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE;
- buffer += 1;
-
- /* Save a pointer to the Length field - to be filled in later */
-
- length_field = ACPI_CAST_PTR(u16, buffer);
- buffer += 2;
-
- /* Set the Resource Type (Memory, Io, bus_number) */
-
- *buffer = (u8) (linked_list->data.address32.resource_type & 0x03);
- buffer += 1;
-
- /* Set the general flags */
-
- *buffer = acpi_rs_encode_general_flags(&linked_list->data);
- buffer += 1;
-
- /* Set the type specific flags */
-
- *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
- buffer += 1;
-
- /* Set the address space granularity */
-
- ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.granularity);
- buffer += 4;
-
- /* Set the address range minimum */
-
- ACPI_MOVE_32_TO_32(buffer,
- &linked_list->data.address32.min_address_range);
- buffer += 4;
-
- /* Set the address range maximum */
-
- ACPI_MOVE_32_TO_32(buffer,
- &linked_list->data.address32.max_address_range);
- buffer += 4;
-
- /* Set the address translation offset */
-
- ACPI_MOVE_32_TO_32(buffer,
- &linked_list->data.address32.
- address_translation_offset);
- buffer += 4;
-
- /* Set the address length */
-
- ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.address_length);
- buffer += 4;
+static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = {
+ {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io_flags)},
- /* Resource Source Index and Resource Source are optional */
+ /* I/O-specific flags */
- if (linked_list->data.address32.resource_source.string_length) {
- *buffer =
- (u8) linked_list->data.address32.resource_source.index;
- buffer += 1;
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.io.range_type),
+ AML_OFFSET(address.specific_flags),
+ 0},
- /* Copy the resource_source string */
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.io.translation),
+ AML_OFFSET(address.specific_flags),
+ 4},
- ACPI_STRCPY((char *)buffer,
- linked_list->data.address32.resource_source.
- string_ptr);
-
- /*
- * Buffer needs to be set to the length of the string + one for the
- * terminating null
- */
- buffer +=
- (acpi_size) (ACPI_STRLEN
- (linked_list->data.address32.resource_source.
- string_ptr) + 1);
- }
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-
- /*
- * Set the length field to the number of bytes consumed
- * minus the header size (3 bytes)
- */
- *length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_1BITFLAG,
+ ACPI_RS_OFFSET(data.address.info.io.translation_type),
+ AML_OFFSET(address.specific_flags),
+ 5}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_address64_resource
+ * FUNCTION: acpi_rs_get_address_common
*
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
+ * PARAMETERS: Resource - Pointer to the internal resource struct
+ * Aml - Pointer to the AML resource descriptor
*
- * RETURN: Status
+ * RETURN: TRUE if the resource_type field is OK, FALSE otherwise
*
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor
+ * to an internal resource descriptor
*
******************************************************************************/
-acpi_status
-acpi_rs_address64_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
+u8
+acpi_rs_get_address_common(struct acpi_resource *resource,
+ union aml_resource *aml)
{
- u16 temp16;
- u8 temp8;
- u8 resource_type;
- u8 *temp_ptr;
- u32 index;
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64);
-
- ACPI_FUNCTION_TRACE("rs_address64_resource");
-
- /* Get the Descriptor Type */
-
- resource_type = *buffer;
-
- /* Get the Descriptor Length field */
-
- buffer += 1;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- /* Validate minimum descriptor length */
-
- if (temp16 < 43) {
- return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
- }
-
- *bytes_consumed = temp16 + 3;
- output_struct->id = ACPI_RSTYPE_ADDRESS64;
-
- /* Get the Resource Type (Byte3) */
-
- buffer += 2;
- temp8 = *buffer;
-
- /* Values 0-2 and 0xC0-0xFF are valid */
-
- if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
- }
-
- output_struct->data.address64.resource_type = temp8;
-
- /* Get the General Flags (Byte4) */
-
- buffer += 1;
- acpi_rs_decode_general_flags(&output_struct->data, *buffer);
-
- /* Get the Type Specific Flags (Byte5) */
-
- buffer += 1;
- acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
+ ACPI_FUNCTION_ENTRY();
- if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
- /* Move past revision_id and Reserved byte */
+ /* Validate the Resource Type */
- buffer += 2;
+ if ((aml->address.resource_type > 2)
+ && (aml->address.resource_type < 0xC0)) {
+ return (FALSE);
}
- /* Get Granularity (Bytes 6-13) or (Bytes 8-15) */
-
- buffer += 1;
- ACPI_MOVE_64_TO_64(&output_struct->data.address64.granularity, buffer);
-
- /* Get min_address_range (Bytes 14-21) or (Bytes 16-23) */
-
- buffer += 8;
- ACPI_MOVE_64_TO_64(&output_struct->data.address64.min_address_range,
- buffer);
-
- /* Get max_address_range (Bytes 22-29) or (Bytes 24-31) */
-
- buffer += 8;
- ACPI_MOVE_64_TO_64(&output_struct->data.address64.max_address_range,
- buffer);
-
- /* Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */
-
- buffer += 8;
- ACPI_MOVE_64_TO_64(&output_struct->data.address64.
- address_translation_offset, buffer);
+ /* Get the Resource Type and General Flags */
- /* Get address_length (Bytes 38-45) or (Bytes 40-47) */
+ (void)acpi_rs_convert_aml_to_resource(resource, aml,
+ acpi_rs_convert_general_flags);
- buffer += 8;
- ACPI_MOVE_64_TO_64(&output_struct->data.address64.address_length,
- buffer);
+ /* Get the Type-Specific Flags (Memory and I/O descriptors only) */
- output_struct->data.address64.resource_source.index = 0;
- output_struct->data.address64.resource_source.string_length = 0;
- output_struct->data.address64.resource_source.string_ptr = NULL;
-
- if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
- /* Get type_specific_attribute (Bytes 48-55) */
-
- buffer += 8;
- ACPI_MOVE_64_TO_64(&output_struct->data.address64.
- type_specific_attributes, buffer);
+ if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
+ (void)acpi_rs_convert_aml_to_resource(resource, aml,
+ acpi_rs_convert_mem_flags);
+ } else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
+ (void)acpi_rs_convert_aml_to_resource(resource, aml,
+ acpi_rs_convert_io_flags);
} else {
- output_struct->data.address64.type_specific_attributes = 0;
-
- /* Resource Source Index (if present) */
-
- buffer += 8;
-
- /*
- * This will leave us pointing to the Resource Source Index
- * If it is present, then save it off and calculate the
- * pointer to where the null terminated string goes:
- * Each Interrupt takes 32-bits + the 5 bytes of the
- * stream that are default.
- *
- * Note: Some resource descriptors will have an additional null, so
- * we add 1 to the length.
- */
- if (*bytes_consumed > (46 + 1)) {
- /* Dereference the Index */
-
- output_struct->data.address64.resource_source.index =
- (u32) * buffer;
-
- /* Point to the String */
-
- buffer += 1;
-
- /* Point the String pointer to the end of this structure */
-
- output_struct->data.address64.resource_source.
- string_ptr =
- (char *)((u8 *) output_struct + struct_size);
-
- temp_ptr = (u8 *)
- output_struct->data.address64.resource_source.
- string_ptr;
-
- /* Copy the resource_source string into the buffer */
-
- index = 0;
- while (*buffer) {
- *temp_ptr = *buffer;
-
- temp_ptr++;
- buffer++;
- index++;
- }
-
- /*
- * Add the terminating null and set the string length
- */
- *temp_ptr = 0;
- output_struct->data.address64.resource_source.
- string_length = index + 1;
-
- /*
- * In order for the struct_size to fall on a 32-bit boundary,
- * calculate the length of the string and expand the
- * struct_size to the next 32-bit boundary.
- */
- temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
- }
- }
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
+ /* Generic resource type, just grab the type_specific byte */
- /* Return the final size of the structure */
+ resource->data.address.info.type_specific =
+ aml->address.specific_flags;
+ }
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
+ return (TRUE);
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_address64_stream
+ * FUNCTION: acpi_rs_set_address_common
*
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
+ * PARAMETERS: Aml - Pointer to the AML resource descriptor
+ * Resource - Pointer to the internal resource struct
*
- * RETURN: Status
+ * RETURN: None
*
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * DESCRIPTION: Convert common flag fields from a resource descriptor to an
+ * AML descriptor
*
******************************************************************************/
-acpi_status
-acpi_rs_address64_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
+void
+acpi_rs_set_address_common(union aml_resource *aml,
+ struct acpi_resource *resource)
{
- u8 *buffer;
- u16 *length_field;
-
- ACPI_FUNCTION_TRACE("rs_address64_stream");
-
- buffer = *output_buffer;
-
- /* Set the Descriptor Type field */
-
- *buffer = ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE;
- buffer += 1;
-
- /* Save a pointer to the Length field - to be filled in later */
-
- length_field = ACPI_CAST_PTR(u16, buffer);
- buffer += 2;
-
- /* Set the Resource Type (Memory, Io, bus_number) */
-
- *buffer = (u8) (linked_list->data.address64.resource_type & 0x03);
- buffer += 1;
-
- /* Set the general flags */
-
- *buffer = acpi_rs_encode_general_flags(&linked_list->data);
- buffer += 1;
-
- /* Set the type specific flags */
-
- *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
- buffer += 1;
-
- /* Set the address space granularity */
-
- ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.granularity);
- buffer += 8;
-
- /* Set the address range minimum */
-
- ACPI_MOVE_64_TO_64(buffer,
- &linked_list->data.address64.min_address_range);
- buffer += 8;
-
- /* Set the address range maximum */
-
- ACPI_MOVE_64_TO_64(buffer,
- &linked_list->data.address64.max_address_range);
- buffer += 8;
-
- /* Set the address translation offset */
-
- ACPI_MOVE_64_TO_64(buffer,
- &linked_list->data.address64.
- address_translation_offset);
- buffer += 8;
-
- /* Set the address length */
-
- ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.address_length);
- buffer += 8;
+ ACPI_FUNCTION_ENTRY();
- /* Resource Source Index and Resource Source are optional */
+ /* Set the Resource Type and General Flags */
- if (linked_list->data.address64.resource_source.string_length) {
- *buffer =
- (u8) linked_list->data.address64.resource_source.index;
- buffer += 1;
+ (void)acpi_rs_convert_resource_to_aml(resource, aml,
+ acpi_rs_convert_general_flags);
- /* Copy the resource_source string */
+ /* Set the Type-Specific Flags (Memory and I/O descriptors only) */
- ACPI_STRCPY((char *)buffer,
- linked_list->data.address64.resource_source.
- string_ptr);
+ if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
+ (void)acpi_rs_convert_resource_to_aml(resource, aml,
+ acpi_rs_convert_mem_flags);
+ } else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
+ (void)acpi_rs_convert_resource_to_aml(resource, aml,
+ acpi_rs_convert_io_flags);
+ } else {
+ /* Generic resource type, just copy the type_specific byte */
- /*
- * Buffer needs to be set to the length of the string + one for the
- * terminating null
- */
- buffer +=
- (acpi_size) (ACPI_STRLEN
- (linked_list->data.address64.resource_source.
- string_ptr) + 1);
+ aml->address.specific_flags =
+ resource->data.address.info.type_specific;
}
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
-
- /*
- * Set the length field to the number of bytes consumed
- * minus the header size (3 bytes)
- */
- *length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 378f58390fc..4038dbfa63a 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,652 +49,431 @@
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rscalc")
+/* Local prototypes */
+static u8 acpi_rs_count_set_bits(u16 bit_field);
+
+static acpi_rs_length
+acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
+
+static u32
+acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
+
/*******************************************************************************
*
- * FUNCTION: acpi_rs_get_byte_stream_length
+ * FUNCTION: acpi_rs_count_set_bits
*
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * size_needed - u32 pointer of the size buffer needed
- * to properly return the parsed data
+ * PARAMETERS: bit_field - Field in which to count bits
*
- * RETURN: Status
+ * RETURN: Number of bits set within the field
*
- * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
- * the size buffer needed to hold the linked list that conveys
- * the resource data.
+ * DESCRIPTION: Count the number of bits set in a resource field. Used for
+ * (Short descriptor) interrupt and DMA lists.
*
******************************************************************************/
-acpi_status
-acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list,
- acpi_size * size_needed)
-{
- acpi_size byte_stream_size_needed = 0;
- acpi_size segment_size;
- u8 done = FALSE;
-
- ACPI_FUNCTION_TRACE("rs_get_byte_stream_length");
-
- while (!done) {
- /* Init the variable that will hold the size to add to the total. */
-
- segment_size = 0;
-
- switch (linked_list->id) {
- case ACPI_RSTYPE_IRQ:
- /*
- * IRQ Resource
- * For an IRQ Resource, Byte 3, although optional, will always be
- * created - it holds IRQ information.
- */
- segment_size = 4;
- break;
-
- case ACPI_RSTYPE_DMA:
- /*
- * DMA Resource
- * For this resource the size is static
- */
- segment_size = 3;
- break;
-
- case ACPI_RSTYPE_START_DPF:
- /*
- * Start Dependent Functions Resource
- * For a start_dependent_functions Resource, Byte 1, although
- * optional, will always be created.
- */
- segment_size = 2;
- break;
-
- case ACPI_RSTYPE_END_DPF:
- /*
- * End Dependent Functions Resource
- * For this resource the size is static
- */
- segment_size = 1;
- break;
-
- case ACPI_RSTYPE_IO:
- /*
- * IO Port Resource
- * For this resource the size is static
- */
- segment_size = 8;
- break;
- case ACPI_RSTYPE_FIXED_IO:
- /*
- * Fixed IO Port Resource
- * For this resource the size is static
- */
- segment_size = 4;
- break;
-
- case ACPI_RSTYPE_VENDOR:
- /*
- * Vendor Defined Resource
- * For a Vendor Specific resource, if the Length is between 1 and 7
- * it will be created as a Small Resource data type, otherwise it
- * is a Large Resource data type.
- */
- if (linked_list->data.vendor_specific.length > 7) {
- segment_size = 3;
- } else {
- segment_size = 1;
- }
- segment_size +=
- linked_list->data.vendor_specific.length;
- break;
-
- case ACPI_RSTYPE_END_TAG:
- /*
- * End Tag
- * For this resource the size is static
- */
- segment_size = 2;
- done = TRUE;
- break;
-
- case ACPI_RSTYPE_MEM24:
- /*
- * 24-Bit Memory Resource
- * For this resource the size is static
- */
- segment_size = 12;
- break;
+static u8 acpi_rs_count_set_bits(u16 bit_field)
+{
+ u8 bits_set;
- case ACPI_RSTYPE_MEM32:
- /*
- * 32-Bit Memory Range Resource
- * For this resource the size is static
- */
- segment_size = 20;
- break;
+ ACPI_FUNCTION_ENTRY();
- case ACPI_RSTYPE_FIXED_MEM32:
- /*
- * 32-Bit Fixed Memory Resource
- * For this resource the size is static
- */
- segment_size = 12;
- break;
+ for (bits_set = 0; bit_field; bits_set++) {
+ /* Zero the least significant bit that is set */
- case ACPI_RSTYPE_ADDRESS16:
- /*
- * 16-Bit Address Resource
- * The base size of this byte stream is 16. If a Resource Source
- * string is not NULL, add 1 for the Index + the length of the null
- * terminated string Resource Source + 1 for the null.
- */
- segment_size = 16;
-
- if (linked_list->data.address16.resource_source.
- string_ptr) {
- segment_size +=
- linked_list->data.address16.resource_source.
- string_length;
- segment_size++;
- }
- break;
+ bit_field &= (bit_field - 1);
+ }
- case ACPI_RSTYPE_ADDRESS32:
- /*
- * 32-Bit Address Resource
- * The base size of this byte stream is 26. If a Resource
- * Source string is not NULL, add 1 for the Index + the
- * length of the null terminated string Resource Source +
- * 1 for the null.
- */
- segment_size = 26;
-
- if (linked_list->data.address32.resource_source.
- string_ptr) {
- segment_size +=
- linked_list->data.address32.resource_source.
- string_length;
- segment_size++;
- }
- break;
+ return (bits_set);
+}
- case ACPI_RSTYPE_ADDRESS64:
- /*
- * 64-Bit Address Resource
- * The base size of this byte stream is 46. If a resource_source
- * string is not NULL, add 1 for the Index + the length of the null
- * terminated string Resource Source + 1 for the null.
- */
- segment_size = 46;
-
- if (linked_list->data.address64.resource_source.
- string_ptr) {
- segment_size +=
- linked_list->data.address64.resource_source.
- string_length;
- segment_size++;
- }
- break;
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_struct_option_length
+ *
+ * PARAMETERS: resource_source - Pointer to optional descriptor field
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Common code to handle optional resource_source_index and
+ * resource_source fields in some Large descriptors. Used during
+ * list-to-stream conversion
+ *
+ ******************************************************************************/
- case ACPI_RSTYPE_EXT_IRQ:
- /*
- * Extended IRQ Resource
- * The base size of this byte stream is 9. This is for an Interrupt
- * table length of 1. For each additional interrupt, add 4.
- * If a Resource Source string is not NULL, add 1 for the
- * Index + the length of the null terminated string
- * Resource Source + 1 for the null.
- */
- segment_size = 9 + (((acpi_size)
- linked_list->data.extended_irq.
- number_of_interrupts - 1) * 4);
-
- if (linked_list->data.extended_irq.resource_source.
- string_ptr) {
- segment_size +=
- linked_list->data.extended_irq.
- resource_source.string_length;
- segment_size++;
- }
- break;
+static acpi_rs_length
+acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
+{
+ ACPI_FUNCTION_ENTRY();
- default:
+ /*
+ * If the resource_source string is valid, return the size of the string
+ * (string_length includes the NULL terminator) plus the size of the
+ * resource_source_index (1).
+ */
+ if (resource_source->string_ptr) {
+ return ((acpi_rs_length) (resource_source->string_length + 1));
+ }
- /* If we get here, everything is out of sync, exit with error */
+ return (0);
+}
- return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_stream_option_length
+ *
+ * PARAMETERS: resource_length - Length from the resource header
+ * minimum_total_length - Minimum length of this resource, before
+ * any optional fields. Includes header size
+ *
+ * RETURN: Length of optional string (0 if no string present)
+ *
+ * DESCRIPTION: Common code to handle optional resource_source_index and
+ * resource_source fields in some Large descriptors. Used during
+ * stream-to-list conversion
+ *
+ ******************************************************************************/
- } /* switch (linked_list->Id) */
+static u32
+acpi_rs_stream_option_length(u32 resource_length,
+ u32 minimum_aml_resource_length)
+{
+ u32 string_length = 0;
- /* Update the total */
+ ACPI_FUNCTION_ENTRY();
- byte_stream_size_needed += segment_size;
+ /*
+ * The resource_source_index and resource_source are optional elements of some
+ * Large-type resource descriptors.
+ */
- /* Point to the next object */
+ /*
+ * If the length of the actual resource descriptor is greater than the ACPI
+ * spec-defined minimum length, it means that a resource_source_index exists
+ * and is followed by a (required) null terminated string. The string length
+ * (including the null terminator) is the resource length minus the minimum
+ * length, minus one byte for the resource_source_index itself.
+ */
+ if (resource_length > minimum_aml_resource_length) {
+ /* Compute the length of the optional string */
- linked_list = ACPI_PTR_ADD(struct acpi_resource,
- linked_list, linked_list->length);
+ string_length =
+ resource_length - minimum_aml_resource_length - 1;
}
- /* This is the data the caller needs */
+ /* Round up length to 32 bits for internal structure alignment */
- *size_needed = byte_stream_size_needed;
- return_ACPI_STATUS(AE_OK);
+ return (ACPI_ROUND_UP_to_32_bITS(string_length));
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_get_list_length
+ * FUNCTION: acpi_rs_get_aml_length
*
- * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
- * byte_stream_buffer_length - Size of byte_stream_buffer
- * size_needed - u32 pointer of the size buffer
- * needed to properly return the
- * parsed data
+ * PARAMETERS: Resource - Pointer to the resource linked list
+ * size_needed - Where the required size is returned
*
* RETURN: Status
*
- * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
- * the size buffer needed to hold the linked list that conveys
- * the resource data.
+ * DESCRIPTION: Takes a linked list of internal resource descriptors and
+ * calculates the size buffer needed to hold the corresponding
+ * external resource byte stream.
*
******************************************************************************/
acpi_status
-acpi_rs_get_list_length(u8 * byte_stream_buffer,
- u32 byte_stream_buffer_length, acpi_size * size_needed)
+acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
{
- u32 buffer_size = 0;
- u32 bytes_parsed = 0;
- u8 number_of_interrupts = 0;
- u8 number_of_channels = 0;
- u8 resource_type;
- u32 structure_size;
- u32 bytes_consumed;
- u8 *buffer;
- u8 temp8;
- u16 temp16;
- u8 index;
- u8 additional_bytes;
-
- ACPI_FUNCTION_TRACE("rs_get_list_length");
+ acpi_size aml_size_needed = 0;
+ acpi_rs_length total_size;
- while (bytes_parsed < byte_stream_buffer_length) {
- /* The next byte in the stream is the resource type */
+ ACPI_FUNCTION_TRACE("rs_get_aml_length");
- resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
+ /* Traverse entire list of internal resource descriptors */
- switch (resource_type) {
- case ACPI_RDESC_TYPE_MEMORY_24:
- /*
- * 24-Bit Memory Resource
- */
- bytes_consumed = 12;
-
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
- break;
+ while (resource) {
+ /* Validate the descriptor type */
- case ACPI_RDESC_TYPE_LARGE_VENDOR:
- /*
- * Vendor Defined Resource
- */
- buffer = byte_stream_buffer;
- ++buffer;
-
- ACPI_MOVE_16_TO_16(&temp16, buffer);
- bytes_consumed = temp16 + 3;
-
- /* Ensure a 32-bit boundary for the structure */
+ if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
+ }
- temp16 = (u16) ACPI_ROUND_UP_to_32_bITS(temp16);
+ /* Get the base size of the (external stream) resource descriptor */
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) +
- (temp16 * sizeof(u8));
- break;
+ total_size = acpi_gbl_aml_resource_sizes[resource->type];
- case ACPI_RDESC_TYPE_MEMORY_32:
+ /*
+ * Augment the base size for descriptors with optional and/or
+ * variable-length fields
+ */
+ switch (resource->type) {
+ case ACPI_RESOURCE_TYPE_VENDOR:
/*
- * 32-Bit Memory Range Resource
+ * Vendor Defined Resource:
+ * For a Vendor Specific resource, if the Length is between 1 and 7
+ * it will be created as a Small Resource data type, otherwise it
+ * is a Large Resource data type.
*/
- bytes_consumed = 20;
+ if (resource->data.vendor.byte_length > 7) {
+ /* Base size of a Large resource descriptor */
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32);
- break;
+ total_size =
+ sizeof(struct aml_resource_large_header);
+ }
- case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
- /*
- * 32-Bit Fixed Memory Resource
- */
- bytes_consumed = 12;
+ /* Add the size of the vendor-specific data */
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct
- acpi_resource_fixed_mem32);
+ total_size = (acpi_rs_length)
+ (total_size + resource->data.vendor.byte_length);
break;
- case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
+ case ACPI_RESOURCE_TYPE_END_TAG:
/*
- * 64-Bit Address Resource
+ * End Tag:
+ * We are done -- return the accumulated total size.
*/
- buffer = byte_stream_buffer;
+ *size_needed = aml_size_needed + total_size;
- ++buffer;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
+ /* Normal exit */
- bytes_consumed = temp16 + 3;
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct
- acpi_resource_address64);
- break;
+ return_ACPI_STATUS(AE_OK);
- case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
/*
- * 64-Bit Address Resource
+ * 16-Bit Address Resource:
+ * Add the size of the optional resource_source info
*/
- buffer = byte_stream_buffer;
-
- ++buffer;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- bytes_consumed = temp16 + 3;
+ total_size = (acpi_rs_length)
+ (total_size +
+ acpi_rs_struct_option_length(&resource->data.
+ address16.
+ resource_source));
+ break;
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
/*
- * Resource Source Index and Resource Source are optional elements.
- * Check the length of the Bytestream. If it is greater than 43,
- * that means that an Index exists and is followed by a null
- * terminated string. Therefore, set the temp variable to the
- * length minus the minimum byte stream length plus the byte for
- * the Index to determine the size of the NULL terminated string.
+ * 32-Bit Address Resource:
+ * Add the size of the optional resource_source info
*/
- if (43 < temp16) {
- temp8 = (u8) (temp16 - 44);
- } else {
- temp8 = 0;
- }
-
- /* Ensure a 64-bit boundary for the structure */
-
- temp8 = (u8) ACPI_ROUND_UP_to_64_bITS(temp8);
-
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64)
- + (temp8 * sizeof(u8));
+ total_size = (acpi_rs_length)
+ (total_size +
+ acpi_rs_struct_option_length(&resource->data.
+ address32.
+ resource_source));
break;
- case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
/*
- * 32-Bit Address Resource
+ * 64-Bit Address Resource:
+ * Add the size of the optional resource_source info
*/
- buffer = byte_stream_buffer;
-
- ++buffer;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- bytes_consumed = temp16 + 3;
+ total_size = (acpi_rs_length)
+ (total_size +
+ acpi_rs_struct_option_length(&resource->data.
+ address64.
+ resource_source));
+ break;
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
/*
- * Resource Source Index and Resource Source are optional elements.
- * Check the length of the Bytestream. If it is greater than 23,
- * that means that an Index exists and is followed by a null
- * terminated string. Therefore, set the temp variable to the
- * length minus the minimum byte stream length plus the byte for
- * the Index to determine the size of the NULL terminated string.
+ * Extended IRQ Resource:
+ * Add the size of each additional optional interrupt beyond the
+ * required 1 (4 bytes for each u32 interrupt number)
*/
- if (23 < temp16) {
- temp8 = (u8) (temp16 - 24);
- } else {
- temp8 = 0;
- }
-
- /* Ensure a 32-bit boundary for the structure */
-
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
+ total_size = (acpi_rs_length)
+ (total_size +
+ ((resource->data.extended_irq.interrupt_count -
+ 1) * 4) +
+ /* Add the size of the optional resource_source info */
+ acpi_rs_struct_option_length(&resource->data.
+ extended_irq.
+ resource_source));
+ break;
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32)
- + (temp8 * sizeof(u8));
+ default:
break;
+ }
- case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
- /*
- * 16-Bit Address Resource
- */
- buffer = byte_stream_buffer;
+ /* Update the total */
- ++buffer;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
+ aml_size_needed += total_size;
- bytes_consumed = temp16 + 3;
+ /* Point to the next object */
- /*
- * Resource Source Index and Resource Source are optional elements.
- * Check the length of the Bytestream. If it is greater than 13,
- * that means that an Index exists and is followed by a null
- * terminated string. Therefore, set the temp variable to the
- * length minus the minimum byte stream length plus the byte for
- * the Index to determine the size of the NULL terminated string.
- */
- if (13 < temp16) {
- temp8 = (u8) (temp16 - 14);
- } else {
- temp8 = 0;
- }
+ resource =
+ ACPI_ADD_PTR(struct acpi_resource, resource,
+ resource->length);
+ }
- /* Ensure a 32-bit boundary for the structure */
+ /* Did not find an end_tag resource descriptor */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+}
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16)
- + (temp8 * sizeof(u8));
- break;
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_get_list_length
+ *
+ * PARAMETERS: aml_buffer - Pointer to the resource byte stream
+ * aml_buffer_length - Size of aml_buffer
+ * size_needed - Where the size needed is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Takes an external resource byte stream and calculates the size
+ * buffer needed to hold the corresponding internal resource
+ * descriptor linked list.
+ *
+ ******************************************************************************/
- case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
- /*
- * Extended IRQ
- */
- buffer = byte_stream_buffer;
+acpi_status
+acpi_rs_get_list_length(u8 * aml_buffer,
+ u32 aml_buffer_length, acpi_size * size_needed)
+{
+ acpi_status status;
+ u8 *end_aml;
+ u8 *buffer;
+ u32 buffer_size = 0;
+ u16 temp16;
+ u16 resource_length;
+ u32 extra_struct_bytes;
+ u8 resource_index;
+ u8 minimum_aml_resource_length;
- ++buffer;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
+ ACPI_FUNCTION_TRACE("rs_get_list_length");
- bytes_consumed = temp16 + 3;
+ end_aml = aml_buffer + aml_buffer_length;
- /*
- * Point past the length field and the Interrupt vector flags to
- * save off the Interrupt table length to the Temp8 variable.
- */
- buffer += 3;
- temp8 = *buffer;
+ /* Walk the list of AML resource descriptors */
- /*
- * To compensate for multiple interrupt numbers, add 4 bytes for
- * each additional interrupts greater than 1
- */
- additional_bytes = (u8) ((temp8 - 1) * 4);
+ while (aml_buffer < end_aml) {
+ /* Validate the Resource Type and Resource Length */
- /*
- * Resource Source Index and Resource Source are optional elements.
- * Check the length of the Bytestream. If it is greater than 9,
- * that means that an Index exists and is followed by a null
- * terminated string. Therefore, set the temp variable to the
- * length minus the minimum byte stream length plus the byte for
- * the Index to determine the size of the NULL terminated string.
- */
- if (9 + additional_bytes < temp16) {
- temp8 = (u8) (temp16 - (9 + additional_bytes));
- } else {
- temp8 = 0;
- }
+ status = acpi_ut_validate_resource(aml_buffer, &resource_index);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
- /* Ensure a 32-bit boundary for the structure */
+ /* Get the resource length and base (minimum) AML size */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
+ resource_length = acpi_ut_get_resource_length(aml_buffer);
+ minimum_aml_resource_length =
+ acpi_gbl_resource_aml_sizes[resource_index];
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq) +
- (additional_bytes * sizeof(u8)) +
- (temp8 * sizeof(u8));
- break;
+ /*
+ * Augment the size for descriptors with optional
+ * and/or variable length fields
+ */
+ extra_struct_bytes = 0;
+ buffer =
+ aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
- case ACPI_RDESC_TYPE_IRQ_FORMAT:
+ switch (acpi_ut_get_resource_type(aml_buffer)) {
+ case ACPI_RESOURCE_NAME_IRQ:
/*
- * IRQ Resource.
- * Determine if it there are two or three trailing bytes
+ * IRQ Resource:
+ * Get the number of bits set in the 16-bit IRQ mask
*/
- buffer = byte_stream_buffer;
- temp8 = *buffer;
-
- if (temp8 & 0x01) {
- bytes_consumed = 4;
- } else {
- bytes_consumed = 3;
- }
-
- /* Point past the descriptor */
-
- ++buffer;
-
- /* Look at the number of bits set */
-
ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- for (index = 0; index < 16; index++) {
- if (temp16 & 0x1) {
- ++number_of_interrupts;
- }
-
- temp16 >>= 1;
- }
-
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_io) +
- (number_of_interrupts * sizeof(u32));
+ extra_struct_bytes = acpi_rs_count_set_bits(temp16);
break;
- case ACPI_RDESC_TYPE_DMA_FORMAT:
+ case ACPI_RESOURCE_NAME_DMA:
/*
- * DMA Resource
+ * DMA Resource:
+ * Get the number of bits set in the 8-bit DMA mask
*/
- buffer = byte_stream_buffer;
- bytes_consumed = 3;
-
- /* Point past the descriptor */
-
- ++buffer;
-
- /* Look at the number of bits set */
-
- temp8 = *buffer;
-
- for (index = 0; index < 8; index++) {
- if (temp8 & 0x1) {
- ++number_of_channels;
- }
-
- temp8 >>= 1;
- }
-
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma) +
- (number_of_channels * sizeof(u32));
+ extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
break;
- case ACPI_RDESC_TYPE_START_DEPENDENT:
+ case ACPI_RESOURCE_NAME_VENDOR_SMALL:
/*
- * Start Dependent Functions Resource
- * Determine if it there are two or three trailing bytes
+ * Vendor Resource:
+ * Ensure a 32-bit boundary for the structure
*/
- buffer = byte_stream_buffer;
- temp8 = *buffer;
-
- if (temp8 & 0x01) {
- bytes_consumed = 2;
- } else {
- bytes_consumed = 1;
- }
-
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct
- acpi_resource_start_dpf);
+ extra_struct_bytes =
+ ACPI_ROUND_UP_to_32_bITS(resource_length);
break;
- case ACPI_RDESC_TYPE_END_DEPENDENT:
+ case ACPI_RESOURCE_NAME_END_TAG:
/*
- * End Dependent Functions Resource
+ * End Tag: This is the normal exit, add size of end_tag
*/
- bytes_consumed = 1;
- structure_size = ACPI_RESOURCE_LENGTH;
- break;
+ *size_needed = buffer_size + ACPI_RS_SIZE_MIN;
+ return_ACPI_STATUS(AE_OK);
- case ACPI_RDESC_TYPE_IO_PORT:
+ case ACPI_RESOURCE_NAME_VENDOR_LARGE:
/*
- * IO Port Resource
+ * Vendor Resource:
+ * Add vendor data and ensure a 32-bit boundary for the structure
*/
- bytes_consumed = 8;
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_io);
+ extra_struct_bytes =
+ ACPI_ROUND_UP_to_32_bITS(resource_length);
break;
- case ACPI_RDESC_TYPE_FIXED_IO_PORT:
+ case ACPI_RESOURCE_NAME_ADDRESS32:
+ case ACPI_RESOURCE_NAME_ADDRESS16:
/*
- * Fixed IO Port Resource
+ * 32-Bit or 16-bit Address Resource:
+ * Add the size of any optional data (resource_source)
*/
- bytes_consumed = 4;
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io);
+ extra_struct_bytes =
+ acpi_rs_stream_option_length(resource_length,
+ minimum_aml_resource_length);
break;
- case ACPI_RDESC_TYPE_SMALL_VENDOR:
+ case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
/*
- * Vendor Specific Resource
+ * Extended IRQ:
+ * Point past the interrupt_vector_flags to get the
+ * interrupt_table_length.
*/
- buffer = byte_stream_buffer;
+ buffer++;
- temp8 = *buffer;
- temp8 = (u8) (temp8 & 0x7);
- bytes_consumed = temp8 + 1;
-
- /* Ensure a 32-bit boundary for the structure */
-
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
- structure_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) +
- (temp8 * sizeof(u8));
+ extra_struct_bytes =
+ /*
+ * Add 4 bytes for each additional interrupt. Note: at
+ * least one interrupt is required and is included in
+ * the minimum descriptor size
+ */
+ ((*buffer - 1) * sizeof(u32)) +
+ /* Add the size of any optional data (resource_source) */
+ acpi_rs_stream_option_length(resource_length -
+ extra_struct_bytes,
+ minimum_aml_resource_length);
break;
- case ACPI_RDESC_TYPE_END_TAG:
+ case ACPI_RESOURCE_NAME_ADDRESS64:
/*
- * End Tag
+ * 64-Bit Address Resource:
+ * Add the size of any optional data (resource_source)
+ * Ensure a 64-bit boundary for the structure
*/
- bytes_consumed = 2;
- structure_size = ACPI_RESOURCE_LENGTH;
- byte_stream_buffer_length = bytes_parsed;
+ extra_struct_bytes =
+ ACPI_ROUND_UP_to_64_bITS
+ (acpi_rs_stream_option_length
+ (resource_length, minimum_aml_resource_length));
break;
default:
- /*
- * If we get here, everything is out of sync,
- * exit with an error
- */
- return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
+ break;
}
- /* Update the return value and counter */
-
- buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(structure_size);
- bytes_parsed += bytes_consumed;
+ /* Update the required buffer size for the internal descriptor structs */
- /* Set the byte stream to point to the next resource */
+ temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] +
+ extra_struct_bytes);
+ buffer_size += (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(temp16);
- byte_stream_buffer += bytes_consumed;
+ /*
+ * Point to the next resource within the stream
+ * using the size of the header plus the length contained in the header
+ */
+ aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
}
- /* This is the data the caller needs */
+ /* Did not find an end_tag resource descriptor */
- *size_needed = buffer_size;
- return_ACPI_STATUS(AE_OK);
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
}
/*******************************************************************************
@@ -760,13 +539,13 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
for (table_index = 0; table_index < 4 && !name_found;
table_index++) {
- if ((ACPI_TYPE_STRING ==
- ACPI_GET_OBJECT_TYPE(*sub_object_list))
- ||
- ((ACPI_TYPE_LOCAL_REFERENCE ==
- ACPI_GET_OBJECT_TYPE(*sub_object_list))
- && ((*sub_object_list)->reference.opcode ==
- AML_INT_NAMEPATH_OP))) {
+ if (*sub_object_list && /* Null object allowed */
+ ((ACPI_TYPE_STRING ==
+ ACPI_GET_OBJECT_TYPE(*sub_object_list)) ||
+ ((ACPI_TYPE_LOCAL_REFERENCE ==
+ ACPI_GET_OBJECT_TYPE(*sub_object_list)) &&
+ ((*sub_object_list)->reference.opcode ==
+ AML_INT_NAMEPATH_OP)))) {
name_found = TRUE;
} else {
/* Look at the next element */
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 0911526b7ad..8c128dea325 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,10 +53,10 @@ ACPI_MODULE_NAME("rscreate")
*
* FUNCTION: acpi_rs_create_resource_list
*
- * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
- * output_buffer - Pointer to the user's buffer
+ * PARAMETERS: aml_buffer - Pointer to the resource byte stream
+ * output_buffer - Pointer to the user's buffer
*
- * RETURN: Status - AE_OK if okay, else a valid acpi_status code
+ * RETURN: Status: AE_OK if okay, else a valid acpi_status code
* If output_buffer is not large enough, output_buffer_length
* indicates how large output_buffer should be, else it
* indicates how may u8 elements of output_buffer are valid.
@@ -67,33 +67,30 @@ ACPI_MODULE_NAME("rscreate")
*
******************************************************************************/
acpi_status
-acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer,
+acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
struct acpi_buffer *output_buffer)
{
acpi_status status;
- u8 *byte_stream_start;
+ u8 *aml_start;
acpi_size list_size_needed = 0;
- u32 byte_stream_buffer_length;
+ u32 aml_buffer_length;
ACPI_FUNCTION_TRACE("rs_create_resource_list");
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_buffer = %p\n",
- byte_stream_buffer));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_buffer = %p\n", aml_buffer));
/* Params already validated, so we don't re-validate here */
- byte_stream_buffer_length = byte_stream_buffer->buffer.length;
- byte_stream_start = byte_stream_buffer->buffer.pointer;
+ aml_buffer_length = aml_buffer->buffer.length;
+ aml_start = aml_buffer->buffer.pointer;
/*
- * Pass the byte_stream_buffer into a module that can calculate
+ * Pass the aml_buffer into a module that can calculate
* the buffer size needed for the linked list
*/
- status =
- acpi_rs_get_list_length(byte_stream_start,
- byte_stream_buffer_length,
- &list_size_needed);
+ status = acpi_rs_get_list_length(aml_start, aml_buffer_length,
+ &list_size_needed);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
status, (u32) list_size_needed));
@@ -110,10 +107,8 @@ acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer,
/* Do the conversion */
- status =
- acpi_rs_byte_stream_to_list(byte_stream_start,
- byte_stream_buffer_length,
- output_buffer->pointer);
+ status = acpi_rs_convert_aml_to_resources(aml_start, aml_buffer_length,
+ output_buffer->pointer);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -212,21 +207,20 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/* Each element of the top-level package must also be a package */
if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "(PRT[%X]) Need sub-package, found %s\n",
- index,
- acpi_ut_get_object_type_name
- (*top_object_list)));
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X]) Need sub-package, found %s",
+ index,
+ acpi_ut_get_object_type_name
+ (*top_object_list)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Each sub-package must be of length 4 */
if ((*top_object_list)->package.count != 4) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "(PRT[%X]) Need package of length 4, found length %d\n",
- index,
- (*top_object_list)->package.count));
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X]) Need package of length 4, found length %d",
+ index, (*top_object_list)->package.count));
return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
}
@@ -243,11 +237,10 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->address = obj_desc->integer.value;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "(PRT[%X].Address) Need Integer, found %s\n",
- index,
- acpi_ut_get_object_type_name
- (obj_desc)));
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X].Address) Need Integer, found %s",
+ index,
+ acpi_ut_get_object_type_name(obj_desc)));
return_ACPI_STATUS(AE_BAD_DATA);
}
@@ -257,76 +250,83 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->pin = (u32) obj_desc->integer.value;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "(PRT[%X].Pin) Need Integer, found %s\n",
- index,
- acpi_ut_get_object_type_name
- (obj_desc)));
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X].Pin) Need Integer, found %s",
+ index,
+ acpi_ut_get_object_type_name(obj_desc)));
return_ACPI_STATUS(AE_BAD_DATA);
}
- /* 3) Third subobject: Dereference the PRT.source_name */
-
+ /*
+ * 3) Third subobject: Dereference the PRT.source_name
+ * The name may be unresolved (slack mode), so allow a null object
+ */
obj_desc = sub_object_list[2];
- switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
- case ACPI_TYPE_LOCAL_REFERENCE:
-
- if (obj_desc->reference.opcode != AML_INT_NAMEPATH_OP) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "(PRT[%X].Source) Need name, found reference op %X\n",
- index,
- obj_desc->reference.opcode));
+ if (obj_desc) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+ if (obj_desc->reference.opcode !=
+ AML_INT_NAMEPATH_OP) {
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X].Source) Need name, found reference op %X",
+ index,
+ obj_desc->reference.
+ opcode));
+ return_ACPI_STATUS(AE_BAD_DATA);
+ }
+
+ node = obj_desc->reference.node;
+
+ /* Use *remaining* length of the buffer as max for pathname */
+
+ path_buffer.length = output_buffer->length -
+ (u32) ((u8 *) user_prt->source -
+ (u8 *) output_buffer->pointer);
+ path_buffer.pointer = user_prt->source;
+
+ status =
+ acpi_ns_handle_to_pathname((acpi_handle)
+ node,
+ &path_buffer);
+
+ /* +1 to include null terminator */
+
+ user_prt->length +=
+ (u32) ACPI_STRLEN(user_prt->source) + 1;
+ break;
+
+ case ACPI_TYPE_STRING:
+
+ ACPI_STRCPY(user_prt->source,
+ obj_desc->string.pointer);
+
+ /*
+ * Add to the Length field the length of the string
+ * (add 1 for terminator)
+ */
+ user_prt->length += obj_desc->string.length + 1;
+ break;
+
+ case ACPI_TYPE_INTEGER:
+ /*
+ * If this is a number, then the Source Name is NULL, since the
+ * entire buffer was zeroed out, we can leave this alone.
+ *
+ * Add to the Length field the length of the u32 NULL
+ */
+ user_prt->length += sizeof(u32);
+ break;
+
+ default:
+
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X].Source) Need Ref/String/Integer, found %s",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
return_ACPI_STATUS(AE_BAD_DATA);
}
-
- node = obj_desc->reference.node;
-
- /* Use *remaining* length of the buffer as max for pathname */
-
- path_buffer.length = output_buffer->length -
- (u32) ((u8 *) user_prt->source -
- (u8 *) output_buffer->pointer);
- path_buffer.pointer = user_prt->source;
-
- status =
- acpi_ns_handle_to_pathname((acpi_handle) node,
- &path_buffer);
-
- /* +1 to include null terminator */
-
- user_prt->length +=
- (u32) ACPI_STRLEN(user_prt->source) + 1;
- break;
-
- case ACPI_TYPE_STRING:
-
- ACPI_STRCPY(user_prt->source, obj_desc->string.pointer);
-
- /*
- * Add to the Length field the length of the string
- * (add 1 for terminator)
- */
- user_prt->length += obj_desc->string.length + 1;
- break;
-
- case ACPI_TYPE_INTEGER:
- /*
- * If this is a number, then the Source Name is NULL, since the
- * entire buffer was zeroed out, we can leave this alone.
- *
- * Add to the Length field the length of the u32 NULL
- */
- user_prt->length += sizeof(u32);
- break;
-
- default:
-
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "(PRT[%X].Source) Need Ref/String/Integer, found %s\n",
- index,
- acpi_ut_get_object_type_name
- (obj_desc)));
- return_ACPI_STATUS(AE_BAD_DATA);
}
/* Now align the current length */
@@ -340,11 +340,10 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->source_index = (u32) obj_desc->integer.value;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "(PRT[%X].source_index) Need Integer, found %s\n",
- index,
- acpi_ut_get_object_type_name
- (obj_desc)));
+ ACPI_ERROR((AE_INFO,
+ "(PRT[%X].source_index) Need Integer, found %s",
+ index,
+ acpi_ut_get_object_type_name(obj_desc)));
return_ACPI_STATUS(AE_BAD_DATA);
}
@@ -360,7 +359,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/*******************************************************************************
*
- * FUNCTION: acpi_rs_create_byte_stream
+ * FUNCTION: acpi_rs_create_aml_resources
*
* PARAMETERS: linked_list_buffer - Pointer to the resource linked list
* output_buffer - Pointer to the user's buffer
@@ -377,13 +376,13 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
******************************************************************************/
acpi_status
-acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
- struct acpi_buffer *output_buffer)
+acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
+ struct acpi_buffer *output_buffer)
{
acpi_status status;
- acpi_size byte_stream_size_needed = 0;
+ acpi_size aml_size_needed = 0;
- ACPI_FUNCTION_TRACE("rs_create_byte_stream");
+ ACPI_FUNCTION_TRACE("rs_create_aml_resources");
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n",
linked_list_buffer));
@@ -394,11 +393,10 @@ acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
* Pass the linked_list_buffer into a module that calculates
* the buffer size needed for the byte stream.
*/
- status = acpi_rs_get_byte_stream_length(linked_list_buffer,
- &byte_stream_size_needed);
+ status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n",
- (u32) byte_stream_size_needed,
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_size_needed=%X, %s\n",
+ (u32) aml_size_needed,
acpi_format_exception(status)));
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -406,8 +404,7 @@ acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
/* Validate/Allocate/Clear caller buffer */
- status =
- acpi_ut_initialize_buffer(output_buffer, byte_stream_size_needed);
+ status = acpi_ut_initialize_buffer(output_buffer, aml_size_needed);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -415,9 +412,9 @@ acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
/* Do the conversion */
status =
- acpi_rs_list_to_byte_stream(linked_list_buffer,
- byte_stream_size_needed,
- output_buffer->pointer);
+ acpi_rs_convert_resources_to_aml(linked_list_buffer,
+ aml_size_needed,
+ output_buffer->pointer);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index 75bd34d1783..e7de061cf88 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,1063 +49,720 @@ ACPI_MODULE_NAME("rsdump")
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/* Local prototypes */
-static void acpi_rs_dump_irq(union acpi_resource_data *data);
+static void acpi_rs_out_string(char *title, char *value);
-static void acpi_rs_dump_address16(union acpi_resource_data *data);
+static void acpi_rs_out_integer8(char *title, u8 value);
-static void acpi_rs_dump_address32(union acpi_resource_data *data);
+static void acpi_rs_out_integer16(char *title, u16 value);
-static void acpi_rs_dump_address64(union acpi_resource_data *data);
+static void acpi_rs_out_integer32(char *title, u32 value);
-static void acpi_rs_dump_dma(union acpi_resource_data *data);
+static void acpi_rs_out_integer64(char *title, u64 value);
-static void acpi_rs_dump_io(union acpi_resource_data *data);
+static void acpi_rs_out_title(char *title);
-static void acpi_rs_dump_extended_irq(union acpi_resource_data *data);
+static void acpi_rs_dump_byte_list(u16 length, u8 * data);
-static void acpi_rs_dump_fixed_io(union acpi_resource_data *data);
+static void acpi_rs_dump_dword_list(u8 length, u32 * data);
-static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data);
+static void acpi_rs_dump_short_byte_list(u8 length, u8 * data);
-static void acpi_rs_dump_memory24(union acpi_resource_data *data);
+static void
+acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source);
-static void acpi_rs_dump_memory32(union acpi_resource_data *data);
+static void acpi_rs_dump_address_common(union acpi_resource_data *resource);
-static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data);
+static void
+acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table);
-static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data);
+#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f)
+#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f)
+#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info))
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dump_irq
+ * Resource Descriptor info tables
*
- * PARAMETERS: Data - pointer to the resource structure to dump.
- *
- * RETURN: None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
+ * Note: The first table entry must be a Title or Literal and must contain
+ * the table length (number of table entries)
*
******************************************************************************/
-static void acpi_rs_dump_irq(union acpi_resource_data *data)
-{
- struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *)data;
- u8 index = 0;
-
- ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf("IRQ Resource\n");
+struct acpi_rsdump_info acpi_rs_dump_irq[6] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering",
+ acpi_gbl_HEdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity",
+ acpi_gbl_LLdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing",
+ acpi_gbl_SHRdecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count),
+ "Interrupt Count", NULL},
+ {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]),
+ "Interrupt List", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_dma[6] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed",
+ acpi_gbl_TYPdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering",
+ acpi_gbl_BMdecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type",
+ acpi_gbl_SIZdecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count",
+ NULL},
+ {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List",
+ NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_start_dpf[3] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf),
+ "Start-Dependent-Functions", NULL},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority),
+ "Compatibility Priority", acpi_gbl_config_decode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness),
+ "Performance/Robustness", acpi_gbl_config_decode}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf),
+ "End-Dependent-Functions", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_io[6] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding",
+ acpi_gbl_io_decode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length",
+ NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io),
+ "Fixed I/O", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length),
+ "Address Length", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_vendor[3] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor),
+ "Vendor Specific", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL},
+ {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data",
+ NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "end_tag",
+ NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_memory24[6] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24),
+ "24-Bit Memory Range", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect),
+ "Write Protect", acpi_gbl_RWdecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum",
+ NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum",
+ NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment",
+ NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length),
+ "Address Length", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_memory32[6] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32),
+ "32-Bit Memory Range", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect),
+ "Write Protect", acpi_gbl_RWdecode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum",
+ NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum",
+ NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment",
+ NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length),
+ "Address Length", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32),
+ "32-Bit Fixed Memory Range", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect),
+ "Write Protect", acpi_gbl_RWdecode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address",
+ NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length),
+ "Address Length", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_address16[8] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16),
+ "16-Bit WORD Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity",
+ NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum",
+ NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum",
+ NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset),
+ "Translation Offset", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length),
+ "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_address32[8] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32),
+ "32-Bit DWORD Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity",
+ NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum",
+ NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum",
+ NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset),
+ "Translation Offset", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length),
+ "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_address64[8] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64),
+ "64-Bit QWORD Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity",
+ NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum",
+ NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum",
+ NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset),
+ "Translation Offset", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length),
+ "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64),
+ "64-Bit Extended Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity),
+ "Granularity", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum),
+ "Address Minimum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum),
+ "Address Maximum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset),
+ "Translation Offset", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length),
+ "Address Length", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific),
+ "Type-Specific Attribute", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq),
+ "Extended IRQ", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer),
+ "Type", acpi_gbl_consume_decode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering),
+ "Triggering", acpi_gbl_HEdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity",
+ acpi_gbl_LLdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing",
+ acpi_gbl_SHRdecode},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL,
+ NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count),
+ "Interrupt Count", NULL},
+ {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]),
+ "Interrupt List", NULL}
+};
+
+struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg),
+ "Generic Register", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID",
+ NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width",
+ NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset",
+ NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size),
+ "Access Size", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL}
+};
- acpi_os_printf(" %s Triggered\n",
- ACPI_LEVEL_SENSITIVE ==
- irq_data->edge_level ? "Level" : "Edge");
-
- acpi_os_printf(" Active %s\n",
- ACPI_ACTIVE_LOW ==
- irq_data->active_high_low ? "Low" : "High");
-
- acpi_os_printf(" %s\n",
- ACPI_SHARED ==
- irq_data->shared_exclusive ? "Shared" : "Exclusive");
-
- acpi_os_printf(" %X Interrupts ( ", irq_data->number_of_interrupts);
-
- for (index = 0; index < irq_data->number_of_interrupts; index++) {
- acpi_os_printf("%X ", irq_data->interrupts[index]);
- }
+/*
+ * Tables used for common address descriptor flag fields
+ */
+static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL,
+ NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer),
+ "Consumer/Producer", acpi_gbl_consume_decode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode",
+ acpi_gbl_DECdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed),
+ "Min Relocatability", acpi_gbl_min_decode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed),
+ "Max Relocatability", acpi_gbl_max_decode}
+};
+
+static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = {
+ {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags),
+ "Resource Type", (void *)"Memory Range"},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect),
+ "Write Protect", acpi_gbl_RWdecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching),
+ "Caching", acpi_gbl_MEMdecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type),
+ "Range Type", acpi_gbl_MTPdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation),
+ "Translation", acpi_gbl_TTPdecode}
+};
+
+static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = {
+ {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags),
+ "Resource Type", (void *)"I/O Range"},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type),
+ "Range Type", acpi_gbl_RNGdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation),
+ "Translation", acpi_gbl_TTPdecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type),
+ "Translation Type", acpi_gbl_TRSdecode}
+};
- acpi_os_printf(")\n");
- return;
-}
+/*
+ * Table used to dump _PRT contents
+ */
+static struct acpi_rsdump_info acpi_rs_dump_prt[5] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL},
+ {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL},
+ {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL},
+ {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dump_dma
+ * FUNCTION: acpi_rs_dump_descriptor
*
- * PARAMETERS: Data - pointer to the resource structure to dump.
+ * PARAMETERS: Resource
*
* RETURN: None
*
- * DESCRIPTION: Prints out the various members of the Data structure type.
+ * DESCRIPTION:
*
******************************************************************************/
-static void acpi_rs_dump_dma(union acpi_resource_data *data)
+static void
+acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
{
- struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *)data;
- u8 index = 0;
-
- ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf("DMA Resource\n");
-
- switch (dma_data->type) {
- case ACPI_COMPATIBILITY:
- acpi_os_printf(" Compatibility mode\n");
- break;
-
- case ACPI_TYPE_A:
- acpi_os_printf(" Type A\n");
- break;
-
- case ACPI_TYPE_B:
- acpi_os_printf(" Type B\n");
- break;
-
- case ACPI_TYPE_F:
- acpi_os_printf(" Type F\n");
- break;
-
- default:
- acpi_os_printf(" Invalid DMA type\n");
- break;
- }
-
- acpi_os_printf(" %sBus Master\n",
- ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a ");
-
- switch (dma_data->transfer) {
- case ACPI_TRANSFER_8:
- acpi_os_printf(" 8-bit only transfer\n");
- break;
+ u8 *target = NULL;
+ u8 *previous_target;
+ char *name;
+ u8 count;
+
+ /* First table entry must contain the table length (# of table entries) */
+
+ count = table->offset;
+
+ while (count) {
+ previous_target = target;
+ target = ACPI_ADD_PTR(u8, resource, table->offset);
+ name = table->name;
+
+ switch (table->opcode) {
+ case ACPI_RSD_TITLE:
+ /*
+ * Optional resource title
+ */
+ if (table->name) {
+ acpi_os_printf("%s Resource\n", name);
+ }
+ break;
- case ACPI_TRANSFER_8_16:
- acpi_os_printf(" 8 and 16-bit transfer\n");
- break;
+ /* Strings */
- case ACPI_TRANSFER_16:
- acpi_os_printf(" 16 bit only transfer\n");
- break;
+ case ACPI_RSD_LITERAL:
+ acpi_rs_out_string(name,
+ ACPI_CAST_PTR(char, table->pointer));
+ break;
- default:
- acpi_os_printf(" Invalid transfer preference\n");
- break;
- }
+ case ACPI_RSD_STRING:
+ acpi_rs_out_string(name, ACPI_CAST_PTR(char, target));
+ break;
- acpi_os_printf(" Number of Channels: %X ( ",
- dma_data->number_of_channels);
+ /* Data items, 8/16/32/64 bit */
- for (index = 0; index < dma_data->number_of_channels; index++) {
- acpi_os_printf("%X ", dma_data->channels[index]);
- }
+ case ACPI_RSD_UINT8:
+ acpi_rs_out_integer8(name, ACPI_GET8(target));
+ break;
- acpi_os_printf(")\n");
- return;
-}
+ case ACPI_RSD_UINT16:
+ acpi_rs_out_integer16(name, ACPI_GET16(target));
+ break;
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_dump_start_depend_fns
- *
- * PARAMETERS: Data - pointer to the resource structure to dump.
- *
- * RETURN: None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
+ case ACPI_RSD_UINT32:
+ acpi_rs_out_integer32(name, ACPI_GET32(target));
+ break;
-static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data)
-{
- struct acpi_resource_start_dpf *sdf_data =
- (struct acpi_resource_start_dpf *)data;
+ case ACPI_RSD_UINT64:
+ acpi_rs_out_integer64(name, ACPI_GET64(target));
+ break;
- ACPI_FUNCTION_ENTRY();
+ /* Flags: 1-bit and 2-bit flags supported */
- acpi_os_printf("Start Dependent Functions Resource\n");
+ case ACPI_RSD_1BITFLAG:
+ acpi_rs_out_string(name, ACPI_CAST_PTR(char,
+ table->
+ pointer[*target &
+ 0x01]));
+ break;
- switch (sdf_data->compatibility_priority) {
- case ACPI_GOOD_CONFIGURATION:
- acpi_os_printf(" Good configuration\n");
- break;
+ case ACPI_RSD_2BITFLAG:
+ acpi_rs_out_string(name, ACPI_CAST_PTR(char,
+ table->
+ pointer[*target &
+ 0x03]));
+ break;
- case ACPI_ACCEPTABLE_CONFIGURATION:
- acpi_os_printf(" Acceptable configuration\n");
- break;
+ case ACPI_RSD_SHORTLIST:
+ /*
+ * Short byte list (single line output) for DMA and IRQ resources
+ * Note: The list length is obtained from the previous table entry
+ */
+ if (previous_target) {
+ acpi_rs_out_title(name);
+ acpi_rs_dump_short_byte_list(*previous_target,
+ target);
+ }
+ break;
- case ACPI_SUB_OPTIMAL_CONFIGURATION:
- acpi_os_printf(" Sub-optimal configuration\n");
- break;
+ case ACPI_RSD_LONGLIST:
+ /*
+ * Long byte list for Vendor resource data
+ * Note: The list length is obtained from the previous table entry
+ */
+ if (previous_target) {
+ acpi_rs_dump_byte_list(ACPI_GET16
+ (previous_target),
+ target);
+ }
+ break;
- default:
- acpi_os_printf(" Invalid compatibility priority\n");
- break;
- }
+ case ACPI_RSD_DWORDLIST:
+ /*
+ * Dword list for Extended Interrupt resources
+ * Note: The list length is obtained from the previous table entry
+ */
+ if (previous_target) {
+ acpi_rs_dump_dword_list(*previous_target,
+ ACPI_CAST_PTR(u32,
+ target));
+ }
+ break;
- switch (sdf_data->performance_robustness) {
- case ACPI_GOOD_CONFIGURATION:
- acpi_os_printf(" Good configuration\n");
- break;
+ case ACPI_RSD_ADDRESS:
+ /*
+ * Common flags for all Address resources
+ */
+ acpi_rs_dump_address_common(ACPI_CAST_PTR
+ (union acpi_resource_data,
+ target));
+ break;
- case ACPI_ACCEPTABLE_CONFIGURATION:
- acpi_os_printf(" Acceptable configuration\n");
- break;
+ case ACPI_RSD_SOURCE:
+ /*
+ * Optional resource_source for Address resources
+ */
+ acpi_rs_dump_resource_source(ACPI_CAST_PTR
+ (struct
+ acpi_resource_source,
+ target));
+ break;
- case ACPI_SUB_OPTIMAL_CONFIGURATION:
- acpi_os_printf(" Sub-optimal configuration\n");
- break;
+ default:
+ acpi_os_printf("**** Invalid table opcode [%X] ****\n",
+ table->opcode);
+ return;
+ }
- default:
- acpi_os_printf(" Invalid performance robustness preference\n");
- break;
+ table++;
+ count--;
}
-
- return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_dump_io
- *
- * PARAMETERS: Data - pointer to the resource structure to dump.
- *
- * RETURN: None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_io(union acpi_resource_data *data)
-{
- struct acpi_resource_io *io_data = (struct acpi_resource_io *)data;
-
- ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf("Io Resource\n");
-
- acpi_os_printf(" %d bit decode\n",
- ACPI_DECODE_16 == io_data->io_decode ? 16 : 10);
-
- acpi_os_printf(" Range minimum base: %08X\n",
- io_data->min_base_address);
-
- acpi_os_printf(" Range maximum base: %08X\n",
- io_data->max_base_address);
-
- acpi_os_printf(" Alignment: %08X\n", io_data->alignment);
-
- acpi_os_printf(" Range Length: %08X\n", io_data->range_length);
-
- return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_dump_fixed_io
- *
- * PARAMETERS: Data - pointer to the resource structure to dump.
- *
- * RETURN: None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_fixed_io(union acpi_resource_data *data)
-{
- struct acpi_resource_fixed_io *fixed_io_data =
- (struct acpi_resource_fixed_io *)data;
-
- ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf("Fixed Io Resource\n");
- acpi_os_printf(" Range base address: %08X",
- fixed_io_data->base_address);
-
- acpi_os_printf(" Range length: %08X", fixed_io_data->range_length);
-
- return;
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dump_vendor_specific
+ * FUNCTION: acpi_rs_dump_resource_source
*
- * PARAMETERS: Data - pointer to the resource structure to dump.
+ * PARAMETERS: resource_source - Pointer to a Resource Source struct
*
* RETURN: None
*
- * DESCRIPTION: Prints out the various members of the Data structure type.
+ * DESCRIPTION: Common routine for dumping the optional resource_source and the
+ * corresponding resource_source_index.
*
******************************************************************************/
-static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data)
+static void
+acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source)
{
- struct acpi_resource_vendor *vendor_data =
- (struct acpi_resource_vendor *)data;
- u16 index = 0;
-
ACPI_FUNCTION_ENTRY();
- acpi_os_printf("Vendor Specific Resource\n");
-
- acpi_os_printf(" Length: %08X\n", vendor_data->length);
-
- for (index = 0; index < vendor_data->length; index++) {
- acpi_os_printf(" Byte %X: %08X\n",
- index, vendor_data->reserved[index]);
+ if (resource_source->index == 0xFF) {
+ return;
}
- return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_dump_memory24
- *
- * PARAMETERS: Data - pointer to the resource structure to dump.
- *
- * RETURN: None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_memory24(union acpi_resource_data *data)
-{
- struct acpi_resource_mem24 *memory24_data =
- (struct acpi_resource_mem24 *)data;
-
- ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf("24-Bit Memory Range Resource\n");
-
- acpi_os_printf(" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- memory24_data->read_write_attribute ?
- "/Write" : " only");
-
- acpi_os_printf(" Range minimum base: %08X\n",
- memory24_data->min_base_address);
-
- acpi_os_printf(" Range maximum base: %08X\n",
- memory24_data->max_base_address);
-
- acpi_os_printf(" Alignment: %08X\n", memory24_data->alignment);
-
- acpi_os_printf(" Range length: %08X\n", memory24_data->range_length);
-
- return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_dump_memory32
- *
- * PARAMETERS: Data - pointer to the resource structure to dump.
- *
- * RETURN: None
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_memory32(union acpi_resource_data *data)
-{
- struct acpi_resource_mem32 *memory32_data =
- (struct acpi_resource_mem32 *)data;
-
- ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf("32-Bit Memory Range Resource\n");
-
- acpi_os_printf(" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- memory32_data->read_write_attribute ?
- "/Write" : " only");
-
- acpi_os_printf(" Range minimum base: %08X\n",
- memory32_data->min_base_address);
-
- acpi_os_printf(" Range maximum base: %08X\n",
- memory32_data->max_base_address);
-
- acpi_os_printf(" Alignment: %08X\n", memory32_data->alignment);
-
- acpi_os_printf(" Range length: %08X\n", memory32_data->range_length);
+ acpi_rs_out_integer8("Resource Source Index", resource_source->index);
- return;
+ acpi_rs_out_string("Resource Source",
+ resource_source->string_ptr ?
+ resource_source->string_ptr : "[Not Specified]");
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dump_fixed_memory32
+ * FUNCTION: acpi_rs_dump_address_common
*
- * PARAMETERS: Data - pointer to the resource structure to dump.
- *
- * RETURN:
- *
- * DESCRIPTION: Prints out the various members of the Data structure type.
- *
- ******************************************************************************/
-
-static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data)
-{
- struct acpi_resource_fixed_mem32 *fixed_memory32_data =
- (struct acpi_resource_fixed_mem32 *)data;
-
- ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf("32-Bit Fixed Location Memory Range Resource\n");
-
- acpi_os_printf(" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- fixed_memory32_data->
- read_write_attribute ? "/Write" : " Only");
-
- acpi_os_printf(" Range base address: %08X\n",
- fixed_memory32_data->range_base_address);
-
- acpi_os_printf(" Range length: %08X\n",
- fixed_memory32_data->range_length);
-
- return;
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_dump_address16
- *
- * PARAMETERS: Data - pointer to the resource structure to dump.
+ * PARAMETERS: Resource - Pointer to an internal resource descriptor
*
* RETURN: None
*
- * DESCRIPTION: Prints out the various members of the Data structure type.
+ * DESCRIPTION: Dump the fields that are common to all Address resource
+ * descriptors
*
******************************************************************************/
-static void acpi_rs_dump_address16(union acpi_resource_data *data)
+static void acpi_rs_dump_address_common(union acpi_resource_data *resource)
{
- struct acpi_resource_address16 *address16_data =
- (struct acpi_resource_address16 *)data;
-
ACPI_FUNCTION_ENTRY();
- acpi_os_printf("16-Bit Address Space Resource\n");
- acpi_os_printf(" Resource Type: ");
+ /* Decode the type-specific flags */
- switch (address16_data->resource_type) {
+ switch (resource->address.resource_type) {
case ACPI_MEMORY_RANGE:
- acpi_os_printf("Memory Range\n");
-
- switch (address16_data->attribute.memory.cache_attribute) {
- case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf
- (" Type Specific: Noncacheable memory\n");
- break;
-
- case ACPI_CACHABLE_MEMORY:
- acpi_os_printf(" Type Specific: Cacheable memory\n");
- break;
-
- case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf
- (" Type Specific: Write-combining memory\n");
- break;
-
- case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf
- (" Type Specific: Prefetchable memory\n");
- break;
-
- default:
- acpi_os_printf
- (" Type Specific: Invalid cache attribute\n");
- break;
- }
-
- acpi_os_printf(" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address16_data->attribute.memory.
- read_write_attribute ? "/Write" : " Only");
+ acpi_rs_dump_descriptor(resource, acpi_rs_dump_memory_flags);
break;
case ACPI_IO_RANGE:
- acpi_os_printf("I/O Range\n");
-
- switch (address16_data->attribute.io.range_attribute) {
- case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf
- (" Type Specific: Non-ISA Io Addresses\n");
- break;
-
- case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf(" Type Specific: ISA Io Addresses\n");
- break;
-
- case ACPI_ENTIRE_RANGE:
- acpi_os_printf
- (" Type Specific: ISA and non-ISA Io Addresses\n");
- break;
-
- default:
- acpi_os_printf
- (" Type Specific: Invalid range attribute\n");
- break;
- }
-
- acpi_os_printf(" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address16_data->attribute.io.
- translation_attribute ? "Sparse" : "Dense");
+ acpi_rs_dump_descriptor(resource, acpi_rs_dump_io_flags);
break;
case ACPI_BUS_NUMBER_RANGE:
- acpi_os_printf("Bus Number Range\n");
+ acpi_rs_out_string("Resource Type", "Bus Number Range");
break;
default:
- acpi_os_printf("0x%2.2X\n", address16_data->resource_type);
+ acpi_rs_out_integer8("Resource Type",
+ (u8) resource->address.resource_type);
break;
}
- acpi_os_printf(" Resource %s\n",
- ACPI_CONSUMER == address16_data->producer_consumer ?
- "Consumer" : "Producer");
-
- acpi_os_printf(" %s decode\n",
- ACPI_SUB_DECODE == address16_data->decode ?
- "Subtractive" : "Positive");
+ /* Decode the general flags */
- acpi_os_printf(" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ?
- "" : "not");
-
- acpi_os_printf(" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ?
- "" : "not");
-
- acpi_os_printf(" Granularity: %08X\n", address16_data->granularity);
-
- acpi_os_printf(" Address range min: %08X\n",
- address16_data->min_address_range);
-
- acpi_os_printf(" Address range max: %08X\n",
- address16_data->max_address_range);
-
- acpi_os_printf(" Address translation offset: %08X\n",
- address16_data->address_translation_offset);
-
- acpi_os_printf(" Address Length: %08X\n",
- address16_data->address_length);
-
- if (0xFF != address16_data->resource_source.index) {
- acpi_os_printf(" Resource Source Index: %X\n",
- address16_data->resource_source.index);
-
- acpi_os_printf(" Resource Source: %s\n",
- address16_data->resource_source.string_ptr);
- }
-
- return;
+ acpi_rs_dump_descriptor(resource, acpi_rs_dump_general_flags);
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dump_address32
+ * FUNCTION: acpi_rs_dump_resource_list
*
- * PARAMETERS: Data - pointer to the resource structure to dump.
+ * PARAMETERS: resource_list - Pointer to a resource descriptor list
*
* RETURN: None
*
- * DESCRIPTION: Prints out the various members of the Data structure type.
+ * DESCRIPTION: Dispatches the structure to the correct dump routine.
*
******************************************************************************/
-static void acpi_rs_dump_address32(union acpi_resource_data *data)
+void acpi_rs_dump_resource_list(struct acpi_resource *resource_list)
{
- struct acpi_resource_address32 *address32_data =
- (struct acpi_resource_address32 *)data;
+ u32 count = 0;
+ u32 type;
ACPI_FUNCTION_ENTRY();
- acpi_os_printf("32-Bit Address Space Resource\n");
-
- switch (address32_data->resource_type) {
- case ACPI_MEMORY_RANGE:
-
- acpi_os_printf(" Resource Type: Memory Range\n");
-
- switch (address32_data->attribute.memory.cache_attribute) {
- case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf
- (" Type Specific: Noncacheable memory\n");
- break;
-
- case ACPI_CACHABLE_MEMORY:
- acpi_os_printf(" Type Specific: Cacheable memory\n");
- break;
-
- case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf
- (" Type Specific: Write-combining memory\n");
- break;
-
- case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf
- (" Type Specific: Prefetchable memory\n");
- break;
-
- default:
- acpi_os_printf
- (" Type Specific: Invalid cache attribute\n");
- break;
- }
-
- acpi_os_printf(" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address32_data->attribute.memory.
- read_write_attribute ? "/Write" : " Only");
- break;
-
- case ACPI_IO_RANGE:
-
- acpi_os_printf(" Resource Type: Io Range\n");
+ if (!(acpi_dbg_level & ACPI_LV_RESOURCES)
+ || !(_COMPONENT & acpi_dbg_layer)) {
+ return;
+ }
- switch (address32_data->attribute.io.range_attribute) {
- case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf
- (" Type Specific: Non-ISA Io Addresses\n");
- break;
+ /* Walk list and dump all resource descriptors (END_TAG terminates) */
- case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf(" Type Specific: ISA Io Addresses\n");
- break;
+ do {
+ acpi_os_printf("\n[%02X] ", count);
+ count++;
- case ACPI_ENTIRE_RANGE:
- acpi_os_printf
- (" Type Specific: ISA and non-ISA Io Addresses\n");
- break;
+ /* Validate Type before dispatch */
- default:
+ type = resource_list->type;
+ if (type > ACPI_RESOURCE_TYPE_MAX) {
acpi_os_printf
- (" Type Specific: Invalid Range attribute");
- break;
+ ("Invalid descriptor type (%X) in resource list\n",
+ resource_list->type);
+ return;
}
- acpi_os_printf(" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address32_data->attribute.io.
- translation_attribute ? "Sparse" : "Dense");
- break;
-
- case ACPI_BUS_NUMBER_RANGE:
-
- acpi_os_printf(" Resource Type: Bus Number Range\n");
- break;
-
- default:
-
- acpi_os_printf(" Resource Type: 0x%2.2X\n",
- address32_data->resource_type);
- break;
- }
-
- acpi_os_printf(" Resource %s\n",
- ACPI_CONSUMER == address32_data->producer_consumer ?
- "Consumer" : "Producer");
-
- acpi_os_printf(" %s decode\n",
- ACPI_SUB_DECODE == address32_data->decode ?
- "Subtractive" : "Positive");
-
- acpi_os_printf(" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ?
- "" : "not ");
-
- acpi_os_printf(" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ?
- "" : "not ");
+ /* Dump the resource descriptor */
- acpi_os_printf(" Granularity: %08X\n", address32_data->granularity);
+ acpi_rs_dump_descriptor(&resource_list->data,
+ acpi_gbl_dump_resource_dispatch[type]);
- acpi_os_printf(" Address range min: %08X\n",
- address32_data->min_address_range);
+ /* Point to the next resource structure */
- acpi_os_printf(" Address range max: %08X\n",
- address32_data->max_address_range);
+ resource_list =
+ ACPI_ADD_PTR(struct acpi_resource, resource_list,
+ resource_list->length);
- acpi_os_printf(" Address translation offset: %08X\n",
- address32_data->address_translation_offset);
+ /* Exit when END_TAG descriptor is reached */
- acpi_os_printf(" Address Length: %08X\n",
- address32_data->address_length);
-
- if (0xFF != address32_data->resource_source.index) {
- acpi_os_printf(" Resource Source Index: %X\n",
- address32_data->resource_source.index);
-
- acpi_os_printf(" Resource Source: %s\n",
- address32_data->resource_source.string_ptr);
- }
-
- return;
+ } while (type != ACPI_RESOURCE_TYPE_END_TAG);
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dump_address64
+ * FUNCTION: acpi_rs_dump_irq_list
*
- * PARAMETERS: Data - pointer to the resource structure to dump.
+ * PARAMETERS: route_table - Pointer to the routing table to dump.
*
* RETURN: None
*
- * DESCRIPTION: Prints out the various members of the Data structure type.
+ * DESCRIPTION: Print IRQ routing table
*
******************************************************************************/
-static void acpi_rs_dump_address64(union acpi_resource_data *data)
+void acpi_rs_dump_irq_list(u8 * route_table)
{
- struct acpi_resource_address64 *address64_data =
- (struct acpi_resource_address64 *)data;
+ struct acpi_pci_routing_table *prt_element;
+ u8 count;
ACPI_FUNCTION_ENTRY();
- acpi_os_printf("64-Bit Address Space Resource\n");
-
- switch (address64_data->resource_type) {
- case ACPI_MEMORY_RANGE:
-
- acpi_os_printf(" Resource Type: Memory Range\n");
-
- switch (address64_data->attribute.memory.cache_attribute) {
- case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf
- (" Type Specific: Noncacheable memory\n");
- break;
-
- case ACPI_CACHABLE_MEMORY:
- acpi_os_printf(" Type Specific: Cacheable memory\n");
- break;
-
- case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf
- (" Type Specific: Write-combining memory\n");
- break;
-
- case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf
- (" Type Specific: Prefetchable memory\n");
- break;
-
- default:
- acpi_os_printf
- (" Type Specific: Invalid cache attribute\n");
- break;
- }
-
- acpi_os_printf(" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address64_data->attribute.memory.
- read_write_attribute ? "/Write" : " Only");
- break;
-
- case ACPI_IO_RANGE:
-
- acpi_os_printf(" Resource Type: Io Range\n");
-
- switch (address64_data->attribute.io.range_attribute) {
- case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf
- (" Type Specific: Non-ISA Io Addresses\n");
- break;
-
- case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf(" Type Specific: ISA Io Addresses\n");
- break;
-
- case ACPI_ENTIRE_RANGE:
- acpi_os_printf
- (" Type Specific: ISA and non-ISA Io Addresses\n");
- break;
-
- default:
- acpi_os_printf
- (" Type Specific: Invalid Range attribute");
- break;
- }
-
- acpi_os_printf(" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address64_data->attribute.io.
- translation_attribute ? "Sparse" : "Dense");
- break;
-
- case ACPI_BUS_NUMBER_RANGE:
-
- acpi_os_printf(" Resource Type: Bus Number Range\n");
- break;
-
- default:
-
- acpi_os_printf(" Resource Type: 0x%2.2X\n",
- address64_data->resource_type);
- break;
+ if (!(acpi_dbg_level & ACPI_LV_RESOURCES)
+ || !(_COMPONENT & acpi_dbg_layer)) {
+ return;
}
- acpi_os_printf(" Resource %s\n",
- ACPI_CONSUMER == address64_data->producer_consumer ?
- "Consumer" : "Producer");
-
- acpi_os_printf(" %s decode\n",
- ACPI_SUB_DECODE == address64_data->decode ?
- "Subtractive" : "Positive");
-
- acpi_os_printf(" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ?
- "" : "not ");
-
- acpi_os_printf(" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ?
- "" : "not ");
+ prt_element = ACPI_CAST_PTR(struct acpi_pci_routing_table, route_table);
- acpi_os_printf(" Granularity: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64(address64_data->granularity));
+ /* Dump all table elements, Exit on zero length element */
- acpi_os_printf(" Address range min: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64(address64_data->min_address_range));
+ for (count = 0; prt_element->length; count++) {
+ acpi_os_printf("\n[%02X] PCI IRQ Routing Table Package\n",
+ count);
+ acpi_rs_dump_descriptor(prt_element, acpi_rs_dump_prt);
- acpi_os_printf(" Address range max: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64(address64_data->max_address_range));
-
- acpi_os_printf(" Address translation offset: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64(address64_data->
- address_translation_offset));
-
- acpi_os_printf(" Address Length: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64(address64_data->address_length));
-
- acpi_os_printf(" Type Specific Attributes: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64(address64_data->
- type_specific_attributes));
-
- if (0xFF != address64_data->resource_source.index) {
- acpi_os_printf(" Resource Source Index: %X\n",
- address64_data->resource_source.index);
-
- acpi_os_printf(" Resource Source: %s\n",
- address64_data->resource_source.string_ptr);
+ prt_element = ACPI_ADD_PTR(struct acpi_pci_routing_table,
+ prt_element, prt_element->length);
}
-
- return;
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dump_extended_irq
+ * FUNCTION: acpi_rs_out*
*
- * PARAMETERS: Data - pointer to the resource structure to dump.
+ * PARAMETERS: Title - Name of the resource field
+ * Value - Value of the resource field
*
* RETURN: None
*
- * DESCRIPTION: Prints out the various members of the Data structure type.
+ * DESCRIPTION: Miscellaneous helper functions to consistently format the
+ * output of the resource dump routines
*
******************************************************************************/
-static void acpi_rs_dump_extended_irq(union acpi_resource_data *data)
+static void acpi_rs_out_string(char *title, char *value)
{
- struct acpi_resource_ext_irq *ext_irq_data =
- (struct acpi_resource_ext_irq *)data;
- u8 index = 0;
-
- ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf("Extended IRQ Resource\n");
-
- acpi_os_printf(" Resource %s\n",
- ACPI_CONSUMER == ext_irq_data->producer_consumer ?
- "Consumer" : "Producer");
-
- acpi_os_printf(" %s\n",
- ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ?
- "Level" : "Edge");
-
- acpi_os_printf(" Active %s\n",
- ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ?
- "low" : "high");
-
- acpi_os_printf(" %s\n",
- ACPI_SHARED == ext_irq_data->shared_exclusive ?
- "Shared" : "Exclusive");
-
- acpi_os_printf(" Interrupts : %X ( ",
- ext_irq_data->number_of_interrupts);
-
- for (index = 0; index < ext_irq_data->number_of_interrupts; index++) {
- acpi_os_printf("%X ", ext_irq_data->interrupts[index]);
- }
-
- acpi_os_printf(")\n");
-
- if (0xFF != ext_irq_data->resource_source.index) {
- acpi_os_printf(" Resource Source Index: %X",
- ext_irq_data->resource_source.index);
-
- acpi_os_printf(" Resource Source: %s",
- ext_irq_data->resource_source.string_ptr);
+ acpi_os_printf("%27s : %s", title, value);
+ if (!*value) {
+ acpi_os_printf("[NULL NAMESTRING]");
}
-
- return;
+ acpi_os_printf("\n");
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_dump_resource_list
- *
- * PARAMETERS: Resource - pointer to the resource structure to dump.
- *
- * RETURN: None
- *
- * DESCRIPTION: Dispatches the structure to the correct dump routine.
- *
- ******************************************************************************/
-
-void acpi_rs_dump_resource_list(struct acpi_resource *resource)
+static void acpi_rs_out_integer8(char *title, u8 value)
{
- u8 count = 0;
- u8 done = FALSE;
-
- ACPI_FUNCTION_ENTRY();
-
- if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
- while (!done) {
- acpi_os_printf("Resource structure %X.\n", count++);
-
- switch (resource->id) {
- case ACPI_RSTYPE_IRQ:
- acpi_rs_dump_irq(&resource->data);
- break;
-
- case ACPI_RSTYPE_DMA:
- acpi_rs_dump_dma(&resource->data);
- break;
-
- case ACPI_RSTYPE_START_DPF:
- acpi_rs_dump_start_depend_fns(&resource->data);
- break;
-
- case ACPI_RSTYPE_END_DPF:
- acpi_os_printf
- ("end_dependent_functions Resource\n");
- /* acpi_rs_dump_end_dependent_functions (Resource->Data); */
- break;
-
- case ACPI_RSTYPE_IO:
- acpi_rs_dump_io(&resource->data);
- break;
-
- case ACPI_RSTYPE_FIXED_IO:
- acpi_rs_dump_fixed_io(&resource->data);
- break;
-
- case ACPI_RSTYPE_VENDOR:
- acpi_rs_dump_vendor_specific(&resource->data);
- break;
-
- case ACPI_RSTYPE_END_TAG:
- /*rs_dump_end_tag (Resource->Data); */
- acpi_os_printf("end_tag Resource\n");
- done = TRUE;
- break;
-
- case ACPI_RSTYPE_MEM24:
- acpi_rs_dump_memory24(&resource->data);
- break;
-
- case ACPI_RSTYPE_MEM32:
- acpi_rs_dump_memory32(&resource->data);
- break;
-
- case ACPI_RSTYPE_FIXED_MEM32:
- acpi_rs_dump_fixed_memory32(&resource->data);
- break;
-
- case ACPI_RSTYPE_ADDRESS16:
- acpi_rs_dump_address16(&resource->data);
- break;
-
- case ACPI_RSTYPE_ADDRESS32:
- acpi_rs_dump_address32(&resource->data);
- break;
-
- case ACPI_RSTYPE_ADDRESS64:
- acpi_rs_dump_address64(&resource->data);
- break;
-
- case ACPI_RSTYPE_EXT_IRQ:
- acpi_rs_dump_extended_irq(&resource->data);
- break;
+ acpi_os_printf("%27s : %2.2X\n", title, value);
+}
- default:
- acpi_os_printf("Invalid resource type\n");
- break;
+static void acpi_rs_out_integer16(char *title, u16 value)
+{
+ acpi_os_printf("%27s : %4.4X\n", title, value);
+}
- }
+static void acpi_rs_out_integer32(char *title, u32 value)
+{
+ acpi_os_printf("%27s : %8.8X\n", title, value);
+}
- resource =
- ACPI_PTR_ADD(struct acpi_resource, resource,
- resource->length);
- }
- }
+static void acpi_rs_out_integer64(char *title, u64 value)
+{
+ acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
+}
- return;
+static void acpi_rs_out_title(char *title)
+{
+ acpi_os_printf("%27s : ", title);
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dump_irq_list
+ * FUNCTION: acpi_rs_dump*List
*
- * PARAMETERS: route_table - pointer to the routing table to dump.
+ * PARAMETERS: Length - Number of elements in the list
+ * Data - Start of the list
*
* RETURN: None
*
- * DESCRIPTION: Dispatches the structures to the correct dump routine.
+ * DESCRIPTION: Miscellaneous functions to dump lists of raw data
*
******************************************************************************/
-void acpi_rs_dump_irq_list(u8 * route_table)
+static void acpi_rs_dump_byte_list(u16 length, u8 * data)
{
- u8 *buffer = route_table;
- u8 count = 0;
- u8 done = FALSE;
- struct acpi_pci_routing_table *prt_element;
+ u8 i;
- ACPI_FUNCTION_ENTRY();
-
- if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
- prt_element =
- ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
-
- while (!done) {
- acpi_os_printf("PCI IRQ Routing Table structure %X.\n",
- count++);
-
- acpi_os_printf(" Address: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64(prt_element->
- address));
+ for (i = 0; i < length; i++) {
+ acpi_os_printf("%25s%2.2X : %2.2X\n", "Byte", i, data[i]);
+ }
+}
- acpi_os_printf(" Pin: %X\n", prt_element->pin);
+static void acpi_rs_dump_short_byte_list(u8 length, u8 * data)
+{
+ u8 i;
- acpi_os_printf(" Source: %s\n", prt_element->source);
+ for (i = 0; i < length; i++) {
+ acpi_os_printf("%X ", data[i]);
+ }
+ acpi_os_printf("\n");
+}
- acpi_os_printf(" source_index: %X\n",
- prt_element->source_index);
+static void acpi_rs_dump_dword_list(u8 length, u32 * data)
+{
+ u8 i;
- buffer += prt_element->length;
- prt_element =
- ACPI_CAST_PTR(struct acpi_pci_routing_table,
- buffer);
- if (0 == prt_element->length) {
- done = TRUE;
- }
- }
+ for (i = 0; i < length; i++) {
+ acpi_os_printf("%25s%2.2X : %8.8X\n", "Dword", i, data[i]);
}
-
- return;
}
#endif
diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c
new file mode 100644
index 00000000000..d9ae64b77bd
--- /dev/null
+++ b/drivers/acpi/resources/rsinfo.c
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ *
+ * Module Name: rsinfo - Dispatch and Info tables
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2006, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include <acpi/acresrc.h>
+
+#define _COMPONENT ACPI_RESOURCES
+ACPI_MODULE_NAME("rsinfo")
+
+/*
+ * Resource dispatch and information tables. Any new resource types (either
+ * Large or Small) must be reflected in each of these tables, so they are here
+ * in one place.
+ *
+ * The tables for Large descriptors are indexed by bits 6:0 of the AML
+ * descriptor type byte. The tables for Small descriptors are indexed by
+ * bits 6:3 of the descriptor byte. The tables for internal resource
+ * descriptors are indexed by the acpi_resource_type field.
+ */
+/* Dispatch table for resource-to-AML (Set Resource) conversion functions */
+struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[] = {
+ acpi_rs_set_irq, /* 0x00, ACPI_RESOURCE_TYPE_IRQ */
+ acpi_rs_convert_dma, /* 0x01, ACPI_RESOURCE_TYPE_DMA */
+ acpi_rs_set_start_dpf, /* 0x02, ACPI_RESOURCE_TYPE_START_DEPENDENT */
+ acpi_rs_convert_end_dpf, /* 0x03, ACPI_RESOURCE_TYPE_END_DEPENDENT */
+ acpi_rs_convert_io, /* 0x04, ACPI_RESOURCE_TYPE_IO */
+ acpi_rs_convert_fixed_io, /* 0x05, ACPI_RESOURCE_TYPE_FIXED_IO */
+ acpi_rs_set_vendor, /* 0x06, ACPI_RESOURCE_TYPE_VENDOR */
+ acpi_rs_convert_end_tag, /* 0x07, ACPI_RESOURCE_TYPE_END_TAG */
+ acpi_rs_convert_memory24, /* 0x08, ACPI_RESOURCE_TYPE_MEMORY24 */
+ acpi_rs_convert_memory32, /* 0x09, ACPI_RESOURCE_TYPE_MEMORY32 */
+ acpi_rs_convert_fixed_memory32, /* 0x0A, ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */
+ acpi_rs_convert_address16, /* 0x0B, ACPI_RESOURCE_TYPE_ADDRESS16 */
+ acpi_rs_convert_address32, /* 0x0C, ACPI_RESOURCE_TYPE_ADDRESS32 */
+ acpi_rs_convert_address64, /* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */
+ acpi_rs_convert_ext_address64, /* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
+ acpi_rs_convert_ext_irq, /* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
+ acpi_rs_convert_generic_reg /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+};
+
+/* Dispatch tables for AML-to-resource (Get Resource) conversion functions */
+
+struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = {
+ /* Small descriptors */
+
+ NULL, /* 0x00, Reserved */
+ NULL, /* 0x01, Reserved */
+ NULL, /* 0x02, Reserved */
+ NULL, /* 0x03, Reserved */
+ acpi_rs_get_irq, /* 0x04, ACPI_RESOURCE_NAME_IRQ */
+ acpi_rs_convert_dma, /* 0x05, ACPI_RESOURCE_NAME_DMA */
+ acpi_rs_get_start_dpf, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */
+ acpi_rs_convert_end_dpf, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
+ acpi_rs_convert_io, /* 0x08, ACPI_RESOURCE_NAME_IO */
+ acpi_rs_convert_fixed_io, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */
+ NULL, /* 0x0A, Reserved */
+ NULL, /* 0x0B, Reserved */
+ NULL, /* 0x0C, Reserved */
+ NULL, /* 0x0D, Reserved */
+ acpi_rs_get_vendor_small, /* 0x0E, ACPI_RESOURCE_NAME_VENDOR_SMALL */
+ acpi_rs_convert_end_tag, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG */
+
+ /* Large descriptors */
+
+ NULL, /* 0x00, Reserved */
+ acpi_rs_convert_memory24, /* 0x01, ACPI_RESOURCE_NAME_MEMORY24 */
+ acpi_rs_convert_generic_reg, /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */
+ NULL, /* 0x03, Reserved */
+ acpi_rs_get_vendor_large, /* 0x04, ACPI_RESOURCE_NAME_VENDOR_LARGE */
+ acpi_rs_convert_memory32, /* 0x05, ACPI_RESOURCE_NAME_MEMORY32 */
+ acpi_rs_convert_fixed_memory32, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY32 */
+ acpi_rs_convert_address32, /* 0x07, ACPI_RESOURCE_NAME_ADDRESS32 */
+ acpi_rs_convert_address16, /* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */
+ acpi_rs_convert_ext_irq, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */
+ acpi_rs_convert_address64, /* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */
+ acpi_rs_convert_ext_address64 /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */
+};
+
+#ifdef ACPI_FUTURE_USAGE
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+
+/* Dispatch table for resource dump functions */
+
+struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = {
+ acpi_rs_dump_irq, /* ACPI_RESOURCE_TYPE_IRQ */
+ acpi_rs_dump_dma, /* ACPI_RESOURCE_TYPE_DMA */
+ acpi_rs_dump_start_dpf, /* ACPI_RESOURCE_TYPE_START_DEPENDENT */
+ acpi_rs_dump_end_dpf, /* ACPI_RESOURCE_TYPE_END_DEPENDENT */
+ acpi_rs_dump_io, /* ACPI_RESOURCE_TYPE_IO */
+ acpi_rs_dump_fixed_io, /* ACPI_RESOURCE_TYPE_FIXED_IO */
+ acpi_rs_dump_vendor, /* ACPI_RESOURCE_TYPE_VENDOR */
+ acpi_rs_dump_end_tag, /* ACPI_RESOURCE_TYPE_END_TAG */
+ acpi_rs_dump_memory24, /* ACPI_RESOURCE_TYPE_MEMORY24 */
+ acpi_rs_dump_memory32, /* ACPI_RESOURCE_TYPE_MEMORY32 */
+ acpi_rs_dump_fixed_memory32, /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */
+ acpi_rs_dump_address16, /* ACPI_RESOURCE_TYPE_ADDRESS16 */
+ acpi_rs_dump_address32, /* ACPI_RESOURCE_TYPE_ADDRESS32 */
+ acpi_rs_dump_address64, /* ACPI_RESOURCE_TYPE_ADDRESS64 */
+ acpi_rs_dump_ext_address64, /* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
+ acpi_rs_dump_ext_irq, /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
+ acpi_rs_dump_generic_reg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+};
+#endif
+#endif /* ACPI_FUTURE_USAGE */
+/*
+ * Base sizes for external AML resource descriptors, indexed by internal type.
+ * Includes size of the descriptor header (1 byte for small descriptors,
+ * 3 bytes for large descriptors)
+ */
+const u8 acpi_gbl_aml_resource_sizes[] = {
+ sizeof(struct aml_resource_irq), /* ACPI_RESOURCE_TYPE_IRQ (optional Byte 3 always created) */
+ sizeof(struct aml_resource_dma), /* ACPI_RESOURCE_TYPE_DMA */
+ sizeof(struct aml_resource_start_dependent), /* ACPI_RESOURCE_TYPE_START_DEPENDENT (optional Byte 1 always created) */
+ sizeof(struct aml_resource_end_dependent), /* ACPI_RESOURCE_TYPE_END_DEPENDENT */
+ sizeof(struct aml_resource_io), /* ACPI_RESOURCE_TYPE_IO */
+ sizeof(struct aml_resource_fixed_io), /* ACPI_RESOURCE_TYPE_FIXED_IO */
+ sizeof(struct aml_resource_vendor_small), /* ACPI_RESOURCE_TYPE_VENDOR */
+ sizeof(struct aml_resource_end_tag), /* ACPI_RESOURCE_TYPE_END_TAG */
+ sizeof(struct aml_resource_memory24), /* ACPI_RESOURCE_TYPE_MEMORY24 */
+ sizeof(struct aml_resource_memory32), /* ACPI_RESOURCE_TYPE_MEMORY32 */
+ sizeof(struct aml_resource_fixed_memory32), /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */
+ sizeof(struct aml_resource_address16), /* ACPI_RESOURCE_TYPE_ADDRESS16 */
+ sizeof(struct aml_resource_address32), /* ACPI_RESOURCE_TYPE_ADDRESS32 */
+ sizeof(struct aml_resource_address64), /* ACPI_RESOURCE_TYPE_ADDRESS64 */
+ sizeof(struct aml_resource_extended_address64), /*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
+ sizeof(struct aml_resource_extended_irq), /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
+ sizeof(struct aml_resource_generic_register) /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+};
+
+const u8 acpi_gbl_resource_struct_sizes[] = {
+ /* Small descriptors */
+
+ 0,
+ 0,
+ 0,
+ 0,
+ ACPI_RS_SIZE(struct acpi_resource_irq),
+ ACPI_RS_SIZE(struct acpi_resource_dma),
+ ACPI_RS_SIZE(struct acpi_resource_start_dependent),
+ ACPI_RS_SIZE_MIN,
+ ACPI_RS_SIZE(struct acpi_resource_io),
+ ACPI_RS_SIZE(struct acpi_resource_fixed_io),
+ 0,
+ 0,
+ 0,
+ 0,
+ ACPI_RS_SIZE(struct acpi_resource_vendor),
+ ACPI_RS_SIZE_MIN,
+
+ /* Large descriptors */
+
+ 0,
+ ACPI_RS_SIZE(struct acpi_resource_memory24),
+ ACPI_RS_SIZE(struct acpi_resource_generic_register),
+ 0,
+ ACPI_RS_SIZE(struct acpi_resource_vendor),
+ ACPI_RS_SIZE(struct acpi_resource_memory32),
+ ACPI_RS_SIZE(struct acpi_resource_fixed_memory32),
+ ACPI_RS_SIZE(struct acpi_resource_address32),
+ ACPI_RS_SIZE(struct acpi_resource_address16),
+ ACPI_RS_SIZE(struct acpi_resource_extended_irq),
+ ACPI_RS_SIZE(struct acpi_resource_address64),
+ ACPI_RS_SIZE(struct acpi_resource_extended_address64)
+};
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c
index d53bbe89e85..ea567167c4f 100644
--- a/drivers/acpi/resources/rsio.c
+++ b/drivers/acpi/resources/rsio.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,428 +49,206 @@ ACPI_MODULE_NAME("rsio")
/*******************************************************************************
*
- * FUNCTION: acpi_rs_io_resource
+ * acpi_rs_convert_io
*
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
+ ******************************************************************************/
+struct acpi_rsconvert_info acpi_rs_convert_io[5] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IO,
+ ACPI_RS_SIZE(struct acpi_resource_io),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io)},
+
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IO,
+ sizeof(struct aml_resource_io),
+ 0},
+
+ /* Decode flag */
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.io.io_decode),
+ AML_OFFSET(io.flags),
+ 0},
+ /*
+ * These fields are contiguous in both the source and destination:
+ * Address Alignment
+ * Length
+ * Minimum Base Address
+ * Maximum Base Address
+ */
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.io.alignment),
+ AML_OFFSET(io.alignment),
+ 2},
+
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.io.minimum),
+ AML_OFFSET(io.minimum),
+ 2}
+};
+
+/*******************************************************************************
*
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_convert_fixed_io
*
******************************************************************************/
-acpi_status
-acpi_rs_io_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_io);
-
- ACPI_FUNCTION_TRACE("rs_io_resource");
-
- /* The number of bytes consumed are Constant */
-
- *bytes_consumed = 8;
-
- output_struct->id = ACPI_RSTYPE_IO;
-
- /* Check Decode */
-
- buffer += 1;
- temp8 = *buffer;
-
- output_struct->data.io.io_decode = temp8 & 0x01;
-
- /* Check min_base Address */
-
- buffer += 1;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- output_struct->data.io.min_base_address = temp16;
-
- /* Check max_base Address */
- buffer += 2;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- output_struct->data.io.max_base_address = temp16;
-
- /* Check Base alignment */
-
- buffer += 2;
- temp8 = *buffer;
-
- output_struct->data.io.alignment = temp8;
-
- /* Check range_length */
-
- buffer += 1;
- temp8 = *buffer;
-
- output_struct->data.io.range_length = temp8;
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+struct acpi_rsconvert_info acpi_rs_convert_fixed_io[4] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_IO,
+ ACPI_RS_SIZE(struct acpi_resource_fixed_io),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_io)},
+
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_IO,
+ sizeof(struct aml_resource_fixed_io),
+ 0},
+ /*
+ * These fields are contiguous in both the source and destination:
+ * Base Address
+ * Length
+ */
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_io.address_length),
+ AML_OFFSET(fixed_io.address_length),
+ 1},
+
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_io.address),
+ AML_OFFSET(fixed_io.address),
+ 1}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_fixed_io_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_convert_generic_reg
*
******************************************************************************/
-acpi_status
-acpi_rs_fixed_io_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io);
-
- ACPI_FUNCTION_TRACE("rs_fixed_io_resource");
-
- /* The number of bytes consumed are Constant */
-
- *bytes_consumed = 4;
-
- output_struct->id = ACPI_RSTYPE_FIXED_IO;
-
- /* Check Range Base Address */
-
- buffer += 1;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- output_struct->data.fixed_io.base_address = temp16;
-
- /* Check range_length */
-
- buffer += 2;
- temp8 = *buffer;
-
- output_struct->data.fixed_io.range_length = temp8;
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+struct acpi_rsconvert_info acpi_rs_convert_generic_reg[4] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GENERIC_REGISTER,
+ ACPI_RS_SIZE(struct acpi_resource_generic_register),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_generic_reg)},
+
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GENERIC_REGISTER,
+ sizeof(struct aml_resource_generic_register),
+ 0},
+ /*
+ * These fields are contiguous in both the source and destination:
+ * Address Space ID
+ * Register Bit Width
+ * Register Bit Offset
+ * Access Size
+ */
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.generic_reg.space_id),
+ AML_OFFSET(generic_reg.address_space_id),
+ 4},
+
+ /* Get the Register Address */
+
+ {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.generic_reg.address),
+ AML_OFFSET(generic_reg.address),
+ 1}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_io_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_convert_end_dpf
*
******************************************************************************/
-acpi_status
-acpi_rs_io_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
- ACPI_FUNCTION_TRACE("rs_io_stream");
-
- /* The descriptor field is static */
-
- *buffer = 0x47;
- buffer += 1;
-
- /* Io Information Byte */
-
- temp8 = (u8) (linked_list->data.io.io_decode & 0x01);
-
- *buffer = temp8;
- buffer += 1;
-
- /* Set the Range minimum base address */
-
- temp16 = (u16) linked_list->data.io.min_base_address;
-
- ACPI_MOVE_16_TO_16(buffer, &temp16);
- buffer += 2;
-
- /* Set the Range maximum base address */
-
- temp16 = (u16) linked_list->data.io.max_base_address;
+struct acpi_rsconvert_info acpi_rs_convert_end_dpf[2] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_DEPENDENT,
+ ACPI_RS_SIZE_MIN,
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_dpf)},
- ACPI_MOVE_16_TO_16(buffer, &temp16);
- buffer += 2;
-
- /* Set the base alignment */
-
- temp8 = (u8) linked_list->data.io.alignment;
-
- *buffer = temp8;
- buffer += 1;
-
- /* Set the range length */
-
- temp8 = (u8) linked_list->data.io.range_length;
-
- *buffer = temp8;
- buffer += 1;
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_DEPENDENT,
+ sizeof(struct aml_resource_end_dependent),
+ 0}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_fixed_io_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_convert_end_tag
*
******************************************************************************/
-acpi_status
-acpi_rs_fixed_io_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
- ACPI_FUNCTION_TRACE("rs_fixed_io_stream");
-
- /* The descriptor field is static */
-
- *buffer = 0x4B;
-
- buffer += 1;
-
- /* Set the Range base address */
-
- temp16 = (u16) linked_list->data.fixed_io.base_address;
-
- ACPI_MOVE_16_TO_16(buffer, &temp16);
- buffer += 2;
-
- /* Set the range length */
-
- temp8 = (u8) linked_list->data.fixed_io.range_length;
-
- *buffer = temp8;
- buffer += 1;
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
-}
+struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_TAG,
+ ACPI_RS_SIZE_MIN,
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_tag)},
+
+ /*
+ * Note: The checksum field is set to zero, meaning that the resource
+ * data is treated as if the checksum operation succeeded.
+ * (ACPI Spec 1.0b Section 6.4.2.8)
+ */
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_TAG,
+ sizeof(struct aml_resource_end_tag),
+ 0}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dma_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_get_start_dpf
*
******************************************************************************/
-acpi_status
-acpi_rs_dma_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u8 temp8 = 0;
- u8 index;
- u8 i;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma);
-
- ACPI_FUNCTION_TRACE("rs_dma_resource");
-
- /* The number of bytes consumed are Constant */
+struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT,
+ ACPI_RS_SIZE(struct acpi_resource_start_dependent),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)},
- *bytes_consumed = 3;
- output_struct->id = ACPI_RSTYPE_DMA;
+ /* Defaults for Compatibility and Performance priorities */
- /* Point to the 8-bits of Byte 1 */
+ {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.start_dpf.compatibility_priority),
+ ACPI_ACCEPTABLE_CONFIGURATION,
+ 2},
- buffer += 1;
- temp8 = *buffer;
+ /* All done if there is no flag byte present in the descriptor */
- /* Decode the DMA channel bits */
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1},
- for (i = 0, index = 0; index < 8; index++) {
- if ((temp8 >> index) & 0x01) {
- output_struct->data.dma.channels[i] = index;
- i++;
- }
- }
+ /* Flag byte is present, get the flags */
- /* Zero DMA channels is valid */
+ {ACPI_RSC_2BITFLAG,
+ ACPI_RS_OFFSET(data.start_dpf.compatibility_priority),
+ AML_OFFSET(start_dpf.flags),
+ 0},
- output_struct->data.dma.number_of_channels = i;
- if (i > 0) {
- /* Calculate the structure size based upon the number of interrupts */
-
- struct_size += ((acpi_size) i - 1) * 4;
- }
-
- /* Point to Byte 2 */
-
- buffer += 1;
- temp8 = *buffer;
-
- /* Check for transfer preference (Bits[1:0]) */
-
- output_struct->data.dma.transfer = temp8 & 0x03;
-
- if (0x03 == output_struct->data.dma.transfer) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid DMA.Transfer preference (3)\n"));
- return_ACPI_STATUS(AE_BAD_DATA);
- }
-
- /* Get bus master preference (Bit[2]) */
-
- output_struct->data.dma.bus_master = (temp8 >> 2) & 0x01;
-
- /* Get channel speed support (Bits[6:5]) */
-
- output_struct->data.dma.type = (temp8 >> 5) & 0x03;
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_2BITFLAG,
+ ACPI_RS_OFFSET(data.start_dpf.performance_robustness),
+ AML_OFFSET(start_dpf.flags),
+ 2}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_dma_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_set_start_dpf
*
******************************************************************************/
-acpi_status
-acpi_rs_dma_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
-
- ACPI_FUNCTION_TRACE("rs_dma_stream");
-
- /* The descriptor field is static */
-
- *buffer = 0x2A;
- buffer += 1;
- temp8 = 0;
-
- /* Loop through all of the Channels and set the mask bits */
-
- for (index = 0;
- index < linked_list->data.dma.number_of_channels; index++) {
- temp16 = (u16) linked_list->data.dma.channels[index];
- temp8 |= 0x1 << temp16;
- }
-
- *buffer = temp8;
- buffer += 1;
-
- /* Set the DMA Info */
-
- temp8 = (u8) ((linked_list->data.dma.type & 0x03) << 5);
- temp8 |= ((linked_list->data.dma.bus_master & 0x01) << 2);
- temp8 |= (linked_list->data.dma.transfer & 0x03);
-
- *buffer = temp8;
- buffer += 1;
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
-}
+struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = {
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT,
+ sizeof(struct aml_resource_start_dependent),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)},
+
+ /* Set the default flag values */
+
+ {ACPI_RSC_2BITFLAG,
+ ACPI_RS_OFFSET(data.start_dpf.compatibility_priority),
+ AML_OFFSET(start_dpf.flags),
+ 0},
+
+ {ACPI_RSC_2BITFLAG,
+ ACPI_RS_OFFSET(data.start_dpf.performance_robustness),
+ AML_OFFSET(start_dpf.flags),
+ 2},
+ /*
+ * All done if flags byte is necessary -- if either priority value
+ * is not ACPI_ACCEPTABLE_CONFIGURATION
+ */
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+ ACPI_RS_OFFSET(data.start_dpf.compatibility_priority),
+ ACPI_ACCEPTABLE_CONFIGURATION},
+
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+ ACPI_RS_OFFSET(data.start_dpf.performance_robustness),
+ ACPI_ACCEPTABLE_CONFIGURATION},
+
+ /* Flag byte is not necessary */
+
+ {ACPI_RSC_LENGTH, 0, 0,
+ sizeof(struct aml_resource_start_dependent_noprio)}
+};
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c
index 56043fee96c..1fa63bc2e36 100644
--- a/drivers/acpi/resources/rsirq.c
+++ b/drivers/acpi/resources/rsirq.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,504 +49,182 @@ ACPI_MODULE_NAME("rsirq")
/*******************************************************************************
*
- * FUNCTION: acpi_rs_irq_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_get_irq
*
******************************************************************************/
-acpi_status
-acpi_rs_irq_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- u8 i;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq);
-
- ACPI_FUNCTION_TRACE("rs_irq_resource");
-
- /*
- * The number of bytes consumed are contained in the descriptor
- * (Bits:0-1)
- */
- temp8 = *buffer;
- *bytes_consumed = (temp8 & 0x03) + 1;
- output_struct->id = ACPI_RSTYPE_IRQ;
-
- /* Point to the 16-bits of Bytes 1 and 2 */
-
- buffer += 1;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- output_struct->data.irq.number_of_interrupts = 0;
-
- /* Decode the IRQ bits */
-
- for (i = 0, index = 0; index < 16; index++) {
- if ((temp16 >> index) & 0x01) {
- output_struct->data.irq.interrupts[i] = index;
- i++;
- }
- }
+struct acpi_rsconvert_info acpi_rs_get_irq[7] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ,
+ ACPI_RS_SIZE(struct acpi_resource_irq),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)},
- /* Zero interrupts is valid */
+ /* Get the IRQ mask (bytes 1:2) */
- output_struct->data.irq.number_of_interrupts = i;
- if (i > 0) {
- /* Calculate the structure size based upon the number of interrupts */
+ {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]),
+ AML_OFFSET(irq.irq_mask),
+ ACPI_RS_OFFSET(data.irq.interrupt_count)},
- struct_size += ((acpi_size) i - 1) * 4;
- }
+ /* Set default flags (others are zero) */
- /* Point to Byte 3 if it is used */
+ {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.irq.triggering),
+ ACPI_EDGE_SENSITIVE,
+ 1},
- if (4 == *bytes_consumed) {
- buffer += 2;
- temp8 = *buffer;
+ /* All done if no flag byte present in descriptor */
- /* Check for HE, LL interrupts */
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3},
- switch (temp8 & 0x09) {
- case 0x01: /* HE */
- output_struct->data.irq.edge_level =
- ACPI_EDGE_SENSITIVE;
- output_struct->data.irq.active_high_low =
- ACPI_ACTIVE_HIGH;
- break;
+ /* Get flags: Triggering[0], Polarity[3], Sharing[4] */
- case 0x08: /* LL */
- output_struct->data.irq.edge_level =
- ACPI_LEVEL_SENSITIVE;
- output_struct->data.irq.active_high_low =
- ACPI_ACTIVE_LOW;
- break;
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering),
+ AML_OFFSET(irq.flags),
+ 0},
- default:
- /*
- * Only _LL and _HE polarity/trigger interrupts
- * are allowed (ACPI spec, section "IRQ Format")
- * so 0x00 and 0x09 are illegal.
- */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid interrupt polarity/trigger in resource list, %X\n",
- temp8));
- return_ACPI_STATUS(AE_BAD_DATA);
- }
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity),
+ AML_OFFSET(irq.flags),
+ 3},
- /* Check for sharable */
-
- output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
- } else {
- /*
- * Assume Edge Sensitive, Active High, Non-Sharable
- * per ACPI Specification
- */
- output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE;
- output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH;
- output_struct->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
- }
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable),
+ AML_OFFSET(irq.flags),
+ 4}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_irq_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_set_irq
*
******************************************************************************/
-acpi_status
-acpi_rs_irq_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- u8 IRqinfo_byte_needed;
-
- ACPI_FUNCTION_TRACE("rs_irq_stream");
-
- /*
- * The descriptor field is set based upon whether a third byte is
- * needed to contain the IRQ Information.
- */
- if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level &&
- ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
- ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
- *buffer = 0x22;
- IRqinfo_byte_needed = FALSE;
- } else {
- *buffer = 0x23;
- IRqinfo_byte_needed = TRUE;
- }
-
- buffer += 1;
- temp16 = 0;
-
- /* Loop through all of the interrupts and set the mask bits */
-
- for (index = 0;
- index < linked_list->data.irq.number_of_interrupts; index++) {
- temp8 = (u8) linked_list->data.irq.interrupts[index];
- temp16 |= 0x1 << temp8;
- }
-
- ACPI_MOVE_16_TO_16(buffer, &temp16);
- buffer += 2;
-
- /* Set the IRQ Info byte if needed. */
-
- if (IRqinfo_byte_needed) {
- temp8 = 0;
- temp8 = (u8) ((linked_list->data.irq.shared_exclusive &
- 0x01) << 4);
-
- if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level &&
- ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) {
- temp8 |= 0x08;
- } else {
- temp8 |= 0x01;
- }
-
- *buffer = temp8;
- buffer += 1;
- }
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_extended_irq_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_extended_irq_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 *temp_ptr;
- u8 index;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq);
-
- ACPI_FUNCTION_TRACE("rs_extended_irq_resource");
-
- /* Get the Descriptor Length field */
-
- buffer += 1;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
-
- /* Validate minimum descriptor length */
-
- if (temp16 < 6) {
- return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
- }
-
- *bytes_consumed = temp16 + 3;
- output_struct->id = ACPI_RSTYPE_EXT_IRQ;
-
- /* Point to the Byte3 */
-
- buffer += 2;
- temp8 = *buffer;
-
- output_struct->data.extended_irq.producer_consumer = temp8 & 0x01;
+struct acpi_rsconvert_info acpi_rs_set_irq[9] = {
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ,
+ sizeof(struct aml_resource_irq),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)},
- /*
- * Check for Interrupt Mode
- *
- * The definition of an Extended IRQ changed between ACPI spec v1.0b
- * and ACPI spec 2.0 (section 6.4.3.6 in both).
- *
- * - Edge/Level are defined opposite in the table vs the headers
- */
- output_struct->data.extended_irq.edge_level =
- (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
-
- /* Check Interrupt Polarity */
-
- output_struct->data.extended_irq.active_high_low = (temp8 >> 2) & 0x1;
-
- /* Check for sharable */
-
- output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01;
+ /* Convert interrupt list to 16-bit IRQ bitmask */
- /* Point to Byte4 (IRQ Table length) */
+ {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]),
+ AML_OFFSET(irq.irq_mask),
+ ACPI_RS_OFFSET(data.irq.interrupt_count)},
- buffer += 1;
- temp8 = *buffer;
+ /* Set the flags byte by default */
- /* Must have at least one IRQ */
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering),
+ AML_OFFSET(irq.flags),
+ 0},
- if (temp8 < 1) {
- return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
- }
-
- output_struct->data.extended_irq.number_of_interrupts = temp8;
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity),
+ AML_OFFSET(irq.flags),
+ 3},
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable),
+ AML_OFFSET(irq.flags),
+ 4},
/*
- * Add any additional structure size to properly calculate
- * the next pointer at the end of this function
+ * Check if the flags byte is necessary. Not needed if the flags are:
+ * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE
*/
- struct_size += (temp8 - 1) * 4;
-
- /* Point to Byte5 (First IRQ Number) */
-
- buffer += 1;
-
- /* Cycle through every IRQ in the table */
-
- for (index = 0; index < temp8; index++) {
- ACPI_MOVE_32_TO_32(&output_struct->data.extended_irq.
- interrupts[index], buffer);
-
- /* Point to the next IRQ */
-
- buffer += 4;
- }
-
- /*
- * This will leave us pointing to the Resource Source Index
- * If it is present, then save it off and calculate the
- * pointer to where the null terminated string goes:
- * Each Interrupt takes 32-bits + the 5 bytes of the
- * stream that are default.
- *
- * Note: Some resource descriptors will have an additional null, so
- * we add 1 to the length.
- */
- if (*bytes_consumed >
- ((acpi_size) output_struct->data.extended_irq.number_of_interrupts *
- 4) + (5 + 1)) {
- /* Dereference the Index */
-
- temp8 = *buffer;
- output_struct->data.extended_irq.resource_source.index =
- (u32) temp8;
-
- /* Point to the String */
-
- buffer += 1;
-
- /* Point the String pointer to the end of this structure. */
-
- output_struct->data.extended_irq.resource_source.string_ptr =
- (char *)((char *)output_struct + struct_size);
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+ ACPI_RS_OFFSET(data.irq.triggering),
+ ACPI_EDGE_SENSITIVE},
- temp_ptr = (u8 *)
- output_struct->data.extended_irq.resource_source.string_ptr;
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+ ACPI_RS_OFFSET(data.irq.polarity),
+ ACPI_ACTIVE_HIGH},
- /* Copy the string into the buffer */
+ {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE,
+ ACPI_RS_OFFSET(data.irq.sharable),
+ ACPI_EXCLUSIVE},
- index = 0;
- while (*buffer) {
- *temp_ptr = *buffer;
+ /* irq_no_flags() descriptor can be used */
- temp_ptr += 1;
- buffer += 1;
- index += 1;
- }
-
- /* Add the terminating null */
-
- *temp_ptr = 0;
- output_struct->data.extended_irq.resource_source.string_length =
- index + 1;
-
- /*
- * In order for the struct_size to fall on a 32-bit boundary,
- * calculate the length of the string and expand the
- * struct_size to the next 32-bit boundary.
- */
- temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
- } else {
- output_struct->data.extended_irq.resource_source.index = 0;
- output_struct->data.extended_irq.resource_source.string_length =
- 0;
- output_struct->data.extended_irq.resource_source.string_ptr =
- NULL;
- }
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_extended_irq_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_convert_ext_irq
*
******************************************************************************/
-acpi_status
-acpi_rs_extended_irq_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 *length_field;
- u8 temp8 = 0;
- u8 index;
+struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ,
+ ACPI_RS_SIZE(struct acpi_resource_extended_irq),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)},
- ACPI_FUNCTION_TRACE("rs_extended_irq_stream");
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_IRQ,
+ sizeof(struct aml_resource_extended_irq),
+ 0},
- /* Set the Descriptor Type field */
+ /* Flag bits */
- *buffer = ACPI_RDESC_TYPE_EXTENDED_XRUPT;
- buffer += 1;
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer),
+ AML_OFFSET(extended_irq.flags),
+ 0},
- /* Save a pointer to the Length field - to be filled in later */
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.triggering),
+ AML_OFFSET(extended_irq.flags),
+ 1},
- length_field = ACPI_CAST_PTR(u16, buffer);
- buffer += 2;
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.polarity),
+ AML_OFFSET(extended_irq.flags),
+ 2},
- /* Set the Interrupt vector flags */
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.sharable),
+ AML_OFFSET(extended_irq.flags),
+ 3},
- temp8 = (u8) (linked_list->data.extended_irq.producer_consumer & 0x01);
- temp8 |=
- ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
+ /* IRQ Table length (Byte4) */
- /*
- * Set the Interrupt Mode
- *
- * The definition of an Extended IRQ changed between ACPI spec v1.0b
- * and ACPI spec 2.0 (section 6.4.3.6 in both). This code does not
- * implement the more restrictive definition of 1.0b
- *
- * - Edge/Level are defined opposite in the table vs the headers
- */
- if (ACPI_EDGE_SENSITIVE == linked_list->data.extended_irq.edge_level) {
- temp8 |= 0x2;
- }
-
- /* Set the Interrupt Polarity */
+ {ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count),
+ AML_OFFSET(extended_irq.interrupt_count),
+ sizeof(u32)}
+ ,
- temp8 |= ((linked_list->data.extended_irq.active_high_low & 0x1) << 2);
+ /* Copy every IRQ in the table, each is 32 bits */
- *buffer = temp8;
- buffer += 1;
+ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]),
+ AML_OFFSET(extended_irq.interrupts[0]),
+ 0}
+ ,
- /* Set the Interrupt table length */
+ /* Optional resource_source (Index and String) */
- temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts;
+ {ACPI_RSC_SOURCEX, ACPI_RS_OFFSET(data.extended_irq.resource_source),
+ ACPI_RS_OFFSET(data.extended_irq.interrupts[0]),
+ sizeof(struct aml_resource_extended_irq)}
+};
- *buffer = temp8;
- buffer += 1;
-
- for (index = 0;
- index < linked_list->data.extended_irq.number_of_interrupts;
- index++) {
- ACPI_MOVE_32_TO_32(buffer,
- &linked_list->data.extended_irq.
- interrupts[index]);
- buffer += 4;
- }
+/*******************************************************************************
+ *
+ * acpi_rs_convert_dma
+ *
+ ******************************************************************************/
- /* Resource Source Index and Resource Source are optional */
+struct acpi_rsconvert_info acpi_rs_convert_dma[6] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_DMA,
+ ACPI_RS_SIZE(struct acpi_resource_dma),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_dma)},
- if (0 != linked_list->data.extended_irq.resource_source.string_length) {
- *buffer =
- (u8) linked_list->data.extended_irq.resource_source.index;
- buffer += 1;
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_DMA,
+ sizeof(struct aml_resource_dma),
+ 0},
- /* Copy the string */
+ /* Flags: transfer preference, bus mastering, channel speed */
- ACPI_STRCPY((char *)buffer,
- linked_list->data.extended_irq.resource_source.
- string_ptr);
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.transfer),
+ AML_OFFSET(dma.flags),
+ 0},
- /*
- * Buffer needs to be set to the length of the string + one for the
- * terminating null
- */
- buffer +=
- (acpi_size) (ACPI_STRLEN
- (linked_list->data.extended_irq.
- resource_source.string_ptr) + 1);
- }
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.dma.bus_master),
+ AML_OFFSET(dma.flags),
+ 2},
- /* Return the number of bytes consumed in this operation */
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.type),
+ AML_OFFSET(dma.flags),
+ 5},
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ /* DMA channel mask bits */
- /*
- * Set the length field to the number of bytes consumed
- * minus the header size (3 bytes)
- */
- *length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_BITMASK, ACPI_RS_OFFSET(data.dma.channels[0]),
+ AML_OFFSET(dma.dma_channel_mask),
+ ACPI_RS_OFFSET(data.dma.channel_count)}
+};
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index 103eb31c284..1434e786477 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,52 +49,12 @@ ACPI_MODULE_NAME("rslist")
/*******************************************************************************
*
- * FUNCTION: acpi_rs_get_resource_type
+ * FUNCTION: acpi_rs_convert_aml_to_resources
*
- * PARAMETERS: resource_start_byte - Byte 0 of a resource descriptor
- *
- * RETURN: The Resource Type with no extraneous bits
- *
- * DESCRIPTION: Extract the Resource Type/Name from the first byte of
- * a resource descriptor.
- *
- ******************************************************************************/
-u8 acpi_rs_get_resource_type(u8 resource_start_byte)
-{
-
- ACPI_FUNCTION_ENTRY();
-
- /* Determine if this is a small or large resource */
-
- switch (resource_start_byte & ACPI_RDESC_TYPE_MASK) {
- case ACPI_RDESC_TYPE_SMALL:
-
- /* Small Resource Type -- Only bits 6:3 are valid */
-
- return ((u8) (resource_start_byte & ACPI_RDESC_SMALL_MASK));
-
- case ACPI_RDESC_TYPE_LARGE:
-
- /* Large Resource Type -- All bits are valid */
-
- return (resource_start_byte);
-
- default:
- /* Invalid type */
- break;
- }
-
- return (0xFF);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_byte_stream_to_list
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
- * byte_stream_buffer_length - Length of byte_stream_buffer
- * output_buffer - Pointer to the buffer that will
- * contain the output structures
+ * PARAMETERS: Aml - Pointer to the resource byte stream
+ * aml_length - Length of Aml
+ * output_buffer - Pointer to the buffer that will
+ * contain the output structures
*
* RETURN: Status
*
@@ -102,241 +62,78 @@ u8 acpi_rs_get_resource_type(u8 resource_start_byte)
* linked list of resources in the caller's output buffer
*
******************************************************************************/
-
acpi_status
-acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer,
- u32 byte_stream_buffer_length, u8 * output_buffer)
+acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer)
{
+ struct acpi_resource *resource = (void *)output_buffer;
acpi_status status;
- acpi_size bytes_parsed = 0;
- u8 resource_type = 0;
- acpi_size bytes_consumed = 0;
- u8 *buffer = output_buffer;
- acpi_size structure_size = 0;
- u8 end_tag_processed = FALSE;
- struct acpi_resource *resource;
-
- ACPI_FUNCTION_TRACE("rs_byte_stream_to_list");
-
- while (bytes_parsed < byte_stream_buffer_length && !end_tag_processed) {
- /* The next byte in the stream is the resource type */
-
- resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
-
- switch (resource_type) {
- case ACPI_RDESC_TYPE_MEMORY_24:
- /*
- * 24-Bit Memory Resource
- */
- status = acpi_rs_memory24_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_LARGE_VENDOR:
- /*
- * Vendor Defined Resource
- */
- status = acpi_rs_vendor_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_MEMORY_32:
- /*
- * 32-Bit Memory Range Resource
- */
- status =
- acpi_rs_memory32_range_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
- /*
- * 32-Bit Fixed Memory Resource
- */
- status =
- acpi_rs_fixed_memory32_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
- case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
- /*
- * 64-Bit Address Resource
- */
- status = acpi_rs_address64_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
- /*
- * 32-Bit Address Resource
- */
- status = acpi_rs_address32_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
- /*
- * 16-Bit Address Resource
- */
- status = acpi_rs_address16_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
- /*
- * Extended IRQ
- */
- status =
- acpi_rs_extended_irq_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_IRQ_FORMAT:
- /*
- * IRQ Resource
- */
- status = acpi_rs_irq_resource(byte_stream_buffer,
- &bytes_consumed, &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_DMA_FORMAT:
- /*
- * DMA Resource
- */
- status = acpi_rs_dma_resource(byte_stream_buffer,
- &bytes_consumed, &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_START_DEPENDENT:
- /*
- * Start Dependent Functions Resource
- */
- status =
- acpi_rs_start_depend_fns_resource
- (byte_stream_buffer, &bytes_consumed, &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_END_DEPENDENT:
- /*
- * End Dependent Functions Resource
- */
- status =
- acpi_rs_end_depend_fns_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_IO_PORT:
- /*
- * IO Port Resource
- */
- status = acpi_rs_io_resource(byte_stream_buffer,
- &bytes_consumed, &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_FIXED_IO_PORT:
- /*
- * Fixed IO Port Resource
- */
- status = acpi_rs_fixed_io_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_SMALL_VENDOR:
- /*
- * Vendor Specific Resource
- */
- status = acpi_rs_vendor_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- case ACPI_RDESC_TYPE_END_TAG:
- /*
- * End Tag
- */
- end_tag_processed = TRUE;
- status = acpi_rs_end_tag_resource(byte_stream_buffer,
- &bytes_consumed,
- &buffer,
- &structure_size);
- break;
-
- default:
- /*
- * Invalid/Unknown resource type
- */
- status = AE_AML_INVALID_RESOURCE_TYPE;
- break;
- }
+ u8 resource_index;
+ u8 *end_aml;
+
+ ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources");
+ end_aml = aml + aml_length;
+
+ /* Loop until end-of-buffer or an end_tag is found */
+
+ while (aml < end_aml) {
+ /* Validate the Resource Type and Resource Length */
+
+ status = acpi_ut_validate_resource(aml, &resource_index);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- /* Update the return value and counter */
+ /* Convert the AML byte stream resource to a local resource struct */
- bytes_parsed += bytes_consumed;
+ status =
+ acpi_rs_convert_aml_to_resource(resource,
+ ACPI_CAST_PTR(union
+ aml_resource,
+ aml),
+ acpi_gbl_get_resource_dispatch
+ [resource_index]);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not convert AML resource (Type %X)",
+ *aml));
+ return_ACPI_STATUS(status);
+ }
- /* Set the byte stream to point to the next resource */
+ /* Normal exit on completion of an end_tag resource descriptor */
- byte_stream_buffer += bytes_consumed;
+ if (acpi_ut_get_resource_type(aml) ==
+ ACPI_RESOURCE_NAME_END_TAG) {
+ return_ACPI_STATUS(AE_OK);
+ }
- /* Set the Buffer to the next structure */
+ /* Point to the next input AML resource */
- resource = ACPI_CAST_PTR(struct acpi_resource, buffer);
- resource->length =
- (u32) ACPI_ALIGN_RESOURCE_SIZE(resource->length);
- buffer += ACPI_ALIGN_RESOURCE_SIZE(structure_size);
- }
+ aml += acpi_ut_get_descriptor_length(aml);
- /* Check the reason for exiting the while loop */
+ /* Point to the next structure in the output buffer */
- if (!end_tag_processed) {
- return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+ resource =
+ ACPI_ADD_PTR(struct acpi_resource, resource,
+ resource->length);
}
- return_ACPI_STATUS(AE_OK);
+ /* Did not find an end_tag resource descriptor */
+
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_list_to_byte_stream
+ * FUNCTION: acpi_rs_convert_resources_to_aml
*
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * byte_steam_size_needed - Calculated size of the byte stream
- * needed from calling
- * acpi_rs_get_byte_stream_length()
- * The size of the output_buffer is
- * guaranteed to be >=
- * byte_stream_size_needed
- * output_buffer - Pointer to the buffer that will
- * contain the byte stream
+ * PARAMETERS: Resource - Pointer to the resource linked list
+ * aml_size_needed - Calculated size of the byte stream
+ * needed from calling acpi_rs_get_aml_length()
+ * The size of the output_buffer is
+ * guaranteed to be >= aml_size_needed
+ * output_buffer - Pointer to the buffer that will
+ * contain the byte stream
*
* RETURN: Status
*
@@ -346,180 +143,73 @@ acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer,
******************************************************************************/
acpi_status
-acpi_rs_list_to_byte_stream(struct acpi_resource *linked_list,
- acpi_size byte_stream_size_needed,
- u8 * output_buffer)
+acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
+ acpi_size aml_size_needed, u8 * output_buffer)
{
+ u8 *aml = output_buffer;
+ u8 *end_aml = output_buffer + aml_size_needed;
acpi_status status;
- u8 *buffer = output_buffer;
- acpi_size bytes_consumed = 0;
- u8 done = FALSE;
-
- ACPI_FUNCTION_TRACE("rs_list_to_byte_stream");
-
- while (!done) {
- switch (linked_list->id) {
- case ACPI_RSTYPE_IRQ:
- /*
- * IRQ Resource
- */
- status =
- acpi_rs_irq_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_DMA:
- /*
- * DMA Resource
- */
- status =
- acpi_rs_dma_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_START_DPF:
- /*
- * Start Dependent Functions Resource
- */
- status = acpi_rs_start_depend_fns_stream(linked_list,
- &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_END_DPF:
- /*
- * End Dependent Functions Resource
- */
- status = acpi_rs_end_depend_fns_stream(linked_list,
- &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_IO:
- /*
- * IO Port Resource
- */
- status =
- acpi_rs_io_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_FIXED_IO:
- /*
- * Fixed IO Port Resource
- */
- status =
- acpi_rs_fixed_io_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_VENDOR:
- /*
- * Vendor Defined Resource
- */
- status =
- acpi_rs_vendor_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_END_TAG:
- /*
- * End Tag
- */
- status =
- acpi_rs_end_tag_stream(linked_list, &buffer,
- &bytes_consumed);
-
- /* An End Tag indicates the end of the Resource Template */
-
- done = TRUE;
- break;
-
- case ACPI_RSTYPE_MEM24:
- /*
- * 24-Bit Memory Resource
- */
- status =
- acpi_rs_memory24_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_MEM32:
- /*
- * 32-Bit Memory Range Resource
- */
- status =
- acpi_rs_memory32_range_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_FIXED_MEM32:
- /*
- * 32-Bit Fixed Memory Resource
- */
- status =
- acpi_rs_fixed_memory32_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_ADDRESS16:
- /*
- * 16-Bit Address Descriptor Resource
- */
- status = acpi_rs_address16_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_ADDRESS32:
- /*
- * 32-Bit Address Descriptor Resource
- */
- status = acpi_rs_address32_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_ADDRESS64:
- /*
- * 64-Bit Address Descriptor Resource
- */
- status = acpi_rs_address64_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- case ACPI_RSTYPE_EXT_IRQ:
- /*
- * Extended IRQ Resource
- */
- status =
- acpi_rs_extended_irq_stream(linked_list, &buffer,
- &bytes_consumed);
- break;
-
- default:
- /*
- * If we get here, everything is out of sync,
- * so exit with an error
- */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid descriptor type (%X) in resource list\n",
- linked_list->id));
- status = AE_BAD_DATA;
- break;
+
+ ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml");
+
+ /* Walk the resource descriptor list, convert each descriptor */
+
+ while (aml < end_aml) {
+ /* Validate the (internal) Resource Type */
+
+ if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
+ ACPI_ERROR((AE_INFO,
+ "Invalid descriptor type (%X) in resource list",
+ resource->type));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
+ /* Perform the conversion */
+
+ status = acpi_rs_convert_resource_to_aml(resource,
+ ACPI_CAST_PTR(union
+ aml_resource,
+ aml),
+ acpi_gbl_set_resource_dispatch
+ [resource->type]);
if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not convert resource (type %X) to AML",
+ resource->type));
return_ACPI_STATUS(status);
}
- /* Set the Buffer to point to the open byte */
+ /* Perform final sanity check on the new AML resource descriptor */
+
+ status =
+ acpi_ut_validate_resource(ACPI_CAST_PTR
+ (union aml_resource, aml), NULL);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
- buffer += bytes_consumed;
+ /* Check for end-of-list, normal exit */
- /* Point to the next object */
+ if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
+ /* An End Tag indicates the end of the input Resource Template */
- linked_list = ACPI_PTR_ADD(struct acpi_resource,
- linked_list, linked_list->length);
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ /*
+ * Extract the total length of the new descriptor and set the
+ * Aml to point to the next (output) resource descriptor
+ */
+ aml += acpi_ut_get_descriptor_length(aml);
+
+ /* Point to the next input resource descriptor */
+
+ resource =
+ ACPI_ADD_PTR(struct acpi_resource, resource,
+ resource->length);
}
- return_ACPI_STATUS(AE_OK);
+ /* Completed buffer, but did not find an end_tag resource descriptor */
+
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
}
diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c
index daba1a1ed46..a5131936d69 100644
--- a/drivers/acpi/resources/rsmemory.c
+++ b/drivers/acpi/resources/rsmemory.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,454 +49,187 @@ ACPI_MODULE_NAME("rsmemory")
/*******************************************************************************
*
- * FUNCTION: acpi_rs_memory24_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_convert_memory24
*
******************************************************************************/
-acpi_status
-acpi_rs_memory24_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
-
- ACPI_FUNCTION_TRACE("rs_memory24_resource");
-
- /* Point past the Descriptor to get the number of bytes consumed */
-
- buffer += 1;
-
- ACPI_MOVE_16_TO_16(&temp16, buffer);
- buffer += 2;
- *bytes_consumed = (acpi_size) temp16 + 3;
- output_struct->id = ACPI_RSTYPE_MEM24;
-
- /* Check Byte 3 the Read/Write bit */
-
- temp8 = *buffer;
- buffer += 1;
- output_struct->data.memory24.read_write_attribute = temp8 & 0x01;
-
- /* Get min_base_address (Bytes 4-5) */
-
- ACPI_MOVE_16_TO_16(&temp16, buffer);
- buffer += 2;
- output_struct->data.memory24.min_base_address = temp16;
-
- /* Get max_base_address (Bytes 6-7) */
-
- ACPI_MOVE_16_TO_16(&temp16, buffer);
- buffer += 2;
- output_struct->data.memory24.max_base_address = temp16;
+struct acpi_rsconvert_info acpi_rs_convert_memory24[4] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY24,
+ ACPI_RS_SIZE(struct acpi_resource_memory24),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory24)},
- /* Get Alignment (Bytes 8-9) */
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY24,
+ sizeof(struct aml_resource_memory24),
+ 0},
- ACPI_MOVE_16_TO_16(&temp16, buffer);
- buffer += 2;
- output_struct->data.memory24.alignment = temp16;
+ /* Read/Write bit */
- /* Get range_length (Bytes 10-11) */
-
- ACPI_MOVE_16_TO_16(&temp16, buffer);
- output_struct->data.memory24.range_length = temp16;
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory24.write_protect),
+ AML_OFFSET(memory24.flags),
+ 0},
+ /*
+ * These fields are contiguous in both the source and destination:
+ * Minimum Base Address
+ * Maximum Base Address
+ * Address Base Alignment
+ * Range Length
+ */
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.memory24.minimum),
+ AML_OFFSET(memory24.minimum),
+ 4}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_memory24_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_convert_memory32
*
******************************************************************************/
-acpi_status
-acpi_rs_memory24_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
- ACPI_FUNCTION_TRACE("rs_memory24_stream");
-
- /* The descriptor field is static */
-
- *buffer = 0x81;
- buffer += 1;
+struct acpi_rsconvert_info acpi_rs_convert_memory32[4] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY32,
+ ACPI_RS_SIZE(struct acpi_resource_memory32),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory32)},
- /* The length field is static */
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY32,
+ sizeof(struct aml_resource_memory32),
+ 0},
- temp16 = 0x09;
- ACPI_MOVE_16_TO_16(buffer, &temp16);
- buffer += 2;
+ /* Read/Write bit */
- /* Set the Information Byte */
-
- temp8 = (u8) (linked_list->data.memory24.read_write_attribute & 0x01);
- *buffer = temp8;
- buffer += 1;
-
- /* Set the Range minimum base address */
-
- ACPI_MOVE_32_TO_16(buffer,
- &linked_list->data.memory24.min_base_address);
- buffer += 2;
-
- /* Set the Range maximum base address */
-
- ACPI_MOVE_32_TO_16(buffer,
- &linked_list->data.memory24.max_base_address);
- buffer += 2;
-
- /* Set the base alignment */
-
- ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.alignment);
- buffer += 2;
-
- /* Set the range length */
-
- ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.range_length);
- buffer += 2;
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory32.write_protect),
+ AML_OFFSET(memory32.flags),
+ 0},
+ /*
+ * These fields are contiguous in both the source and destination:
+ * Minimum Base Address
+ * Maximum Base Address
+ * Address Base Alignment
+ * Range Length
+ */
+ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.memory32.minimum),
+ AML_OFFSET(memory32.minimum),
+ 4}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_memory32_range_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_convert_fixed_memory32
*
******************************************************************************/
-acpi_status
-acpi_rs_memory32_range_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32);
-
- ACPI_FUNCTION_TRACE("rs_memory32_range_resource");
-
- /* Point past the Descriptor to get the number of bytes consumed */
-
- buffer += 1;
+struct acpi_rsconvert_info acpi_rs_convert_fixed_memory32[4] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_MEMORY32,
+ ACPI_RS_SIZE(struct acpi_resource_fixed_memory32),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_memory32)},
- ACPI_MOVE_16_TO_16(&temp16, buffer);
- buffer += 2;
- *bytes_consumed = (acpi_size) temp16 + 3;
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_MEMORY32,
+ sizeof(struct aml_resource_fixed_memory32),
+ 0},
- output_struct->id = ACPI_RSTYPE_MEM32;
+ /* Read/Write bit */
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.fixed_memory32.write_protect),
+ AML_OFFSET(fixed_memory32.flags),
+ 0},
/*
- * Point to the place in the output buffer where the data portion will
- * begin.
- * 1. Set the RESOURCE_DATA * Data to point to its own address, then
- * 2. Set the pointer to the next address.
- *
- * NOTE: output_struct->Data is cast to u8, otherwise, this addition adds
- * 4 * sizeof(RESOURCE_DATA) instead of 4 * sizeof(u8)
+ * These fields are contiguous in both the source and destination:
+ * Base Address
+ * Range Length
*/
-
- /* Check Byte 3 the Read/Write bit */
-
- temp8 = *buffer;
- buffer += 1;
-
- output_struct->data.memory32.read_write_attribute = temp8 & 0x01;
-
- /* Get min_base_address (Bytes 4-7) */
-
- ACPI_MOVE_32_TO_32(&output_struct->data.memory32.min_base_address,
- buffer);
- buffer += 4;
-
- /* Get max_base_address (Bytes 8-11) */
-
- ACPI_MOVE_32_TO_32(&output_struct->data.memory32.max_base_address,
- buffer);
- buffer += 4;
-
- /* Get Alignment (Bytes 12-15) */
-
- ACPI_MOVE_32_TO_32(&output_struct->data.memory32.alignment, buffer);
- buffer += 4;
-
- /* Get range_length (Bytes 16-19) */
-
- ACPI_MOVE_32_TO_32(&output_struct->data.memory32.range_length, buffer);
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.fixed_memory32.address),
+ AML_OFFSET(fixed_memory32.address),
+ 2}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_fixed_memory32_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * acpi_rs_get_vendor_small
*
******************************************************************************/
-acpi_status
-acpi_rs_fixed_memory32_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_mem32);
-
- ACPI_FUNCTION_TRACE("rs_fixed_memory32_resource");
+struct acpi_rsconvert_info acpi_rs_get_vendor_small[3] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR,
+ ACPI_RS_SIZE(struct acpi_resource_vendor),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_small)},
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Length of the vendor data (byte count) */
- buffer += 1;
- ACPI_MOVE_16_TO_16(&temp16, buffer);
+ {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length),
+ 0,
+ sizeof(u8)}
+ ,
- buffer += 2;
- *bytes_consumed = (acpi_size) temp16 + 3;
+ /* Vendor data */
- output_struct->id = ACPI_RSTYPE_FIXED_MEM32;
-
- /* Check Byte 3 the Read/Write bit */
-
- temp8 = *buffer;
- buffer += 1;
- output_struct->data.fixed_memory32.read_write_attribute = temp8 & 0x01;
-
- /* Get range_base_address (Bytes 4-7) */
-
- ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.
- range_base_address, buffer);
- buffer += 4;
-
- /* Get range_length (Bytes 8-11) */
-
- ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.range_length,
- buffer);
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]),
+ sizeof(struct aml_resource_small_header),
+ 0}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_memory32_range_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_get_vendor_large
*
******************************************************************************/
-acpi_status
-acpi_rs_memory32_range_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
- ACPI_FUNCTION_TRACE("rs_memory32_range_stream");
-
- /* The descriptor field is static */
-
- *buffer = 0x85;
- buffer += 1;
-
- /* The length field is static */
-
- temp16 = 0x11;
-
- ACPI_MOVE_16_TO_16(buffer, &temp16);
- buffer += 2;
-
- /* Set the Information Byte */
-
- temp8 = (u8) (linked_list->data.memory32.read_write_attribute & 0x01);
- *buffer = temp8;
- buffer += 1;
-
- /* Set the Range minimum base address */
-
- ACPI_MOVE_32_TO_32(buffer,
- &linked_list->data.memory32.min_base_address);
- buffer += 4;
-
- /* Set the Range maximum base address */
-
- ACPI_MOVE_32_TO_32(buffer,
- &linked_list->data.memory32.max_base_address);
- buffer += 4;
+struct acpi_rsconvert_info acpi_rs_get_vendor_large[3] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR,
+ ACPI_RS_SIZE(struct acpi_resource_vendor),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_large)},
- /* Set the base alignment */
+ /* Length of the vendor data (byte count) */
- ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.alignment);
- buffer += 4;
+ {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length),
+ 0,
+ sizeof(u8)}
+ ,
- /* Set the range length */
+ /* Vendor data */
- ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.range_length);
- buffer += 4;
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]),
+ sizeof(struct aml_resource_large_header),
+ 0}
+};
/*******************************************************************************
*
- * FUNCTION: acpi_rs_fixed_memory32_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
+ * acpi_rs_set_vendor
*
******************************************************************************/
-acpi_status
-acpi_rs_fixed_memory32_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
- ACPI_FUNCTION_TRACE("rs_fixed_memory32_stream");
+struct acpi_rsconvert_info acpi_rs_set_vendor[7] = {
+ /* Default is a small vendor descriptor */
- /* The descriptor field is static */
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_SMALL,
+ sizeof(struct aml_resource_small_header),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_set_vendor)},
- *buffer = 0x86;
- buffer += 1;
+ /* Get the length and copy the data */
- /* The length field is static */
+ {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length),
+ 0,
+ 0},
- temp16 = 0x09;
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]),
+ sizeof(struct aml_resource_small_header),
+ 0},
- ACPI_MOVE_16_TO_16(buffer, &temp16);
- buffer += 2;
-
- /* Set the Information Byte */
-
- temp8 =
- (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01);
- *buffer = temp8;
- buffer += 1;
-
- /* Set the Range base address */
-
- ACPI_MOVE_32_TO_32(buffer,
- &linked_list->data.fixed_memory32.
- range_base_address);
- buffer += 4;
+ /*
+ * All done if the Vendor byte length is 7 or less, meaning that it will
+ * fit within a small descriptor
+ */
+ {ACPI_RSC_EXIT_LE, 0, 0, 7},
- /* Set the range length */
+ /* Must create a large vendor descriptor */
- ACPI_MOVE_32_TO_32(buffer,
- &linked_list->data.fixed_memory32.range_length);
- buffer += 4;
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_LARGE,
+ sizeof(struct aml_resource_large_header),
+ 0},
- /* Return the number of bytes consumed in this operation */
+ {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length),
+ 0,
+ 0},
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
-}
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]),
+ sizeof(struct aml_resource_large_header),
+ 0}
+};
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index 7a8a34e757f..ed866cf1c6d 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/resources/rsmisc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,481 +47,501 @@
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsmisc")
+#define INIT_RESOURCE_TYPE(i) i->resource_offset
+#define INIT_RESOURCE_LENGTH(i) i->aml_offset
+#define INIT_TABLE_LENGTH(i) i->value
+#define COMPARE_OPCODE(i) i->resource_offset
+#define COMPARE_TARGET(i) i->aml_offset
+#define COMPARE_VALUE(i) i->value
/*******************************************************************************
*
- * FUNCTION: acpi_rs_end_tag_resource
+ * FUNCTION: acpi_rs_convert_aml_to_resource
*
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
+ * PARAMETERS: Resource - Pointer to the resource descriptor
+ * Aml - Where the AML descriptor is returned
+ * Info - Pointer to appropriate conversion table
*
* RETURN: Status
*
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
+ * internal resource descriptor
*
******************************************************************************/
acpi_status
-acpi_rs_end_tag_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
+acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
+ union aml_resource *aml,
+ struct acpi_rsconvert_info *info)
{
- struct acpi_resource *output_struct = (void *)*output_buffer;
- acpi_size struct_size = ACPI_RESOURCE_LENGTH;
-
- ACPI_FUNCTION_TRACE("rs_end_tag_resource");
-
- /* The number of bytes consumed is static */
-
- *bytes_consumed = 2;
-
- /* Fill out the structure */
-
- output_struct->id = ACPI_RSTYPE_END_TAG;
-
- /* Set the Length parameter */
-
- output_struct->length = 0;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_end_tag_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_end_tag_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u8 temp8 = 0;
-
- ACPI_FUNCTION_TRACE("rs_end_tag_stream");
-
- /* The descriptor field is static */
-
- *buffer = 0x79;
- buffer += 1;
-
- /*
- * Set the Checksum - zero means that the resource data is treated as if
- * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8)
- */
- temp8 = 0;
-
- *buffer = temp8;
- buffer += 1;
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_vendor_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_vendor_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_rs_length aml_resource_length;
+ void *source;
+ void *destination;
+ char *target;
+ u8 count;
+ u8 flags_mode = FALSE;
+ u16 item_count = 0;
u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor);
-
- ACPI_FUNCTION_TRACE("rs_vendor_resource");
-
- /* Dereference the Descriptor to find if this is a large or small item. */
-
- temp8 = *buffer;
-
- if (temp8 & 0x80) {
- /* Large Item, point to the length field */
-
- buffer += 1;
- /* Dereference */
+ ACPI_FUNCTION_TRACE("rs_get_resource");
- ACPI_MOVE_16_TO_16(&temp16, buffer);
+ if (((acpi_native_uint) resource) & 0x3) {
+ /* Each internal resource struct is expected to be 32-bit aligned */
- /* Calculate bytes consumed */
-
- *bytes_consumed = (acpi_size) temp16 + 3;
-
- /* Point to the first vendor byte */
-
- buffer += 2;
- } else {
- /* Small Item, dereference the size */
-
- temp16 = (u8) (*buffer & 0x07);
-
- /* Calculate bytes consumed */
-
- *bytes_consumed = (acpi_size) temp16 + 1;
-
- /* Point to the first vendor byte */
-
- buffer += 1;
+ ACPI_WARNING((AE_INFO,
+ "Misaligned resource pointer (get): %p Type %2.2X Len %X",
+ resource, resource->type, resource->length));
}
- output_struct->id = ACPI_RSTYPE_VENDOR;
- output_struct->data.vendor_specific.length = temp16;
+ /* Extract the resource Length field (does not include header length) */
- for (index = 0; index < temp16; index++) {
- output_struct->data.vendor_specific.reserved[index] = *buffer;
- buffer += 1;
- }
+ aml_resource_length = acpi_ut_get_resource_length(aml);
/*
- * In order for the struct_size to fall on a 32-bit boundary,
- * calculate the length of the vendor string and expand the
- * struct_size to the next 32-bit boundary.
+ * First table entry must be ACPI_RSC_INITxxx and must contain the
+ * table length (# of table entries)
*/
- struct_size += ACPI_ROUND_UP_to_32_bITS(temp16);
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_vendor_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_vendor_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
-
- ACPI_FUNCTION_TRACE("rs_vendor_stream");
-
- /* Dereference the length to find if this is a large or small item. */
-
- if (linked_list->data.vendor_specific.length > 7) {
- /* Large Item, Set the descriptor field and length bytes */
-
- *buffer = 0x84;
- buffer += 1;
-
- temp16 = (u16) linked_list->data.vendor_specific.length;
-
- ACPI_MOVE_16_TO_16(buffer, &temp16);
- buffer += 2;
- } else {
- /* Small Item, Set the descriptor field */
-
- temp8 = 0x70;
- temp8 |= (u8) linked_list->data.vendor_specific.length;
+ count = INIT_TABLE_LENGTH(info);
+
+ while (count) {
+ /*
+ * Source is the external AML byte stream buffer,
+ * destination is the internal resource descriptor
+ */
+ source = ACPI_ADD_PTR(void, aml, info->aml_offset);
+ destination =
+ ACPI_ADD_PTR(void, resource, info->resource_offset);
+
+ switch (info->opcode) {
+ case ACPI_RSC_INITGET:
+ /*
+ * Get the resource type and the initial (minimum) length
+ */
+ ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info));
+ resource->type = INIT_RESOURCE_TYPE(info);
+ resource->length = INIT_RESOURCE_LENGTH(info);
+ break;
+
+ case ACPI_RSC_INITSET:
+ break;
+
+ case ACPI_RSC_FLAGINIT:
+
+ flags_mode = TRUE;
+ break;
+
+ case ACPI_RSC_1BITFLAG:
+ /*
+ * Mask and shift the flag bit
+ */
+ ACPI_SET8(destination) = (u8)
+ ((ACPI_GET8(source) >> info->value) & 0x01);
+ break;
+
+ case ACPI_RSC_2BITFLAG:
+ /*
+ * Mask and shift the flag bits
+ */
+ ACPI_SET8(destination) = (u8)
+ ((ACPI_GET8(source) >> info->value) & 0x03);
+ break;
+
+ case ACPI_RSC_COUNT:
+
+ item_count = ACPI_GET8(source);
+ ACPI_SET8(destination) = (u8) item_count;
+
+ resource->length = resource->length +
+ (info->value * (item_count - 1));
+ break;
+
+ case ACPI_RSC_COUNT16:
+
+ item_count = aml_resource_length;
+ ACPI_SET16(destination) = item_count;
+
+ resource->length = resource->length +
+ (info->value * (item_count - 1));
+ break;
+
+ case ACPI_RSC_LENGTH:
+
+ resource->length = resource->length + info->value;
+ break;
+
+ case ACPI_RSC_MOVE8:
+ case ACPI_RSC_MOVE16:
+ case ACPI_RSC_MOVE32:
+ case ACPI_RSC_MOVE64:
+ /*
+ * Raw data move. Use the Info value field unless item_count has
+ * been previously initialized via a COUNT opcode
+ */
+ if (info->value) {
+ item_count = info->value;
+ }
+ acpi_rs_move_data(destination, source, item_count,
+ info->opcode);
+ break;
+
+ case ACPI_RSC_SET8:
+
+ ACPI_MEMSET(destination, info->aml_offset, info->value);
+ break;
+
+ case ACPI_RSC_DATA8:
+
+ target = ACPI_ADD_PTR(char, resource, info->value);
+ ACPI_MEMCPY(destination, source, ACPI_GET16(target));
+ break;
+
+ case ACPI_RSC_ADDRESS:
+ /*
+ * Common handler for address descriptor flags
+ */
+ if (!acpi_rs_get_address_common(resource, aml)) {
+ return_ACPI_STATUS
+ (AE_AML_INVALID_RESOURCE_TYPE);
+ }
+ break;
+
+ case ACPI_RSC_SOURCE:
+ /*
+ * Optional resource_source (Index and String)
+ */
+ resource->length +=
+ acpi_rs_get_resource_source(aml_resource_length,
+ info->value,
+ destination, aml, NULL);
+ break;
+
+ case ACPI_RSC_SOURCEX:
+ /*
+ * Optional resource_source (Index and String). This is the more
+ * complicated case used by the Interrupt() macro
+ */
+ target =
+ ACPI_ADD_PTR(char, resource,
+ info->aml_offset + (item_count * 4));
+
+ resource->length +=
+ acpi_rs_get_resource_source(aml_resource_length,
+ (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target);
+ break;
+
+ case ACPI_RSC_BITMASK:
+ /*
+ * 8-bit encoded bitmask (DMA macro)
+ */
+ item_count =
+ acpi_rs_decode_bitmask(ACPI_GET8(source),
+ destination);
+ if (item_count) {
+ resource->length += (item_count - 1);
+ }
+
+ target = ACPI_ADD_PTR(char, resource, info->value);
+ ACPI_SET8(target) = (u8) item_count;
+ break;
+
+ case ACPI_RSC_BITMASK16:
+ /*
+ * 16-bit encoded bitmask (IRQ macro)
+ */
+ ACPI_MOVE_16_TO_16(&temp16, source);
+
+ item_count =
+ acpi_rs_decode_bitmask(temp16, destination);
+ if (item_count) {
+ resource->length += (item_count - 1);
+ }
+
+ target = ACPI_ADD_PTR(char, resource, info->value);
+ ACPI_SET8(target) = (u8) item_count;
+ break;
+
+ case ACPI_RSC_EXIT_NE:
+ /*
+ * Control - Exit conversion if not equal
+ */
+ switch (info->resource_offset) {
+ case ACPI_RSC_COMPARE_AML_LENGTH:
+ if (aml_resource_length != info->value) {
+ goto exit;
+ }
+ break;
+
+ case ACPI_RSC_COMPARE_VALUE:
+ if (ACPI_GET8(source) != info->value) {
+ goto exit;
+ }
+ break;
+
+ default:
+
+ ACPI_ERROR((AE_INFO,
+ "Invalid conversion sub-opcode"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+ break;
+
+ default:
+
+ ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
- *buffer = temp8;
- buffer += 1;
+ count--;
+ info++;
}
- /* Loop through all of the Vendor Specific fields */
+ exit:
+ if (!flags_mode) {
+ /* Round the resource struct length up to the next 32-bit boundary */
- for (index = 0; index < linked_list->data.vendor_specific.length;
- index++) {
- temp8 = linked_list->data.vendor_specific.reserved[index];
-
- *buffer = temp8;
- buffer += 1;
+ resource->length = ACPI_ROUND_UP_to_32_bITS(resource->length);
}
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
- * FUNCTION: acpi_rs_start_depend_fns_resource
+ * FUNCTION: acpi_rs_convert_resource_to_aml
*
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
+ * PARAMETERS: Resource - Pointer to the resource descriptor
+ * Aml - Where the AML descriptor is returned
+ * Info - Pointer to appropriate conversion table
*
* RETURN: Status
*
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
+ * DESCRIPTION: Convert an internal resource descriptor to the corresponding
+ * external AML resource descriptor.
*
******************************************************************************/
acpi_status
-acpi_rs_start_depend_fns_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer,
- acpi_size * structure_size)
+acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
+ union aml_resource *aml,
+ struct acpi_rsconvert_info *info)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *)*output_buffer;
- u8 temp8 = 0;
- acpi_size struct_size =
- ACPI_SIZEOF_RESOURCE(struct acpi_resource_start_dpf);
-
- ACPI_FUNCTION_TRACE("rs_start_depend_fns_resource");
-
- /* The number of bytes consumed are found in the descriptor (Bits:0-1) */
-
- temp8 = *buffer;
-
- *bytes_consumed = (temp8 & 0x01) + 1;
-
- output_struct->id = ACPI_RSTYPE_START_DPF;
-
- /* Point to Byte 1 if it is used */
-
- if (2 == *bytes_consumed) {
- buffer += 1;
- temp8 = *buffer;
-
- /* Check Compatibility priority */
-
- output_struct->data.start_dpf.compatibility_priority =
- temp8 & 0x03;
-
- if (3 == output_struct->data.start_dpf.compatibility_priority) {
- return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
- }
-
- /* Check Performance/Robustness preference */
+ void *source = NULL;
+ void *destination;
+ acpi_rsdesc_size aml_length = 0;
+ u8 count;
+ u16 temp16 = 0;
+ u16 item_count = 0;
- output_struct->data.start_dpf.performance_robustness =
- (temp8 >> 2) & 0x03;
+ ACPI_FUNCTION_TRACE("rs_convert_resource_to_aml");
- if (3 == output_struct->data.start_dpf.performance_robustness) {
- return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
+ /*
+ * First table entry must be ACPI_RSC_INITxxx and must contain the
+ * table length (# of table entries)
+ */
+ count = INIT_TABLE_LENGTH(info);
+
+ while (count) {
+ /*
+ * Source is the internal resource descriptor,
+ * destination is the external AML byte stream buffer
+ */
+ source = ACPI_ADD_PTR(void, resource, info->resource_offset);
+ destination = ACPI_ADD_PTR(void, aml, info->aml_offset);
+
+ switch (info->opcode) {
+ case ACPI_RSC_INITSET:
+
+ ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info));
+ aml_length = INIT_RESOURCE_LENGTH(info);
+ acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info),
+ aml_length, aml);
+ break;
+
+ case ACPI_RSC_INITGET:
+ break;
+
+ case ACPI_RSC_FLAGINIT:
+ /*
+ * Clear the flag byte
+ */
+ ACPI_SET8(destination) = 0;
+ break;
+
+ case ACPI_RSC_1BITFLAG:
+ /*
+ * Mask and shift the flag bit
+ */
+ ACPI_SET8(destination) |= (u8)
+ ((ACPI_GET8(source) & 0x01) << info->value);
+ break;
+
+ case ACPI_RSC_2BITFLAG:
+ /*
+ * Mask and shift the flag bits
+ */
+ ACPI_SET8(destination) |= (u8)
+ ((ACPI_GET8(source) & 0x03) << info->value);
+ break;
+
+ case ACPI_RSC_COUNT:
+
+ item_count = ACPI_GET8(source);
+ ACPI_SET8(destination) = (u8) item_count;
+
+ aml_length =
+ (u16) (aml_length +
+ (info->value * (item_count - 1)));
+ break;
+
+ case ACPI_RSC_COUNT16:
+
+ item_count = ACPI_GET16(source);
+ aml_length = (u16) (aml_length + item_count);
+ acpi_rs_set_resource_length(aml_length, aml);
+ break;
+
+ case ACPI_RSC_LENGTH:
+
+ acpi_rs_set_resource_length(info->value, aml);
+ break;
+
+ case ACPI_RSC_MOVE8:
+ case ACPI_RSC_MOVE16:
+ case ACPI_RSC_MOVE32:
+ case ACPI_RSC_MOVE64:
+
+ if (info->value) {
+ item_count = info->value;
+ }
+ acpi_rs_move_data(destination, source, item_count,
+ info->opcode);
+ break;
+
+ case ACPI_RSC_ADDRESS:
+
+ /* Set the Resource Type, General Flags, and Type-Specific Flags */
+
+ acpi_rs_set_address_common(aml, resource);
+ break;
+
+ case ACPI_RSC_SOURCEX:
+ /*
+ * Optional resource_source (Index and String)
+ */
+ aml_length =
+ acpi_rs_set_resource_source(aml,
+ (acpi_rs_length)
+ aml_length, source);
+ acpi_rs_set_resource_length(aml_length, aml);
+ break;
+
+ case ACPI_RSC_SOURCE:
+ /*
+ * Optional resource_source (Index and String). This is the more
+ * complicated case used by the Interrupt() macro
+ */
+ aml_length =
+ acpi_rs_set_resource_source(aml, info->value,
+ source);
+ acpi_rs_set_resource_length(aml_length, aml);
+ break;
+
+ case ACPI_RSC_BITMASK:
+ /*
+ * 8-bit encoded bitmask (DMA macro)
+ */
+ ACPI_SET8(destination) = (u8)
+ acpi_rs_encode_bitmask(source,
+ *ACPI_ADD_PTR(u8, resource,
+ info->value));
+ break;
+
+ case ACPI_RSC_BITMASK16:
+ /*
+ * 16-bit encoded bitmask (IRQ macro)
+ */
+ temp16 = acpi_rs_encode_bitmask(source,
+ *ACPI_ADD_PTR(u8,
+ resource,
+ info->
+ value));
+ ACPI_MOVE_16_TO_16(destination, &temp16);
+ break;
+
+ case ACPI_RSC_EXIT_LE:
+ /*
+ * Control - Exit conversion if less than or equal
+ */
+ if (item_count <= info->value) {
+ goto exit;
+ }
+ break;
+
+ case ACPI_RSC_EXIT_NE:
+ /*
+ * Control - Exit conversion if not equal
+ */
+ switch (COMPARE_OPCODE(info)) {
+ case ACPI_RSC_COMPARE_VALUE:
+
+ if (*ACPI_ADD_PTR(u8, resource,
+ COMPARE_TARGET(info)) !=
+ COMPARE_VALUE(info)) {
+ goto exit;
+ }
+ break;
+
+ default:
+
+ ACPI_ERROR((AE_INFO,
+ "Invalid conversion sub-opcode"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+ break;
+
+ default:
+
+ ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- } else {
- output_struct->data.start_dpf.compatibility_priority =
- ACPI_ACCEPTABLE_CONFIGURATION;
- output_struct->data.start_dpf.performance_robustness =
- ACPI_ACCEPTABLE_CONFIGURATION;
+ count--;
+ info++;
}
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
+ exit:
return_ACPI_STATUS(AE_OK);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_end_depend_fns_resource
- *
- * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte
- * stream
- * bytes_consumed - Pointer to where the number of bytes
- * consumed the byte_stream_buffer is
- * returned
- * output_buffer - Pointer to the return data buffer
- * structure_size - Pointer to where the number of bytes
- * in the return data struct is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the resource byte stream and fill out the appropriate
- * structure pointed to by the output_buffer. Return the
- * number of bytes consumed from the byte stream.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_end_depend_fns_resource(u8 * byte_stream_buffer,
- acpi_size * bytes_consumed,
- u8 ** output_buffer, acpi_size * structure_size)
-{
- struct acpi_resource *output_struct = (void *)*output_buffer;
- acpi_size struct_size = ACPI_RESOURCE_LENGTH;
-
- ACPI_FUNCTION_TRACE("rs_end_depend_fns_resource");
-
- /* The number of bytes consumed is static */
-
- *bytes_consumed = 1;
+#if 0
+/* Previous resource validations */
- /* Fill out the structure */
-
- output_struct->id = ACPI_RSTYPE_END_DPF;
-
- /* Set the Length parameter */
-
- output_struct->length = (u32) struct_size;
-
- /* Return the final size of the structure */
-
- *structure_size = struct_size;
- return_ACPI_STATUS(AE_OK);
+if (aml->ext_address64.revision_iD != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) {
+ return_ACPI_STATUS(AE_SUPPORT);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_start_depend_fns_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - u32 pointer that is filled with
- * the number of bytes of the
- * output_buffer used
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_start_depend_fns_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
- u8 temp8 = 0;
-
- ACPI_FUNCTION_TRACE("rs_start_depend_fns_stream");
+if (resource->data.start_dpf.performance_robustness >= 3) {
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
+}
+if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) {
/*
- * The descriptor field is set based upon whether a byte is needed
- * to contain Priority data.
+ * Only [active_high, edge_sensitive] or [active_low, level_sensitive]
+ * polarity/trigger interrupts are allowed (ACPI spec, section
+ * "IRQ Format"), so 0x00 and 0x09 are illegal.
*/
- if (ACPI_ACCEPTABLE_CONFIGURATION ==
- linked_list->data.start_dpf.compatibility_priority &&
- ACPI_ACCEPTABLE_CONFIGURATION ==
- linked_list->data.start_dpf.performance_robustness) {
- *buffer = 0x30;
- } else {
- *buffer = 0x31;
- buffer += 1;
-
- /* Set the Priority Byte Definition */
-
- temp8 = 0;
- temp8 =
- (u8) ((linked_list->data.start_dpf.
- performance_robustness & 0x03) << 2);
- temp8 |=
- (linked_list->data.start_dpf.compatibility_priority & 0x03);
- *buffer = temp8;
- }
-
- buffer += 1;
-
- /* Return the number of bytes consumed in this operation */
-
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
+ ACPI_ERROR((AE_INFO,
+ "Invalid interrupt polarity/trigger in resource list, %X",
+ aml->irq.flags));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_rs_end_depend_fns_stream
- *
- * PARAMETERS: linked_list - Pointer to the resource linked list
- * output_buffer - Pointer to the user's return buffer
- * bytes_consumed - Pointer to where the number of bytes
- * used in the output_buffer is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Take the linked list resource structure and fills in the
- * the appropriate bytes in a byte stream
- *
- ******************************************************************************/
-
-acpi_status
-acpi_rs_end_depend_fns_stream(struct acpi_resource *linked_list,
- u8 ** output_buffer, acpi_size * bytes_consumed)
-{
- u8 *buffer = *output_buffer;
-
- ACPI_FUNCTION_TRACE("rs_end_depend_fns_stream");
-
- /* The descriptor field is static */
-
- *buffer = 0x38;
- buffer += 1;
+resource->data.extended_irq.interrupt_count = temp8;
+if (temp8 < 1) {
+ /* Must have at least one IRQ */
- /* Return the number of bytes consumed in this operation */
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
+}
- *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
- return_ACPI_STATUS(AE_OK);
+if (resource->data.dma.transfer == 0x03) {
+ ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)"));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
+#endif
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 4446778eaf7..25b5aedd661 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,389 @@ ACPI_MODULE_NAME("rsutils")
/*******************************************************************************
*
+ * FUNCTION: acpi_rs_decode_bitmask
+ *
+ * PARAMETERS: Mask - Bitmask to decode
+ * List - Where the converted list is returned
+ *
+ * RETURN: Count of bits set (length of list)
+ *
+ * DESCRIPTION: Convert a bit mask into a list of values
+ *
+ ******************************************************************************/
+u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
+{
+ acpi_native_uint i;
+ u8 bit_count;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Decode the mask bits */
+
+ for (i = 0, bit_count = 0; mask; i++) {
+ if (mask & 0x0001) {
+ list[bit_count] = (u8) i;
+ bit_count++;
+ }
+
+ mask >>= 1;
+ }
+
+ return (bit_count);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_encode_bitmask
+ *
+ * PARAMETERS: List - List of values to encode
+ * Count - Length of list
+ *
+ * RETURN: Encoded bitmask
+ *
+ * DESCRIPTION: Convert a list of values to an encoded bitmask
+ *
+ ******************************************************************************/
+
+u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
+{
+ acpi_native_uint i;
+ u16 mask;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Encode the list into a single bitmask */
+
+ for (i = 0, mask = 0; i < count; i++) {
+ mask |= (0x0001 << list[i]);
+ }
+
+ return (mask);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_move_data
+ *
+ * PARAMETERS: Destination - Pointer to the destination descriptor
+ * Source - Pointer to the source descriptor
+ * item_count - How many items to move
+ * move_type - Byte width
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Move multiple data items from one descriptor to another. Handles
+ * alignment issues and endian issues if necessary, as configured
+ * via the ACPI_MOVE_* macros. (This is why a memcpy is not used)
+ *
+ ******************************************************************************/
+
+void
+acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
+{
+ acpi_native_uint i;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* One move per item */
+
+ for (i = 0; i < item_count; i++) {
+ switch (move_type) {
+ /*
+ * For the 8-bit case, we can perform the move all at once
+ * since there are no alignment or endian issues
+ */
+ case ACPI_RSC_MOVE8:
+ ACPI_MEMCPY(destination, source, item_count);
+ return;
+
+ /*
+ * 16-, 32-, and 64-bit cases must use the move macros that perform
+ * endian conversion and/or accomodate hardware that cannot perform
+ * misaligned memory transfers
+ */
+ case ACPI_RSC_MOVE16:
+ ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i],
+ &ACPI_CAST_PTR(u16, source)[i]);
+ break;
+
+ case ACPI_RSC_MOVE32:
+ ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i],
+ &ACPI_CAST_PTR(u32, source)[i]);
+ break;
+
+ case ACPI_RSC_MOVE64:
+ ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i],
+ &ACPI_CAST_PTR(u64, source)[i]);
+ break;
+
+ default:
+ return;
+ }
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_set_resource_length
+ *
+ * PARAMETERS: total_length - Length of the AML descriptor, including
+ * the header and length fields.
+ * Aml - Pointer to the raw AML descriptor
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set the resource_length field of an AML
+ * resource descriptor, both Large and Small descriptors are
+ * supported automatically. Note: Descriptor Type field must
+ * be valid.
+ *
+ ******************************************************************************/
+
+void
+acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
+ union aml_resource *aml)
+{
+ acpi_rs_length resource_length;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Length is the total descriptor length minus the header length */
+
+ resource_length = (acpi_rs_length)
+ (total_length - acpi_ut_get_resource_header_length(aml));
+
+ /* Length is stored differently for large and small descriptors */
+
+ if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
+ /* Large descriptor -- bytes 1-2 contain the 16-bit length */
+
+ ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
+ &resource_length);
+ } else {
+ /* Small descriptor -- bits 2:0 of byte 0 contain the length */
+
+ aml->small_header.descriptor_type = (u8)
+
+ /* Clear any existing length, preserving descriptor type bits */
+ ((aml->small_header.
+ descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
+
+ | resource_length);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_set_resource_header
+ *
+ * PARAMETERS: descriptor_type - Byte to be inserted as the type
+ * total_length - Length of the AML descriptor, including
+ * the header and length fields.
+ * Aml - Pointer to the raw AML descriptor
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML
+ * resource descriptor, both Large and Small descriptors are
+ * supported automatically
+ *
+ ******************************************************************************/
+
+void
+acpi_rs_set_resource_header(u8 descriptor_type,
+ acpi_rsdesc_size total_length,
+ union aml_resource *aml)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ /* Set the Resource Type */
+
+ aml->small_header.descriptor_type = descriptor_type;
+
+ /* Set the Resource Length */
+
+ acpi_rs_set_resource_length(total_length, aml);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_strcpy
+ *
+ * PARAMETERS: Destination - Pointer to the destination string
+ * Source - Pointer to the source string
+ *
+ * RETURN: String length, including NULL terminator
+ *
+ * DESCRIPTION: Local string copy that returns the string length, saving a
+ * strcpy followed by a strlen.
+ *
+ ******************************************************************************/
+
+static u16 acpi_rs_strcpy(char *destination, char *source)
+{
+ u16 i;
+
+ ACPI_FUNCTION_ENTRY();
+
+ for (i = 0; source[i]; i++) {
+ destination[i] = source[i];
+ }
+
+ destination[i] = 0;
+
+ /* Return string length including the NULL terminator */
+
+ return ((u16) (i + 1));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_get_resource_source
+ *
+ * PARAMETERS: resource_length - Length field of the descriptor
+ * minimum_length - Minimum length of the descriptor (minus
+ * any optional fields)
+ * resource_source - Where the resource_source is returned
+ * Aml - Pointer to the raw AML descriptor
+ * string_ptr - (optional) where to store the actual
+ * resource_source string
+ *
+ * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit
+ *
+ * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
+ * to an internal resource descriptor
+ *
+ ******************************************************************************/
+
+acpi_rs_length
+acpi_rs_get_resource_source(acpi_rs_length resource_length,
+ acpi_rs_length minimum_length,
+ struct acpi_resource_source * resource_source,
+ union aml_resource * aml, char *string_ptr)
+{
+ acpi_rsdesc_size total_length;
+ u8 *aml_resource_source;
+
+ ACPI_FUNCTION_ENTRY();
+
+ total_length =
+ resource_length + sizeof(struct aml_resource_large_header);
+ aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
+
+ /*
+ * resource_source is present if the length of the descriptor is longer than
+ * the minimum length.
+ *
+ * Note: Some resource descriptors will have an additional null, so
+ * we add 1 to the minimum length.
+ */
+ if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) {
+ /* Get the resource_source_index */
+
+ resource_source->index = aml_resource_source[0];
+
+ resource_source->string_ptr = string_ptr;
+ if (!string_ptr) {
+ /*
+ * String destination pointer is not specified; Set the String
+ * pointer to the end of the current resource_source structure.
+ */
+ resource_source->string_ptr =
+ ACPI_ADD_PTR(char, resource_source,
+ sizeof(struct acpi_resource_source));
+ }
+
+ /*
+ * In order for the struct_size to fall on a 32-bit boundary, calculate
+ * the length of the string (+1 for the NULL terminator) and expand the
+ * struct_size to the next 32-bit boundary.
+ *
+ * Zero the entire area of the buffer.
+ */
+ total_length =
+ ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN
+ ((char *)&aml_resource_source[1]) +
+ 1);
+ ACPI_MEMSET(resource_source->string_ptr, 0, total_length);
+
+ /* Copy the resource_source string to the destination */
+
+ resource_source->string_length =
+ acpi_rs_strcpy(resource_source->string_ptr,
+ (char *)&aml_resource_source[1]);
+
+ return ((acpi_rs_length) total_length);
+ }
+
+ /* resource_source is not present */
+
+ resource_source->index = 0;
+ resource_source->string_length = 0;
+ resource_source->string_ptr = NULL;
+ return (0);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_set_resource_source
+ *
+ * PARAMETERS: Aml - Pointer to the raw AML descriptor
+ * minimum_length - Minimum length of the descriptor (minus
+ * any optional fields)
+ * resource_source - Internal resource_source
+
+ *
+ * RETURN: Total length of the AML descriptor
+ *
+ * DESCRIPTION: Convert an optional resource_source from internal format to a
+ * raw AML resource descriptor
+ *
+ ******************************************************************************/
+
+acpi_rsdesc_size
+acpi_rs_set_resource_source(union aml_resource * aml,
+ acpi_rs_length minimum_length,
+ struct acpi_resource_source * resource_source)
+{
+ u8 *aml_resource_source;
+ acpi_rsdesc_size descriptor_length;
+
+ ACPI_FUNCTION_ENTRY();
+
+ descriptor_length = minimum_length;
+
+ /* Non-zero string length indicates presence of a resource_source */
+
+ if (resource_source->string_length) {
+ /* Point to the end of the AML descriptor */
+
+ aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
+
+ /* Copy the resource_source_index */
+
+ aml_resource_source[0] = (u8) resource_source->index;
+
+ /* Copy the resource_source string */
+
+ ACPI_STRCPY((char *)&aml_resource_source[1],
+ resource_source->string_ptr);
+
+ /*
+ * Add the length of the string (+ 1 for null terminator) to the
+ * final descriptor length
+ */
+ descriptor_length +=
+ ((acpi_rsdesc_size) resource_source->string_length + 1);
+ }
+
+ /* Return the new total length of the AML descriptor */
+
+ return (descriptor_length);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_rs_get_prt_method_data
*
* PARAMETERS: Handle - a handle to the containing object
@@ -65,8 +448,9 @@ ACPI_MODULE_NAME("rsutils")
* and the contents of the callers buffer is undefined.
*
******************************************************************************/
+
acpi_status
-acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
+acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
{
union acpi_operand_object *obj_desc;
acpi_status status;
@@ -284,7 +668,7 @@ acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
* Convert the linked list into a byte stream
*/
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_rs_create_byte_stream(in_buffer->pointer, &buffer);
+ status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index ee5a5c50919..88b67077aee 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,13 +57,17 @@ ACPI_MODULE_NAME("rsxface")
ACPI_COPY_FIELD(out, in, decode); \
ACPI_COPY_FIELD(out, in, min_address_fixed); \
ACPI_COPY_FIELD(out, in, max_address_fixed); \
- ACPI_COPY_FIELD(out, in, attribute); \
+ ACPI_COPY_FIELD(out, in, info); \
ACPI_COPY_FIELD(out, in, granularity); \
- ACPI_COPY_FIELD(out, in, min_address_range); \
- ACPI_COPY_FIELD(out, in, max_address_range); \
- ACPI_COPY_FIELD(out, in, address_translation_offset); \
+ ACPI_COPY_FIELD(out, in, minimum); \
+ ACPI_COPY_FIELD(out, in, maximum); \
+ ACPI_COPY_FIELD(out, in, translation_offset); \
ACPI_COPY_FIELD(out, in, address_length); \
ACPI_COPY_FIELD(out, in, resource_source);
+/* Local prototypes */
+static acpi_status
+acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
+
/*******************************************************************************
*
* FUNCTION: acpi_get_irq_routing_table
@@ -86,6 +90,7 @@ ACPI_MODULE_NAME("rsxface")
* the object indicated by the passed device_handle.
*
******************************************************************************/
+
acpi_status
acpi_get_irq_routing_table(acpi_handle device_handle,
struct acpi_buffer *ret_buffer)
@@ -222,12 +227,12 @@ EXPORT_SYMBOL(acpi_get_possible_resources);
*
* FUNCTION: acpi_walk_resources
*
- * PARAMETERS: device_handle - a handle to the device object for the
+ * PARAMETERS: device_handle - Handle to the device object for the
* device we are querying
- * Path - method name of the resources we want
+ * Name - Method name of the resources we want
* (METHOD_NAME__CRS or METHOD_NAME__PRS)
- * user_function - called for each resource
- * Context - passed to user_function
+ * user_function - Called for each resource
+ * Context - Passed to user_function
*
* RETURN: Status
*
@@ -239,79 +244,74 @@ EXPORT_SYMBOL(acpi_get_possible_resources);
acpi_status
acpi_walk_resources(acpi_handle device_handle,
- char *path,
+ char *name,
ACPI_WALK_RESOURCE_CALLBACK user_function, void *context)
{
acpi_status status;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer buffer;
struct acpi_resource *resource;
- struct acpi_resource *buffer_end;
+ struct acpi_resource *resource_end;
ACPI_FUNCTION_TRACE("acpi_walk_resources");
- if (!device_handle ||
- (ACPI_STRNCMP(path, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
- ACPI_STRNCMP(path, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
+ /* Parameter validation */
+
+ if (!device_handle || !user_function || !name ||
+ (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
+ ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_rs_get_method_data(device_handle, path, &buffer);
+ /* Get the _CRS or _PRS resource list */
+
+ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ status = acpi_rs_get_method_data(device_handle, name, &buffer);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- /* Setup pointers */
+ /* Buffer now contains the resource list */
- resource = (struct acpi_resource *)buffer.pointer;
- buffer_end = ACPI_CAST_PTR(struct acpi_resource,
- ((u8 *) buffer.pointer + buffer.length));
+ resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer);
+ resource_end =
+ ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length);
- /* Walk the resource list */
+ /* Walk the resource list until the end_tag is found (or buffer end) */
- for (;;) {
- if (!resource || resource->id == ACPI_RSTYPE_END_TAG) {
+ while (resource < resource_end) {
+ /* Sanity check the resource */
+
+ if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
+ status = AE_AML_INVALID_RESOURCE_TYPE;
break;
}
- status = user_function(resource, context);
-
- switch (status) {
- case AE_OK:
- case AE_CTRL_DEPTH:
+ /* Invoke the user function, abort on any error returned */
- /* Just keep going */
+ status = user_function(resource, context);
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_CTRL_TERMINATE) {
+ /* This is an OK termination by the user function */
- status = AE_OK;
+ status = AE_OK;
+ }
break;
+ }
- case AE_CTRL_TERMINATE:
-
- /* Exit now, with OK stats */
-
- status = AE_OK;
- goto cleanup;
-
- default:
-
- /* All others are valid exceptions */
+ /* end_tag indicates end-of-list */
- goto cleanup;
+ if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
+ break;
}
/* Get the next resource descriptor */
- resource = ACPI_NEXT_RESOURCE(resource);
-
- /* Check for end-of-buffer */
-
- if (resource >= buffer_end) {
- goto cleanup;
- }
+ resource =
+ ACPI_ADD_PTR(struct acpi_resource, resource,
+ resource->length);
}
- cleanup:
-
- acpi_os_free(buffer.pointer);
+ ACPI_MEM_FREE(buffer.pointer);
return_ACPI_STATUS(status);
}
@@ -360,8 +360,8 @@ EXPORT_SYMBOL(acpi_set_current_resources);
*
* FUNCTION: acpi_resource_to_address64
*
- * PARAMETERS: resource - Pointer to a resource
- * out - Pointer to the users's return
+ * PARAMETERS: Resource - Pointer to a resource
+ * Out - Pointer to the users's return
* buffer (a struct
* struct acpi_resource_address64)
*
@@ -381,20 +381,26 @@ acpi_resource_to_address64(struct acpi_resource *resource,
struct acpi_resource_address16 *address16;
struct acpi_resource_address32 *address32;
- switch (resource->id) {
- case ACPI_RSTYPE_ADDRESS16:
+ if (!resource || !out) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Convert 16 or 32 address descriptor to 64 */
+
+ switch (resource->type) {
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
address16 = (struct acpi_resource_address16 *)&resource->data;
ACPI_COPY_ADDRESS(out, address16);
break;
- case ACPI_RSTYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
address32 = (struct acpi_resource_address32 *)&resource->data;
ACPI_COPY_ADDRESS(out, address32);
break;
- case ACPI_RSTYPE_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
/* Simple copy for 64 bit source */
@@ -410,3 +416,113 @@ acpi_resource_to_address64(struct acpi_resource *resource,
}
EXPORT_SYMBOL(acpi_resource_to_address64);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_get_vendor_resource
+ *
+ * PARAMETERS: device_handle - Handle for the parent device object
+ * Name - Method name for the parent resource
+ * (METHOD_NAME__CRS or METHOD_NAME__PRS)
+ * Uuid - Pointer to the UUID to be matched.
+ * includes both subtype and 16-byte UUID
+ * ret_buffer - Where the vendor resource is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Walk a resource template for the specified evice to find a
+ * vendor-defined resource that matches the supplied UUID and
+ * UUID subtype. Returns a struct acpi_resource of type Vendor.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_get_vendor_resource(acpi_handle device_handle,
+ char *name,
+ struct acpi_vendor_uuid * uuid,
+ struct acpi_buffer * ret_buffer)
+{
+ struct acpi_vendor_walk_info info;
+ acpi_status status;
+
+ /* Other parameters are validated by acpi_walk_resources */
+
+ if (!uuid || !ret_buffer) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ info.uuid = uuid;
+ info.buffer = ret_buffer;
+ info.status = AE_NOT_EXIST;
+
+ /* Walk the _CRS or _PRS resource list for this device */
+
+ status =
+ acpi_walk_resources(device_handle, name,
+ acpi_rs_match_vendor_resource, &info);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ return (info.status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_match_vendor_resource
+ *
+ * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
+{
+ struct acpi_vendor_walk_info *info = context;
+ struct acpi_resource_vendor_typed *vendor;
+ struct acpi_buffer *buffer;
+ acpi_status status;
+
+ /* Ignore all descriptors except Vendor */
+
+ if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {
+ return (AE_OK);
+ }
+
+ vendor = &resource->data.vendor_typed;
+
+ /*
+ * For a valid match, these conditions must hold:
+ *
+ * 1) Length of descriptor data must be at least as long as a UUID struct
+ * 2) The UUID subtypes must match
+ * 3) The UUID data must match
+ */
+ if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||
+ (vendor->uuid_subtype != info->uuid->subtype) ||
+ (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {
+ return (AE_OK);
+ }
+
+ /* Validate/Allocate/Clear caller buffer */
+
+ buffer = info->buffer;
+ status = acpi_ut_initialize_buffer(buffer, resource->length);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Found the correct resource, copy and return it */
+
+ ACPI_MEMCPY(buffer->pointer, resource, resource->length);
+ buffer->length = resource->length;
+
+ /* Found the desired descriptor, terminate resource walk */
+
+ info->status = AE_OK;
+ return (AE_CTRL_TERMINATE);
+}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 3b26a710436..9271e5209ac 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -851,7 +851,7 @@ static void acpi_device_set_id(struct acpi_device *device,
* ----
* Fix for the system root bus device -- the only root-level device.
*/
- if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
+ if (((acpi_handle)parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
hid = ACPI_BUS_HID;
strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c
index af7935a95bc..47fb4b394ee 100644
--- a/drivers/acpi/sleep/poweroff.c
+++ b/drivers/acpi/sleep/poweroff.c
@@ -33,9 +33,7 @@ int acpi_sleep_prepare(u32 acpi_state)
ACPI_FLUSH_CPU_CACHE();
acpi_enable_wakeup_device_prep(acpi_state);
#endif
- if (acpi_state == ACPI_STATE_S5) {
- acpi_wakeup_gpe_poweroff_prepare();
- }
+ acpi_gpe_sleep_prepare(acpi_state);
acpi_enter_sleep_state_prep(acpi_state);
return 0;
}
@@ -53,11 +51,16 @@ void acpi_power_off(void)
static int acpi_shutdown(struct sys_device *x)
{
- if (system_state == SYSTEM_POWER_OFF) {
- /* Prepare if we are going to power off the system */
+ switch (system_state) {
+ case SYSTEM_POWER_OFF:
+ /* Prepare to power off the system */
return acpi_sleep_prepare(ACPI_STATE_S5);
+ case SYSTEM_SUSPEND_DISK:
+ /* Prepare to suspend the system to disk */
+ return acpi_sleep_prepare(ACPI_STATE_S4);
+ default:
+ return 0;
}
- return 0;
}
static struct sysdev_class acpi_sysclass = {
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
index efd0001c6f0..f3e70397a7d 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep/sleep.h
@@ -5,4 +5,4 @@ extern int acpi_suspend (u32 state);
extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
extern void acpi_enable_wakeup_device(u8 sleep_state);
extern void acpi_disable_wakeup_device(u8 sleep_state);
-extern void acpi_wakeup_gpe_poweroff_prepare(void);
+extern void acpi_gpe_sleep_prepare(u32 sleep_state);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index 4134ed43d02..85df0ceda2a 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -192,7 +192,7 @@ late_initcall(acpi_wakeup_device_init);
* RUNTIME GPEs, we simply mark all GPES that
* are not enabled for wakeup from S5 as RUNTIME.
*/
-void acpi_wakeup_gpe_poweroff_prepare(void)
+void acpi_gpe_sleep_prepare(u32 sleep_state)
{
struct list_head *node, *next;
@@ -201,8 +201,8 @@ void acpi_wakeup_gpe_poweroff_prepare(void)
struct acpi_device,
wakeup_list);
- /* The GPE can wakeup system from S5, don't touch it */
- if ((u32) dev->wakeup.sleep_state == ACPI_STATE_S5)
+ /* The GPE can wakeup system from this state, don't touch it */
+ if ((u32) dev->wakeup.sleep_state >= sleep_state)
continue;
/* acpi_set_gpe_type will automatically disable GPE */
acpi_set_gpe_type(dev->wakeup.gpe_device,
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
index a03939399fa..03b37d2223b 100644
--- a/drivers/acpi/tables/tbconvrt.c
+++ b/drivers/acpi/tables/tbconvrt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -501,8 +501,8 @@ acpi_status acpi_tb_convert_table_fadt(void)
* at least as long as the version 1.0 FADT
*/
if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) {
- ACPI_REPORT_ERROR(("FADT is invalid, too short: 0x%X\n",
- acpi_gbl_FADT->length));
+ ACPI_ERROR((AE_INFO, "FADT is invalid, too short: 0x%X",
+ acpi_gbl_FADT->length));
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
@@ -517,7 +517,10 @@ acpi_status acpi_tb_convert_table_fadt(void)
if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) {
/* Length is too short to be a V2.0 table */
- ACPI_REPORT_WARNING(("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n", acpi_gbl_FADT->length, acpi_gbl_FADT->revision));
+ ACPI_WARNING((AE_INFO,
+ "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table",
+ acpi_gbl_FADT->length,
+ acpi_gbl_FADT->revision));
acpi_tb_convert_fadt1(local_fadt,
(void *)acpi_gbl_FADT);
@@ -554,7 +557,9 @@ acpi_status acpi_tb_convert_table_fadt(void)
ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
"Hex dump of common internal FADT, size %d (%X)\n",
acpi_gbl_FADT->length, acpi_gbl_FADT->length));
- ACPI_DUMP_BUFFER((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length);
+
+ ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_FADT),
+ acpi_gbl_FADT->length);
return_ACPI_STATUS(AE_OK);
}
@@ -580,13 +585,15 @@ acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info)
/* Absolute minimum length is 24, but the ACPI spec says 64 */
if (acpi_gbl_FACS->length < 24) {
- ACPI_REPORT_ERROR(("Invalid FACS table length: 0x%X\n",
- acpi_gbl_FACS->length));
+ ACPI_ERROR((AE_INFO, "Invalid FACS table length: 0x%X",
+ acpi_gbl_FACS->length));
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
if (acpi_gbl_FACS->length < 64) {
- ACPI_REPORT_WARNING(("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n", acpi_gbl_FACS->length));
+ ACPI_WARNING((AE_INFO,
+ "FACS is shorter than the ACPI specification allows: 0x%X, using anyway",
+ acpi_gbl_FACS->length));
}
/* Copy fields to the new FACS */
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 6acd5aeb093..09b4ee6dfd6 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -91,9 +91,9 @@ acpi_tb_get_table(struct acpi_pointer *address,
status = acpi_tb_get_table_body(address, &header, table_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not get ACPI table (size %X), %s\n",
- header.length,
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not get ACPI table (size %X)",
+ header.length));
return_ACPI_STATUS(status);
}
@@ -148,7 +148,6 @@ acpi_tb_get_table_header(struct acpi_pointer *address,
sizeof(struct acpi_table_header),
(void *)&header);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not map memory at %8.8X%8.8X for length %X\n", ACPI_FORMAT_UINT64(address->pointer.physical), sizeof(struct acpi_table_header)));
return_ACPI_STATUS(status);
}
@@ -161,8 +160,8 @@ acpi_tb_get_table_header(struct acpi_pointer *address,
default:
- ACPI_REPORT_ERROR(("Invalid address flags %X\n",
- address->pointer_type));
+ ACPI_ERROR((AE_INFO, "Invalid address flags %X",
+ address->pointer_type));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -253,8 +252,8 @@ acpi_tb_table_override(struct acpi_table_header *header,
if (ACPI_FAILURE(status)) {
/* Some severe error from the OSL, but we basically ignore it */
- ACPI_REPORT_ERROR(("Could not override ACPI table, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not override ACPI table"));
return_ACPI_STATUS(status);
}
@@ -273,15 +272,14 @@ acpi_tb_table_override(struct acpi_table_header *header,
status = acpi_tb_get_this_table(&address, new_table, table_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not copy override ACPI table, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "Could not copy ACPI table"));
return_ACPI_STATUS(status);
}
/* Copy the table info */
- ACPI_REPORT_INFO(("Table [%4.4s] replaced by host OS\n",
- table_info->pointer->signature));
+ ACPI_INFO((AE_INFO, "Table [%4.4s] replaced by host OS",
+ table_info->pointer->signature));
return_ACPI_STATUS(AE_OK);
}
@@ -327,7 +325,9 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
full_table = ACPI_MEM_ALLOCATE(header->length);
if (!full_table) {
- ACPI_REPORT_ERROR(("Could not allocate table memory for [%4.4s] length %X\n", header->signature, header->length));
+ ACPI_ERROR((AE_INFO,
+ "Could not allocate table memory for [%4.4s] length %X",
+ header->signature, header->length));
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -351,7 +351,12 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
(acpi_size) header->length,
(void *)&full_table);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", header->signature, ACPI_FORMAT_UINT64(address->pointer.physical), header->length));
+ ACPI_ERROR((AE_INFO,
+ "Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X",
+ header->signature,
+ ACPI_FORMAT_UINT64(address->pointer.
+ physical),
+ header->length));
return (status);
}
@@ -362,8 +367,8 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid address flags %X\n",
- address->pointer_type));
+ ACPI_ERROR((AE_INFO, "Invalid address flags %X",
+ address->pointer_type));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c
index 8d72343537e..134e5dce0bc 100644
--- a/drivers/acpi/tables/tbgetall.c
+++ b/drivers/acpi/tables/tbgetall.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -152,7 +152,9 @@ acpi_tb_get_secondary_table(struct acpi_pointer *address,
/* Signature must match request */
if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) {
- ACPI_REPORT_ERROR(("Incorrect table signature - wanted [%s] found [%4.4s]\n", signature, header.signature));
+ ACPI_ERROR((AE_INFO,
+ "Incorrect table signature - wanted [%s] found [%4.4s]",
+ signature, header.signature));
return_ACPI_STATUS(AE_BAD_SIGNATURE);
}
@@ -231,14 +233,18 @@ acpi_status acpi_tb_get_required_tables(void)
*/
status = acpi_tb_get_primary_table(&address, &table_info);
if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) {
- ACPI_REPORT_WARNING(("%s, while getting table at %8.8X%8.8X\n", acpi_format_exception(status), ACPI_FORMAT_UINT64(address.pointer.value)));
+ ACPI_WARNING((AE_INFO,
+ "%s, while getting table at %8.8X%8.8X",
+ acpi_format_exception(status),
+ ACPI_FORMAT_UINT64(address.pointer.
+ value)));
}
}
/* We must have a FADT to continue */
if (!acpi_gbl_FADT) {
- ACPI_REPORT_ERROR(("No FADT present in RSDT/XSDT\n"));
+ ACPI_ERROR((AE_INFO, "No FADT present in RSDT/XSDT"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
@@ -248,7 +254,8 @@ acpi_status acpi_tb_get_required_tables(void)
*/
status = acpi_tb_convert_table_fadt();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not convert FADT to internal common format\n"));
+ ACPI_ERROR((AE_INFO,
+ "Could not convert FADT to internal common format"));
return_ACPI_STATUS(status);
}
@@ -258,8 +265,8 @@ acpi_status acpi_tb_get_required_tables(void)
status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not get/install the FACS, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not get/install the FACS"));
return_ACPI_STATUS(status);
}
@@ -278,7 +285,7 @@ acpi_status acpi_tb_get_required_tables(void)
status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not get/install the DSDT\n"));
+ ACPI_ERROR((AE_INFO, "Could not get/install the DSDT"));
return_ACPI_STATUS(status);
}
@@ -292,7 +299,9 @@ acpi_status acpi_tb_get_required_tables(void)
"Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n",
acpi_gbl_DSDT->length, acpi_gbl_DSDT->length,
acpi_gbl_integer_bit_width));
- ACPI_DUMP_BUFFER((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length);
+
+ ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_DSDT),
+ acpi_gbl_DSDT->length);
/* Always delete the RSDP mapping, we are done with it */
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 10db8484e46..7ffd0fddb4e 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -128,8 +128,8 @@ acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info)
status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not acquire table mutex, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not acquire table mutex"));
return_ACPI_STATUS(status);
}
@@ -146,9 +146,9 @@ acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info)
status = acpi_tb_init_table_descriptor(table_info->type, table_info);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Could not install table [%4.4s], %s\n",
- table_info->pointer->signature,
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not install table [%4.4s]",
+ table_info->pointer->signature));
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n",
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index ad0252c2f7d..4d308220225 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -176,7 +176,7 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
{
int no_match;
- ACPI_FUNCTION_NAME("tb_validate_rsdt");
+ ACPI_FUNCTION_ENTRY();
/*
* Search for appropriate signature, RSDT or XSDT
@@ -192,24 +192,24 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
if (no_match) {
/* Invalid RSDT or XSDT signature */
- ACPI_REPORT_ERROR(("Invalid signature where RSDP indicates RSDT/XSDT should be located\n"));
+ ACPI_ERROR((AE_INFO,
+ "Invalid signature where RSDP indicates RSDT/XSDT should be located. RSDP:"));
ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20);
- ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR,
- "RSDT/XSDT signature at %X (%p) is invalid\n",
- acpi_gbl_RSDP->rsdt_physical_address,
- (void *)(acpi_native_uint) acpi_gbl_RSDP->
- rsdt_physical_address));
+ ACPI_ERROR((AE_INFO,
+ "RSDT/XSDT signature at %X (%p) is invalid",
+ acpi_gbl_RSDP->rsdt_physical_address,
+ (void *)(acpi_native_uint) acpi_gbl_RSDP->
+ rsdt_physical_address));
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
- ACPI_REPORT_ERROR(("Looking for RSDT\n"))
+ ACPI_ERROR((AE_INFO, "Looking for RSDT"));
} else {
- ACPI_REPORT_ERROR(("Looking for XSDT\n"))
+ ACPI_ERROR((AE_INFO, "Looking for XSDT"));
}
ACPI_DUMP_BUFFER((char *)table_ptr, 48);
-
return (AE_BAD_SIGNATURE);
}
@@ -243,15 +243,13 @@ acpi_status acpi_tb_get_table_rsdt(void)
table_info.type = ACPI_TABLE_XSDT;
status = acpi_tb_get_table(&address, &table_info);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not get the RSDT/XSDT, %s\n",
- acpi_format_exception(status)));
-
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not get the RSDT/XSDT"));
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n",
+ "RSDP located at %p, points to RSDT physical=%8.8X%8.8X\n",
acpi_gbl_RSDP,
ACPI_FORMAT_UINT64(address.pointer.value)));
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index 4b2fbb592f4..bc571592f08 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -94,9 +94,8 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc)
new_table_desc->pointer->length)
&&
(!ACPI_MEMCMP
- ((const char *)table_desc->pointer,
- (const char *)new_table_desc->pointer,
- (acpi_size) new_table_desc->pointer->length))) {
+ (table_desc->pointer, new_table_desc->pointer,
+ new_table_desc->pointer->length))) {
/* Match: this table is already installed */
ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
@@ -145,14 +144,13 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header)
{
acpi_name signature;
- ACPI_FUNCTION_NAME("tb_validate_table_header");
+ ACPI_FUNCTION_ENTRY();
/* Verify that this is a valid address */
if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Cannot read table header at %p\n",
- table_header));
+ ACPI_ERROR((AE_INFO,
+ "Cannot read table header at %p", table_header));
return (AE_BAD_ADDRESS);
}
@@ -161,12 +159,12 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header)
ACPI_MOVE_32_TO_32(&signature, table_header->signature);
if (!acpi_ut_valid_acpi_name(signature)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Table signature at %p [%p] has invalid characters\n",
- table_header, &signature));
+ ACPI_ERROR((AE_INFO,
+ "Table signature at %p [%p] has invalid characters",
+ table_header, &signature));
- ACPI_REPORT_WARNING(("Invalid table signature found: [%4.4s]\n",
- (char *)&signature));
+ ACPI_WARNING((AE_INFO, "Invalid table signature found: [%4.4s]",
+ ACPI_CAST_PTR(char, &signature)));
ACPI_DUMP_BUFFER(table_header,
sizeof(struct acpi_table_header));
@@ -176,11 +174,13 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header)
/* Validate the table length */
if (table_header->length < sizeof(struct acpi_table_header)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid length in table header %p name %4.4s\n",
- table_header, (char *)&signature));
+ ACPI_ERROR((AE_INFO,
+ "Invalid length in table header %p name %4.4s",
+ table_header, (char *)&signature));
- ACPI_REPORT_WARNING(("Invalid table header length (0x%X) found\n", (u32) table_header->length));
+ ACPI_WARNING((AE_INFO,
+ "Invalid table header length (0x%X) found",
+ (u32) table_header->length));
ACPI_DUMP_BUFFER(table_header,
sizeof(struct acpi_table_header));
@@ -219,7 +219,10 @@ acpi_tb_verify_table_checksum(struct acpi_table_header * table_header)
/* Return the appropriate exception */
if (checksum) {
- ACPI_REPORT_WARNING(("Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n", table_header->signature, (u32) table_header->checksum, (u32) checksum));
+ ACPI_WARNING((AE_INFO,
+ "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)",
+ table_header->signature,
+ (u32) table_header->checksum, (u32) checksum));
status = AE_BAD_CHECKSUM;
}
@@ -241,16 +244,16 @@ acpi_tb_verify_table_checksum(struct acpi_table_header * table_header)
u8 acpi_tb_generate_checksum(void *buffer, u32 length)
{
- const u8 *limit;
- const u8 *rover;
+ u8 *end_buffer;
+ u8 *rover;
u8 sum = 0;
if (buffer && length) {
/* Buffer and Length are valid */
- limit = (u8 *) buffer + length;
+ end_buffer = ACPI_ADD_PTR(u8, buffer, length);
- for (rover = buffer; rover < limit; rover++) {
+ for (rover = buffer; rover < end_buffer; rover++) {
sum = (u8) (sum + *rover);
}
}
@@ -292,8 +295,7 @@ acpi_tb_handle_to_object(u16 table_id,
}
}
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "table_id=%X does not exist\n",
- table_id));
+ ACPI_ERROR((AE_INFO, "table_id=%X does not exist", table_id));
return (AE_BAD_PARAMETER);
}
#endif
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 3f96a4909aa..9fe53c9d5b9 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -75,8 +75,7 @@ acpi_status acpi_load_tables(void)
status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING,
&rsdp_address);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_load_tables: Could not get RSDP, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP"));
goto error_exit;
}
@@ -86,7 +85,7 @@ acpi_status acpi_load_tables(void)
status = acpi_tb_verify_rsdp(&rsdp_address);
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_load_tables: RSDP Failed validation: %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation"));
goto error_exit;
}
@@ -94,7 +93,7 @@ acpi_status acpi_load_tables(void)
status = acpi_tb_get_table_rsdt();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_load_tables: Could not load RSDT: %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT"));
goto error_exit;
}
@@ -102,7 +101,8 @@ acpi_status acpi_load_tables(void)
status = acpi_tb_get_required_tables();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not get all required tables (DSDT/FADT/FACS)"));
goto error_exit;
}
@@ -112,16 +112,14 @@ acpi_status acpi_load_tables(void)
status = acpi_ns_load_namespace();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("acpi_load_tables: Could not load namespace: %s\n", acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace"));
goto error_exit;
}
return_ACPI_STATUS(AE_OK);
error_exit:
- ACPI_REPORT_ERROR(("acpi_load_tables: Could not load tables: %s\n",
- acpi_format_exception(status)));
-
+ ACPI_EXCEPTION((AE_INFO, status, "Could not load tables"));
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index 3b8a7e063e8..a62db6af83c 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -251,7 +251,7 @@ acpi_get_firmware_table(acpi_string signature,
acpi_tb_get_rsdt_address(&address);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
+ "RSDP located at %p, RSDT physical=%8.8X%8.8X\n",
acpi_gbl_RSDP,
ACPI_FORMAT_UINT64(address.pointer.value)));
@@ -396,9 +396,8 @@ acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
status = acpi_tb_find_rsdp(&table_info, flags);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "RSDP structure not found, %s Flags=%X\n",
- acpi_format_exception(status), flags));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "RSDP structure not found - Flags=%X", flags));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
@@ -503,10 +502,10 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
ACPI_EBDA_PTR_LENGTH,
(void *)&table_ptr);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- ACPI_EBDA_PTR_LOCATION,
- ACPI_EBDA_PTR_LENGTH));
+ ACPI_ERROR((AE_INFO,
+ "Could not map memory at %8.8X for length %X",
+ ACPI_EBDA_PTR_LOCATION,
+ ACPI_EBDA_PTR_LENGTH));
return_ACPI_STATUS(status);
}
@@ -530,10 +529,10 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
ACPI_EBDA_WINDOW_SIZE,
(void *)&table_ptr);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- physical_address,
- ACPI_EBDA_WINDOW_SIZE));
+ ACPI_ERROR((AE_INFO,
+ "Could not map memory at %8.8X for length %X",
+ physical_address,
+ ACPI_EBDA_WINDOW_SIZE));
return_ACPI_STATUS(status);
}
@@ -563,10 +562,10 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
(void *)&table_ptr);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- ACPI_HI_RSDP_WINDOW_BASE,
- ACPI_HI_RSDP_WINDOW_SIZE));
+ ACPI_ERROR((AE_INFO,
+ "Could not map memory at %8.8X for length %X",
+ ACPI_HI_RSDP_WINDOW_BASE,
+ ACPI_HI_RSDP_WINDOW_SIZE));
return_ACPI_STATUS(status);
}
@@ -635,7 +634,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
/* A valid RSDP was not found */
- ACPI_REPORT_ERROR(("No valid RSDP was found\n"));
+ ACPI_ERROR((AE_INFO, "No valid RSDP was found"));
return_ACPI_STATUS(AE_NOT_FOUND);
}
diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile
index e87108b7338..88eff14c489 100644
--- a/drivers/acpi/utilities/Makefile
+++ b/drivers/acpi/utilities/Makefile
@@ -2,7 +2,8 @@
# Makefile for all Linux ACPI interpreter subdirectories
#
-obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
- utcopy.o utdelete.o utglobal.o utmath.o utobject.o utstate.o utmutex.o utobject.o utcache.o
+obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
+ utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
+ utstate.o utmutex.o utobject.o utcache.o utresrc.o
EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 068450b3647..03b0044974c 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
ACPI_MODULE_NAME("utalloc")
/* Local prototypes */
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation);
static acpi_status
@@ -58,9 +58,7 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
static acpi_status
acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
u32 component, char *module, u32 line);
-#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
static acpi_status
acpi_ut_create_list(char *list_name,
u16 object_size, struct acpi_memory_list **return_cache);
@@ -303,8 +301,8 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
/* Check for an inadvertent size of zero bytes */
if (!size) {
- _ACPI_REPORT_ERROR(module, line, component,
- ("ut_allocate: Attempt to allocate zero bytes\n"));
+ ACPI_ERROR((module, line,
+ "ut_allocate: Attempt to allocate zero bytes, allocating 1 byte"));
size = 1;
}
@@ -312,9 +310,9 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR(module, line, component,
- ("ut_allocate: Could not allocate size %X\n",
- (u32) size));
+ ACPI_ERROR((module, line,
+ "ut_allocate: Could not allocate size %X",
+ (u32) size));
return_PTR(NULL);
}
@@ -346,18 +344,17 @@ void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line)
/* Check for an inadvertent size of zero bytes */
if (!size) {
- _ACPI_REPORT_ERROR(module, line, component,
- ("ut_callocate: Attempt to allocate zero bytes\n"));
- return_PTR(NULL);
+ ACPI_ERROR((module, line,
+ "Attempt to allocate zero bytes, allocating 1 byte"));
+ size = 1;
}
allocation = acpi_os_allocate(size);
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR(module, line, component,
- ("ut_callocate: Could not allocate size %X\n",
- (u32) size));
+ ACPI_ERROR((module, line,
+ "Could not allocate size %X", (u32) size));
return_PTR(NULL);
}
@@ -482,9 +479,8 @@ void *acpi_ut_callocate_and_track(acpi_size size,
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR(module, line, component,
- ("ut_callocate: Could not allocate size %X\n",
- (u32) size));
+ ACPI_ERROR((module, line,
+ "Could not allocate size %X", (u32) size));
return (NULL);
}
@@ -526,8 +522,7 @@ acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line)
ACPI_FUNCTION_TRACE_PTR("ut_free", allocation);
if (NULL == allocation) {
- _ACPI_REPORT_ERROR(module, line, component,
- ("acpi_ut_free: Attempt to delete a NULL address\n"));
+ ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
return_VOID;
}
@@ -542,14 +537,11 @@ acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line)
status = acpi_ut_remove_allocation(debug_block,
component, module, line);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not free memory, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
}
acpi_os_free(debug_block);
-
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
-
return_VOID;
}
@@ -626,10 +618,12 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
*/
element = acpi_ut_find_allocation(allocation);
if (element) {
- ACPI_REPORT_ERROR(("ut_track_allocation: Allocation already present in list! (%p)\n", allocation));
+ ACPI_ERROR((AE_INFO,
+ "ut_track_allocation: Allocation already present in list! (%p)",
+ allocation));
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Element %p Address %p\n",
- element, allocation));
+ ACPI_ERROR((AE_INFO, "Element %p Address %p",
+ element, allocation));
goto unlock_and_exit;
}
@@ -689,8 +683,8 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
if (NULL == mem_list->list_head) {
/* No allocations! */
- _ACPI_REPORT_ERROR(module, line, component,
- ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
+ ACPI_ERROR((module, line,
+ "Empty allocation list, nothing to free!"));
return_ACPI_STATUS(AE_OK);
}
@@ -865,12 +859,11 @@ void acpi_ut_dump_allocations(u32 component, char *module)
/* Print summary */
if (!num_outstanding) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No outstanding allocations.\n"));
+ ACPI_INFO((AE_INFO, "No outstanding allocations"));
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%d(%X) Outstanding allocations\n",
- num_outstanding, num_outstanding));
+ ACPI_ERROR((AE_INFO,
+ "%d(%X) Outstanding allocations",
+ num_outstanding, num_outstanding));
}
return_VOID;
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
index 93d48681d27..2177cb1ef2c 100644
--- a/drivers/acpi/utilities/utcache.c
+++ b/drivers/acpi/utilities/utcache.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 5442b32de61..df2d32096b7 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -398,14 +398,17 @@ acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
* Build a simple object (no nested objects)
*/
status = acpi_ut_copy_isimple_to_esimple(internal_object,
- (union acpi_object *)
- ret_buffer->pointer,
- ((u8 *) ret_buffer->
- pointer +
- ACPI_ROUND_UP_TO_NATIVE_WORD
- (sizeof
- (union
- acpi_object))),
+ ACPI_CAST_PTR(union
+ acpi_object,
+ ret_buffer->
+ pointer),
+ ACPI_ADD_PTR(u8,
+ ret_buffer->
+ pointer,
+ ACPI_ROUND_UP_TO_NATIVE_WORD
+ (sizeof
+ (union
+ acpi_object))),
&ret_buffer->length);
/*
* build simple does not include the object size in the length
@@ -603,8 +606,8 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
/*
* Packages as external input to control methods are not supported,
*/
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Packages as parameters not implemented!\n"));
+ ACPI_ERROR((AE_INFO,
+ "Packages as parameters not implemented!"));
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
@@ -867,7 +870,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
count +
1) * sizeof(void *));
if (!dest_obj->package.elements) {
- ACPI_REPORT_ERROR(("aml_build_copy_internal_package_object: Package allocation failure\n"));
+ ACPI_ERROR((AE_INFO, "Package allocation failure"));
return_ACPI_STATUS(AE_NO_MEMORY);
}
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index d80e9263993..35f3d581e03 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 2bc878f7a12..1db9695b002 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -363,8 +363,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown action (%X)\n",
- action));
+ ACPI_ERROR((AE_INFO, "Unknown action (%X)", action));
break;
}
@@ -374,9 +373,9 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
*/
if (count > ACPI_MAX_REFERENCE_COUNT) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "**** Warning **** Large Reference Count (%X) in object %p\n\n",
- count, object));
+ ACPI_WARNING((AE_INFO,
+ "Large Reference Count (%X) in object %p",
+ count, object));
}
return;
@@ -535,8 +534,8 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action)
error_exit:
- ACPI_REPORT_ERROR(("Could not update object reference count, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not update object reference count"));
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 7b81d5ef3c3..106cc97cb4a 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -95,7 +95,9 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
if (!ACPI_STRCMP(string_desc->string.pointer,
- (char *)acpi_gbl_valid_osi_strings[i])) {
+ ACPI_CAST_PTR(char,
+ acpi_gbl_valid_osi_strings[i])))
+ {
/* This string is supported */
return_desc->integer.value = 0xFFFFFFFF;
@@ -152,8 +154,8 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
acpi_ut_get_node_name(prefix_node),
path));
} else {
- ACPI_REPORT_METHOD_ERROR("Method execution failed",
- prefix_node, path, status);
+ ACPI_ERROR_METHOD("Method execution failed",
+ prefix_node, path, status);
}
return_ACPI_STATUS(status);
@@ -163,9 +165,8 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
if (!info.return_object) {
if (expected_return_btypes) {
- ACPI_REPORT_METHOD_ERROR("No object was returned from",
- prefix_node, path,
- AE_NOT_EXIST);
+ ACPI_ERROR_METHOD("No object was returned from",
+ prefix_node, path, AE_NOT_EXIST);
return_ACPI_STATUS(AE_NOT_EXIST);
}
@@ -210,15 +211,14 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
/* Is the return object one of the expected types? */
if (!(expected_return_btypes & return_btype)) {
- ACPI_REPORT_METHOD_ERROR("Return object type is incorrect",
- prefix_node, path, AE_TYPE);
+ ACPI_ERROR_METHOD("Return object type is incorrect",
+ prefix_node, path, AE_TYPE);
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Type returned from %s was incorrect: %s, expected Btypes: %X\n",
- path,
- acpi_ut_get_object_type_name(info.
- return_object),
- expected_return_btypes));
+ ACPI_ERROR((AE_INFO,
+ "Type returned from %s was incorrect: %s, expected Btypes: %X",
+ path,
+ acpi_ut_get_object_type_name(info.return_object),
+ expected_return_btypes));
/* On error exit, we must delete the return object */
@@ -592,7 +592,7 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
"_STA on %4.4s was not found, assuming device is present\n",
acpi_ut_get_node_name(device_node)));
- *flags = 0x0F;
+ *flags = ACPI_UINT32_MAX;
status = AE_OK;
}
@@ -637,17 +637,17 @@ acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest)
for (i = 0; i < 4; i++) {
highest[i] = 0xFF;
status = acpi_ut_evaluate_object(device_node,
- (char *)
- acpi_gbl_highest_dstate_names
- [i], ACPI_BTYPE_INTEGER,
- &obj_desc);
+ ACPI_CAST_PTR(char,
+ acpi_gbl_highest_dstate_names
+ [i]),
+ ACPI_BTYPE_INTEGER, &obj_desc);
if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"%s on Device %4.4s, %s\n",
- (char *)
- acpi_gbl_highest_dstate_names
- [i],
+ ACPI_CAST_PTR(char,
+ acpi_gbl_highest_dstate_names
+ [i]),
acpi_ut_get_node_name
(device_node),
acpi_format_exception
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index 399e64b5188..ffd13383a32 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,8 +67,11 @@ const char *acpi_format_exception(acpi_status status)
acpi_status sub_status;
const char *exception = NULL;
- ACPI_FUNCTION_NAME("format_exception");
+ ACPI_FUNCTION_ENTRY();
+ /*
+ * Status is composed of two parts, a "type" and an actual code
+ */
sub_status = (status & ~AE_CODE_MASK);
switch (status & AE_CODE_MASK) {
@@ -118,13 +121,13 @@ const char *acpi_format_exception(acpi_status status)
if (!exception) {
/* Exception code was not recognized */
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unknown exception code: 0x%8.8X\n", status));
+ ACPI_ERROR((AE_INFO,
+ "Unknown exception code: 0x%8.8X", status));
- return ((const char *)"UNKNOWN_STATUS_CODE");
+ exception = "UNKNOWN_STATUS_CODE";
}
- return ((const char *)exception);
+ return (ACPI_CAST_PTR(const char, exception));
}
/*******************************************************************************
@@ -217,23 +220,23 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
* 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to
* perform a Notify() operation on it.
*/
-const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
- { {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
-{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
-{"_SB_", ACPI_TYPE_DEVICE, NULL},
-{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
-{"_TZ_", ACPI_TYPE_THERMAL, NULL},
-{"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
-{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
-{"_GL_", ACPI_TYPE_MUTEX, (char *)1},
+const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = {
+ {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
+ {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
+ {"_SB_", ACPI_TYPE_DEVICE, NULL},
+ {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
+ {"_TZ_", ACPI_TYPE_THERMAL, NULL},
+ {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
+ {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
+ {"_GL_", ACPI_TYPE_MUTEX, (char *)1},
#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
-{"_OSI", ACPI_TYPE_METHOD, (char *)1},
+ {"_OSI", ACPI_TYPE_METHOD, (char *)1},
#endif
/* Table terminator */
-{NULL, ACPI_TYPE_ANY, NULL}
+ {NULL, ACPI_TYPE_ANY, NULL}
};
/*
@@ -485,7 +488,7 @@ char *acpi_ut_get_region_name(u8 space_id)
return ("invalid_space_id");
}
- return ((char *)acpi_gbl_region_types[space_id]);
+ return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id]));
}
/*******************************************************************************
@@ -503,11 +506,13 @@ char *acpi_ut_get_region_name(u8 space_id)
/* Event type decoding */
static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
+/*! [Begin] no source code translation (keep these strings as-is) */
"PM_Timer",
- "global_lock",
- "power_button",
- "sleep_button",
- "real_time_clock",
+ "GlobalLock",
+ "PowerButton",
+ "SleepButton",
+ "RealTimeClock",
+/*! [End] no source code translation !*/
};
char *acpi_ut_get_event_name(u32 event_id)
@@ -517,7 +522,7 @@ char *acpi_ut_get_event_name(u32 event_id)
return ("invalid_event_iD");
}
- return ((char *)acpi_gbl_event_types[event_id]);
+ return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id]));
}
/*******************************************************************************
@@ -545,12 +550,13 @@ static const char acpi_gbl_bad_type[] = "UNDEFINED";
/* Printable names of the ACPI object types */
static const char *acpi_gbl_ns_type_names[] = {
+/*! [Begin] no source code translation (keep these strings as-is) */
/* 00 */ "Untyped",
/* 01 */ "Integer",
/* 02 */ "String",
/* 03 */ "Buffer",
/* 04 */ "Package",
- /* 05 */ "field_unit",
+ /* 05 */ "FieldUnit",
/* 06 */ "Device",
/* 07 */ "Event",
/* 08 */ "Method",
@@ -559,33 +565,34 @@ static const char *acpi_gbl_ns_type_names[] = {
/* 11 */ "Power",
/* 12 */ "Processor",
/* 13 */ "Thermal",
- /* 14 */ "buffer_field",
- /* 15 */ "ddb_handle",
- /* 16 */ "debug_object",
- /* 17 */ "region_field",
- /* 18 */ "bank_field",
- /* 19 */ "index_field",
+ /* 14 */ "BufferField",
+ /* 15 */ "DdbHandle",
+ /* 16 */ "DebugObject",
+ /* 17 */ "RegionField",
+ /* 18 */ "BankField",
+ /* 19 */ "IndexField",
/* 20 */ "Reference",
/* 21 */ "Alias",
- /* 22 */ "method_alias",
+ /* 22 */ "MethodAlias",
/* 23 */ "Notify",
- /* 24 */ "addr_handler",
- /* 25 */ "resource_desc",
- /* 26 */ "resource_fld",
+ /* 24 */ "AddrHandler",
+ /* 25 */ "ResourceDesc",
+ /* 26 */ "ResourceFld",
/* 27 */ "Scope",
/* 28 */ "Extra",
/* 29 */ "Data",
/* 30 */ "Invalid"
+/*! [End] no source code translation !*/
};
char *acpi_ut_get_type_name(acpi_object_type type)
{
if (type > ACPI_TYPE_INVALID) {
- return ((char *)acpi_gbl_bad_type);
+ return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
}
- return ((char *)acpi_gbl_ns_type_names[type]);
+ return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type]));
}
char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
@@ -634,7 +641,7 @@ char *acpi_ut_get_node_name(void *object)
/* Name must be a valid ACPI name */
- if (!acpi_ut_valid_acpi_name(*(u32 *) node->name.ascii)) {
+ if (!acpi_ut_valid_acpi_name(node->name.integer)) {
return ("????");
}
@@ -658,15 +665,16 @@ char *acpi_ut_get_node_name(void *object)
/* Printable names of object descriptor types */
static const char *acpi_gbl_desc_type_names[] = {
+/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
/* 00 */ "Invalid",
/* 01 */ "Cached",
/* 02 */ "State-Generic",
/* 03 */ "State-Update",
/* 04 */ "State-Package",
/* 05 */ "State-Control",
- /* 06 */ "State-root_parse_scope",
- /* 07 */ "State-parse_scope",
- /* 08 */ "State-walk_scope",
+ /* 06 */ "State-RootParseScope",
+ /* 07 */ "State-ParseScope",
+ /* 08 */ "State-WalkScope",
/* 09 */ "State-Result",
/* 10 */ "State-Notify",
/* 11 */ "State-Thread",
@@ -674,6 +682,7 @@ static const char *acpi_gbl_desc_type_names[] = {
/* 13 */ "Parser",
/* 14 */ "Operand",
/* 15 */ "Node"
+/*! [End] no source code translation !*/
};
char *acpi_ut_get_descriptor_name(void *object)
@@ -684,11 +693,12 @@ char *acpi_ut_get_descriptor_name(void *object)
}
if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) {
- return ((char *)acpi_gbl_bad_type);
+ return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
}
- return ((char *)
- acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE(object)]);
+ return (ACPI_CAST_PTR(char,
+ acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE
+ (object)]));
}
@@ -787,6 +797,11 @@ void acpi_ut_init_globals(void)
acpi_gbl_mutex_info[i].use_count = 0;
}
+ for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) {
+ acpi_gbl_owner_id_mask[i] = 0;
+ }
+ acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* Last ID is never valid */
+
/* GPE support */
acpi_gbl_gpe_xrupt_list_head = NULL;
@@ -824,7 +839,11 @@ void acpi_ut_init_globals(void)
acpi_gbl_ns_lookup_count = 0;
acpi_gbl_ps_find_count = 0;
acpi_gbl_acpi_hardware_present = TRUE;
- acpi_gbl_owner_id_mask = 0;
+ acpi_gbl_last_owner_id_index = 0;
+ acpi_gbl_next_owner_id_offset = 0;
+ acpi_gbl_trace_method_name = 0;
+ acpi_gbl_trace_dbg_level = 0;
+ acpi_gbl_trace_dbg_layer = 0;
acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
@@ -836,7 +855,6 @@ void acpi_ut_init_globals(void)
/* Namespace */
acpi_gbl_root_node = NULL;
-
acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED;
acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
index 9dde82b0bea..ba771b4f39b 100644
--- a/drivers/acpi/utilities/utinit.c
+++ b/drivers/acpi/utilities/utinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -72,9 +72,9 @@ static void
acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset)
{
- ACPI_REPORT_WARNING(("Invalid FADT value %s=%X at offset %X FADT=%p\n",
- register_name, value, (u32) offset,
- acpi_gbl_FADT));
+ ACPI_WARNING((AE_INFO,
+ "Invalid FADT value %s=%X at offset %X FADT=%p",
+ register_name, value, (u32) offset, acpi_gbl_FADT));
}
/******************************************************************************
@@ -221,15 +221,14 @@ void acpi_ut_subsystem_shutdown(void)
/* Just exit if subsystem is already shutdown */
if (acpi_gbl_shutdown) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "ACPI Subsystem is already terminated\n"));
+ ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated"));
return_VOID;
}
/* Subsystem appears active, go ahead and shut it down */
acpi_gbl_shutdown = TRUE;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem...\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
/* Close the acpi_event Handling */
diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c
index 68a0a6f9412..4a3360484e7 100644
--- a/drivers/acpi/utilities/utmath.c
+++ b/drivers/acpi/utilities/utmath.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,7 +82,7 @@ acpi_ut_short_divide(acpi_integer dividend,
/* Always check for a zero divisor */
if (divisor == 0) {
- ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n"));
+ ACPI_ERROR((AE_INFO, "Divide by zero"));
return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
@@ -144,7 +144,7 @@ acpi_ut_divide(acpi_integer in_dividend,
/* Always check for a zero divisor */
if (in_divisor == 0) {
- ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n"));
+ ACPI_ERROR((AE_INFO, "Divide by zero"));
return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
@@ -266,7 +266,7 @@ acpi_ut_short_divide(acpi_integer in_dividend,
/* Always check for a zero divisor */
if (divisor == 0) {
- ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n"));
+ ACPI_ERROR((AE_INFO, "Divide by zero"));
return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
@@ -292,7 +292,7 @@ acpi_ut_divide(acpi_integer in_dividend,
/* Always check for a zero divisor */
if (in_divisor == 0) {
- ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n"));
+ ACPI_ERROR((AE_INFO, "Divide by zero"));
return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 2ce872d7589..7364f5f8c9c 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,8 @@ ACPI_MODULE_NAME("utmisc")
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
{
acpi_native_uint i;
+ acpi_native_uint j;
+ acpi_native_uint k;
acpi_status status;
ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
@@ -70,8 +72,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
/* Guard against multiple allocations of ID to the same location */
if (*owner_id) {
- ACPI_REPORT_ERROR(("Owner ID [%2.2X] already exists\n",
- *owner_id));
+ ACPI_ERROR((AE_INFO, "Owner ID [%2.2X] already exists",
+ *owner_id));
return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
@@ -82,31 +84,67 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
return_ACPI_STATUS(status);
}
- /* Find a free owner ID */
+ /*
+ * Find a free owner ID, cycle through all possible IDs on repeated
+ * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
+ * to be scanned twice.
+ */
+ for (i = 0, j = acpi_gbl_last_owner_id_index;
+ i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) {
+ if (j >= ACPI_NUM_OWNERID_MASKS) {
+ j = 0; /* Wraparound to start of mask array */
+ }
+
+ for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) {
+ if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) {
+ /* There are no free IDs in this mask */
- for (i = 0; i < 64; i++) {
- if (!(acpi_gbl_owner_id_mask & (1ULL << i))) {
- ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
- "Current owner_id mask: %16.16LX New ID: %2.2X\n",
- acpi_gbl_owner_id_mask,
- (unsigned int)(i + 1)));
+ break;
+ }
- acpi_gbl_owner_id_mask |= (1ULL << i);
- *owner_id = (acpi_owner_id) (i + 1);
- goto exit;
+ if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) {
+ /*
+ * Found a free ID. The actual ID is the bit index plus one,
+ * making zero an invalid Owner ID. Save this as the last ID
+ * allocated and update the global ID mask.
+ */
+ acpi_gbl_owner_id_mask[j] |= (1 << k);
+
+ acpi_gbl_last_owner_id_index = (u8) j;
+ acpi_gbl_next_owner_id_offset = (u8) (k + 1);
+
+ /*
+ * Construct encoded ID from the index and bit position
+ *
+ * Note: Last [j].k (bit 255) is never used and is marked
+ * permanently allocated (prevents +1 overflow)
+ */
+ *owner_id =
+ (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j));
+
+ ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
+ "Allocated owner_id: %2.2X\n",
+ (unsigned int)*owner_id));
+ goto exit;
+ }
}
+
+ acpi_gbl_next_owner_id_offset = 0;
}
/*
- * If we are here, all owner_ids have been allocated. This probably should
+ * All owner_ids have been allocated. This typically should
* not happen since the IDs are reused after deallocation. The IDs are
* allocated upon table load (one per table) and method execution, and
* they are released when a table is unloaded or a method completes
* execution.
+ *
+ * If this error happens, there may be very deep nesting of invoked control
+ * methods, or there may be a bug where the IDs are not released.
*/
- *owner_id = 0;
status = AE_OWNER_ID_LIMIT;
- ACPI_REPORT_ERROR(("Could not allocate new owner_id (64 max), AE_OWNER_ID_LIMIT\n"));
+ ACPI_ERROR((AE_INFO,
+ "Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT"));
exit:
(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
@@ -123,7 +161,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
* control method or unloading a table. Either way, we would
* ignore any error anyway.
*
- * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 64
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
*
******************************************************************************/
@@ -131,6 +169,8 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
{
acpi_owner_id owner_id = *owner_id_ptr;
acpi_status status;
+ acpi_native_uint index;
+ u32 bit;
ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id);
@@ -140,8 +180,8 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
/* Zero is not a valid owner_iD */
- if ((owner_id == 0) || (owner_id > 64)) {
- ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id));
+ if (owner_id == 0) {
+ ACPI_ERROR((AE_INFO, "Invalid owner_id: %2.2X", owner_id));
return_VOID;
}
@@ -156,10 +196,19 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
owner_id--;
+ /* Decode ID to index/offset pair */
+
+ index = ACPI_DIV_32(owner_id);
+ bit = 1 << ACPI_MOD_32(owner_id);
+
/* Free the owner ID only if it is valid */
- if (acpi_gbl_owner_id_mask & (1ULL << owner_id)) {
- acpi_gbl_owner_id_mask ^= (1ULL << owner_id);
+ if (acpi_gbl_owner_id_mask[index] & bit) {
+ acpi_gbl_owner_id_mask[index] ^= bit;
+ } else {
+ ACPI_ERROR((AE_INFO,
+ "Release of non-allocated owner_id: %2.2X",
+ owner_id + 1));
}
(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
@@ -790,109 +839,97 @@ u8 acpi_ut_generate_checksum(u8 * buffer, u32 length)
/*******************************************************************************
*
- * FUNCTION: acpi_ut_get_resource_end_tag
+ * FUNCTION: acpi_ut_error, acpi_ut_warning, acpi_ut_info
*
- * PARAMETERS: obj_desc - The resource template buffer object
+ * PARAMETERS: module_name - Caller's module name (for error output)
+ * line_number - Caller's line number (for error output)
+ * Format - Printf format string + additional args
*
- * RETURN: Pointer to the end tag
+ * RETURN: None
*
- * DESCRIPTION: Find the END_TAG resource descriptor in a resource template
+ * DESCRIPTION: Print message with module/line/version info
*
******************************************************************************/
-u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc)
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_error(char *module_name, u32 line_number, char *format, ...)
{
- u8 buffer_byte;
- u8 *buffer;
- u8 *end_buffer;
+ va_list args;
- buffer = obj_desc->buffer.pointer;
- end_buffer = buffer + obj_desc->buffer.length;
+ acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
- while (buffer < end_buffer) {
- buffer_byte = *buffer;
- if (buffer_byte & ACPI_RDESC_TYPE_MASK) {
- /* Large Descriptor - Length is next 2 bytes */
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
+ acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+}
- buffer += ((*(buffer + 1) | (*(buffer + 2) << 8)) + 3);
- } else {
- /* Small Descriptor. End Tag will be found here */
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_exception(char *module_name,
+ u32 line_number, acpi_status status, char *format, ...)
+{
+ va_list args;
- if ((buffer_byte & ACPI_RDESC_SMALL_MASK) ==
- ACPI_RDESC_TYPE_END_TAG) {
- /* Found the end tag descriptor, all done. */
+ acpi_os_printf("ACPI Exception (%s-%04d): %s, ", module_name,
+ line_number, acpi_format_exception(status));
- return (buffer);
- }
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
+ acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+}
- /* Length is in the header */
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
+{
+ va_list args;
- buffer += ((buffer_byte & 0x07) + 1);
- }
- }
+ acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number);
+
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
+ acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+}
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_info(char *module_name, u32 line_number, char *format, ...)
+{
+ va_list args;
- /* End tag not found */
+ acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number);
- return (NULL);
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
+ acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
}
/*******************************************************************************
*
- * FUNCTION: acpi_ut_report_error
+ * FUNCTION: acpi_ut_report_error, Warning, Info
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
- * component_id - Caller's component ID (for error output)
*
* RETURN: None
*
* DESCRIPTION: Print error message
*
+ * Note: Legacy only, should be removed when no longer used by drivers.
+ *
******************************************************************************/
-void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id)
+void acpi_ut_report_error(char *module_name, u32 line_number)
{
- acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
+ acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_report_warning
- *
- * PARAMETERS: module_name - Caller's module name (for error output)
- * line_number - Caller's line number (for error output)
- * component_id - Caller's component ID (for error output)
- *
- * RETURN: None
- *
- * DESCRIPTION: Print warning message
- *
- ******************************************************************************/
-
-void
-acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id)
+void acpi_ut_report_warning(char *module_name, u32 line_number)
{
- acpi_os_printf("%8s-%04d: *** Warning: ", module_name, line_number);
+ acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_report_info
- *
- * PARAMETERS: module_name - Caller's module name (for error output)
- * line_number - Caller's line number (for error output)
- * component_id - Caller's component ID (for error output)
- *
- * RETURN: None
- *
- * DESCRIPTION: Print information message
- *
- ******************************************************************************/
-
-void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id)
+void acpi_ut_report_info(char *module_name, u32 line_number)
{
- acpi_os_printf("%8s-%04d: *** Info: ", module_name, line_number);
+ acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number);
}
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
index 90134c56ece..45a7244df92 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/drivers/acpi/utilities/utmutex.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -214,23 +214,22 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
* the ACPI subsystem code.
*/
for (i = mutex_id; i < MAX_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
+ if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
if (i == mutex_id) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Mutex [%s] already acquired by this thread [%X]\n",
- acpi_ut_get_mutex_name
- (mutex_id),
- this_thread_id));
+ ACPI_ERROR((AE_INFO,
+ "Mutex [%s] already acquired by this thread [%X]",
+ acpi_ut_get_mutex_name
+ (mutex_id),
+ this_thread_id));
return (AE_ALREADY_ACQUIRED);
}
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
- this_thread_id,
- acpi_ut_get_mutex_name(i),
- acpi_ut_get_mutex_name
- (mutex_id)));
+ ACPI_ERROR((AE_INFO,
+ "Invalid acquire order: Thread %X owns [%s], wants [%s]",
+ this_thread_id,
+ acpi_ut_get_mutex_name(i),
+ acpi_ut_get_mutex_name(mutex_id)));
return (AE_ACQUIRE_DEADLOCK);
}
@@ -253,11 +252,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
acpi_gbl_mutex_info[mutex_id].use_count++;
acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
} else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Thread %X could not acquire Mutex [%s] %s\n",
- this_thread_id,
- acpi_ut_get_mutex_name(mutex_id),
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Thread %X could not acquire Mutex [%X]",
+ this_thread_id, mutex_id));
}
return (status);
@@ -295,9 +292,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
* Mutex must be acquired in order to release it!
*/
if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Mutex [%s] is not acquired, cannot release\n",
- acpi_ut_get_mutex_name(mutex_id)));
+ ACPI_ERROR((AE_INFO,
+ "Mutex [%X] is not acquired, cannot release",
+ mutex_id));
return (AE_NOT_ACQUIRED);
}
@@ -313,16 +310,15 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
* the ACPI subsystem code.
*/
for (i = mutex_id; i < MAX_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
+ if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
if (i == mutex_id) {
continue;
}
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid release order: owns [%s], releasing [%s]\n",
- acpi_ut_get_mutex_name(i),
- acpi_ut_get_mutex_name
- (mutex_id)));
+ ACPI_ERROR((AE_INFO,
+ "Invalid release order: owns [%s], releasing [%s]",
+ acpi_ut_get_mutex_name(i),
+ acpi_ut_get_mutex_name(mutex_id)));
return (AE_RELEASE_DEADLOCK);
}
@@ -338,11 +334,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
acpi_os_signal_semaphore(acpi_gbl_mutex_info[mutex_id].mutex, 1);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Thread %X could not release Mutex [%s] %s\n",
- this_thread_id,
- acpi_ut_get_mutex_name(mutex_id),
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Thread %X could not release Mutex [%X]",
+ this_thread_id, mutex_id));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
"Thread %X released Mutex [%s]\n",
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index 3015e154005..7ee2d1d9807 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -177,7 +177,8 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size)
buffer = ACPI_MEM_CALLOCATE(buffer_size);
if (!buffer) {
- ACPI_REPORT_ERROR(("create_buffer: could not allocate size %X\n", (u32) buffer_size));
+ ACPI_ERROR((AE_INFO, "Could not allocate size %X",
+ (u32) buffer_size));
acpi_ut_remove_reference(buffer_desc);
return_PTR(NULL);
}
@@ -228,7 +229,8 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size)
*/
string = ACPI_MEM_CALLOCATE(string_size + 1);
if (!string) {
- ACPI_REPORT_ERROR(("create_string: could not allocate size %X\n", (u32) string_size));
+ ACPI_ERROR((AE_INFO, "Could not allocate size %X",
+ (u32) string_size));
acpi_ut_remove_reference(string_desc);
return_PTR(NULL);
}
@@ -310,8 +312,8 @@ void *acpi_ut_allocate_object_desc_dbg(char *module_name,
object = acpi_os_acquire_object(acpi_gbl_operand_cache);
if (!object) {
- _ACPI_REPORT_ERROR(module_name, line_number, component_id,
- ("Could not allocate an object descriptor\n"));
+ ACPI_ERROR((module_name, line_number,
+ "Could not allocate an object descriptor"));
return_PTR(NULL);
}
@@ -345,9 +347,9 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object)
/* Object must be an union acpi_operand_object */
if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "%p is not an ACPI Operand object [%s]\n",
- object, acpi_ut_get_descriptor_name(object)));
+ ACPI_ERROR((AE_INFO,
+ "%p is not an ACPI Operand object [%s]", object,
+ acpi_ut_get_descriptor_name(object)));
return_VOID;
}
@@ -449,10 +451,10 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
* Notably, Locals and Args are not supported, but this may be
* required eventually.
*/
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unsupported Reference opcode=%X in object %p\n",
- internal_object->reference.opcode,
- internal_object));
+ ACPI_ERROR((AE_INFO,
+ "Unsupported Reference opcode=%X in object %p",
+ internal_object->reference.opcode,
+ internal_object));
status = AE_TYPE;
break;
}
@@ -460,10 +462,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unsupported type=%X in object %p\n",
- ACPI_GET_OBJECT_TYPE(internal_object),
- internal_object));
+ ACPI_ERROR((AE_INFO, "Unsupported type=%X in object %p",
+ ACPI_GET_OBJECT_TYPE(internal_object),
+ internal_object));
status = AE_TYPE;
break;
}
diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c
new file mode 100644
index 00000000000..16461317113
--- /dev/null
+++ b/drivers/acpi/utilities/utresrc.c
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ *
+ * Module Name: utresrc - Resource managment utilities
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2006, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include <acpi/amlresrc.h>
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utmisc")
+
+#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
+/*
+ * Strings used to decode resource descriptors.
+ * Used by both the disasssembler and the debugger resource dump routines
+ */
+const char *acpi_gbl_BMdecode[2] = {
+ "not_bus_master",
+ "bus_master"
+};
+
+const char *acpi_gbl_config_decode[4] = {
+ "0 - Good Configuration",
+ "1 - Acceptable Configuration",
+ "2 - Suboptimal Configuration",
+ "3 - ***Invalid Configuration***",
+};
+
+const char *acpi_gbl_consume_decode[2] = {
+ "resource_producer",
+ "resource_consumer"
+};
+
+const char *acpi_gbl_DECdecode[2] = {
+ "pos_decode",
+ "sub_decode"
+};
+
+const char *acpi_gbl_HEdecode[2] = {
+ "Level",
+ "Edge"
+};
+
+const char *acpi_gbl_io_decode[2] = {
+ "Decode10",
+ "Decode16"
+};
+
+const char *acpi_gbl_LLdecode[2] = {
+ "active_high",
+ "active_low"
+};
+
+const char *acpi_gbl_max_decode[2] = {
+ "max_not_fixed",
+ "max_fixed"
+};
+
+const char *acpi_gbl_MEMdecode[4] = {
+ "non_cacheable",
+ "Cacheable",
+ "write_combining",
+ "Prefetchable"
+};
+
+const char *acpi_gbl_min_decode[2] = {
+ "min_not_fixed",
+ "min_fixed"
+};
+
+const char *acpi_gbl_MTPdecode[4] = {
+ "address_range_memory",
+ "address_range_reserved",
+ "address_range_aCPI",
+ "address_range_nVS"
+};
+
+const char *acpi_gbl_RNGdecode[4] = {
+ "invalid_ranges",
+ "non_iSAonly_ranges",
+ "ISAonly_ranges",
+ "entire_range"
+};
+
+const char *acpi_gbl_RWdecode[2] = {
+ "read_only",
+ "read_write"
+};
+
+const char *acpi_gbl_SHRdecode[2] = {
+ "Exclusive",
+ "Shared"
+};
+
+const char *acpi_gbl_SIZdecode[4] = {
+ "Transfer8",
+ "Transfer8_16",
+ "Transfer16",
+ "invalid_size"
+};
+
+const char *acpi_gbl_TRSdecode[2] = {
+ "dense_translation",
+ "sparse_translation"
+};
+
+const char *acpi_gbl_TTPdecode[2] = {
+ "type_static",
+ "type_translation"
+};
+
+const char *acpi_gbl_TYPdecode[4] = {
+ "Compatibility",
+ "type_a",
+ "type_b",
+ "type_f"
+};
+
+#endif
+
+/*
+ * Base sizes of the raw AML resource descriptors, indexed by resource type.
+ * Zero indicates a reserved (and therefore invalid) resource type.
+ */
+const u8 acpi_gbl_resource_aml_sizes[] = {
+ /* Small descriptors */
+
+ 0,
+ 0,
+ 0,
+ 0,
+ ACPI_AML_SIZE_SMALL(struct aml_resource_irq),
+ ACPI_AML_SIZE_SMALL(struct aml_resource_dma),
+ ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent),
+ ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
+ ACPI_AML_SIZE_SMALL(struct aml_resource_io),
+ ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
+ 0,
+ 0,
+ 0,
+ 0,
+ ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small),
+ ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag),
+
+ /* Large descriptors */
+
+ 0,
+ ACPI_AML_SIZE_LARGE(struct aml_resource_memory24),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register),
+ 0,
+ ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_memory32),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_address32),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64)
+};
+
+/*
+ * Resource types, used to validate the resource length field.
+ * The length of fixed-length types must match exactly, variable
+ * lengths must meet the minimum required length, etc.
+ * Zero indicates a reserved (and therefore invalid) resource type.
+ */
+static const u8 acpi_gbl_resource_types[] = {
+ /* Small descriptors */
+
+ 0,
+ 0,
+ 0,
+ 0,
+ ACPI_SMALL_VARIABLE_LENGTH,
+ ACPI_FIXED_LENGTH,
+ ACPI_SMALL_VARIABLE_LENGTH,
+ ACPI_FIXED_LENGTH,
+ ACPI_FIXED_LENGTH,
+ ACPI_FIXED_LENGTH,
+ 0,
+ 0,
+ 0,
+ 0,
+ ACPI_VARIABLE_LENGTH,
+ ACPI_FIXED_LENGTH,
+
+ /* Large descriptors */
+
+ 0,
+ ACPI_FIXED_LENGTH,
+ ACPI_FIXED_LENGTH,
+ 0,
+ ACPI_VARIABLE_LENGTH,
+ ACPI_FIXED_LENGTH,
+ ACPI_FIXED_LENGTH,
+ ACPI_VARIABLE_LENGTH,
+ ACPI_VARIABLE_LENGTH,
+ ACPI_VARIABLE_LENGTH,
+ ACPI_VARIABLE_LENGTH,
+ ACPI_FIXED_LENGTH
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_validate_resource
+ *
+ * PARAMETERS: Aml - Pointer to the raw AML resource descriptor
+ * return_index - Where the resource index is returned. NULL
+ * if the index is not required.
+ *
+ * RETURN: Status, and optionally the Index into the global resource tables
+ *
+ * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
+ * Type and Resource Length. Returns an index into the global
+ * resource information/dispatch tables for later use.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
+{
+ u8 resource_type;
+ u8 resource_index;
+ acpi_rs_length resource_length;
+ acpi_rs_length minimum_resource_length;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /*
+ * 1) Validate the resource_type field (Byte 0)
+ */
+ resource_type = ACPI_GET8(aml);
+
+ /*
+ * Byte 0 contains the descriptor name (Resource Type)
+ * Examine the large/small bit in the resource header
+ */
+ if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
+ /* Verify the large resource type (name) against the max */
+
+ if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
+ return (AE_AML_INVALID_RESOURCE_TYPE);
+ }
+
+ /*
+ * Large Resource Type -- bits 6:0 contain the name
+ * Translate range 0x80-0x8B to index range 0x10-0x1B
+ */
+ resource_index = (u8) (resource_type - 0x70);
+ } else {
+ /*
+ * Small Resource Type -- bits 6:3 contain the name
+ * Shift range to index range 0x00-0x0F
+ */
+ resource_index = (u8)
+ ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
+ }
+
+ /* Check validity of the resource type, zero indicates name is invalid */
+
+ if (!acpi_gbl_resource_types[resource_index]) {
+ return (AE_AML_INVALID_RESOURCE_TYPE);
+ }
+
+ /*
+ * 2) Validate the resource_length field. This ensures that the length
+ * is at least reasonable, and guarantees that it is non-zero.
+ */
+ resource_length = acpi_ut_get_resource_length(aml);
+ minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
+
+ /* Validate based upon the type of resource - fixed length or variable */
+
+ switch (acpi_gbl_resource_types[resource_index]) {
+ case ACPI_FIXED_LENGTH:
+
+ /* Fixed length resource, length must match exactly */
+
+ if (resource_length != minimum_resource_length) {
+ return (AE_AML_BAD_RESOURCE_LENGTH);
+ }
+ break;
+
+ case ACPI_VARIABLE_LENGTH:
+
+ /* Variable length resource, length must be at least the minimum */
+
+ if (resource_length < minimum_resource_length) {
+ return (AE_AML_BAD_RESOURCE_LENGTH);
+ }
+ break;
+
+ case ACPI_SMALL_VARIABLE_LENGTH:
+
+ /* Small variable length resource, length can be (Min) or (Min-1) */
+
+ if ((resource_length > minimum_resource_length) ||
+ (resource_length < (minimum_resource_length - 1))) {
+ return (AE_AML_BAD_RESOURCE_LENGTH);
+ }
+ break;
+
+ default:
+
+ /* Shouldn't happen (because of validation earlier), but be sure */
+
+ return (AE_AML_INVALID_RESOURCE_TYPE);
+ }
+
+ /* Optionally return the resource table index */
+
+ if (return_index) {
+ *return_index = resource_index;
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_get_resource_type
+ *
+ * PARAMETERS: Aml - Pointer to the raw AML resource descriptor
+ *
+ * RETURN: The Resource Type with no extraneous bits (except the
+ * Large/Small descriptor bit -- this is left alone)
+ *
+ * DESCRIPTION: Extract the Resource Type/Name from the first byte of
+ * a resource descriptor.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_get_resource_type(void *aml)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ /*
+ * Byte 0 contains the descriptor name (Resource Type)
+ * Examine the large/small bit in the resource header
+ */
+ if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+ /* Large Resource Type -- bits 6:0 contain the name */
+
+ return (ACPI_GET8(aml));
+ } else {
+ /* Small Resource Type -- bits 6:3 contain the name */
+
+ return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_get_resource_length
+ *
+ * PARAMETERS: Aml - Pointer to the raw AML resource descriptor
+ *
+ * RETURN: Byte Length
+ *
+ * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
+ * definition, this does not include the size of the descriptor
+ * header or the length field itself.
+ *
+ ******************************************************************************/
+
+u16 acpi_ut_get_resource_length(void *aml)
+{
+ acpi_rs_length resource_length;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /*
+ * Byte 0 contains the descriptor name (Resource Type)
+ * Examine the large/small bit in the resource header
+ */
+ if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+ /* Large Resource type -- bytes 1-2 contain the 16-bit length */
+
+ ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
+
+ } else {
+ /* Small Resource type -- bits 2:0 of byte 0 contain the length */
+
+ resource_length = (u16) (ACPI_GET8(aml) &
+ ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
+ }
+
+ return (resource_length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_get_resource_header_length
+ *
+ * PARAMETERS: Aml - Pointer to the raw AML resource descriptor
+ *
+ * RETURN: Length of the AML header (depends on large/small descriptor)
+ *
+ * DESCRIPTION: Get the length of the header for this resource.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_get_resource_header_length(void *aml)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ /* Examine the large/small bit in the resource header */
+
+ if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+ return (sizeof(struct aml_resource_large_header));
+ } else {
+ return (sizeof(struct aml_resource_small_header));
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_get_descriptor_length
+ *
+ * PARAMETERS: Aml - Pointer to the raw AML resource descriptor
+ *
+ * RETURN: Byte length
+ *
+ * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
+ * length of the descriptor header and the length field itself.
+ * Used to walk descriptor lists.
+ *
+ ******************************************************************************/
+
+u32 acpi_ut_get_descriptor_length(void *aml)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ /*
+ * Get the Resource Length (does not include header length) and add
+ * the header length (depends on if this is a small or large resource)
+ */
+ return (acpi_ut_get_resource_length(aml) +
+ acpi_ut_get_resource_header_length(aml));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_get_resource_end_tag
+ *
+ * PARAMETERS: obj_desc - The resource template buffer object
+ * end_tag - Where the pointer to the end_tag is returned
+ *
+ * RETURN: Status, pointer to the end tag
+ *
+ * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template
+ * Note: allows a buffer length of zero.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc,
+ u8 ** end_tag)
+{
+ acpi_status status;
+ u8 *aml;
+ u8 *end_aml;
+
+ ACPI_FUNCTION_TRACE("ut_get_resource_end_tag");
+
+ /* Get start and end pointers */
+
+ aml = obj_desc->buffer.pointer;
+ end_aml = aml + obj_desc->buffer.length;
+
+ /* Allow a buffer length of zero */
+
+ if (!obj_desc->buffer.length) {
+ *end_tag = aml;
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ /* Walk the resource template, one descriptor per iteration */
+
+ while (aml < end_aml) {
+ /* Validate the Resource Type and Resource Length */
+
+ status = acpi_ut_validate_resource(aml, NULL);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* end_tag resource indicates the end of the resource template */
+
+ if (acpi_ut_get_resource_type(aml) ==
+ ACPI_RESOURCE_NAME_END_TAG) {
+ /*
+ * There must be at least one more byte in the buffer for
+ * the 2nd byte of the end_tag
+ */
+ if ((aml + 1) >= end_aml) {
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+ }
+
+ /* Return the pointer to the end_tag */
+
+ *end_tag = aml;
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ /*
+ * Point to the next resource descriptor in the AML buffer. The
+ * descriptor length is guaranteed to be non-zero by resource
+ * validation above.
+ */
+ aml += acpi_ut_get_descriptor_length(aml);
+ }
+
+ /* Did not find an end_tag resource descriptor */
+
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+}
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c
index c1cb27583be..4b134a72290 100644
--- a/drivers/acpi/utilities/utstate.c
+++ b/drivers/acpi/utilities/utstate.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,7 @@ acpi_status
acpi_ut_create_pkg_state_and_push(void *internal_object,
void *external_object,
u16 index,
- union acpi_generic_state ** state_list)
+ union acpi_generic_state **state_list)
{
union acpi_generic_state *state;
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index f06bd5e5e9d..308a960871b 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -75,8 +75,7 @@ acpi_status acpi_initialize_subsystem(void)
status = acpi_os_initialize();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("OSD failed to initialize, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization"));
return_ACPI_STATUS(status);
}
@@ -88,8 +87,8 @@ acpi_status acpi_initialize_subsystem(void)
status = acpi_ut_mutex_initialize();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Global mutex creation failure, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During Global Mutex creation"));
return_ACPI_STATUS(status);
}
@@ -99,15 +98,14 @@ acpi_status acpi_initialize_subsystem(void)
*/
status = acpi_ns_root_initialize();
if (ACPI_FAILURE(status)) {
- ACPI_REPORT_ERROR(("Namespace initialization failure, %s\n",
- acpi_format_exception(status)));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During Namespace initialization"));
return_ACPI_STATUS(status);
}
/* If configured, initialize the AML debugger */
ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
-
return_ACPI_STATUS(status);
}
@@ -154,8 +152,7 @@ acpi_status acpi_enable_subsystem(u32 flags)
status = acpi_enable();
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "acpi_enable failed.\n"));
+ ACPI_WARNING((AE_INFO, "acpi_enable failed"));
return_ACPI_STATUS(status);
}
}
@@ -178,10 +175,14 @@ acpi_status acpi_enable_subsystem(u32 flags)
/*
* Initialize ACPI Event handling (Fixed and General Purpose)
*
- * NOTE: We must have the hardware AND events initialized before we can
- * execute ANY control methods SAFELY. Any control method can require
- * ACPI hardware support, so the hardware MUST be initialized before
- * execution!
+ * Note1: We must have the hardware and events initialized before we can
+ * execute any control methods safely. Any control method can require
+ * ACPI hardware support, so the hardware must be fully initialized before
+ * any method execution!
+ *
+ * Note2: Fixed events are initialized and enabled here. GPEs are
+ * initialized, but cannot be enabled until after the hardware is
+ * completely initialized (SCI and global_lock activated)
*/
if (!(flags & ACPI_NO_EVENT_INIT)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -193,8 +194,10 @@ acpi_status acpi_enable_subsystem(u32 flags)
}
}
- /* Install the SCI handler and Global Lock handler */
-
+ /*
+ * Install the SCI handler and Global Lock handler. This completes the
+ * hardware initialization.
+ */
if (!(flags & ACPI_NO_HANDLER_INIT)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"[Init] Installing SCI/GL handlers\n"));
@@ -205,6 +208,24 @@ acpi_status acpi_enable_subsystem(u32 flags)
}
}
+ /*
+ * Complete the GPE initialization for the GPE blocks defined in the FADT
+ * (GPE block 0 and 1).
+ *
+ * Note1: This is where the _PRW methods are executed for the GPEs. These
+ * methods can only be executed after the SCI and Global Lock handlers are
+ * installed and initialized.
+ *
+ * Note2: Currently, there seems to be no need to run the _REG methods
+ * before execution of the _PRW methods and enabling of the GPEs.
+ */
+ if (!(flags & ACPI_NO_EVENT_INIT)) {
+ status = acpi_ev_install_fadt_gpes();
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ }
+
return_ACPI_STATUS(status);
}
@@ -230,9 +251,9 @@ acpi_status acpi_initialize_objects(u32 flags)
/*
* Run all _REG methods
*
- * NOTE: Any objects accessed
- * by the _REG methods will be automatically initialized, even if they
- * contain executable AML (see call to acpi_ns_initialize_objects below).
+ * Note: Any objects accessed by the _REG methods will be automatically
+ * initialized, even if they contain executable AML (see the call to
+ * acpi_ns_initialize_objects below).
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -245,9 +266,9 @@ acpi_status acpi_initialize_objects(u32 flags)
}
/*
- * Initialize the objects that remain uninitialized. This
- * runs the executable AML that may be part of the declaration of these
- * objects: operation_regions, buffer_fields, Buffers, and Packages.
+ * Initialize the objects that remain uninitialized. This runs the
+ * executable AML that may be part of the declaration of these objects:
+ * operation_regions, buffer_fields, Buffers, and Packages.
*/
if (!(flags & ACPI_NO_OBJECT_INIT)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -260,8 +281,8 @@ acpi_status acpi_initialize_objects(u32 flags)
}
/*
- * Initialize all device objects in the namespace
- * This runs the _STA and _INI methods.
+ * Initialize all device objects in the namespace. This runs the device
+ * _STA and _INI methods.
*/
if (!(flags & ACPI_NO_DEVICE_INIT)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index d10668f1469..bd488751837 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -920,8 +920,8 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create 'state' fs entry\n"));
else {
+ acpi_video_device_state_fops.write = acpi_video_device_write_state;
entry->proc_fops = &acpi_video_device_state_fops;
- entry->proc_fops->write = acpi_video_device_write_state;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -934,8 +934,8 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create 'brightness' fs entry\n"));
else {
+ acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
entry->proc_fops = &acpi_video_device_brightness_fops;
- entry->proc_fops->write = acpi_video_device_write_brightness;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -1239,8 +1239,8 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create 'POST' fs entry\n"));
else {
+ acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
entry->proc_fops = &acpi_video_bus_POST_fops;
- entry->proc_fops->write = acpi_video_bus_write_POST;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -1253,8 +1253,8 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create 'DOS' fs entry\n"));
else {
+ acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
entry->proc_fops = &acpi_video_bus_DOS_fops;
- entry->proc_fops->write = acpi_video_bus_write_DOS;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index f12898d5307..e99471d3232 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -8,6 +8,7 @@ obj-y += power/
obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
+obj-$(CONFIG_SMP) += topology.o
ifeq ($(CONFIG_DEBUG_DRIVER),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/base/base.h b/drivers/base/base.h
index e3b548d46cf..5735b38582d 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -19,6 +19,10 @@ extern void bus_remove_driver(struct device_driver *);
extern void driver_detach(struct device_driver * drv);
extern int driver_probe_device(struct device_driver *, struct device *);
+extern void sysdev_shutdown(void);
+extern int sysdev_suspend(pm_message_t state);
+extern int sysdev_resume(void);
+
static inline struct class_device *to_class_dev(struct kobject *obj)
{
return container_of(obj, struct class_device, kobj);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 29f6af554e7..c3141565d59 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -133,6 +133,8 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL);
+#ifdef CONFIG_HOTPLUG
+
/* Manually detach a device from its associated driver. */
static int driver_helper(struct device *dev, void *data)
{
@@ -193,6 +195,7 @@ static ssize_t driver_bind(struct device_driver *drv,
}
static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
+#endif
static struct device * next_device(struct klist_iter * i)
{
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index d1a05224627..105a0d61eb1 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -303,7 +303,7 @@ static int block_size_init(void)
*/
#ifdef CONFIG_ARCH_MEMORY_PROBE
static ssize_t
-memory_probe_store(struct class *class, const char __user *buf, size_t count)
+memory_probe_store(struct class *class, const char *buf, size_t count)
{
u64 phys_addr;
int ret;
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 0a7aa07b9a2..317edbf0fec 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -9,10 +9,9 @@
*/
#include <linux/device.h>
+#include "../base.h"
#include "power.h"
-extern int sysdev_resume(void);
-
/**
* resume_device - Restore state for one device.
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index c2475f3134e..8826a5b6673 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <asm/semaphore.h>
+#include "../base.h"
#include "power.h"
#define to_dev(node) container_of(node, struct device, kobj.entry)
@@ -28,7 +29,6 @@ extern struct subsystem devices_subsys;
* they only get one called once when interrupts are disabled.
*/
-extern int sysdev_shutdown(void);
/**
* device_shutdown - call ->shutdown() on each device to shutdown.
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 50501764d05..8660779fb28 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -9,10 +9,9 @@
*/
#include <linux/device.h>
+#include "../base.h"
#include "power.h"
-extern int sysdev_suspend(pm_message_t state);
-
/*
* The entries in the dpm_active list are in a depth first order, simply
* because children are guaranteed to be discovered after parents, and
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index f3a0c562bcb..40d7242a07c 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -27,22 +27,30 @@
static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
{
- return sprintf(buf, "%u\n", dev->power.power_state.event);
+ if (dev->power.power_state.event)
+ return sprintf(buf, "2\n");
+ else
+ return sprintf(buf, "0\n");
}
static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
{
pm_message_t state;
- char * rest;
- int error = 0;
+ int error = -EINVAL;
- state.event = simple_strtoul(buf, &rest, 10);
- if (*rest)
- return -EINVAL;
- if (state.event)
+ state.event = PM_EVENT_SUSPEND;
+ /* Older apps expected to write "3" here - confused with PCI D3 */
+ if ((n == 1) && !strcmp(buf, "3"))
error = dpm_runtime_suspend(dev, state);
- else
+
+ if ((n == 1) && !strcmp(buf, "2"))
+ error = dpm_runtime_suspend(dev, state);
+
+ if ((n == 1) && !strcmp(buf, "0")) {
dpm_runtime_resume(dev);
+ error = 0;
+ }
+
return error ? error : n;
}
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 66ed8f2fece..6fc23ab127b 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,8 +21,11 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/pm.h>
+#include <linux/device.h>
#include <asm/semaphore.h>
+#include "base.h"
+
extern struct subsystem devices_subsys;
#define to_sysdev(k) container_of(k, struct sys_device, kobj)
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
new file mode 100644
index 00000000000..915810f6237
--- /dev/null
+++ b/drivers/base/topology.c
@@ -0,0 +1,148 @@
+/*
+ * driver/base/topology.c - Populate sysfs with cpu topology information
+ *
+ * Written by: Zhang Yanmin, Intel Corporation
+ *
+ * Copyright (C) 2006, Intel Corp.
+ *
+ * All rights reserved.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/topology.h>
+
+#define define_one_ro(_name) \
+static SYSDEV_ATTR(_name, 0444, show_##_name, NULL)
+
+#define define_id_show_func(name) \
+static ssize_t show_##name(struct sys_device *dev, char *buf) \
+{ \
+ unsigned int cpu = dev->id; \
+ return sprintf(buf, "%d\n", topology_##name(cpu)); \
+}
+
+#define define_siblings_show_func(name) \
+static ssize_t show_##name(struct sys_device *dev, char *buf) \
+{ \
+ ssize_t len = -1; \
+ unsigned int cpu = dev->id; \
+ len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu)); \
+ return (len + sprintf(buf + len, "\n")); \
+}
+
+#ifdef topology_physical_package_id
+define_id_show_func(physical_package_id);
+define_one_ro(physical_package_id);
+#define ref_physical_package_id_attr &attr_physical_package_id.attr,
+#else
+#define ref_physical_package_id_attr
+#endif
+
+#ifdef topology_core_id
+define_id_show_func(core_id);
+define_one_ro(core_id);
+#define ref_core_id_attr &attr_core_id.attr,
+#else
+#define ref_core_id_attr
+#endif
+
+#ifdef topology_thread_siblings
+define_siblings_show_func(thread_siblings);
+define_one_ro(thread_siblings);
+#define ref_thread_siblings_attr &attr_thread_siblings.attr,
+#else
+#define ref_thread_siblings_attr
+#endif
+
+#ifdef topology_core_siblings
+define_siblings_show_func(core_siblings);
+define_one_ro(core_siblings);
+#define ref_core_siblings_attr &attr_core_siblings.attr,
+#else
+#define ref_core_siblings_attr
+#endif
+
+static struct attribute *default_attrs[] = {
+ ref_physical_package_id_attr
+ ref_core_id_attr
+ ref_thread_siblings_attr
+ ref_core_siblings_attr
+ NULL
+};
+
+static struct attribute_group topology_attr_group = {
+ .attrs = default_attrs,
+ .name = "topology"
+};
+
+/* Add/Remove cpu_topology interface for CPU device */
+static int __cpuinit topology_add_dev(struct sys_device * sys_dev)
+{
+ sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
+ return 0;
+}
+
+static int __cpuinit topology_remove_dev(struct sys_device * sys_dev)
+{
+ sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
+ return 0;
+}
+
+static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+ struct sys_device *sys_dev;
+
+ sys_dev = get_cpu_sysdev(cpu);
+ switch (action) {
+ case CPU_ONLINE:
+ topology_add_dev(sys_dev);
+ break;
+ case CPU_DEAD:
+ topology_remove_dev(sys_dev);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block topology_cpu_notifier =
+{
+ .notifier_call = topology_cpu_callback,
+};
+
+static int __cpuinit topology_sysfs_init(void)
+{
+ int i;
+
+ for_each_online_cpu(i) {
+ topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE,
+ (void *)(long)i);
+ }
+
+ register_cpu_notifier(&topology_cpu_notifier);
+
+ return 0;
+}
+
+device_initcall(topology_sysfs_init);
+
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 139cbba7618..8b133167740 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -433,12 +433,12 @@ config CDROM_PKTCDVD_BUFFERS
This controls the maximum number of active concurrent packets. More
concurrent packets can increase write performance, but also require
more memory. Each concurrent packet will require approximately 64Kb
- of non-swappable kernel memory, memory which will be allocated at
- pktsetup time.
+ of non-swappable kernel memory, memory which will be allocated when
+ a disc is opened for writing.
config CDROM_PKTCDVD_WCACHE
- bool "Enable write caching"
- depends on CDROM_PKTCDVD
+ bool "Enable write caching (EXPERIMENTAL)"
+ depends on CDROM_PKTCDVD && EXPERIMENTAL
help
If enabled, write caching will be set for the CD-R/W device. For now
this option is dangerous unless the CD-RW media is known good, as we
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 12d7b9bdfa9..0d65394707d 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2183,6 +2183,7 @@ static void cciss_softirq_done(struct request *rq)
{
CommandList_struct *cmd = rq->completion_data;
ctlr_info_t *h = hba[cmd->ctlr];
+ unsigned long flags;
u64bit temp64;
int i, ddir;
@@ -2205,10 +2206,10 @@ static void cciss_softirq_done(struct request *rq)
printk("Done with %p\n", rq);
#endif /* CCISS_DEBUG */
- spin_lock_irq(&h->lock);
+ spin_lock_irqsave(&h->lock, flags);
end_that_request_last(rq, rq->errors);
cmd_free(h, cmd,1);
- spin_unlock_irq(&h->lock);
+ spin_unlock_irqrestore(&h->lock, flags);
}
/* checks the status of the job and calls complete buffers to mark all
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 93affeeef7b..bc9b2bcd7db 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -43,8 +43,6 @@
*
*************************************************************************/
-#define VERSION_CODE "v0.2.0a 2004-07-14 Jens Axboe (axboe@suse.de) and petero2@telia.com"
-
#include <linux/pktcdvd.h>
#include <linux/config.h>
#include <linux/module.h>
@@ -60,6 +58,7 @@
#include <linux/suspend.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi.h>
#include <asm/uaccess.h>
@@ -131,7 +130,7 @@ static struct bio *pkt_bio_alloc(int nr_iovecs)
/*
* Allocate a packet_data struct
*/
-static struct packet_data *pkt_alloc_packet_data(void)
+static struct packet_data *pkt_alloc_packet_data(int frames)
{
int i;
struct packet_data *pkt;
@@ -140,11 +139,12 @@ static struct packet_data *pkt_alloc_packet_data(void)
if (!pkt)
goto no_pkt;
- pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE);
+ pkt->frames = frames;
+ pkt->w_bio = pkt_bio_alloc(frames);
if (!pkt->w_bio)
goto no_bio;
- for (i = 0; i < PAGES_PER_PACKET; i++) {
+ for (i = 0; i < frames / FRAMES_PER_PAGE; i++) {
pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
if (!pkt->pages[i])
goto no_page;
@@ -152,7 +152,7 @@ static struct packet_data *pkt_alloc_packet_data(void)
spin_lock_init(&pkt->lock);
- for (i = 0; i < PACKET_MAX_SIZE; i++) {
+ for (i = 0; i < frames; i++) {
struct bio *bio = pkt_bio_alloc(1);
if (!bio)
goto no_rd_bio;
@@ -162,14 +162,14 @@ static struct packet_data *pkt_alloc_packet_data(void)
return pkt;
no_rd_bio:
- for (i = 0; i < PACKET_MAX_SIZE; i++) {
+ for (i = 0; i < frames; i++) {
struct bio *bio = pkt->r_bios[i];
if (bio)
bio_put(bio);
}
no_page:
- for (i = 0; i < PAGES_PER_PACKET; i++)
+ for (i = 0; i < frames / FRAMES_PER_PAGE; i++)
if (pkt->pages[i])
__free_page(pkt->pages[i]);
bio_put(pkt->w_bio);
@@ -186,12 +186,12 @@ static void pkt_free_packet_data(struct packet_data *pkt)
{
int i;
- for (i = 0; i < PACKET_MAX_SIZE; i++) {
+ for (i = 0; i < pkt->frames; i++) {
struct bio *bio = pkt->r_bios[i];
if (bio)
bio_put(bio);
}
- for (i = 0; i < PAGES_PER_PACKET; i++)
+ for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++)
__free_page(pkt->pages[i]);
bio_put(pkt->w_bio);
kfree(pkt);
@@ -206,17 +206,17 @@ static void pkt_shrink_pktlist(struct pktcdvd_device *pd)
list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) {
pkt_free_packet_data(pkt);
}
+ INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
}
static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
{
struct packet_data *pkt;
- INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
- INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
- spin_lock_init(&pd->cdrw.active_list_lock);
+ BUG_ON(!list_empty(&pd->cdrw.pkt_free_list));
+
while (nr_packets > 0) {
- pkt = pkt_alloc_packet_data();
+ pkt = pkt_alloc_packet_data(pd->settings.size >> 2);
if (!pkt) {
pkt_shrink_pktlist(pd);
return 0;
@@ -381,6 +381,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
+ rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
rq->ref_count++;
rq->flags |= REQ_NOMERGE;
@@ -646,7 +647,7 @@ static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct pag
* b) The data can be used as cache to avoid read requests if we receive a
* new write request for the same zone.
*/
-static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, int *offsets)
+static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec)
{
int f, p, offs;
@@ -654,15 +655,15 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in
p = 0;
offs = 0;
for (f = 0; f < pkt->frames; f++) {
- if (pages[f] != pkt->pages[p]) {
- void *vfrom = kmap_atomic(pages[f], KM_USER0) + offsets[f];
+ if (bvec[f].bv_page != pkt->pages[p]) {
+ void *vfrom = kmap_atomic(bvec[f].bv_page, KM_USER0) + bvec[f].bv_offset;
void *vto = page_address(pkt->pages[p]) + offs;
memcpy(vto, vfrom, CD_FRAMESIZE);
kunmap_atomic(vfrom, KM_USER0);
- pages[f] = pkt->pages[p];
- offsets[f] = offs;
+ bvec[f].bv_page = pkt->pages[p];
+ bvec[f].bv_offset = offs;
} else {
- BUG_ON(offsets[f] != offs);
+ BUG_ON(bvec[f].bv_offset != offs);
}
offs += CD_FRAMESIZE;
if (offs >= PAGE_SIZE) {
@@ -951,7 +952,7 @@ try_next_bio:
pd->current_sector = zone + pd->settings.size;
pkt->sector = zone;
- pkt->frames = pd->settings.size >> 2;
+ BUG_ON(pkt->frames != pd->settings.size >> 2);
pkt->write_size = 0;
/*
@@ -992,18 +993,17 @@ try_next_bio:
static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
{
struct bio *bio;
- struct page *pages[PACKET_MAX_SIZE];
- int offsets[PACKET_MAX_SIZE];
int f;
int frames_write;
+ struct bio_vec *bvec = pkt->w_bio->bi_io_vec;
for (f = 0; f < pkt->frames; f++) {
- pages[f] = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
- offsets[f] = (f * CD_FRAMESIZE) % PAGE_SIZE;
+ bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
+ bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
}
/*
- * Fill-in pages[] and offsets[] with data from orig_bios.
+ * Fill-in bvec with data from orig_bios.
*/
frames_write = 0;
spin_lock(&pkt->lock);
@@ -1025,11 +1025,11 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
}
if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) {
- pages[f] = src_bvl->bv_page;
- offsets[f] = src_bvl->bv_offset + src_offs;
+ bvec[f].bv_page = src_bvl->bv_page;
+ bvec[f].bv_offset = src_bvl->bv_offset + src_offs;
} else {
pkt_copy_bio_data(bio, segment, src_offs,
- pages[f], offsets[f]);
+ bvec[f].bv_page, bvec[f].bv_offset);
}
src_offs += CD_FRAMESIZE;
frames_write++;
@@ -1043,7 +1043,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
BUG_ON(frames_write != pkt->write_size);
if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) {
- pkt_make_local_copy(pkt, pages, offsets);
+ pkt_make_local_copy(pkt, bvec);
pkt->cache_valid = 1;
} else {
pkt->cache_valid = 0;
@@ -1056,17 +1056,9 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
pkt->w_bio->bi_bdev = pd->bdev;
pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
pkt->w_bio->bi_private = pkt;
- for (f = 0; f < pkt->frames; f++) {
- if ((f + 1 < pkt->frames) && (pages[f + 1] == pages[f]) &&
- (offsets[f + 1] = offsets[f] + CD_FRAMESIZE)) {
- if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE * 2, offsets[f]))
- BUG();
- f++;
- } else {
- if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE, offsets[f]))
- BUG();
- }
- }
+ for (f = 0; f < pkt->frames; f++)
+ if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
+ BUG();
VPRINTK("pktcdvd: vcnt=%d\n", pkt->w_bio->bi_vcnt);
atomic_set(&pkt->io_wait, 1);
@@ -1505,40 +1497,42 @@ static int pkt_set_write_settings(struct pktcdvd_device *pd)
}
/*
- * 0 -- we can write to this track, 1 -- we can't
+ * 1 -- we can write to this track, 0 -- we can't
*/
-static int pkt_good_track(track_information *ti)
+static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
{
- /*
- * only good for CD-RW at the moment, not DVD-RW
- */
+ switch (pd->mmc3_profile) {
+ case 0x1a: /* DVD+RW */
+ case 0x12: /* DVD-RAM */
+ /* The track is always writable on DVD+RW/DVD-RAM */
+ return 1;
+ default:
+ break;
+ }
- /*
- * FIXME: only for FP
- */
- if (ti->fp == 0)
+ if (!ti->packet || !ti->fp)
return 0;
/*
* "good" settings as per Mt Fuji.
*/
- if (ti->rt == 0 && ti->blank == 0 && ti->packet == 1)
- return 0;
+ if (ti->rt == 0 && ti->blank == 0)
+ return 1;
- if (ti->rt == 0 && ti->blank == 1 && ti->packet == 1)
- return 0;
+ if (ti->rt == 0 && ti->blank == 1)
+ return 1;
- if (ti->rt == 1 && ti->blank == 0 && ti->packet == 1)
- return 0;
+ if (ti->rt == 1 && ti->blank == 0)
+ return 1;
printk("pktcdvd: bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
- return 1;
+ return 0;
}
/*
- * 0 -- we can write to this disc, 1 -- we can't
+ * 1 -- we can write to this disc, 0 -- we can't
*/
-static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
+static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
{
switch (pd->mmc3_profile) {
case 0x0a: /* CD-RW */
@@ -1547,10 +1541,10 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
case 0x1a: /* DVD+RW */
case 0x13: /* DVD-RW */
case 0x12: /* DVD-RAM */
- return 0;
- default:
- printk("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile);
return 1;
+ default:
+ VPRINTK("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile);
+ return 0;
}
/*
@@ -1559,25 +1553,25 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
*/
if (di->disc_type == 0xff) {
printk("pktcdvd: Unknown disc. No track?\n");
- return 1;
+ return 0;
}
if (di->disc_type != 0x20 && di->disc_type != 0) {
printk("pktcdvd: Wrong disc type (%x)\n", di->disc_type);
- return 1;
+ return 0;
}
if (di->erasable == 0) {
printk("pktcdvd: Disc not erasable\n");
- return 1;
+ return 0;
}
if (di->border_status == PACKET_SESSION_RESERVED) {
printk("pktcdvd: Can't write to last track (reserved)\n");
- return 1;
+ return 0;
}
- return 0;
+ return 1;
}
static int pkt_probe_settings(struct pktcdvd_device *pd)
@@ -1602,23 +1596,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
return ret;
}
- if (pkt_good_disc(pd, &di))
- return -ENXIO;
+ if (!pkt_writable_disc(pd, &di))
+ return -EROFS;
- switch (pd->mmc3_profile) {
- case 0x1a: /* DVD+RW */
- printk("pktcdvd: inserted media is DVD+RW\n");
- break;
- case 0x13: /* DVD-RW */
- printk("pktcdvd: inserted media is DVD-RW\n");
- break;
- case 0x12: /* DVD-RAM */
- printk("pktcdvd: inserted media is DVD-RAM\n");
- break;
- default:
- printk("pktcdvd: inserted media is CD-R%s\n", di.erasable ? "W" : "");
- break;
- }
pd->type = di.erasable ? PACKET_CDRW : PACKET_CDR;
track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */
@@ -1627,9 +1607,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
return ret;
}
- if (pkt_good_track(&ti)) {
+ if (!pkt_writable_track(pd, &ti)) {
printk("pktcdvd: can't write to this track\n");
- return -ENXIO;
+ return -EROFS;
}
/*
@@ -1639,11 +1619,11 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
if (pd->settings.size == 0) {
printk("pktcdvd: detected zero packet size!\n");
- pd->settings.size = 128;
+ return -ENXIO;
}
if (pd->settings.size > PACKET_MAX_SECTORS) {
printk("pktcdvd: packet size is too big\n");
- return -ENXIO;
+ return -EROFS;
}
pd->settings.fp = ti.fp;
pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
@@ -1685,7 +1665,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
break;
default:
printk("pktcdvd: unknown data mode\n");
- return 1;
+ return -EROFS;
}
return 0;
}
@@ -1895,8 +1875,8 @@ static int pkt_open_write(struct pktcdvd_device *pd)
unsigned int write_speed, media_write_speed, read_speed;
if ((ret = pkt_probe_settings(pd))) {
- DPRINTK("pktcdvd: %s failed probe\n", pd->name);
- return -EIO;
+ VPRINTK("pktcdvd: %s failed probe\n", pd->name);
+ return ret;
}
if ((ret = pkt_set_write_settings(pd))) {
@@ -1987,8 +1967,14 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
if ((ret = pkt_set_segment_merging(pd, q)))
goto out_unclaim;
- if (write)
+ if (write) {
+ if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
+ printk("pktcdvd: not enough memory for buffers\n");
+ ret = -ENOMEM;
+ goto out_unclaim;
+ }
printk("pktcdvd: %lukB available on disc\n", lba << 1);
+ }
return 0;
@@ -2014,6 +2000,8 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
bd_release(pd->bdev);
blkdev_put(pd->bdev);
+
+ pkt_shrink_pktlist(pd);
}
static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
@@ -2046,10 +2034,9 @@ static int pkt_open(struct inode *inode, struct file *file)
goto out_dec;
}
} else {
- if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) {
- ret = -EIO;
+ ret = pkt_open_dev(pd, file->f_mode & FMODE_WRITE);
+ if (ret)
goto out_dec;
- }
/*
* needed here as well, since ext2 (among others) may change
* the blocksize at mount time
@@ -2379,12 +2366,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
/* This is safe, since we have a reference from open(). */
__module_get(THIS_MODULE);
- if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
- printk("pktcdvd: not enough memory for buffers\n");
- ret = -ENOMEM;
- goto out_mem;
- }
-
pd->bdev = bdev;
set_blocksize(bdev, CD_FRAMESIZE);
@@ -2395,7 +2376,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
if (IS_ERR(pd->cdrw.thread)) {
printk("pktcdvd: can't start kernel thread\n");
ret = -ENOMEM;
- goto out_thread;
+ goto out_mem;
}
proc = create_proc_entry(pd->name, 0, pkt_proc);
@@ -2406,8 +2387,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
return 0;
-out_thread:
- pkt_shrink_pktlist(pd);
out_mem:
blkdev_put(bdev);
/* This is safe: open() is still holding a reference. */
@@ -2437,11 +2416,12 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
* The door gets locked when the device is opened, so we
* have to unlock it or else the eject command fails.
*/
- pkt_lock_door(pd, 0);
+ if (pd->refcnt == 1)
+ pkt_lock_door(pd, 0);
return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
default:
- printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
+ VPRINTK("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
return -ENOTTY;
}
@@ -2503,6 +2483,10 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
goto out_mem;
pd->disk = disk;
+ INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
+ INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
+ spin_lock_init(&pd->cdrw.active_list_lock);
+
spin_lock_init(&pd->lock);
spin_lock_init(&pd->iosched.lock);
sprintf(pd->name, "pktcdvd%d", idx);
@@ -2567,8 +2551,6 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
blkdev_put(pd->bdev);
- pkt_shrink_pktlist(pd);
-
remove_proc_entry(pd->name, pkt_proc);
DPRINTK("pktcdvd: writer %s unmapped\n", pd->name);
@@ -2678,7 +2660,6 @@ static int __init pkt_init(void)
pkt_proc = proc_mkdir("pktcdvd", proc_root_driver);
- DPRINTK("pktcdvd: %s\n", VERSION_CODE);
return 0;
out:
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index a05fe5843e6..f04d864770a 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -14,7 +14,6 @@
* -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
* -- verify the 13 conditions and do bulk resets
* -- kill last_pipe and simply do two-state clearing on both pipes
- * -- verify protocol (bulk) from USB descriptors (maybe...)
* -- highmem
* -- move top_sense and work_bcs into separate allocations (if they survive)
* for cache purists and esoteric architectures.
@@ -355,7 +354,7 @@ struct ub_lun {
* The USB device instance.
*/
struct ub_dev {
- spinlock_t lock;
+ spinlock_t *lock;
atomic_t poison; /* The USB device is disconnected */
int openc; /* protected by ub_lock! */
/* kref is too implicit for our taste */
@@ -420,11 +419,13 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
int stalled_pipe);
static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
-static void ub_reset_enter(struct ub_dev *sc);
+static void ub_reset_enter(struct ub_dev *sc, int try);
static void ub_reset_task(void *arg);
static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
struct ub_capacity *ret);
+static int ub_sync_reset(struct ub_dev *sc);
+static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe);
static int ub_probe_lun(struct ub_dev *sc, int lnum);
/*
@@ -452,6 +453,10 @@ MODULE_DEVICE_TABLE(usb, ub_usb_ids);
#define UB_MAX_HOSTS 26
static char ub_hostv[UB_MAX_HOSTS];
+#define UB_QLOCK_NUM 5
+static spinlock_t ub_qlockv[UB_QLOCK_NUM];
+static int ub_qlock_next = 0;
+
static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */
/*
@@ -531,7 +536,7 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
return 0;
cnt = 0;
- spin_lock_irqsave(&sc->lock, flags);
+ spin_lock_irqsave(sc->lock, flags);
cnt += sprintf(page + cnt,
"poison %d reset %d\n",
@@ -579,7 +584,7 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
if (++nc == SCMD_TRACE_SZ) nc = 0;
}
- spin_unlock_irqrestore(&sc->lock, flags);
+ spin_unlock_irqrestore(sc->lock, flags);
return cnt;
}
@@ -627,6 +632,24 @@ static void ub_id_put(int id)
}
/*
+ * This is necessitated by the fact that blk_cleanup_queue does not
+ * necesserily destroy the queue. Instead, it may merely decrease q->refcnt.
+ * Since our blk_init_queue() passes a spinlock common with ub_dev,
+ * we have life time issues when ub_cleanup frees ub_dev.
+ */
+static spinlock_t *ub_next_lock(void)
+{
+ unsigned long flags;
+ spinlock_t *ret;
+
+ spin_lock_irqsave(&ub_lock, flags);
+ ret = &ub_qlockv[ub_qlock_next];
+ ub_qlock_next = (ub_qlock_next + 1) % UB_QLOCK_NUM;
+ spin_unlock_irqrestore(&ub_lock, flags);
+ return ret;
+}
+
+/*
* Downcount for deallocation. This rides on two assumptions:
* - once something is poisoned, its refcount cannot grow
* - opens cannot happen at this time (del_gendisk was done)
@@ -961,7 +984,7 @@ static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
if (atomic_read(&sc->poison))
return -ENXIO;
- ub_reset_enter(sc);
+ ub_reset_enter(sc, urq->current_try);
if (urq->current_try >= 3)
return -EIO;
@@ -997,8 +1020,6 @@ static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
* No exceptions.
*
* Host is assumed locked.
- *
- * XXX We only support Bulk for the moment.
*/
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
@@ -1083,9 +1104,10 @@ static void ub_urb_timeout(unsigned long arg)
struct ub_dev *sc = (struct ub_dev *) arg;
unsigned long flags;
- spin_lock_irqsave(&sc->lock, flags);
- usb_unlink_urb(&sc->work_urb);
- spin_unlock_irqrestore(&sc->lock, flags);
+ spin_lock_irqsave(sc->lock, flags);
+ if (!ub_is_completed(&sc->work_done))
+ usb_unlink_urb(&sc->work_urb);
+ spin_unlock_irqrestore(sc->lock, flags);
}
/*
@@ -1108,10 +1130,9 @@ static void ub_scsi_action(unsigned long _dev)
struct ub_dev *sc = (struct ub_dev *) _dev;
unsigned long flags;
- spin_lock_irqsave(&sc->lock, flags);
- del_timer(&sc->work_timer);
+ spin_lock_irqsave(sc->lock, flags);
ub_scsi_dispatch(sc);
- spin_unlock_irqrestore(&sc->lock, flags);
+ spin_unlock_irqrestore(sc->lock, flags);
}
static void ub_scsi_dispatch(struct ub_dev *sc)
@@ -1133,6 +1154,7 @@ static void ub_scsi_dispatch(struct ub_dev *sc)
} else {
if (!ub_is_completed(&sc->work_done))
break;
+ del_timer(&sc->work_timer);
ub_scsi_urb_compl(sc, cmd);
}
}
@@ -1680,16 +1702,18 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
/*
* Reset management
+ * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing.
+ * XXX Make usb_sync_reset asynchronous.
*/
-static void ub_reset_enter(struct ub_dev *sc)
+static void ub_reset_enter(struct ub_dev *sc, int try)
{
if (sc->reset) {
/* This happens often on multi-LUN devices. */
return;
}
- sc->reset = 1;
+ sc->reset = try + 1;
#if 0 /* Not needed because the disconnect waits for us. */
unsigned long flags;
@@ -1727,6 +1751,11 @@ static void ub_reset_task(void *arg)
if (atomic_read(&sc->poison)) {
printk(KERN_NOTICE "%s: Not resetting disconnected device\n",
sc->name); /* P3 This floods. Remove soon. XXX */
+ } else if ((sc->reset & 1) == 0) {
+ ub_sync_reset(sc);
+ msleep(700); /* usb-storage sleeps 6s (!) */
+ ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
+ ub_probe_clear_stall(sc, sc->send_bulk_pipe);
} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
printk(KERN_NOTICE "%s: Not resetting multi-interface device\n",
sc->name); /* P3 This floods. Remove soon. XXX */
@@ -1754,7 +1783,7 @@ static void ub_reset_task(void *arg)
* queues of resets or anything. We do need a spinlock though,
* to interact with block layer.
*/
- spin_lock_irqsave(&sc->lock, flags);
+ spin_lock_irqsave(sc->lock, flags);
sc->reset = 0;
tasklet_schedule(&sc->tasklet);
list_for_each(p, &sc->luns) {
@@ -1762,7 +1791,7 @@ static void ub_reset_task(void *arg)
blk_start_queue(lun->disk->queue);
}
wake_up(&sc->reset_wait);
- spin_unlock_irqrestore(&sc->lock, flags);
+ spin_unlock_irqrestore(sc->lock, flags);
}
/*
@@ -1990,11 +2019,11 @@ static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun)
cmd->done = ub_probe_done;
cmd->back = &compl;
- spin_lock_irqsave(&sc->lock, flags);
+ spin_lock_irqsave(sc->lock, flags);
cmd->tag = sc->tagcnt++;
rc = ub_submit_scsi(sc, cmd);
- spin_unlock_irqrestore(&sc->lock, flags);
+ spin_unlock_irqrestore(sc->lock, flags);
if (rc != 0) {
printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */
@@ -2052,11 +2081,11 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
cmd->done = ub_probe_done;
cmd->back = &compl;
- spin_lock_irqsave(&sc->lock, flags);
+ spin_lock_irqsave(sc->lock, flags);
cmd->tag = sc->tagcnt++;
rc = ub_submit_scsi(sc, cmd);
- spin_unlock_irqrestore(&sc->lock, flags);
+ spin_unlock_irqrestore(sc->lock, flags);
if (rc != 0) {
printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */
@@ -2118,6 +2147,52 @@ static void ub_probe_timeout(unsigned long arg)
}
/*
+ * Reset with a Bulk reset.
+ */
+static int ub_sync_reset(struct ub_dev *sc)
+{
+ int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
+ struct usb_ctrlrequest *cr;
+ struct completion compl;
+ struct timer_list timer;
+ int rc;
+
+ init_completion(&compl);
+
+ cr = &sc->work_cr;
+ cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ cr->bRequest = US_BULK_RESET_REQUEST;
+ cr->wValue = cpu_to_le16(0);
+ cr->wIndex = cpu_to_le16(ifnum);
+ cr->wLength = cpu_to_le16(0);
+
+ usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+ (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
+ sc->work_urb.actual_length = 0;
+ sc->work_urb.error_count = 0;
+ sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+ printk(KERN_WARNING
+ "%s: Unable to submit a bulk reset (%d)\n", sc->name, rc);
+ return rc;
+ }
+
+ init_timer(&timer);
+ timer.function = ub_probe_timeout;
+ timer.data = (unsigned long) &compl;
+ timer.expires = jiffies + UB_CTRL_TIMEOUT;
+ add_timer(&timer);
+
+ wait_for_completion(&compl);
+
+ del_timer_sync(&timer);
+ usb_kill_urb(&sc->work_urb);
+
+ return sc->work_urb.status;
+}
+
+/*
* Get number of LUNs by the way of Bulk GetMaxLUN command.
*/
static int ub_sync_getmaxlun(struct ub_dev *sc)
@@ -2333,7 +2408,7 @@ static int ub_probe(struct usb_interface *intf,
if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
goto err_core;
memset(sc, 0, sizeof(struct ub_dev));
- spin_lock_init(&sc->lock);
+ sc->lock = ub_next_lock();
INIT_LIST_HEAD(&sc->luns);
usb_init_urb(&sc->work_urb);
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
@@ -2483,7 +2558,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
disk->driverfs_dev = &sc->intf->dev;
rc = -ENOMEM;
- if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL)
+ if ((q = blk_init_queue(ub_request_fn, sc->lock)) == NULL)
goto err_blkqinit;
disk->queue = q;
@@ -2554,7 +2629,7 @@ static void ub_disconnect(struct usb_interface *intf)
* and the whole queue drains. So, we just use this code to
* print warnings.
*/
- spin_lock_irqsave(&sc->lock, flags);
+ spin_lock_irqsave(sc->lock, flags);
{
struct ub_scsi_cmd *cmd;
int cnt = 0;
@@ -2571,7 +2646,7 @@ static void ub_disconnect(struct usb_interface *intf)
"%d was queued after shutdown\n", sc->name, cnt);
}
}
- spin_unlock_irqrestore(&sc->lock, flags);
+ spin_unlock_irqrestore(sc->lock, flags);
/*
* Unregister the upper layer.
@@ -2590,19 +2665,15 @@ static void ub_disconnect(struct usb_interface *intf)
}
/*
- * Taking a lock on a structure which is about to be freed
- * is very nonsensual. Here it is largely a way to do a debug freeze,
- * and a bracket which shows where the nonsensual code segment ends.
- *
* Testing for -EINPROGRESS is always a bug, so we are bending
* the rules a little.
*/
- spin_lock_irqsave(&sc->lock, flags);
+ spin_lock_irqsave(sc->lock, flags);
if (sc->work_urb.status == -EINPROGRESS) { /* janitors: ignore */
printk(KERN_WARNING "%s: "
"URB is active after disconnect\n", sc->name);
}
- spin_unlock_irqrestore(&sc->lock, flags);
+ spin_unlock_irqrestore(sc->lock, flags);
/*
* There is virtually no chance that other CPU runs times so long
@@ -2636,6 +2707,10 @@ static struct usb_driver ub_driver = {
static int __init ub_init(void)
{
int rc;
+ int i;
+
+ for (i = 0; i < UB_QLOCK_NUM; i++)
+ spin_lock_init(&ub_qlockv[i]);
if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
goto err_regblkdev;
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index a3614e6a68d..4ada1268b40 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -882,7 +882,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
card->card_number, dev->bus->number, dev->devfn);
if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) &&
- !pci_set_dma_mask(dev, 0xffffffffLL)) {
+ pci_set_dma_mask(dev, 0xffffffffLL)) {
printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards);
return -ENOMEM;
}
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index e522d19ad88..7e21b1ff27c 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -474,18 +474,6 @@ static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long
/* ======================== Card services HCI interaction ======================== */
-static struct device *bt3c_device(void)
-{
- static struct device dev = {
- .bus_id = "pcmcia",
- };
- kobject_set_name(&dev.kobj, "bt3c");
- kobject_init(&dev.kobj);
-
- return &dev;
-}
-
-
static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count)
{
char *ptr = (char *) firmware;
@@ -574,6 +562,7 @@ static int bt3c_open(bt3c_info_t *info)
{
const struct firmware *firmware;
struct hci_dev *hdev;
+ client_handle_t handle;
int err;
spin_lock_init(&(info->lock));
@@ -605,8 +594,10 @@ static int bt3c_open(bt3c_info_t *info)
hdev->owner = THIS_MODULE;
+ handle = info->link.handle;
+
/* Load firmware */
- err = request_firmware(&firmware, "BT3CPCC.bin", bt3c_device());
+ err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle));
if (err < 0) {
BT_ERR("Firmware request failed");
goto error;
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 193446e6a08..e2761725955 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -42,8 +42,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <asm/bug.h>
-
#include <asm/vio.h>
#include <asm/scatterlist.h>
#include <asm/iseries/hv_types.h>
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 4135d8c5bca..05ba410682a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -222,7 +222,7 @@ config SYNCLINKMP
config SYNCLINK_GT
tristate "SyncLink GT/AC support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && PCI
help
Support for SyncLink GT and SyncLink AC families of
synchronous and asynchronous serial adapters
@@ -992,7 +992,7 @@ config HPET_MMAP
config HANGCHECK_TIMER
tristate "Hangcheck timer"
- depends on X86 || IA64 || PPC64 || S390
+ depends on X86 || IA64 || PPC64
help
The hangcheck-timer module detects when the system has gone
out to lunch past a certain margin. It can reboot the system
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 39c61a71176..cc7acf877dc 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1233,7 +1233,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
info->idle_stats.recv_idle = jiffies;
}
- schedule_delayed_work(&tty->buf.work, 1);
+ tty_schedule_flip(tty);
}
/* end of service */
cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
@@ -1606,7 +1606,7 @@ cyz_handle_rx(struct cyclades_port *info,
}
#endif
info->idle_stats.recv_idle = jiffies;
- schedule_delayed_work(&tty->buf.work, 1);
+ tty_schedule_flip(tty);
}
/* Update rx_get */
cy_writel(&buf_ctrl->rx_get, new_rx_get);
@@ -1809,7 +1809,7 @@ cyz_handle_cmd(struct cyclades_card *cinfo)
if(delta_count)
cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
if(special_count)
- schedule_delayed_work(&tty->buf.work, 1);
+ tty_schedule_flip(tty);
}
}
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index 5485382cade..bd7be09ea53 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -59,17 +59,16 @@ static void *drm_ati_alloc_pcigart_table(void)
int i;
DRM_DEBUG("%s\n", __FUNCTION__);
- address = __get_free_pages(GFP_KERNEL, ATI_PCIGART_TABLE_ORDER);
+ address = __get_free_pages(GFP_KERNEL | __GFP_COMP,
+ ATI_PCIGART_TABLE_ORDER);
if (address == 0UL) {
- return 0;
+ return NULL;
}
page = virt_to_page(address);
- for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
- get_page(page);
+ for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++)
SetPageReserved(page);
- }
DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
return (void *)address;
@@ -83,10 +82,8 @@ static void drm_ati_free_pcigart_table(void *address)
page = virt_to_page((unsigned long)address);
- for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
- __put_page(page);
+ for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++)
ClearPageReserved(page);
- }
free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER);
}
@@ -127,7 +124,7 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
&& gart_info->addr) {
drm_ati_free_pcigart_table(gart_info->addr);
- gart_info->addr = 0;
+ gart_info->addr = NULL;
}
return 1;
@@ -168,7 +165,7 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
if (bus_address == 0) {
DRM_ERROR("unable to map PCIGART pages!\n");
drm_ati_free_pcigart_table(address);
- address = 0;
+ address = NULL;
goto done;
}
} else {
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 54b561e6948..107df9fdba4 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -57,6 +57,7 @@
#include <linux/smp_lock.h> /* For (un)lock_kernel */
#include <linux/mm.h>
#include <linux/cdev.h>
+#include <linux/mutex.h>
#if defined(__alpha__) || defined(__powerpc__)
#include <asm/pgtable.h> /* For pte_wrprotect */
#endif
@@ -623,7 +624,7 @@ typedef struct drm_device {
/** \name Locks */
/*@{ */
spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
- struct semaphore struct_sem; /**< For others */
+ struct mutex struct_mutex; /**< For others */
/*@} */
/** \name Usage Counters */
@@ -658,7 +659,7 @@ typedef struct drm_device {
/*@{ */
drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
int ctx_count; /**< Number of context handles */
- struct semaphore ctxlist_sem; /**< For ctxlist */
+ struct mutex ctxlist_mutex; /**< For ctxlist */
drm_map_t **context_sareas; /**< per-context SAREA's */
int max_context;
@@ -979,7 +980,7 @@ extern int drm_put_head(drm_head_t * head);
extern unsigned int drm_debug;
extern unsigned int drm_cards_limit;
extern drm_head_t **drm_heads;
-extern struct drm_sysfs_class *drm_class;
+extern struct class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
/* Proc support (drm_proc.h) */
@@ -1010,11 +1011,9 @@ extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
/* sysfs support (drm_sysfs.c) */
-struct drm_sysfs_class;
-extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner,
- char *name);
-extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);
-extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
+extern struct class *drm_sysfs_create(struct module *owner, char *name);
+extern void drm_sysfs_destroy(struct class *cs);
+extern struct class_device *drm_sysfs_device_add(struct class *cs,
drm_head_t *head);
extern void drm_sysfs_device_remove(struct class_device *class_dev);
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index a47b502bc7c..2a37586a7ee 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -56,7 +56,7 @@ static int drm_hash_magic(drm_magic_t magic)
* \param magic magic number.
*
* Searches in drm_device::magiclist within all files with the same hash key
- * the one with matching magic number, while holding the drm_device::struct_sem
+ * the one with matching magic number, while holding the drm_device::struct_mutex
* lock.
*/
static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
@@ -65,14 +65,14 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
drm_magic_entry_t *pt;
int hash = drm_hash_magic(magic);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
if (pt->magic == magic) {
retval = pt->priv;
break;
}
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return retval;
}
@@ -85,7 +85,7 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
*
* Creates a drm_magic_entry structure and appends to the linked list
* associated the magic number hash key in drm_device::magiclist, while holding
- * the drm_device::struct_sem lock.
+ * the drm_device::struct_mutex lock.
*/
static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
drm_magic_t magic)
@@ -104,7 +104,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
entry->priv = priv;
entry->next = NULL;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
if (dev->magiclist[hash].tail) {
dev->magiclist[hash].tail->next = entry;
dev->magiclist[hash].tail = entry;
@@ -112,7 +112,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
dev->magiclist[hash].head = entry;
dev->magiclist[hash].tail = entry;
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -124,7 +124,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
* \param magic magic number.
*
* Searches and unlinks the entry in drm_device::magiclist with the magic
- * number hash key, while holding the drm_device::struct_sem lock.
+ * number hash key, while holding the drm_device::struct_mutex lock.
*/
static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
{
@@ -135,7 +135,7 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
DRM_DEBUG("%d\n", magic);
hash = drm_hash_magic(magic);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
if (pt->magic == magic) {
if (dev->magiclist[hash].head == pt) {
@@ -147,11 +147,11 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
if (prev) {
prev->next = pt->next;
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 1db12dcb680..e2637b4d51d 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -255,14 +255,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
memset(list, 0, sizeof(*list));
list->map = map;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
list_add(&list->head, &dev->maplist->head);
/* Assign a 32-bit handle */
- /* We do it here so that dev->struct_sem protects the increment */
+ /* We do it here so that dev->struct_mutex protects the increment */
list->user_token = HandleID(map->type == _DRM_SHM
? (unsigned long)map->handle
: map->offset, dev);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
*maplist = list;
return 0;
@@ -392,9 +392,9 @@ int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
{
int ret;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
ret = drm_rmmap_locked(dev, map);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -423,7 +423,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
return -EFAULT;
}
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
list_for_each(list, &dev->maplist->head) {
drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
@@ -439,7 +439,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
* find anything.
*/
if (list == (&dev->maplist->head)) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
@@ -448,13 +448,13 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
/* Register and framebuffer maps are permanent */
if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
ret = drm_rmmap_locked(dev, map);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -566,16 +566,16 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
entry = &dma->bufs[order];
if (entry->buf_count) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
if (count < 0 || count > 4096) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -EINVAL;
}
@@ -583,7 +583,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -616,7 +616,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
drm_cleanup_buf_error(dev, entry);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -638,7 +638,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -656,7 +656,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
request->count = entry->buf_count;
request->size = size;
@@ -722,16 +722,16 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
entry = &dma->bufs[order];
if (entry->buf_count) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
if (count < 0 || count > 4096) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -EINVAL;
}
@@ -739,7 +739,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -750,7 +750,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
if (!entry->seglist) {
drm_free(entry->buflist,
count * sizeof(*entry->buflist), DRM_MEM_BUFS);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -766,7 +766,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
count * sizeof(*entry->buflist), DRM_MEM_BUFS);
drm_free(entry->seglist,
count * sizeof(*entry->seglist), DRM_MEM_SEGS);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -790,7 +790,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
drm_free(temp_pagelist,
(dma->page_count + (count << page_order))
* sizeof(*dma->pagelist), DRM_MEM_PAGES);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -831,7 +831,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
(count << page_order))
* sizeof(*dma->pagelist),
DRM_MEM_PAGES);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -853,7 +853,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
drm_free(temp_pagelist,
(dma->page_count + (count << page_order))
* sizeof(*dma->pagelist), DRM_MEM_PAGES);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -878,7 +878,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
dma->page_count += entry->seg_count << page_order;
dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
request->count = entry->buf_count;
request->size = size;
@@ -948,16 +948,16 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
entry = &dma->bufs[order];
if (entry->buf_count) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
if (count < 0 || count > 4096) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -EINVAL;
}
@@ -965,7 +965,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -999,7 +999,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
drm_cleanup_buf_error(dev, entry);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -1022,7 +1022,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -1040,7 +1040,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
request->count = entry->buf_count;
request->size = size;
@@ -1110,16 +1110,16 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
entry = &dma->bufs[order];
if (entry->buf_count) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
if (count < 0 || count > 4096) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -EINVAL;
}
@@ -1127,7 +1127,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -1160,7 +1160,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
drm_cleanup_buf_error(dev, entry);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -1182,7 +1182,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
@@ -1200,7 +1200,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
request->count = entry->buf_count;
request->size = size;
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index f8425452694..83094c73da6 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -53,7 +53,7 @@
* \param ctx_handle context handle.
*
* Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::context_sareas, while holding the drm_device::struct_sem
+ * in drm_device::context_sareas, while holding the drm_device::struct_mutex
* lock.
*/
void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
@@ -64,10 +64,10 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
goto failed;
if (ctx_handle < DRM_MAX_CTXBITMAP) {
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
clear_bit(ctx_handle, dev->ctx_bitmap);
dev->context_sareas[ctx_handle] = NULL;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return;
}
failed:
@@ -83,7 +83,7 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
*
* Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
* drm_device::context_sareas to accommodate the new entry while holding the
- * drm_device::struct_sem lock.
+ * drm_device::struct_mutex lock.
*/
static int drm_ctxbitmap_next(drm_device_t * dev)
{
@@ -92,7 +92,7 @@ static int drm_ctxbitmap_next(drm_device_t * dev)
if (!dev->ctx_bitmap)
return -1;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
if (bit < DRM_MAX_CTXBITMAP) {
set_bit(bit, dev->ctx_bitmap);
@@ -113,7 +113,7 @@ static int drm_ctxbitmap_next(drm_device_t * dev)
DRM_MEM_MAPS);
if (!ctx_sareas) {
clear_bit(bit, dev->ctx_bitmap);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -1;
}
dev->context_sareas = ctx_sareas;
@@ -126,16 +126,16 @@ static int drm_ctxbitmap_next(drm_device_t * dev)
DRM_MEM_MAPS);
if (!dev->context_sareas) {
clear_bit(bit, dev->ctx_bitmap);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -1;
}
dev->context_sareas[bit] = NULL;
}
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return bit;
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -1;
}
@@ -145,24 +145,24 @@ static int drm_ctxbitmap_next(drm_device_t * dev)
* \param dev DRM device.
*
* Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_sem lock.
+ * the drm_device::struct_mutex lock.
*/
int drm_ctxbitmap_init(drm_device_t * dev)
{
int i;
int temp;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
DRM_MEM_CTXBITMAP);
if (dev->ctx_bitmap == NULL) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -ENOMEM;
}
memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
dev->context_sareas = NULL;
dev->max_context = -1;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
temp = drm_ctxbitmap_next(dev);
@@ -178,17 +178,17 @@ int drm_ctxbitmap_init(drm_device_t * dev)
* \param dev DRM device.
*
* Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_sem lock.
+ * the drm_device::struct_mutex lock.
*/
void drm_ctxbitmap_cleanup(drm_device_t * dev)
{
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
if (dev->context_sareas)
drm_free(dev->context_sareas,
sizeof(*dev->context_sareas) *
dev->max_context, DRM_MEM_MAPS);
drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
}
/*@}*/
@@ -222,15 +222,15 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
if (dev->max_context < 0
|| request.ctx_id >= (unsigned)dev->max_context) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
map = dev->context_sareas[request.ctx_id];
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
request.handle = NULL;
list_for_each_entry(_entry, &dev->maplist->head, head) {
@@ -274,7 +274,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
(drm_ctx_priv_map_t __user *) arg, sizeof(request)))
return -EFAULT;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
if (r_list->map
@@ -282,7 +282,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
goto found;
}
bad:
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
found:
@@ -294,7 +294,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
if (request.ctx_id >= (unsigned)dev->max_context)
goto bad;
dev->context_sareas[request.ctx_id] = map;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -448,10 +448,10 @@ int drm_addctx(struct inode *inode, struct file *filp,
ctx_entry->handle = ctx.handle;
ctx_entry->tag = priv;
- down(&dev->ctxlist_sem);
+ mutex_lock(&dev->ctxlist_mutex);
list_add(&ctx_entry->head, &dev->ctxlist->head);
++dev->ctx_count;
- up(&dev->ctxlist_sem);
+ mutex_unlock(&dev->ctxlist_mutex);
if (copy_to_user(argp, &ctx, sizeof(ctx)))
return -EFAULT;
@@ -574,7 +574,7 @@ int drm_rmctx(struct inode *inode, struct file *filp,
drm_ctxbitmap_free(dev, ctx.handle);
}
- down(&dev->ctxlist_sem);
+ mutex_lock(&dev->ctxlist_mutex);
if (!list_empty(&dev->ctxlist->head)) {
drm_ctx_list_t *pos, *n;
@@ -586,7 +586,7 @@ int drm_rmctx(struct inode *inode, struct file *filp,
}
}
}
- up(&dev->ctxlist_sem);
+ mutex_unlock(&dev->ctxlist_mutex);
return 0;
}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index c4fa5a29582..dc6bbe8a18d 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -151,7 +151,7 @@ int drm_lastclose(drm_device_t * dev)
if (dev->irq_enabled)
drm_irq_uninstall(dev);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
del_timer(&dev->timer);
/* Clear pid list */
@@ -231,7 +231,7 @@ int drm_lastclose(drm_device_t * dev)
dev->lock.filp = NULL;
wake_up_interruptible(&dev->lock.lock_queue);
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
DRM_DEBUG("lastclose completed\n");
return 0;
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 403f44a1bf0..641f7633878 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -262,7 +262,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
goto out_free;
}
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
if (!dev->file_last) {
priv->next = NULL;
priv->prev = NULL;
@@ -276,7 +276,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
dev->file_last->next = priv;
dev->file_last = priv;
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
#ifdef __alpha__
/*
@@ -413,7 +413,7 @@ int drm_release(struct inode *inode, struct file *filp)
drm_fasync(-1, filp, 0);
- down(&dev->ctxlist_sem);
+ mutex_lock(&dev->ctxlist_mutex);
if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
drm_ctx_list_t *pos, *n;
@@ -432,9 +432,9 @@ int drm_release(struct inode *inode, struct file *filp)
}
}
}
- up(&dev->ctxlist_sem);
+ mutex_unlock(&dev->ctxlist_mutex);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
if (priv->remove_auth_on_close == 1) {
drm_file_t *temp = dev->file_first;
while (temp) {
@@ -452,7 +452,7 @@ int drm_release(struct inode *inode, struct file *filp)
} else {
dev->file_last = priv->prev;
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
if (dev->driver->postclose)
dev->driver->postclose(dev, priv);
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index bcd4e604d3e..555f323b8a3 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -194,9 +194,9 @@ int drm_getmap(struct inode *inode, struct file *filp,
return -EFAULT;
idx = map.offset;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
if (idx < 0) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
@@ -209,7 +209,7 @@ int drm_getmap(struct inode *inode, struct file *filp,
i++;
}
if (!r_list || !r_list->map) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
@@ -219,7 +219,7 @@ int drm_getmap(struct inode *inode, struct file *filp,
map.flags = r_list->map->flags;
map.handle = (void *)(unsigned long)r_list->user_token;
map.mtrr = r_list->map->mtrr;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
if (copy_to_user(argp, &map, sizeof(map)))
return -EFAULT;
@@ -253,11 +253,11 @@ int drm_getclient(struct inode *inode, struct file *filp,
if (copy_from_user(&client, argp, sizeof(client)))
return -EFAULT;
idx = client.idx;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
if (!pt) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
client.auth = pt->authenticated;
@@ -265,7 +265,7 @@ int drm_getclient(struct inode *inode, struct file *filp,
client.uid = pt->uid;
client.magic = pt->magic;
client.iocs = pt->ioctl_count;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
if (copy_to_user(argp, &client, sizeof(client)))
return -EFAULT;
@@ -292,7 +292,7 @@ int drm_getstats(struct inode *inode, struct file *filp,
memset(&stats, 0, sizeof(stats));
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
for (i = 0; i < dev->counters; i++) {
if (dev->types[i] == _DRM_STAT_LOCK)
@@ -305,7 +305,7 @@ int drm_getstats(struct inode *inode, struct file *filp,
stats.count = dev->counters;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
return -EFAULT;
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index b0d4b236e83..611a1173091 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -98,20 +98,20 @@ static int drm_irq_install(drm_device_t * dev)
if (dev->irq == 0)
return -EINVAL;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
/* Driver must have been initialized */
if (!dev->dev_private) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
if (dev->irq_enabled) {
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return -EBUSY;
}
dev->irq_enabled = 1;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
@@ -135,9 +135,9 @@ static int drm_irq_install(drm_device_t * dev)
ret = request_irq(dev->irq, dev->driver->irq_handler,
sh_flags, dev->devname, dev);
if (ret < 0) {
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
dev->irq_enabled = 0;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -161,10 +161,10 @@ int drm_irq_uninstall(drm_device_t * dev)
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return -EINVAL;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
irq_enabled = dev->irq_enabled;
dev->irq_enabled = 0;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
if (!irq_enabled)
return -EINVAL;
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 5b1d3a04458..2c17e88a884 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -3,6 +3,7 @@
Please contact dri-devel@lists.sf.net to add new cards to this list
*/
#define radeon_PCI_IDS \
+ {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\
{0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \
{0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
{0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
@@ -84,7 +85,6 @@
{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
- {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
{0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
@@ -242,5 +242,6 @@
{0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 6f943e3309e..362a270af0f 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -258,7 +258,7 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
}
/**
- * Simply calls _vm_info() while holding the drm_device::struct_sem lock.
+ * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
*/
static int drm_vm_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
@@ -266,9 +266,9 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
drm_device_t *dev = (drm_device_t *) data;
int ret;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
ret = drm__vm_info(buf, start, offset, request, eof, data);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -331,7 +331,7 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
}
/**
- * Simply calls _queues_info() while holding the drm_device::struct_sem lock.
+ * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
*/
static int drm_queues_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
@@ -339,9 +339,9 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
drm_device_t *dev = (drm_device_t *) data;
int ret;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
ret = drm__queues_info(buf, start, offset, request, eof, data);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -403,7 +403,7 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
}
/**
- * Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
+ * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock.
*/
static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
@@ -411,9 +411,9 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
drm_device_t *dev = (drm_device_t *) data;
int ret;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
ret = drm__bufs_info(buf, start, offset, request, eof, data);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -459,7 +459,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
}
/**
- * Simply calls _clients_info() while holding the drm_device::struct_sem lock.
+ * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
*/
static int drm_clients_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
@@ -467,9 +467,9 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
drm_device_t *dev = (drm_device_t *) data;
int ret;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
ret = drm__clients_info(buf, start, offset, request, eof, data);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -540,9 +540,9 @@ static int drm_vma_info(char *buf, char **start, off_t offset, int request,
drm_device_t *dev = (drm_device_t *) data;
int ret;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
ret = drm__vma_info(buf, start, offset, request, eof, data);
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
#endif
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 42d766359ca..68073e14fde 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -50,7 +50,7 @@ module_param_named(cards_limit, drm_cards_limit, int, 0444);
module_param_named(debug, drm_debug, int, 0600);
drm_head_t **drm_heads;
-struct drm_sysfs_class *drm_class;
+struct class *drm_class;
struct proc_dir_entry *drm_proc_root;
static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
@@ -61,8 +61,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
spin_lock_init(&dev->count_lock);
init_timer(&dev->timer);
- sema_init(&dev->struct_sem, 1);
- sema_init(&dev->ctxlist_sem, 1);
+ mutex_init(&dev->struct_mutex);
+ mutex_init(&dev->ctxlist_mutex);
dev->pdev = pdev;
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 68e43ddc16a..0b9f98a7eb1 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -1,3 +1,4 @@
+
/*
* drm_sysfs.c - Modifications to drm_sysfs_class.c to support
* extra sysfs attribute from DRM. Normal drm_sysfs_class
@@ -19,36 +20,6 @@
#include "drm_core.h"
#include "drmP.h"
-struct drm_sysfs_class {
- struct class_device_attribute attr;
- struct class class;
-};
-#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
-
-struct simple_dev {
- dev_t dev;
- struct class_device class_dev;
-};
-#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-
-static void release_simple_dev(struct class_device *class_dev)
-{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
- kfree(s_dev);
-}
-
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
- return print_dev_t(buf, s_dev->dev);
-}
-
-static void drm_sysfs_class_release(struct class *class)
-{
- struct drm_sysfs_class *cs = to_drm_sysfs_class(class);
- kfree(cs);
-}
-
/* Display the version of drm_core. This doesn't work right in current design */
static ssize_t version_show(struct class *dev, char *buf)
{
@@ -69,38 +40,16 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
* Note, the pointer created here is to be destroyed when finished by making a
* call to drm_sysfs_destroy().
*/
-struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
+struct class *drm_sysfs_create(struct module *owner, char *name)
{
- struct drm_sysfs_class *cs;
- int retval;
-
- cs = kmalloc(sizeof(*cs), GFP_KERNEL);
- if (!cs) {
- retval = -ENOMEM;
- goto error;
- }
- memset(cs, 0x00, sizeof(*cs));
-
- cs->class.name = name;
- cs->class.class_release = drm_sysfs_class_release;
- cs->class.release = release_simple_dev;
-
- cs->attr.attr.name = "dev";
- cs->attr.attr.mode = S_IRUGO;
- cs->attr.attr.owner = owner;
- cs->attr.show = show_dev;
- cs->attr.store = NULL;
-
- retval = class_register(&cs->class);
- if (retval)
- goto error;
- class_create_file(&cs->class, &class_attr_version);
-
- return cs;
-
- error:
- kfree(cs);
- return ERR_PTR(retval);
+ struct class *class;
+
+ class = class_create(owner, name);
+ if (!class)
+ return class;
+
+ class_create_file(class, &class_attr_version);
+ return class;
}
/**
@@ -110,12 +59,13 @@ struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
* Note, the pointer to be destroyed must have been created with a call to
* drm_sysfs_create().
*/
-void drm_sysfs_destroy(struct drm_sysfs_class *cs)
+void drm_sysfs_destroy(struct class *class)
{
- if ((cs == NULL) || (IS_ERR(cs)))
+ if ((class == NULL) || (IS_ERR(class)))
return;
- class_unregister(&cs->class);
+ class_remove_file(class, &class_attr_version);
+ class_destroy(class);
}
static ssize_t show_dri(struct class_device *class_device, char *buf)
@@ -132,7 +82,7 @@ static struct class_device_attribute class_device_attrs[] = {
/**
* drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
+ * @cs: pointer to the struct class that this device should be registered to.
* @dev: the dev_t for the device to be added.
* @device: a pointer to a struct device that is assiociated with this class device.
* @fmt: string for the class device's name
@@ -141,46 +91,26 @@ static struct class_device_attribute class_device_attrs[] = {
* class. A "dev" file will be created, showing the dev_t for the device. The
* pointer to the struct class_device will be returned from the call. Any further
* sysfs files that might be required can be created using this pointer.
- * Note: the struct drm_sysfs_class passed to this function must have previously been
+ * Note: the struct class passed to this function must have previously been
* created with a call to drm_sysfs_create().
*/
-struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
- drm_head_t *head)
+struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
{
- struct simple_dev *s_dev = NULL;
- int i, retval;
-
- if ((cs == NULL) || (IS_ERR(cs))) {
- retval = -ENODEV;
- goto error;
- }
-
- s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
- if (!s_dev) {
- retval = -ENOMEM;
- goto error;
- }
- memset(s_dev, 0x00, sizeof(*s_dev));
-
- s_dev->dev = MKDEV(DRM_MAJOR, head->minor);
- s_dev->class_dev.dev = &(head->dev->pdev)->dev;
- s_dev->class_dev.class = &cs->class;
+ struct class_device *class_dev;
+ int i;
- snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor);
- retval = class_device_register(&s_dev->class_dev);
- if (retval)
- goto error;
+ class_dev = class_device_create(cs, NULL,
+ MKDEV(DRM_MAJOR, head->minor),
+ &(head->dev->pdev)->dev,
+ "card%d", head->minor);
+ if (!class_dev)
+ return NULL;
- class_device_create_file(&s_dev->class_dev, &cs->attr);
- class_set_devdata(&s_dev->class_dev, head);
+ class_set_devdata(class_dev, head);
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
- class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]);
- return &s_dev->class_dev;
-
-error:
- kfree(s_dev);
- return ERR_PTR(retval);
+ class_device_create_file(class_dev, &class_device_attrs[i]);
+ return class_dev;
}
/**
@@ -192,10 +122,9 @@ error:
*/
void drm_sysfs_device_remove(struct class_device *class_dev)
{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
int i;
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
- class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]);
- class_device_unregister(&s_dev->class_dev);
+ class_device_remove_file(class_dev, &class_device_attrs[i]);
+ class_device_unregister(class_dev);
}
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index 3f73aa774c8..0291cd62c69 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -188,7 +188,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
map = vma->vm_private_data;
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
next = pt->next;
if (pt->vma->vm_private_data == map)
@@ -248,7 +248,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
}
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
}
/**
@@ -404,12 +404,12 @@ static void drm_vm_open(struct vm_area_struct *vma)
vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
if (vma_entry) {
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
vma_entry->vma = vma;
vma_entry->next = dev->vmalist;
vma_entry->pid = current->pid;
dev->vmalist = vma_entry;
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
}
}
@@ -431,7 +431,7 @@ static void drm_vm_close(struct vm_area_struct *vma)
vma->vm_start, vma->vm_end - vma->vm_start);
atomic_dec(&dev->vma_count);
- down(&dev->struct_sem);
+ mutex_lock(&dev->struct_mutex);
for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
if (pt->vma == vma) {
if (prev) {
@@ -443,7 +443,7 @@ static void drm_vm_close(struct vm_area_struct *vma)
break;
}
}
- up(&dev->struct_sem);
+ mutex_unlock(&dev->struct_mutex);
}
/**
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index cc1b8908687..ae0aa6d7e0b 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -958,7 +958,7 @@ static int i810_flush_queue(drm_device_t * dev)
}
/* Must be called with the lock held */
-void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
{
drm_device_dma_t *dma = dev->dma;
int i;
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index a18b80d9192..e8cf3ff606f 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -113,8 +113,6 @@ typedef struct drm_i810_private {
} drm_i810_private_t;
/* i810_dma.c */
-extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp);
-
extern int i810_driver_dma_quiescent(drm_device_t * dev);
extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
struct file *filp);
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 4fea32aed6d..163f2cbfe60 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -1239,7 +1239,7 @@ static int i830_flush_queue(drm_device_t * dev)
}
/* Must be called with the lock held */
-void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
{
drm_device_dma_t *dma = dev->dma;
int i;
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index bf9075b576b..85bc5be6f91 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -123,9 +123,6 @@ typedef struct drm_i830_private {
extern drm_ioctl_desc_t i830_ioctls[];
extern int i830_max_ioctl;
-/* i830_dma.c */
-extern void i830_reclaim_buffers(drm_device_t * dev, struct file *filp);
-
/* i830_irq.c */
extern int i830_irq_emit(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 9140703da1b..1ff4c7ca0bf 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -344,18 +344,20 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
int i;
RING_LOCALS;
+ if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
+ return DRM_ERR(EINVAL);
+
+ BEGIN_LP_RING(((dwords+1)&~1));
+
for (i = 0; i < dwords;) {
int cmd, sz;
if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
return DRM_ERR(EINVAL);
-/* printk("%d/%d ", i, dwords); */
-
if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
return DRM_ERR(EINVAL);
- BEGIN_LP_RING(sz);
OUT_RING(cmd);
while (++i, --sz) {
@@ -365,9 +367,13 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
}
OUT_RING(cmd);
}
- ADVANCE_LP_RING();
}
+ if (dwords & 1)
+ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+
return 0;
}
@@ -401,6 +407,21 @@ static int i915_emit_box(drm_device_t * dev,
return 0;
}
+static void i915_emit_breadcrumb(drm_device_t *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+
+ BEGIN_LP_RING(4);
+ OUT_RING(CMD_STORE_DWORD_IDX);
+ OUT_RING(20);
+ OUT_RING(dev_priv->counter);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+}
+
static int i915_dispatch_cmdbuffer(drm_device_t * dev,
drm_i915_cmdbuffer_t * cmd)
{
@@ -429,6 +450,7 @@ static int i915_dispatch_cmdbuffer(drm_device_t * dev,
return ret;
}
+ i915_emit_breadcrumb(dev);
return 0;
}
@@ -475,12 +497,7 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev,
dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
- BEGIN_LP_RING(4);
- OUT_RING(CMD_STORE_DWORD_IDX);
- OUT_RING(20);
- OUT_RING(dev_priv->counter);
- OUT_RING(0);
- ADVANCE_LP_RING();
+ i915_emit_breadcrumb(dev);
return 0;
}
@@ -657,7 +674,7 @@ static int i915_getparam(DRM_IOCTL_ARGS)
value = READ_BREADCRUMB(dev_priv);
break;
default:
- DRM_ERROR("Unkown parameter %d\n", param.param);
+ DRM_ERROR("Unknown parameter %d\n", param.param);
return DRM_ERR(EINVAL);
}
@@ -742,7 +759,8 @@ drm_ioctl_desc_t i915_ioctls[] = {
[DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},
[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
- [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}
+ [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 77412ddac00..4cb3da57833 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -74,6 +74,30 @@ typedef struct _drm_i915_sarea {
int pf_active;
int pf_current_page; /* which buffer is being displayed? */
int perf_boxes; /* performance boxes to be displayed */
+ int width, height; /* screen size in pixels */
+
+ drm_handle_t front_handle;
+ int front_offset;
+ int front_size;
+
+ drm_handle_t back_handle;
+ int back_offset;
+ int back_size;
+
+ drm_handle_t depth_handle;
+ int depth_offset;
+ int depth_size;
+
+ drm_handle_t tex_handle;
+ int tex_offset;
+ int tex_size;
+ int log_tex_granularity;
+ int pitch;
+ int rotation; /* 0, 90, 180 or 270 */
+ int rotated_offset;
+ int rotated_size;
+ int rotated_pitch;
+ int virtualX, virtualY;
} drm_i915_sarea_t;
/* Flags for perf_boxes
@@ -99,6 +123,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_FREE 0x09
#define DRM_I915_INIT_HEAP 0x0a
#define DRM_I915_CMDBUFFER 0x0b
+#define DRM_I915_DESTROY_HEAP 0x0c
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -112,6 +137,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
+#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -191,4 +217,11 @@ typedef struct drm_i915_mem_init_heap {
int start;
} drm_i915_mem_init_heap_t;
+/* Allow memory manager to be torn down and re-initialized (eg on
+ * rotate):
+ */
+typedef struct drm_i915_mem_destroy_heap {
+ int region;
+} drm_i915_mem_destroy_heap_t;
+
#endif /* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index c6c71b45f10..7a65666899e 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -37,16 +37,17 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20051209"
+#define DRIVER_DATE "20060119"
/* Interface history:
*
* 1.1: Original.
* 1.2: Add Power Management
* 1.3: Add vblank support
+ * 1.4: Fix cmdbuffer path, add heap destroy
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 3
+#define DRIVER_MINOR 4
#define DRIVER_PATCHLEVEL 0
typedef struct _drm_i915_ring_buffer {
@@ -123,6 +124,7 @@ extern void i915_driver_irq_uninstall(drm_device_t * dev);
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
extern int i915_mem_free(DRM_IOCTL_ARGS);
extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
+extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
extern void i915_mem_takedown(struct mem_block **heap);
extern void i915_mem_release(drm_device_t * dev,
DRMFILE filp, struct mem_block *heap);
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index ba87ff17ff6..52c67324df5 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -365,3 +365,34 @@ int i915_mem_init_heap(DRM_IOCTL_ARGS)
return init_heap(heap, initheap.start, initheap.size);
}
+
+int i915_mem_destroy_heap( DRM_IOCTL_ARGS )
+{
+ DRM_DEVICE;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_mem_destroy_heap_t destroyheap;
+ struct mem_block **heap;
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ return DRM_ERR(EINVAL);
+ }
+
+ DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data,
+ sizeof(destroyheap) );
+
+ heap = get_heap( dev_priv, destroyheap.region );
+ if (!heap) {
+ DRM_ERROR("get_heap failed");
+ return DRM_ERR(EFAULT);
+ }
+
+ if (!*heap) {
+ DRM_ERROR("heap not initialized?");
+ return DRM_ERR(EFAULT);
+ }
+
+ i915_mem_takedown( heap );
+ return 0;
+}
+
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 915665c7fe7..9bb8ae0c1c2 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1640,7 +1640,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
{
drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
- dev_priv->gart_info.addr = 0;
+ dev_priv->gart_info.addr = NULL;
}
}
/* only clear to the start of flags */
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index 0d426deeefe..59c7520bf9a 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -32,6 +32,8 @@
#define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */
#define SAVAGE_FREELIST_DEBUG 0
+static int savage_do_cleanup_bci(drm_device_t *dev);
+
static int
savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
{
@@ -895,7 +897,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init)
return 0;
}
-int savage_do_cleanup_bci(drm_device_t * dev)
+static int savage_do_cleanup_bci(drm_device_t * dev)
{
drm_savage_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
index dd46cb85439..8f04b3d8229 100644
--- a/drivers/char/drm/savage_drv.h
+++ b/drivers/char/drm/savage_drv.h
@@ -212,7 +212,6 @@ extern int savage_driver_load(drm_device_t *dev, unsigned long chipset);
extern int savage_driver_firstopen(drm_device_t *dev);
extern void savage_driver_lastclose(drm_device_t *dev);
extern int savage_driver_unload(drm_device_t *dev);
-extern int savage_do_cleanup_bci(drm_device_t * dev);
extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp);
/* state functions */
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index 593c0b8f650..a691ae74129 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -222,7 +222,7 @@ static int via_initialize(drm_device_t * dev,
return 0;
}
-int via_dma_init(DRM_IOCTL_ARGS)
+static int via_dma_init(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -321,7 +321,7 @@ int via_driver_dma_quiescent(drm_device_t * dev)
return 0;
}
-int via_flush_ioctl(DRM_IOCTL_ARGS)
+static int via_flush_ioctl(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
@@ -330,7 +330,7 @@ int via_flush_ioctl(DRM_IOCTL_ARGS)
return via_driver_dma_quiescent(dev);
}
-int via_cmdbuffer(DRM_IOCTL_ARGS)
+static int via_cmdbuffer(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_via_cmdbuffer_t cmdbuf;
@@ -375,7 +375,7 @@ static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
return ret;
}
-int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
+static int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_via_cmdbuffer_t cmdbuf;
@@ -665,7 +665,7 @@ static void via_cmdbuf_reset(drm_via_private_t * dev_priv)
* User interface to the space and lag functions.
*/
-int via_cmdbuf_size(DRM_IOCTL_ARGS)
+static int via_cmdbuf_size(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_via_cmdbuf_size_t d_siz;
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 9d5e027dae0..b7f17457b42 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -108,7 +108,7 @@ via_map_blit_for_device(struct pci_dev *pdev,
int num_desc = 0;
int cur_line;
dma_addr_t next = 0 | VIA_DMA_DPR_EC;
- drm_via_descriptor_t *desc_ptr = 0;
+ drm_via_descriptor_t *desc_ptr = NULL;
if (mode == 1)
desc_ptr = vsg->desc_pages[cur_descriptor_page];
@@ -167,7 +167,7 @@ via_map_blit_for_device(struct pci_dev *pdev,
*/
-void
+static void
via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
{
struct page *page;
@@ -581,7 +581,7 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
int ret = 0;
vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
- vsg->bounce_buffer = 0;
+ vsg->bounce_buffer = NULL;
vsg->state = dr_via_sg_init;
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index aad4f99f540..52bcc7b1ba4 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -110,11 +110,6 @@ extern int via_mem_free(DRM_IOCTL_ARGS);
extern int via_agp_init(DRM_IOCTL_ARGS);
extern int via_map_init(DRM_IOCTL_ARGS);
extern int via_decoder_futex(DRM_IOCTL_ARGS);
-extern int via_dma_init(DRM_IOCTL_ARGS);
-extern int via_cmdbuffer(DRM_IOCTL_ARGS);
-extern int via_flush_ioctl(DRM_IOCTL_ARGS);
-extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
-extern int via_cmdbuf_size(DRM_IOCTL_ARGS);
extern int via_wait_irq(DRM_IOCTL_ARGS);
extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
extern int via_dma_blit( DRM_IOCTL_ARGS );
@@ -139,8 +134,6 @@ extern int via_driver_dma_quiescent(drm_device_t * dev);
extern void via_init_futex(drm_via_private_t * dev_priv);
extern void via_cleanup_futex(drm_via_private_t * dev_priv);
extern void via_release_futex(drm_via_private_t * dev_priv, int context);
-extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq,
- int force_sequence, unsigned int *sequence);
extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
extern void via_init_dmablit(drm_device_t *dev);
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index 56d7e3daea1..6152415644e 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -190,7 +190,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
-int
+static int
via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
unsigned int *sequence)
{
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index dd5dc8fa490..09dc4b01232 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -150,17 +150,6 @@ static void rs_wait_until_sent(struct tty_struct *, int);
/* Standard COM flags (except for COM4, because of the 8514 problem) */
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf;
-
static inline int serial_paranoia_check(struct esp_struct *info,
char *name, const char *routine)
{
@@ -359,7 +348,7 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
}
}
- schedule_delayed_work(&tty->buf.work, 1);
+ tty_schedule_flip(tty);
info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
release_pio_buffer(pio_buf);
@@ -426,7 +415,7 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
}
tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag);
}
- schedule_delayed_work(&tty->buf.work, 1);
+ tty_schedule_flip(tty);
}
if (dma_bytes != num_bytes) {
@@ -1267,7 +1256,7 @@ static int rs_write(struct tty_struct * tty,
if (serial_paranoia_check(info, tty->name, "rs_write"))
return 0;
- if (!tty || !info->xmit_buf || !tmp_buf)
+ if (!tty || !info->xmit_buf)
return 0;
while (1) {
@@ -2291,11 +2280,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
tty->driver_data = info;
info->tty = tty;
- if (!tmp_buf) {
- tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL);
- if (!tmp_buf)
- return -ENOMEM;
- }
+ spin_unlock_irqrestore(&info->lock, flags);
/*
* Start up serial port
@@ -2492,6 +2477,7 @@ static int __init espserial_init(void)
}
memset((void *)info, 0, sizeof(struct esp_struct));
+ spin_lock_init(&info->lock);
/* rx_trigger, tx_trigger are needed by autoconfig */
info->config.rx_trigger = rx_trigger;
info->config.tx_trigger = tx_trigger;
@@ -2528,7 +2514,6 @@ static int __init espserial_init(void)
init_waitqueue_head(&info->close_wait);
init_waitqueue_head(&info->delta_msr_wait);
init_waitqueue_head(&info->break_wait);
- spin_lock_init(&info->lock);
ports = info;
printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ",
info->line, info->port, info->irq);
@@ -2602,9 +2587,6 @@ static void __exit espserial_exit(void)
free_pages((unsigned long)dma_buffer,
get_order(DMA_BUFFER_SZ));
- if (tmp_buf)
- free_page((unsigned long)tmp_buf);
-
while (free_pio_buf) {
pio_buf = free_pio_buf->next;
kfree(free_pio_buf);
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 40a67c86420..ac626418b32 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -117,12 +117,9 @@ __setup("hcheck_reboot", hangcheck_parse_reboot);
__setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
#endif /* not MODULE */
-#if defined(CONFIG_X86)
+#if defined(CONFIG_X86) || defined(CONFIG_S390)
# define HAVE_MONOTONIC
# define TIMER_FREQ 1000000000ULL
-#elif defined(CONFIG_S390)
-/* FA240000 is 1 Second in the IBM time universe (Page 4-38 Principles of Op for zSeries */
-# define TIMER_FREQ 0xFA240000ULL
#elif defined(CONFIG_IA64)
# define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq)
#elif defined(CONFIG_PPC64)
@@ -134,12 +131,7 @@ extern unsigned long long monotonic_clock(void);
#else
static inline unsigned long long monotonic_clock(void)
{
-# ifdef __s390__
- /* returns the TOD. see 4-38 Principles of Op of zSeries */
- return get_clock();
-# else
return get_cycles();
-# endif /* __s390__ */
}
#endif /* HAVE_MONOTONIC */
@@ -188,8 +180,6 @@ static int __init hangcheck_init(void)
VERSION_STR, hangcheck_tick, hangcheck_margin);
#if defined (HAVE_MONOTONIC)
printk("Hangcheck: Using monotonic_clock().\n");
-#elif defined(__s390__)
- printk("Hangcheck: Using TOD.\n");
#else
printk("Hangcheck: Using get_cycles().\n");
#endif /* HAVE_MONOTONIC */
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 3808d957261..ef140ebde11 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -927,9 +927,9 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
if (ACPI_SUCCESS(status)) {
unsigned long size;
- size = addr.max_address_range - addr.min_address_range + 1;
- hdp->hd_phys_address = addr.min_address_range;
- hdp->hd_address = ioremap(addr.min_address_range, size);
+ size = addr.maximum - addr.minimum + 1;
+ hdp->hd_phys_address = addr.minimum;
+ hdp->hd_address = ioremap(addr.minimum, size);
if (hpet_is_known(hdp)) {
printk(KERN_DEBUG "%s: 0x%lx is busy\n",
@@ -937,15 +937,15 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
iounmap(hdp->hd_address);
return -EBUSY;
}
- } else if (res->id == ACPI_RSTYPE_FIXED_MEM32) {
- struct acpi_resource_fixed_mem32 *fixmem32;
+ } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
+ struct acpi_resource_fixed_memory32 *fixmem32;
fixmem32 = &res->data.fixed_memory32;
if (!fixmem32)
return -EINVAL;
- hdp->hd_phys_address = fixmem32->range_base_address;
- hdp->hd_address = ioremap(fixmem32->range_base_address,
+ hdp->hd_phys_address = fixmem32->address;
+ hdp->hd_address = ioremap(fixmem32->address,
HPET_RANGE_SIZE);
if (hpet_is_known(hdp)) {
@@ -954,24 +954,20 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
iounmap(hdp->hd_address);
return -EBUSY;
}
- } else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
- struct acpi_resource_ext_irq *irqp;
- int i;
+ } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
+ struct acpi_resource_extended_irq *irqp;
+ int i, irq;
irqp = &res->data.extended_irq;
- if (irqp->number_of_interrupts > 0) {
- hdp->hd_nirqs = irqp->number_of_interrupts;
-
- for (i = 0; i < hdp->hd_nirqs; i++) {
- int rc =
- acpi_register_gsi(irqp->interrupts[i],
- irqp->edge_level,
- irqp->active_high_low);
- if (rc < 0)
- return AE_ERROR;
- hdp->hd_irq[i] = rc;
- }
+ for (i = 0; i < irqp->interrupt_count; i++) {
+ irq = acpi_register_gsi(irqp->interrupts[i],
+ irqp->triggering, irqp->polarity);
+ if (irq < 0)
+ return AE_ERROR;
+
+ hdp->hd_irq[hdp->hd_nirqs] = irq;
+ hdp->hd_nirqs++;
}
}
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c
index cb8f4198e9a..e7af647800b 100644
--- a/drivers/char/ip2/i2cmd.c
+++ b/drivers/char/ip2/i2cmd.c
@@ -139,7 +139,6 @@ static UCHAR ct79[] = { 2, BYP, 0x4F,0 }; // XMIT_NOW
//static UCHAR ct86[]={ 2, BTH, 0x56,0 }; // RCV_ENABLE
static UCHAR ct87[] = { 1, BYP, 0x57 }; // HW_TEST
//static UCHAR ct88[]={ 3, BTH, 0x58,0,0 }; // RCV_THRESHOLD
-static UCHAR ct89[]={ 1, BYP, 0x59 }; // DSS_NOW
//static UCHAR ct90[]={ 3, BYP, 0x5A,0,0 }; // Set SILO
//static UCHAR ct91[]={ 2, BYP, 0x5B,0 }; // timed break
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index 56e93a5a1e2..48fcfba37bf 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -2906,65 +2906,16 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
rc = -EINVAL;
break;
case 3: // Trace device
- if ( cmd == 1 ) {
- rc = put_user(iiSendPendingMail, pIndex++ );
- rc = put_user(i2InitChannels, pIndex++ );
- rc = put_user(i2QueueNeeds, pIndex++ );
- rc = put_user(i2QueueCommands, pIndex++ );
- rc = put_user(i2GetStatus, pIndex++ );
- rc = put_user(i2Input, pIndex++ );
- rc = put_user(i2InputFlush, pIndex++ );
- rc = put_user(i2Output, pIndex++ );
- rc = put_user(i2FlushOutput, pIndex++ );
- rc = put_user(i2DrainWakeup, pIndex++ );
- rc = put_user(i2DrainOutput, pIndex++ );
- rc = put_user(i2OutputFree, pIndex++ );
- rc = put_user(i2StripFifo, pIndex++ );
- rc = put_user(i2StuffFifoBypass, pIndex++ );
- rc = put_user(i2StuffFifoFlow, pIndex++ );
- rc = put_user(i2StuffFifoInline, pIndex++ );
- rc = put_user(i2ServiceBoard, pIndex++ );
- rc = put_user(serviceOutgoingFifo, pIndex++ );
- // rc = put_user(ip2_init, pIndex++ );
- rc = put_user(ip2_init_board, pIndex++ );
- rc = put_user(find_eisa_board, pIndex++ );
- rc = put_user(set_irq, pIndex++ );
- rc = put_user(ip2_interrupt, pIndex++ );
- rc = put_user(ip2_poll, pIndex++ );
- rc = put_user(service_all_boards, pIndex++ );
- rc = put_user(do_input, pIndex++ );
- rc = put_user(do_status, pIndex++ );
-#ifndef IP2DEBUG_OPEN
- rc = put_user(0, pIndex++ );
-#else
- rc = put_user(open_sanity_check, pIndex++ );
-#endif
- rc = put_user(ip2_open, pIndex++ );
- rc = put_user(ip2_close, pIndex++ );
- rc = put_user(ip2_hangup, pIndex++ );
- rc = put_user(ip2_write, pIndex++ );
- rc = put_user(ip2_putchar, pIndex++ );
- rc = put_user(ip2_flush_chars, pIndex++ );
- rc = put_user(ip2_write_room, pIndex++ );
- rc = put_user(ip2_chars_in_buf, pIndex++ );
- rc = put_user(ip2_flush_buffer, pIndex++ );
-
- //rc = put_user(ip2_wait_until_sent, pIndex++ );
- rc = put_user(0, pIndex++ );
-
- rc = put_user(ip2_throttle, pIndex++ );
- rc = put_user(ip2_unthrottle, pIndex++ );
- rc = put_user(ip2_ioctl, pIndex++ );
- rc = put_user(0, pIndex++ );
- rc = put_user(get_serial_info, pIndex++ );
- rc = put_user(set_serial_info, pIndex++ );
- rc = put_user(ip2_set_termios, pIndex++ );
- rc = put_user(ip2_set_line_discipline, pIndex++ );
- rc = put_user(set_params, pIndex++ );
- } else {
+ /*
+ * akpm: This used to write a whole bunch of function addresses
+ * to userspace, which generated lots of put_user() warnings.
+ * I killed it all. Just return "success" and don't do
+ * anything.
+ */
+ if (cmd == 1)
+ rc = 0;
+ else
rc = -EINVAL;
- }
-
break;
default:
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 0097f06fa67..d745004281d 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -481,7 +481,7 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len)
}
if ((addr->channel == IPMI_BMC_CHANNEL)
- || (addr->channel >= IPMI_NUM_CHANNELS)
+ || (addr->channel >= IPMI_MAX_CHANNELS)
|| (addr->channel < 0))
return -EINVAL;
@@ -1321,7 +1321,7 @@ static int i_ipmi_request(ipmi_user_t user,
unsigned char ipmb_seq;
long seqid;
- if (addr->channel >= IPMI_NUM_CHANNELS) {
+ if (addr->channel >= IPMI_MAX_CHANNELS) {
spin_lock_irqsave(&intf->counter_lock, flags);
intf->sent_invalid_commands++;
spin_unlock_irqrestore(&intf->counter_lock, flags);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index c67ef3e47ad..e59b638766e 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1270,36 +1270,36 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
return 0;
}
-static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset)
+static unsigned char intf_mem_inb(struct si_sm_io *io, unsigned int offset)
{
return readb((io->addr)+(offset * io->regspacing));
}
-static void mem_outb(struct si_sm_io *io, unsigned int offset,
+static void intf_mem_outb(struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
writeb(b, (io->addr)+(offset * io->regspacing));
}
-static unsigned char mem_inw(struct si_sm_io *io, unsigned int offset)
+static unsigned char intf_mem_inw(struct si_sm_io *io, unsigned int offset)
{
return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift)
&& 0xff;
}
-static void mem_outw(struct si_sm_io *io, unsigned int offset,
+static void intf_mem_outw(struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
writeb(b << io->regshift, (io->addr)+(offset * io->regspacing));
}
-static unsigned char mem_inl(struct si_sm_io *io, unsigned int offset)
+static unsigned char intf_mem_inl(struct si_sm_io *io, unsigned int offset)
{
return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift)
&& 0xff;
}
-static void mem_outl(struct si_sm_io *io, unsigned int offset,
+static void intf_mem_outl(struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
writel(b << io->regshift, (io->addr)+(offset * io->regspacing));
@@ -1349,16 +1349,16 @@ static int mem_setup(struct smi_info *info)
upon the register size. */
switch (info->io.regsize) {
case 1:
- info->io.inputb = mem_inb;
- info->io.outputb = mem_outb;
+ info->io.inputb = intf_mem_inb;
+ info->io.outputb = intf_mem_outb;
break;
case 2:
- info->io.inputb = mem_inw;
- info->io.outputb = mem_outw;
+ info->io.inputb = intf_mem_inw;
+ info->io.outputb = intf_mem_outw;
break;
case 4:
- info->io.inputb = mem_inl;
- info->io.outputb = mem_outl;
+ info->io.inputb = intf_mem_inl;
+ info->io.outputb = intf_mem_outl;
break;
#ifdef readq
case 8:
@@ -1580,11 +1580,6 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
if (! is_new_interface(-1, addr_space, spmi->addr.address))
return -ENODEV;
- if (! spmi->addr.register_bit_width) {
- acpi_failure = 1;
- return -ENODEV;
- }
-
/* Figure out the interface type. */
switch (spmi->InterfaceType)
{
@@ -1634,9 +1629,6 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
regspacings[intf_num] = spmi->addr.register_bit_width / 8;
info->io.regspacing = spmi->addr.register_bit_width / 8;
} else {
- /* Some broken systems get this wrong and set the value
- * to zero. Assume it is the default spacing. If that
- * is wrong, too bad, the vendor should fix the tables. */
regspacings[intf_num] = DEFAULT_REGSPACING;
info->io.regspacing = DEFAULT_REGSPACING;
}
diff --git a/drivers/char/rio/brates.h b/drivers/char/rio/brates.h
deleted file mode 100644
index dd686d58fd6..00000000000
--- a/drivers/char/rio/brates.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* BRATES.H *******
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date : 1 Nov 1990
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _brates_h
-#ifndef lint
-/* static char * _brates_h_sccs = "@(#)brates.h 1.4"; */
-#endif
-#define _brates_h 1
-/* List of baud rate defines. Most are borrowed from /usr/include/sys/termio.h
-*/
-#ifndef INKERNEL
-
-#define B0 0x00
-#define B50 0x01
-#define B75 0x02
-#define B110 0x03
-#define B134 0x04
-#define B150 0x05
-#define B200 0x06
-#define B300 0x07
-#define B600 0x08
-#define B1200 0x09
-#define B1800 0x0a
-#define B2400 0x0b
-#define B4800 0x0c
-#define B9600 0x0d
-#define B19200 0x0e
-#define B38400 0x0f
-
-#endif
-
-/*
-** The following baudrates may or may not be defined
-** on various UNIX systems.
-** If they are not then we define them.
-** If they are then we do not define them ;-)
-**
-** This is appalling that we use same definitions as UNIX
-** for our own download code as there is no garuntee that
-** B57600 will be defined as 0x11 by a UNIX system....
-** Arghhhhh!!!!!!!!!!!!!!
-*/
-#if !defined(B56000)
-#define B56000 0x10
-#endif
-
-#if !defined(B57600)
-#define B57600 0x11
-#endif
-
-#if !defined(B64000)
-#define B64000 0x12
-#endif
-
-#if !defined(B115200)
-#define B115200 0x13
-#endif
-
-
-#if !defined(B2000)
-#define B2000 0x14
-#endif
-
-
-#define MAX_RATE B2000
-
-struct baud_rate { /* Tag for baud rates */
- /* short host_rate, *//* As passed by the driver */
- short divisor, /* The divisor */
- prescaler; /* The pre-scaler */
-};
-
-#endif
diff --git a/drivers/char/rio/chan.h b/drivers/char/rio/chan.h
deleted file mode 100644
index af14311f9b6..00000000000
--- a/drivers/char/rio/chan.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-#ifndef _chan_h
-#define _chan_h
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_chan_h_sccs = "@(#)chan.h 1.1";
-#endif
-#endif
-
-#define Link0 0
-#define Link1 1
-#define Link2 2
-#define Link3 3
-
-#endif
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h
index 217ff09f2fa..89bd94eb45b 100644
--- a/drivers/char/rio/cirrus.h
+++ b/drivers/char/rio/cirrus.h
@@ -40,148 +40,6 @@
#endif
#define _cirrus_h 1
-#ifdef RTA
-#define TO_UART RX
-#define TO_DRIVER TX
-#endif
-
-#ifdef HOST
-#define TO_UART TX
-#define TO_DRIVER RX
-#endif
-#ifdef RTA
-/* Miscellaneous defines for CIRRUS addresses and related logic for
- interrupts etc.
-*/
-#define MAP(a) ((short *)(cirrus_base + (a)))
-#define outp(a,b) (*MAP (a) =(b))
-#define inp(a) ((*MAP (a)) & 0xff)
-#define CIRRUS_FIRST (short*)0x7300
-#define CIRRUS_SECOND (short*)0x7200
-#define CIRRUS_THIRD (short*)0x7100
-#define CIRRUS_FOURTH (short*)0x7000
-#define PORTS_ON_CIRRUS 4
-#define CIRRUS_FIFO_SIZE 12
-#define SPACE 0x20
-#define TAB 0x09
-#define LINE_FEED 0x0a
-#define CARRIAGE_RETURN 0x0d
-#define BACKSPACE 0x08
-#define SPACES_IN_TABS 8
-#define SEND_ESCAPE 0x00
-#define START_BREAK 0x81
-#define TIMER_TICK 0x82
-#define STOP_BREAK 0x83
-#define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH)))
-#define txack1 ((short *)0x7104)
-#define rxack1 ((short *)0x7102)
-#define mdack1 ((short *)0x7106)
-#define txack2 ((short *)0x7006)
-#define rxack2 ((short *)0x7004)
-#define mdack2 ((short *)0x7100)
-#define int_latch ((short *) 0x7800)
-#define int_status ((short *) 0x7c00)
-#define tx1_pending 0x20
-#define rx1_pending 0x10
-#define md1_pending 0x40
-#define tx2_pending 0x02
-#define rx2_pending 0x01
-#define md2_pending 0x40
-#define module1_bits 0x07
-#define module1_modern 0x08
-#define module2_bits 0x70
-#define module2_modern 0x80
-#define module_blank 0xf
-#define rs232_d25 0x0
-#define rs232_rj45 0x1
-#define rs422_d25 0x3
-#define parallel 0x5
-
-#define CLK0 0x00
-#define CLK1 0x01
-#define CLK2 0x02
-#define CLK3 0x03
-#define CLK4 0x04
-
-#define CIRRUS_REVC 0x42
-#define CIRRUS_REVE 0x44
-
-#define TURNON 1
-#define TURNOFF 0
-
-/* The list of CIRRUS registers.
- NB. These registers are relative values on 8 bit boundaries whereas
- on the RTA's the CIRRUS registers are on word boundaries. Use pointer
- arithmetic (short *) to obtain the real addresses required */
-#define ccr 0x05 /* Channel Command Register */
-#define ier 0x06 /* Interrupt Enable Register */
-#define cor1 0x08 /* Channel Option Register 1 */
-#define cor2 0x09 /* Channel Option Register 2 */
-#define cor3 0x0a /* Channel Option Register 3 */
-#define cor4 0x1e /* Channel Option Register 4 */
-#define cor5 0x1f /* Channel Option Register 5 */
-
-#define ccsr 0x0b /* Channel Control Status Register */
-#define rdcr 0x0e /* Receive Data Count Register */
-#define tdcr 0x12 /* Transmit Data Count Register */
-#define mcor1 0x15 /* Modem Change Option Register 1 */
-#define mcor2 0x16 /* Modem Change Option Regsiter 2 */
-
-#define livr 0x18 /* Local Interrupt Vector Register */
-#define schr1 0x1a /* Special Character Register 1 */
-#define schr2 0x1b /* Special Character Register 2 */
-#define schr3 0x1c /* Special Character Register 3 */
-#define schr4 0x1d /* Special Character Register 4 */
-
-#define rtr 0x20 /* Receive Timer Register */
-#define rtpr 0x21 /* Receive Timeout Period Register */
-#define lnc 0x24 /* Lnext character */
-
-#define rivr 0x43 /* Receive Interrupt Vector Register */
-#define tivr 0x42 /* Transmit Interrupt Vector Register */
-#define mivr 0x41 /* Modem Interrupt Vector Register */
-#define gfrcr 0x40 /* Global Firmware Revision code Reg */
-#define ricr 0x44 /* Receive Interrupting Channel Reg */
-#define ticr 0x45 /* Transmit Interrupting Channel Reg */
-#define micr 0x46 /* Modem Interrupting Channel Register */
-
-#define gcr 0x4b /* Global configuration register */
-#define misr 0x4c /* Modem interrupt status register */
-
-#define rbusr 0x59
-#define tbusr 0x5a
-#define mbusr 0x5b
-
-#define eoir 0x60 /* End Of Interrupt Register */
-#define rdsr 0x62 /* Receive Data / Status Register */
-#define tdr 0x63 /* Transmit Data Register */
-#define svrr 0x67 /* Service Request Register */
-
-#define car 0x68 /* Channel Access Register */
-#define mir 0x69 /* Modem Interrupt Register */
-#define tir 0x6a /* Transmit Interrupt Register */
-#define rir 0x6b /* Receive Interrupt Register */
-#define msvr1 0x6c /* Modem Signal Value Register 1 */
-#define msvr2 0x6d /* Modem Signal Value Register 2 */
-#define psvr 0x6f /* Printer Signal Value Register */
-
-#define tbpr 0x72 /* Transmit Baud Rate Period Register */
-#define tcor 0x76 /* Transmit Clock Option Register */
-
-#define rbpr 0x78 /* Receive Baud Rate Period Register */
-#define rber 0x7a /* Receive Baud Rate Extension Register */
-#define rcor 0x7c /* Receive Clock Option Register */
-#define ppr 0x7e /* Prescalar Period Register */
-
-/* Misc registers used for forcing the 1400 out of its reset woes */
-#define airl 0x6d
-#define airm 0x6e
-#define airh 0x6f
-#define btcr 0x66
-#define mtcr 0x6c
-#define tber 0x74
-
-#endif /* #ifdef RTA */
/* Bit fields for particular registers */
diff --git a/drivers/char/rio/cmd.h b/drivers/char/rio/cmd.h
deleted file mode 100644
index 797b62400c9..00000000000
--- a/drivers/char/rio/cmd.h
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-/****************************************************************************
- ******* *******
- ******* C O M M A N D P A C K E T H E A D E R S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-
-#ifndef _cmd_h
-#define _cmd_h
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1";
-#endif
-#endif
-
-
-#define PRE_EMPTIVE_CMD 0x80
-#define INLINE_CMD ~PRE_EMPTIVE_CMD
-
-#define CMD_IGNORE_PKT ( (ushort) 0)
-#define CMD_STATUS_REQ ( (ushort) 1)
-#define CMD_UNIT_STATUS_REQ ( (ushort) 2) /* Is this needed ??? */
-#define CMD_CONF_PORT ( (ushort) 3)
-#define CMD_CONF_UNIT ( (ushort) 4)
-#define CMD_ROUTE_MAP_REQ ( (ushort) 5)
-#define CMD_FLUSH_TX ( (ushort) 6)
-#define CMD_FLUSH_RX ( (ushort) 7)
-#define CMD_PARTION_PORT ( (ushort) 8)
-#define CMD_RESET_PORT ( (ushort) 0x0a)
-#define CMD_BOOT_UNIT ( (ushort) 0x0b)
-#define CMD_FOUND_UNIT ( (ushort) 0x0c)
-#define CMD_ATTACHED_RTA_2 ( (ushort) 0x0d)
-#define CMD_PROVIDE_BOOT ( (ushort) 0x0e)
-#define CMD_CIRRUS ( (ushort) 0x0f)
-
-#define FORM_STATUS_PKT ( (ushort) 1 )
-#define FORM_POLL_PKT ( (ushort) 2 )
-#define FORM_LINK_STATUS_PKT ( (ushort) 3 )
-
-
-#define CMD_DATA_PORT ( (ushort) 1 )
-#define CMD_DATA ( (ushort) 2 )
-
-#define CMD_TX_PART ( (ushort) 2 )
-#define CMD_RX_PART ( (ushort) 3 )
-#define CMD_RX_LIMIT ( (ushort) 4 )
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/data.h b/drivers/char/rio/data.h
deleted file mode 100644
index dabc2d1fa40..00000000000
--- a/drivers/char/rio/data.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-** Module : data.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:09
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)data.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_datadex__
-#define __rio_datadex__
-
-#ifndef lint
-static char *_data_h_sccs_ = "@(#)data.h 1.2";
-#endif
-
-#endif
diff --git a/drivers/char/rio/debug.h b/drivers/char/rio/debug.h
deleted file mode 100644
index 6ae95c00db4..00000000000
--- a/drivers/char/rio/debug.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-** File: debug.h
-**
-** Author: David Dix
-**
-** Created: 12th March 1993
-**
-** Last modified: 93/04/27
-**
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _debug_h_
-#define _debug_h_
-
-
-#if defined(DCIRRUS)
-#define DBPACKET(pkt, opt, str, chn) debug_packet((pkt), (opt), (str), (chn))
-#else
-#define DBPACKET(pkt, opt, str, c)
-#endif /* DCIRRUS */
-
-
-#endif /* _debug_h_ */
diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h
index 5b600c32ac0..d55c2f6a987 100644
--- a/drivers/char/rio/defaults.h
+++ b/drivers/char/rio/defaults.h
@@ -45,13 +45,6 @@ static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1";
#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */
#define SECOND (int) 15625 /* Low priority ticks */
-#ifdef RTA
-#define RX_LIMIT (ushort) 3
-#endif
-#ifdef HOST
-#define RX_LIMIT (ushort) 1
-#endif
-
#define LINK_TIMEOUT (int) (POLL_PERIOD / 2)
diff --git a/drivers/char/rio/eisa.h b/drivers/char/rio/eisa.h
deleted file mode 100644
index c2abaf0eab0..00000000000
--- a/drivers/char/rio/eisa.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-** Module : eisa.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:10
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)eisa.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_eisa_h__
-#define __rio_eisa_h__
-
-#ifdef SCCS_LABELS
-#ifndef lint
-static char *_eisa_h_sccs_ = "@(#)eisa.h 1.2";
-#endif
-#endif
-
-/*
-** things to do with the EISA bus
-*/
-
-#define RIO_EISA_STRING_ADDRESS 0xfffd9 /* where EISA is stored */
-
-#define RIO_MAX_EISA_SLOTS 16 /* how many EISA slots? */
-
-#define RIO_EISA_IDENT 0x984D /* Specialix */
-#define RIO_EISA_PRODUCT_CODE 0x14 /* Code 14 */
-#define RIO_EISA_ENABLE_BIT 0x01 /* To enable card */
-
-#define EISA_MEMORY_BASE_LO 0xC00 /* A16-A23 */
-#define EISA_MEMORY_BASE_HI 0xC01 /* A24-A31 */
-#define EISA_INTERRUPT_VEC 0xC02 /* see below */
-#define EISA_CONTROL_PORT 0xC02 /* see below */
-#define EISA_INTERRUPT_RESET 0xC03 /* read to clear IRQ */
-
-#define EISA_PRODUCT_IDENT_LO 0xC80 /* where RIO_EISA_IDENT is */
-#define EISA_PRODUCT_IDENT_HI 0xC81
-#define EISA_PRODUCT_NUMBER 0xC82 /* where PROD_CODE is */
-#define EISA_REVISION_NUMBER 0xC83 /* revision (1dp) */
-#define EISA_ENABLE 0xC84 /* set LSB to enable card */
-#define EISA_UNIQUE_NUM_0 0xC88 /* vomit */
-#define EISA_UNIQUE_NUM_1 0xC8A
-#define EISA_UNIQUE_NUM_2 0xC90 /* bit strangely arranged */
-#define EISA_UNIQUE_NUM_3 0xC92
-#define EISA_MANUF_YEAR 0xC98 /* when */
-#define EISA_MANUF_WEEK 0xC9A /* more when */
-
-#define EISA_TP_BOOT_FROM_RAM 0x01
-#define EISA_TP_BOOT_FROM_LINK 0x00
-#define EISA_TP_FAST_LINKS 0x02
-#define EISA_TP_SLOW_LINKS 0x00
-#define EISA_TP_BUS_ENABLE 0x04
-#define EISA_TP_BUS_DISABLE 0x00
-#define EISA_TP_RUN 0x08
-#define EISA_TP_RESET 0x00
-#define EISA_POLLED 0x00
-#define EISA_IRQ_3 0x30
-#define EISA_IRQ_4 0x40
-#define EISA_IRQ_5 0x50
-#define EISA_IRQ_6 0x60
-#define EISA_IRQ_7 0x70
-#define EISA_IRQ_9 0x90
-#define EISA_IRQ_10 0xA0
-#define EISA_IRQ_11 0xB0
-#define EISA_IRQ_12 0xC0
-#define EISA_IRQ_14 0xE0
-#define EISA_IRQ_15 0xF0
-
-#define EISA_INTERRUPT_MASK 0xF0
-#define EISA_CONTROL_MASK 0x0F
-
-#define RIO_EISA_DEFAULT_MODE EISA_TP_SLOW_LINKS
-
-#define RIOEisaToIvec(X) (uchar )((uchar)((X) & EISA_INTERRUPT_MASK)>>4)
-
-#define INBZ(z,x) inb(((z)<<12) | (x))
-#define OUTBZ(z,x,y) outb((((z)<<12) | (x)), y)
-
-#endif /* __rio_eisa_h__ */
diff --git a/drivers/char/rio/enable.h b/drivers/char/rio/enable.h
deleted file mode 100644
index e06673fa48c..00000000000
--- a/drivers/char/rio/enable.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* E N A B L E H E A D E R S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_enable_h_sccs = "@(#)enable.h 1.1";
-#endif
-#endif
-
-
-#define ENABLE_LTT TRUE
-#define ENABLE_LRT TRUE
-
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/formpkt.h b/drivers/char/rio/formpkt.h
deleted file mode 100644
index 3c7c91ace3e..00000000000
--- a/drivers/char/rio/formpkt.h
+++ /dev/null
@@ -1,153 +0,0 @@
-
-
-/****************************************************************************
- ******* *******
- ******* F O R M P A C K E T H E A D E R F I L E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _formpkt_h
-#define _formpkt_h 1
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_formpkt_h_sccs = "@(#)formpkt.h 1.1";
-#endif
-#endif
-
-typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1;
-struct FORM_BOOT_PKT_1 {
- ushort pkt_number;
- ushort pkt_total;
- ushort boot_top;
-};
-
-typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2;
-struct FORM_BOOT_PKT_2 {
- ushort pkt_number;
- char boot_data[10];
-};
-
-
-typedef struct FORM_ATTACH_RTA FORM_ATTACH_RTA;
-struct FORM_ATTACH_RTA {
- char cmd_code;
- char booter_serial[4];
- char booter_link;
- char bootee_serial[4];
- char bootee_link;
-};
-
-
-typedef struct FORM_BOOT_ID FORM_BOOT_ID;
-struct FORM_BOOT_ID {
- char cmd_code;
- char bootee_serial[4];
- char bootee_prod_id;
- char bootee_link;
-};
-
-
-
-typedef struct FORM_ROUTE_1 FORM_ROUTE_1;
-struct FORM_ROUTE_1 {
- char cmd_code;
- char pkt_number;
- char total_in_sequence;
- char unit_id;
- char host_unit_id;
-};
-
-typedef struct FORM_ROUTE_2 FORM_ROUTE_2;
-struct FORM_ROUTE_2 {
- char cmd_code;
- char pkt_number;
- char total_in_sequence;
- char route_data[9];
-};
-
-typedef struct FORM_ROUTE_REQ FORM_ROUTE_REQ;
-struct FORM_ROUTE_REQ {
- char cmd_code;
- char pkt_number;
- char total_in_sequence;
- char route_data[10];
-};
-
-
-typedef struct FORM_ERROR FORM_ERROR;
-struct FORM_ERROR {
- char cmd_code;
- char error_code;
-
-};
-
-typedef struct FORM_STATUS FORM_STATUS;
-struct FORM_STATUS {
- char cmd_code;
- char status_code;
- char last_packet_valid;
- char tx_buffer;
- char rx_buffer;
- char port_status;
- char phb_status;
-};
-
-
-typedef struct FORM_LINK_STATUS FORM_LINK_STATUS;
-struct FORM_LINK_STATUS {
- char cmd_code;
- char status_code;
- char link_number;
- ushort rx_errors;
- ushort tx_errors;
- ushort csum_errors;
- ushort disconnects;
-};
-
-
-
-typedef struct FORM_PARTITION FORM_PARTITION;
-struct FORM_PARTITION {
- char cmd_code;
- char status_code;
- char port_number;
- char tx_max;
- char rx_max;
- char rx_limit;
-};
-
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/hosthw.h b/drivers/char/rio/hosthw.h
deleted file mode 100644
index 6281fe47f4e..00000000000
--- a/drivers/char/rio/hosthw.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* H O S T H A R D W A R E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_hosthw_h_sccs = "@(#)hosthw.h 1.2";
-#endif
-#endif
-
-#define SET_OTHER_INTERRUPT ( (volatile u_short *) 0x7c80 )
-#define SET_EISA_INTERRUPT ( (volatile u_short *) 0x7ef0 )
-
-#define EISA_HOST 0x30
-#define AT_HOST 0xa0
-#define MCA_HOST 0xb0
-#define PCI_HOST 0xd0
-
-#define PRODUCT_MASK 0xf0
-
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h
index bfba5b0c033..48d68ca7f82 100644
--- a/drivers/char/rio/link.h
+++ b/drivers/char/rio/link.h
@@ -102,30 +102,14 @@
/*
** LED stuff
*/
-#if defined(RTA)
-#define LED_OFF ((ushort) 0) /* LED off */
-#define LED_RED ((ushort) 1) /* LED Red */
-#define LED_GREEN ((ushort) 2) /* LED Green */
-#define LED_ORANGE ((ushort) 4) /* LED Orange */
-#define LED_1TO8_OPEN ((ushort) 1) /* Port 1->8 LED on */
-#define LED_9TO16_OPEN ((ushort) 2) /* Port 9->16 LED on */
-#define LED_SET_COLOUR(colour) (link->led = (colour))
-#define LED_OR_COLOUR(colour) (link->led |= (colour))
-#define LED_TIMEOUT(time) (link->led_timeout = RioTimePlus(RioTime(),(time)))
-#else
#define LED_SET_COLOUR(colour)
#define LED_OR_COLOUR(colour)
#define LED_TIMEOUT(time)
-#endif /* RTA */
struct LPB {
WORD link_number; /* Link Number */
Channel_ptr in_ch; /* Link In Channel */
Channel_ptr out_ch; /* Link Out Channel */
-#ifdef RTA
- uchar stat_led; /* Port open leds */
- uchar led; /* True, light led! */
-#endif
BYTE attached_serial[4]; /* Attached serial number */
BYTE attached_host_serial[4];
/* Serial number of Host who
@@ -144,30 +128,12 @@ struct LPB {
WORD WaitNoBoot; /* Secs to hold off booting */
PKT_ptr add_packet_list; /* Add packets to here */
PKT_ptr remove_packet_list; /* Send packets from here */
-#ifdef RTA
-#ifdef DCIRRUS
-#define QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1)
-#else
-#define QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1)
-#endif
- PKT_ptr_ptr rd_add; /* Add a new Packet here */
- Q_BUF_ptr rd_add_qb; /* Pointer to the add Q buf */
- PKT_ptr_ptr rd_add_st_qbb; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr rd_add_end_qbb; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr rd_remove; /* Remove a Packet here */
- Q_BUF_ptr rd_remove_qb; /* Pointer to the remove Q buf */
- PKT_ptr_ptr rd_remove_st_qbb; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr rd_remove_end_qbb; /* Pointer to the end of the Q buf */
- ushort pkts_in_q; /* Packets in queue */
-#endif
Channel_ptr lrt_fail_chan; /* Lrt's failure channel */
Channel_ptr ltt_fail_chan; /* Ltt's failure channel */
-#if defined (HOST) || defined (INKERNEL)
/* RUP structure for HOST to driver communications */
struct RUP rup;
-#endif
struct RUP link_rup; /* RUP for the link (POLL,
topology etc.) */
WORD attached_link; /* Number of attached link */
diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h
index 36aad4c9cb3..79b853140ae 100644
--- a/drivers/char/rio/list.h
+++ b/drivers/char/rio/list.h
@@ -44,8 +44,6 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9";
#define PKT_IN_USE 0x1
-#ifdef INKERNEL
-
#define ZERO_PTR (ushort) 0x8000
#define CaD PortP->Caddr
@@ -54,143 +52,5 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9";
** to by the TxAdd pointer has PKT_IN_USE clear in its address.
*/
-#ifndef linux
-#if defined( MIPS ) && !defined( MIPSEISA )
-/* May the shoes of the Devil dance on your grave for creating this */
-#define can_add_transmit(PacketP,PortP) \
- (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \
- & (PKT_IN_USE<<2)))
-
-#elif defined(MIPSEISA) || defined(nx6000) || \
- defined(drs6000) || defined(UWsparc)
-
-#define can_add_transmit(PacketP,PortP) \
- (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \
- & PKT_IN_USE))
-
-#else
-#define can_add_transmit(PacketP,PortP) \
- (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,*PortP->TxAdd)) \
- & PKT_IN_USE))
-#endif
-
-/*
-** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
-** and then move the TxAdd pointer along one position to point to the next
-** packet pointer. You must wrap the pointer from the end back to the start.
-*/
-#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
-# define add_transmit(PortP) \
- WINDW(PortP->TxAdd,RINDW(PortP->TxAdd) | PKT_IN_USE);\
- if (PortP->TxAdd == PortP->TxEnd)\
- PortP->TxAdd = PortP->TxStart;\
- else\
- PortP->TxAdd++;\
- WWORD(PortP->PhbP->tx_add , RIO_OFF(CaD,PortP->TxAdd));
-#elif defined(AIX)
-# define add_transmit(PortP) \
- {\
- register ushort *TxAddP = (ushort *)RIO_PTR(Cad,PortP->TxAddO);\
- WINDW( TxAddP, RINDW( TxAddP ) | PKT_IN_USE );\
- if (PortP->TxAddO == PortP->TxEndO )\
- PortP->TxAddO = PortP->TxStartO;\
- else\
- PortP->TxAddO += sizeof(ushort);\
- WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->tx_add , PortP->TxAddO );\
- }
-#else
-# define add_transmit(PortP) \
- *PortP->TxAdd |= PKT_IN_USE;\
- if (PortP->TxAdd == PortP->TxEnd)\
- PortP->TxAdd = PortP->TxStart;\
- else\
- PortP->TxAdd++;\
- PortP->PhbP->tx_add = RIO_OFF(CaD,PortP->TxAdd);
-#endif
-
-/*
-** can_remove_receive( PacketP, PortP ) returns non-zero if PKT_IN_USE is set
-** for the next packet on the queue. It will also set PacketP to point to the
-** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
-** then can_remove_receive() returns 0.
-*/
-#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
-# define can_remove_receive(PacketP,PortP) \
- ((RINDW(PortP->RxRemove) & PKT_IN_USE) ? \
- (PacketP=(struct PKT *)RIO_PTR(CaD,(RINDW(PortP->RxRemove) & ~PKT_IN_USE))):0)
-#elif defined(AIX)
-# define can_remove_receive(PacketP,PortP) \
- ((RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & PKT_IN_USE) ? \
- (PacketP=(struct PKT *)RIO_PTR(Cad,RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & ~PKT_IN_USE)):0)
-#else
-# define can_remove_receive(PacketP,PortP) \
- ((*PortP->RxRemove & PKT_IN_USE) ? \
- (PacketP=(struct PKT *)RIO_PTR(CaD,(*PortP->RxRemove & ~PKT_IN_USE))):0)
-#endif
-
-
-/*
-** Will God see it within his heart to forgive us for this thing that
-** we have created? To remove a packet from the receive queue you clear
-** its PKT_IN_USE bit, and then bump the pointers. Once the pointers
-** get to the end, they must be wrapped back to the start.
-*/
-#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
-# define remove_receive(PortP) \
- WINDW(PortP->RxRemove, (RINDW(PortP->RxRemove) & ~PKT_IN_USE));\
- if (PortP->RxRemove == PortP->RxEnd)\
- PortP->RxRemove = PortP->RxStart;\
- else\
- PortP->RxRemove++;\
- WWORD(PortP->PhbP->rx_remove , RIO_OFF(CaD,PortP->RxRemove));
-#elif defined(AIX)
-# define remove_receive(PortP) \
- {\
- register ushort *RxRemoveP = (ushort *)RIO_PTR(Cad,PortP->RxRemoveO);\
- WINDW( RxRemoveP, RINDW( RxRemoveP ) & ~PKT_IN_USE );\
- if (PortP->RxRemoveO == PortP->RxEndO)\
- PortP->RxRemoveO = PortP->RxStartO;\
- else\
- PortP->RxRemoveO += sizeof(ushort);\
- WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->rx_remove, PortP->RxRemoveO );\
- }
-#else
-# define remove_receive(PortP) \
- *PortP->RxRemove &= ~PKT_IN_USE;\
- if (PortP->RxRemove == PortP->RxEnd)\
- PortP->RxRemove = PortP->RxStart;\
- else\
- PortP->RxRemove++;\
- PortP->PhbP->rx_remove = RIO_OFF(CaD,PortP->RxRemove);
-#endif
-#endif
-
-
-#else /* !IN_KERNEL */
-
-#define ZERO_PTR NULL
-
-
-#ifdef HOST
-/* #define can_remove_transmit(pkt,phb) ((((char*)pkt = (*(char**)(phb->tx_remove))-1) || 1)) && (*phb->u3.s2.tx_remove_ptr & PKT_IN_USE)) */
-#define remove_transmit(phb) *phb->u3.s2.tx_remove_ptr &= ~(ushort)PKT_IN_USE;\
- if (phb->tx_remove == phb->tx_end)\
- phb->tx_remove = phb->tx_start;\
- else\
- phb->tx_remove++;
-#define can_add_receive(phb) !(*phb->u4.s2.rx_add_ptr & PKT_IN_USE)
-#define add_receive(pkt,phb) *phb->rx_add = pkt;\
- *phb->u4.s2.rx_add_ptr |= PKT_IN_USE;\
- if (phb->rx_add == phb->rx_end)\
- phb->rx_add = phb->rx_start;\
- else\
- phb->rx_add++;
-#endif
-#endif
-
-#ifdef RTA
-#define splx(oldspl) if ((oldspl) == 0) spl0()
-#endif
-
#endif /* ifndef _list.h */
/*********** end of file ***********/
diff --git a/drivers/char/rio/lrt.h b/drivers/char/rio/lrt.h
deleted file mode 100644
index b41764d7a22..00000000000
--- a/drivers/char/rio/lrt.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* L R T
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_lrt_h_sccs = "@(#)lrt.h 1.1";
-#endif
-#endif
-
-
-#ifdef DCIRRUS
-#define LRT_STACK (unsigned short) 600
-#else
-#define LRT_STACK (ushort) 200
-#endif
-
-
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/ltt.h b/drivers/char/rio/ltt.h
deleted file mode 100644
index ab04004d404..00000000000
--- a/drivers/char/rio/ltt.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* L T T
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_ltt_h_sccs = "@(#)ltt.h 1.1";
-#endif
-#endif
-
-#ifdef DCIRRUS
-#define LTT_STACK (unsigned short) 600
-#else
-#define LTT_STACK (ushort) 200
-#endif
-
-
-
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/lttwake.h b/drivers/char/rio/lttwake.h
deleted file mode 100644
index fdf0c1f250a..00000000000
--- a/drivers/char/rio/lttwake.h
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-/****************************************************************************
- ******* *******
- ******* L T T W A K E U P H E A D E R
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_lttwake_h_sccs = "@(#)lttwake.h 1.1";
-#endif
-#endif
-
-#define LTT_WAKEUP_STACK 500
-#define LTT_WAKEUP_INTERVAL (int) (500 * MILLISECOND)
-
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/mca.h b/drivers/char/rio/mca.h
deleted file mode 100644
index d01e76be7a1..00000000000
--- a/drivers/char/rio/mca.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-** Module : mca.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:11
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)mca.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_mca_h__
-#define __rio_mca_h__
-
-#ifdef SCCS_LABELS
-static char *_mca_h_sccs_ = "@(#)mca.h 1.2";
-#endif
-
-/*
-** Micro Channel stuff
-*/
-
-#define McaMaxSlots 8
-#define McaSlotSelect 0x96
-#define McaSlotEnable 0x08
-#define McaIdLow 0x100
-#define McaIdHigh 0x101
-#define McaIrqEnable 0x102
-#define McaMemory 0x103
-#define McaRIOId 0x6a5c
-#define McaIrq9 0x00
-#define McaIrq3 0x02
-#define McaIrq4 0x04
-#define McaIrq7 0x06
-#define McaIrq10 0x08
-#define McaIrq11 0x0A
-#define McaIrq12 0x0C
-#define McaIrq15 0x0E
-#define McaIrqMask 0x0E
-#define McaCardEnable 0x01
-#define McaAddress(X) (((X)&0xFF)<<16)
-
-#define McaTpFastLinks 0x40
-#define McaTpSlowLinks 0x00
-#define McaTpBootFromRam 0x01
-#define McaTpBootFromLink 0x00
-#define McaTpBusEnable 0x02
-#define McaTpBusDisable 0x00
-
-#define RIO_MCA_DEFAULT_MODE SLOW_LINKS
-
-#endif /* __rio_mca_h__ */
diff --git a/drivers/char/rio/mesg.h b/drivers/char/rio/mesg.h
deleted file mode 100644
index dd9be586ec6..00000000000
--- a/drivers/char/rio/mesg.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-** Module : mesg.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:12
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)mesg.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_mesg_h__
-#define __rio_mesg_h__
-
-#ifdef SCCS_LABELS
-static char *_mesg_h_sccs_ = "@(#)mesg.h 1.2";
-#endif
-
-
-#endif /* __rio_mesg_h__ */
diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h
index fe4e0056706..e24acc1d184 100644
--- a/drivers/char/rio/parmmap.h
+++ b/drivers/char/rio/parmmap.h
@@ -78,14 +78,9 @@ struct PARM_MAP {
WORD idle_count; /* Idle time counter */
WORD busy_count; /* Busy counter */
WORD idle_control; /* Control Idle Process */
-#if defined(HOST) || defined(INKERNEL)
WORD tx_intr; /* TX interrupt pending */
WORD rx_intr; /* RX interrupt pending */
WORD rup_intr; /* RUP interrupt pending */
-#endif
-#if defined(RTA)
- WORD dying_count; /* Count of processes dead */
-#endif
};
#endif
diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h
index 3baebf8513a..2663ca0306e 100644
--- a/drivers/char/rio/phb.h
+++ b/drivers/char/rio/phb.h
@@ -44,17 +44,6 @@
#endif
- /*************************************************
- * Set the LIMIT values.
- ************************************************/
-#ifdef RTA
-#define RX_LIMIT (ushort) 3
-#endif
-#ifdef HOST
-#define RX_LIMIT (ushort) 1
-#endif
-
-
/*************************************************
* Handshake asserted. Deasserted by the LTT(s)
************************************************/
@@ -69,11 +58,7 @@
/*************************************************
* Maximum number of PHB's
************************************************/
-#if defined (HOST) || defined (INKERNEL)
#define MAX_PHB ((ushort) 128) /* range 0-127 */
-#else
-#define MAX_PHB ((ushort) 8) /* range 0-7 */
-#endif
/*************************************************
* Defines for the mode fields
@@ -139,141 +124,23 @@
* the start. The pointer tx_add points to a SPACE to put a Packet.
* The pointer tx_remove points to the next Packet to remove
*************************************************************************/
-#ifndef INKERNEL
-#define src_unit u2.s2.unit
-#define src_port u2.s2.port
-#define dest_unit u1.s1.unit
-#define dest_port u1.s1.port
-#endif
-#ifdef HOST
-#define tx_start u3.s1.tx_start_ptr_ptr
-#define tx_add u3.s1.tx_add_ptr_ptr
-#define tx_end u3.s1.tx_end_ptr_ptr
-#define tx_remove u3.s1.tx_remove_ptr_ptr
-#define rx_start u4.s1.rx_start_ptr_ptr
-#define rx_add u4.s1.rx_add_ptr_ptr
-#define rx_end u4.s1.rx_end_ptr_ptr
-#define rx_remove u4.s1.rx_remove_ptr_ptr
-#endif
typedef struct PHB PHB;
struct PHB {
-#ifdef RTA
- ushort port;
-#endif
-#ifdef INKERNEL
WORD source;
-#else
- union {
- ushort source; /* Complete source */
- struct {
- unsigned char unit; /* Source unit */
- unsigned char port; /* Source port */
- } s2;
- } u2;
-#endif
WORD handshake;
WORD status;
NUMBER timeout; /* Maximum of 1.9 seconds */
WORD link; /* Send down this link */
-#ifdef INKERNEL
WORD destination;
-#else
- union {
- ushort destination; /* Complete destination */
- struct {
- unsigned char unit; /* Destination unit */
- unsigned char port; /* Destination port */
- } s1;
- } u1;
-#endif
-#ifdef RTA
- ushort tx_pkts_added;
- ushort tx_pkts_removed;
- Q_BUF_ptr tx_q_start; /* Start of the Q list chain */
- short num_tx_q_bufs; /* Number of Q buffers in the chain */
- PKT_ptr_ptr tx_add; /* Add a new Packet here */
- Q_BUF_ptr tx_add_qb; /* Pointer to the add Q buf */
- PKT_ptr_ptr tx_add_st_qbb; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr tx_add_end_qbb; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr tx_remove; /* Remove a Packet here */
- Q_BUF_ptr tx_remove_qb; /* Pointer to the remove Q buf */
- PKT_ptr_ptr tx_remove_st_qbb; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr tx_remove_end_qbb; /* Pointer to the end of the Q buf */
-#endif
-#ifdef INKERNEL
PKT_ptr_ptr tx_start;
PKT_ptr_ptr tx_end;
PKT_ptr_ptr tx_add;
PKT_ptr_ptr tx_remove;
-#endif
-#ifdef HOST
- union {
- struct {
- PKT_ptr_ptr tx_start_ptr_ptr;
- PKT_ptr_ptr tx_end_ptr_ptr;
- PKT_ptr_ptr tx_add_ptr_ptr;
- PKT_ptr_ptr tx_remove_ptr_ptr;
- } s1;
- struct {
- ushort *tx_start_ptr;
- ushort *tx_end_ptr;
- ushort *tx_add_ptr;
- ushort *tx_remove_ptr;
- } s2;
- } u3;
-#endif
-#ifdef RTA
- ushort rx_pkts_added;
- ushort rx_pkts_removed;
- Q_BUF_ptr rx_q_start; /* Start of the Q list chain */
- short num_rx_q_bufs; /* Number of Q buffers in the chain */
- PKT_ptr_ptr rx_add; /* Add a new Packet here */
- Q_BUF_ptr rx_add_qb; /* Pointer to the add Q buf */
- PKT_ptr_ptr rx_add_st_qbb; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr rx_add_end_qbb; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr rx_remove; /* Remove a Packet here */
- Q_BUF_ptr rx_remove_qb; /* Pointer to the remove Q buf */
- PKT_ptr_ptr rx_remove_st_qbb; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr rx_remove_end_qbb; /* Pointer to the end of the Q buf */
-#endif
-#ifdef INKERNEL
PKT_ptr_ptr rx_start;
PKT_ptr_ptr rx_end;
PKT_ptr_ptr rx_add;
PKT_ptr_ptr rx_remove;
-#endif
-#ifdef HOST
- union {
- struct {
- PKT_ptr_ptr rx_start_ptr_ptr;
- PKT_ptr_ptr rx_end_ptr_ptr;
- PKT_ptr_ptr rx_add_ptr_ptr;
- PKT_ptr_ptr rx_remove_ptr_ptr;
- } s1;
- struct {
- ushort *rx_start_ptr;
- ushort *rx_end_ptr;
- ushort *rx_add_ptr;
- ushort *rx_remove_ptr;
- } s2;
- } u4;
-#endif
-
-#ifdef RTA /* some fields for the remotes */
- ushort flush_count; /* Count of write flushes */
- ushort txmode; /* Modes for tx */
- ushort rxmode; /* Modes for rx */
- ushort portmode; /* Generic modes */
- ushort column; /* TAB3 column count */
- ushort tx_subscript; /* (TX) Subscript into data field */
- ushort rx_subscript; /* (RX) Subscript into data field */
- PKT_ptr rx_incomplete; /* Hold an incomplete packet here */
- ushort modem_bits; /* Modem bits to mask */
- ushort lastModem; /* Modem control lines. */
- ushort addr; /* Address for sub commands */
- ushort MonitorTstate; /* TRUE if monitoring tstop */
-#endif
};
diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h
index 882fd429ac2..7011e52e82d 100644
--- a/drivers/char/rio/pkt.h
+++ b/drivers/char/rio/pkt.h
@@ -70,39 +70,12 @@
#define CONTROL_DATA_WNDW (DATA_WNDW << 8)
struct PKT {
-#ifdef INKERNEL
BYTE dest_unit; /* Destination Unit Id */
BYTE dest_port; /* Destination POrt */
BYTE src_unit; /* Source Unit Id */
BYTE src_port; /* Source POrt */
-#else
- union {
- ushort destination; /* Complete destination */
- struct {
- unsigned char unit; /* Destination unit */
- unsigned char port; /* Destination port */
- } s1;
- } u1;
- union {
- ushort source; /* Complete source */
- struct {
- unsigned char unit; /* Source unit */
- unsigned char port; /* Source port */
- } s2;
- } u2;
-#endif
-#ifdef INKERNEL
BYTE len;
BYTE control;
-#else
- union {
- ushort control;
- struct {
- unsigned char len;
- unsigned char control;
- } s3;
- } u3;
-#endif
BYTE data[PKT_MAX_DATA_LEN];
/* Actual data :-) */
WORD csum; /* C-SUM */
diff --git a/drivers/char/rio/poll.h b/drivers/char/rio/poll.h
deleted file mode 100644
index 9616ee4c6cd..00000000000
--- a/drivers/char/rio/poll.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* P O L L
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _poll_h
-#define _poll_h
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_poll_h_sccs = "@(#)poll.h 1.2";
-#endif
-#endif
-
-
-#ifdef HOST
-#define POLL_STACK 100
-#endif
-#ifdef RTA
-#define POLL_STACK 200
-#endif
-
-#define POLL_PERIOD (int) SECOND
-
-/* The various poll commands */
-#define POLL_POLL 0 /* We are connected and happy.. */
-#define POLL_INTRO 1 /* Introduction packet */
-#define POLL_TOPOLOGY 2 /* Topology update */
-#define POLL_ASSIGN 3 /* ID assign */
-#define POLL_FOAD 4 /* F*** Off And Die */
-#define POLL_LMD 5 /* Let Me Die */
-#define POLL_DYB 6 /* Die You Ba***** */
-
-/* The way data fields are split up for POLL packets */
-#define POLL_HOST_SERIAL 2 /* Host who booted me */
-#define POLL_MY_SERIAL 6 /* My serial number */
-#define POLL_YOUR_ID 1 /* Your ID number */
-#define POLL_TOPOLOGY_FIELDS 2 /* Topology maps */
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/proto.h b/drivers/char/rio/proto.h
deleted file mode 100644
index f9a3376333e..00000000000
--- a/drivers/char/rio/proto.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef _prototypes_h
-#define _prototypes_h
-
-
-/*
-** boot.c
-*/
-void init_boot(char *p, short stage);
-
-/*
-** disconct.c
-*/
-void kill_boot(LPB * link);
-void disconnected(LPB * link);
-short boot_3(LPB * link, PKT * pkt);
-short send_3_pkt(LPB * link, PKT * pkt);
-
-/*
-** error.c
-*/
-void du_error(void);
-
-/*
-** formpkt.c
-*/
-ushort sum_it(PKT * pkt);
-void form_rup_pkt(RUP * form_rup, PKT * pkt);
-void form_poll_pkt(int type, LPB * link, int node);
-void form_route_pkt(int type, PKT * pkt, LPB * link);
-
-/*
-** idle.c
-*/
-void idle(Process * idle_p);
-
-/*
-** init.c
-*/
-void general_init(void);
-void mem_halt(int error);
-
-/*
-** linkinit.c
-*/
-void initlink(u_short number, LPB * link);
-void runlink(LPB * link);
-
-/*
-** list.c
-*/
-PKT *get_free_start(void);
-void put_free_start(PKT * pkt);
-
-#ifdef HOST
-int can_remove_transmit(PKT ** pkt, PKT * pointer);
-#endif
-
-#ifdef RTA
-int spl7(void);
-int spl0(void);
-Q_BUF *get_free_q(void);
-PKT *get_free_end(void);
-int add_end(PKT * pkt, PHB * phb, int type);
-unsigned short free_packets(PHB * phb, int type);
-int can_remove_start(PKT ** pkt, PHB * phb, int type);
-int can_add_start(PHB * phb, int type);
-int can_add_end(PHB * phb, int type);
-void put_free_end(PKT * pkt);
-int remove_start(PKT ** pkt, PHB * phb, int type);
-#endif
-
-/*
-** Lrt.c
-*/
-void lrt(Process * lrt_p, LPB * link);
-
-#ifdef RTA
-void set_led_red(LPB * link);
-#endif
-
-/*
-** ltt.c
-*/
-void ltt(Process * ltt_p, LPB * link, PHB * phb_ptr[]);
-void send_poll(LPB * link);
-void request_id(LPB * link);
-void send_topology_update(LPB * link);
-void send_topology(LPB * link);
-void supply_id(LPB * link);
-
-#ifdef RTA
-void redirect_queue(LPB * link, ushort flush);
-int obtain_rup(int rup_number, PKT ** pkt_address, LPB * link);
-#endif
-
-#ifdef TESTING_PERF
-int consume_cpu(void);
-#endif
-
-/*
-** lttwake.c
-*/
-#ifdef HOST
-void ltt_wakeup(Process * ltt_wakeup_p);
-#endif
-
-/*
-** mapgen.c
-*/
-void generate_id_map(short mapping, ROUTE_STR route[]);
-void gen_map(int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl);
-void adjust_ttl(int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl);
-void init_sys_map(void);
-
-/*
-** mmu.c
-*/
-char *rio_malloc(unsigned int amount);
-char *rio_calloc(unsigned int num, unsigned int size);
-ERROR rio_mmu_init(uint total_mem);
-
-/*
-** partn.c
-*/
-void partition_tx(struct PHB *phb, u_short tx_size, u_short rx_size, u_short rx_limit);
-
-/*
-** poll.c
-*/
-void tx_poll(Process * tx_poll_p);
-
-/*
-** process.c
-*/
-int get_proc_space(Process ** pd, int **pws, int wssize);
-
-/*
-** readrom.c
-*/
-void read_serial_number(char *buf);
-
-/*
-** rio.c
-*/
-int main(void);
-
-/*
-** route.c
-*/
-void route_update(PKT * pkt, LPB * link);
-
-/*
-** rtainit.c
-*/
-#if defined(RTA)
-void rta_init(ushort RtaType);
-#endif /* defined(RTA) */
-
-/*
-** rupboot.c
-*/
-void rup_boot(PKT * pkt, RUP * this_rup, LPB * link);
-
-#ifdef RTA
-void kill_your_neighbour(int link_to_kill);
-#endif
-
-/*
-** rupcmd.c
-*/
-void rup_command(PKT * pkt, struct RUP *this_rup, LPB * link);
-
-/*
-** ruperr.c
-*/
-void rup_error(PKT * pkt, RUP * this_rup, LPB * link);
-void illegal_cmd(PKT * src_pkt);
-
-/*
-** ruppoll.c
-*/
-void rup_poll(PKT * pkt, RUP * this_rup, LPB * link);
-
-/*
-** ruppower.c
-*/
-void rup_power(PKT * pkt, RUP * this_rup, LPB * link);
-
-/*
-** ruprm.c
-*/
-void rup_route_map(PKT * pkt, RUP * this_rup, LPB * link);
-
-/*
-** rupstat.c
-*/
-void rup_status(PKT * pkt, RUP * this_rup, LPB * link);
-
-/*
-** rupsync.c
-*/
-void rup_sync(PKT * pkt);
-
-/*
-** rxpkt.c
-*/
-ERROR rx_pkt(PKT_ptr_ptr pkt_address, LPB * link);
-
-/*
-** sendsts.c
-*/
-void send_status(PKT * requesting_pkt, RUP * this_rup);
-
-/*
-** serial.c
-*/
-void assign_serial(char *ser_in, char *ser_out);
-int cmp_serial(char *ser_1, char *ser_2);
-
-/*
-** txpkt.c
-*/
-ERROR tx_pkt(PKT * pkt, LPB * link);
-short send_sync(LPB * link);
-
-#endif /* _prototypes_h */
diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h
index acd9e8e5307..391ffc33553 100644
--- a/drivers/char/rio/qbuf.h
+++ b/drivers/char/rio/qbuf.h
@@ -46,11 +46,7 @@ static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1";
-#ifdef HOST
-#define PKTS_PER_BUFFER 1
-#else
#define PKTS_PER_BUFFER (220 / PKT_LENGTH)
-#endif
typedef struct Q_BUF Q_BUF;
struct Q_BUF {
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 8825bd61b7d..c9af283a811 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -132,16 +132,6 @@ more than 512 ports.... */
*/
#define IRQ_RATE_LIMIT 200
-#if 0
-/* Not implemented */
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#define RIO_REPORT_FIFO
-#define RIO_REPORT_OVERRUN
-#endif
-
/* These constants are derived from SCO Source */
static struct Conf
@@ -573,21 +563,6 @@ static void rio_shutdown_port(void *ptr)
PortP = (struct Port *) ptr;
PortP->gs.tty = NULL;
-#if 0
- port->gs.flags &= ~GS_ACTIVE;
- if (!port->gs.tty) {
- rio_dprintk(RIO_DBUG_TTY, "No tty.\n");
- return;
- }
- if (!port->gs.tty->termios) {
- rio_dprintk(RIO_DEBUG_TTY, "No termios.\n");
- return;
- }
- if (port->gs.tty->termios->c_cflag & HUPCL) {
- rio_setsignals(port, 0, 0);
- }
-#endif
-
func_exit();
}
@@ -663,11 +638,6 @@ static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd
rc = 0;
switch (cmd) {
-#if 0
- case TIOCGSOFTCAR:
- rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned int *) arg);
- break;
-#endif
case TIOCSSOFTCAR:
if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0);
@@ -709,36 +679,6 @@ static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd
if (access_ok(VERIFY_READ, (void *) arg, sizeof(struct serial_struct)))
rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
break;
-#if 0
- /*
- * note: these IOCTLs no longer reach here. Use
- * tiocmset/tiocmget driver methods instead. The
- * #if 0 disablement predates this comment.
- */
- case TIOCMGET:
- rc = -EFAULT;
- if (access_ok(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) {
- rc = 0;
- ival = rio_getsignals(port);
- put_user(ival, (unsigned int *) arg);
- }
- break;
- case TIOCMBIS:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), ((ival & TIOCM_RTS) ? 1 : -1));
- }
- break;
- case TIOCMBIC:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), ((ival & TIOCM_RTS) ? 0 : -1));
- }
- break;
- case TIOCMSET:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), ((ival & TIOCM_RTS) ? 1 : 0));
- }
- break;
-#endif
default:
rc = -ENOIOCTLCMD;
break;
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
index 34cbb13aad4..92df43552f1 100644
--- a/drivers/char/rio/rioboot.c
+++ b/drivers/char/rio/rioboot.c
@@ -665,13 +665,6 @@ struct PKT *PacketP;
struct CmdBlk *CmdBlkP;
uint sequence;
-#ifdef CHECK
- CheckHost(Host);
- CheckRup(Rup);
- CheckHostP(HostP);
- CheckPacketP(PacketP);
-#endif
-
/*
** If we haven't been told what to boot, we can't boot it.
*/
@@ -956,11 +949,6 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
MyType = "RTA";
MyName = HostP->Mapping[Rup].Name;
}
-#ifdef CHECK
- CheckString(MyType);
- CheckString(MyName);
-#endif
-
MyLink = RBYTE(PktCmdP->LinkNum);
/*
@@ -1309,52 +1297,3 @@ struct Host *HostP;
}
}
-#if 0
-/*
- Function: This function is to disable the disk interrupt
- Returns : Nothing
-*/
-void
-disable_interrupt(vector)
-int vector;
-{
- int ps;
- int val;
-
- disable(ps);
- if (vector > 40) {
- val = 1 << (vector - 40);
- __outb(S8259+1, __inb(S8259+1) | val);
- }
- else {
- val = 1 << (vector - 32);
- __outb(M8259+1, __inb(M8259+1) | val);
- }
- restore(ps);
-}
-
-/*
- Function: This function is to enable the disk interrupt
- Returns : Nothing
-*/
-void
-enable_interrupt(vector)
-int vector;
-{
- int ps;
- int val;
-
- disable(ps);
- if (vector > 40) {
- val = 1 << (vector - 40);
- val = ~val;
- __outb(S8259+1, __inb(S8259+1) & val);
- }
- else {
- val = 1 << (vector - 32);
- val = ~val;
- __outb(M8259+1, __inb(M8259+1) & val);
- }
- restore(ps);
-}
-#endif
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index b97dd9fdb6b..694bfb9d937 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -387,12 +387,6 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *
func_enter();
-#ifdef CHECK
- CheckHost(Host);
- CheckHostP(HostP);
- CheckPacketP(PacketP);
-#endif
-
/*
** 16 port RTA note:
** Command rup packets coming from the RTA will have pkt->data[1] (which
@@ -406,10 +400,6 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *
SysPort = UnixRupP->BaseSysPort + (RBYTE(PktCmdP->PhbNum) % (ushort) PORTS_PER_RTA);
rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
-#ifdef CHECK
- CheckRup(rup);
- CheckUnixRupP(UnixRupP);
-#endif
if (UnixRupP->BaseSysPort == NO_PORT) {
rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
@@ -429,9 +419,6 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *
rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command);
return TRUE;
}
-#ifdef CHECK
- CheckSysPort(SysPort);
-#endif
PortP = p->RIOPortp[SysPort];
rio_spin_lock_irqsave(&PortP->portSem, flags);
switch (RBYTE(PktCmdP->Command)) {
@@ -604,11 +591,6 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
struct UnixRup *UnixRupP;
unsigned long flags;
-#ifdef CHECK
- CheckHostP(HostP);
- CheckRup(Rup);
- CheckCmdBlkP(CmdBlkP);
-#endif
if (Rup >= (ushort) (MAX_RUP + LINKS_PER_UNIT)) {
rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup);
RIOFreeCmdBlk(CmdBlkP);
@@ -806,9 +788,6 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
** If it returns RIO_FAIL then don't
** send this command yet!
*/
-#ifdef CHECK
- CheckCmdBlkP(CmdBlkP);
-#endif
if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : TRUE)) {
rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command 0x%x\n", (int) CmdBlkP);
} else {
@@ -816,9 +795,6 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
/*
** Whammy! blat that pack!
*/
-#ifdef CHECK
- CheckPacketP((PKT *) RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt));
-#endif
HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
/*
@@ -852,9 +828,6 @@ int RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
unsigned long flags;
rio_spin_lock_irqsave(&PortP->portSem, flags);
-#ifdef CHECK
- CheckPortP(PortP);
-#endif
PortP->WflushFlag++;
PortP->MagicFlags |= MAGIC_FLUSH;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
@@ -894,9 +867,6 @@ int RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
rio_spin_lock_irqsave(&PortP->portSem, flags);
-#ifdef CHECK
- CheckPortP(PortP);
-#endif
rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n");
if (PortP->InUse) {
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
index 0b7700d2f04..fcf18a06122 100644
--- a/drivers/char/rio/rioctrl.c
+++ b/drivers/char/rio/rioctrl.c
@@ -308,12 +308,7 @@ int su;
}
case RIO_DEBUG_MEM:
-#ifdef DEBUG_MEM_SUPPORT
- RIO_DEBUG_CTRL, if (su)
- return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg);
- else
-#endif
- return -EPERM;
+ return -EPERM;
case RIO_ALL_MODEM:
rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
@@ -591,12 +586,7 @@ int su;
case RIO_GET_LOG:
rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
-#ifdef LOGGING
- RIOGetLog(arg);
- return 0;
-#else
return -EINVAL;
-#endif
case RIO_GET_MODTYPE:
if (copyin((int) arg, (caddr_t) & port, sizeof(uint)) == COPYFAIL) {
@@ -684,52 +674,6 @@ int su;
rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
for (loop = PortSetup.From; loop <= PortSetup.To; loop++) {
rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
-#if 0
- PortP = p->RIOPortp[loop];
- if (!PortP->TtyP)
- PortP->TtyP = &p->channel[loop];
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- if (PortSetup.IxAny)
- PortP->Config |= RIO_IXANY;
- else
- PortP->Config &= ~RIO_IXANY;
- if (PortSetup.IxOn)
- PortP->Config |= RIO_IXON;
- else
- PortP->Config &= ~RIO_IXON;
-
- /*
- ** If the port needs to wait for all a processes output
- ** to drain before closing then this flag will be set.
- */
- if (PortSetup.Drain) {
- PortP->Config |= RIO_WAITDRAIN;
- } else {
- PortP->Config &= ~RIO_WAITDRAIN;
- }
- /*
- ** Store settings if locking or unlocking port or if the
- ** port is not locked, when setting the store option.
- */
- if (PortP->Mapped && ((PortSetup.Lock && !PortP->Lock) || (!PortP->Lock && (PortSetup.Store && !PortP->Store)))) {
- PortP->StoredTty.iflag = PortP->TtyP->tm.c_iflag;
- PortP->StoredTty.oflag = PortP->TtyP->tm.c_oflag;
- PortP->StoredTty.cflag = PortP->TtyP->tm.c_cflag;
- PortP->StoredTty.lflag = PortP->TtyP->tm.c_lflag;
- PortP->StoredTty.line = PortP->TtyP->tm.c_line;
- bcopy(PortP->TtyP->tm.c_cc, PortP->StoredTty.cc, NCC + 5);
- }
- PortP->Lock = PortSetup.Lock;
- PortP->Store = PortSetup.Store;
- PortP->Xprint.XpCps = PortSetup.XpCps;
- bcopy(PortSetup.XpOn, PortP->Xprint.XpOn, MAX_XP_CTRL_LEN);
- bcopy(PortSetup.XpOff, PortP->Xprint.XpOff, MAX_XP_CTRL_LEN);
- PortP->Xprint.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
- PortP->Xprint.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
- PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn) + RIOStrlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-#endif
}
rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval);
@@ -801,12 +745,6 @@ int su;
rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
PortP = (p->RIOPortp[PortTty.port]);
-#if 0
- PortTty.Tty.tm.c_iflag = PortP->TtyP->tm.c_iflag;
- PortTty.Tty.tm.c_oflag = PortP->TtyP->tm.c_oflag;
- PortTty.Tty.tm.c_cflag = PortP->TtyP->tm.c_cflag;
- PortTty.Tty.tm.c_lflag = PortP->TtyP->tm.c_lflag;
-#endif
if (copyout((caddr_t) & PortTty, (int) arg, sizeof(struct PortTty)) == COPYFAIL) {
p->RIOError.Error = COPYOUT_FAILED;
return -EFAULT;
@@ -824,15 +762,6 @@ int su;
return -ENXIO;
}
PortP = (p->RIOPortp[PortTty.port]);
-#if 0
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->TtyP->tm.c_iflag = PortTty.Tty.tm.c_iflag;
- PortP->TtyP->tm.c_oflag = PortTty.Tty.tm.c_oflag;
- PortP->TtyP->tm.c_cflag = PortTty.Tty.tm.c_cflag;
- PortP->TtyP->tm.c_lflag = PortTty.Tty.tm.c_lflag;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-#endif
-
RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
return retval;
@@ -909,23 +838,6 @@ int su;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return retval;
-#ifdef DEBUG_SUPPORTED
- case RIO_READ_LEVELS:
- {
- int num;
- rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_LEVELS\n");
- for (num = 0; RIODbInf[num].Flag; num++);
- rio_dprintk(RIO_DEBUG_CTRL, "%d levels to copy\n", num);
- if (copyout((caddr_t) RIODbInf, (int) arg, sizeof(struct DbInf) * (num + 1)) == COPYFAIL) {
- rio_dprintk(RIO_DEBUG_CTRL, "ReadLevels Copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- rio_dprintk(RIO_DEBUG_CTRL, "%d levels to copied\n", num);
- return retval;
- }
-#endif
-
case RIO_READ_CONFIG:
rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
if (copyout((caddr_t) & p->RIOConf, (int) arg, sizeof(struct Conf)) == COPYFAIL) {
@@ -1084,30 +996,13 @@ int su;
(void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);
bzero((caddr_t) & p->RIOHosts[Host].Flags, ((int) &p->RIOHosts[Host].____end_marker____) - ((int) &p->RIOHosts[Host].Flags));
p->RIOHosts[Host].Flags = RC_WAITING;
-#if 0
- RIOSetupDataStructs(p);
-#endif
}
RIOFoadWakeup(p);
p->RIONumBootPkts = 0;
p->RIOBooting = 0;
-
-#ifdef RINGBUFFER_SUPPORT
- for (loop = 0; loop < RIO_PORTS; loop++)
- if (p->RIOPortp[loop]->TxRingBuffer)
- sysfree((void *) p->RIOPortp[loop]->TxRingBuffer, RIOBufferSize);
-#endif
-#if 0
- bzero((caddr_t) & p->RIOPortp[0], RIO_PORTS * sizeof(struct Port));
-#else
printk("HEEEEELP!\n");
-#endif
for (loop = 0; loop < RIO_PORTS; loop++) {
-#if 0
- p->RIOPortp[loop]->TtyP = &p->channel[loop];
-#endif
-
spin_lock_init(&p->RIOPortp[loop]->portSem);
p->RIOPortp[loop]->InUse = NOT_INUSE;
}
@@ -1653,10 +1548,6 @@ uchar Cmd;
ushort rup;
int port;
-#ifdef CHECK
- CheckPortP(PortP);
-#endif
-
if (PortP->State & RIO_DELETED) {
rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
return RIO_FAIL;
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index 898a126ae3e..0d44ef464e6 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -87,222 +87,8 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
int RIOPCIinit(struct rio_info *p, int Mode);
-#if 0
-static void RIOAllocateInterrupts(struct rio_info *);
-static int RIOReport(struct rio_info *);
-static void RIOStopInterrupts(struct rio_info *, int, int);
-#endif
-
static int RIOScrub(int, BYTE *, int);
-#if 0
-extern int rio_intr();
-
-/*
-** Init time code.
-*/
-void
-rioinit( p, info )
-struct rio_info * p;
-struct RioHostInfo * info;
-{
- /*
- ** Multi-Host card support - taking the easy way out - sorry !
- ** We allocate and set up the Host and Port structs when the
- ** driver is called to 'install' the first host.
- ** We check for this first 'call' by testing the RIOPortp pointer.
- */
- if ( !p->RIOPortp )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Allocating and setting up driver data structures\n");
-
- RIOAllocDataStructs(p); /* allocate host/port structs */
- RIOSetupDataStructs(p); /* setup topology structs */
- }
-
- RIOInitHosts( p, info ); /* hunt down the hardware */
-
- RIOAllocateInterrupts(p); /* allocate interrupts */
- RIOReport(p); /* show what we found */
-}
-
-/*
-** Initialise the Cards
-*/
-void
-RIOInitHosts(p, info)
-struct rio_info * p;
-struct RioHostInfo * info;
-{
-/*
-** 15.10.1998 ARG - ESIL 0762 part fix
-** If there is no ISA card definition - we always look for PCI cards.
-** As we currently only support one host card this lets an ISA card
-** definition take precedence over PLUG and PLAY.
-** No ISA card - we are PLUG and PLAY with PCI.
-*/
-
- /*
- ** Note - for PCI both these will be zero, that's okay because
- ** RIOPCIInit() fills them in if a card is found.
- */
- p->RIOHosts[p->RIONumHosts].Ivec = info->vector;
- p->RIOHosts[p->RIONumHosts].PaddrP = info->location;
-
- /*
- ** Check that we are able to accommodate another host
- */
- if ( p->RIONumHosts >= RIO_HOSTS )
- {
- p->RIOFailed++;
- return;
- }
-
- if ( info->bus & ISA_BUS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (ISA)\n", p->RIONumHosts);
- RIOISAinit(p, p->mode);
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (PCI)\n", p->RIONumHosts);
- RIOPCIinit(p, RIO_PCI_DEFAULT_MODE);
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Total hosts initialised so far : %d\n", p->RIONumHosts);
-
-
-#ifdef FUTURE_RELEASE
- if (p->bus & EISA_BUS)
- /* EISA card */
- RIOEISAinit(p, RIO_EISA_DEFAULT_MODE);
-
- if (p->bus & MCA_BUS)
- /* MCA card */
- RIOMCAinit(p, RIO_MCA_DEFAULT_MODE);
-#endif
-}
-
-/*
-** go through memory for an AT host that we pass in the device info
-** structure and initialise
-*/
-void
-RIOISAinit(p, mode)
-struct rio_info * p;
-int mode;
-{
-
- /* XXX Need to implement this. */
-#if 0
- p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
- (int (*)())rio_intr, (char*)p->RIONumHosts);
-
- rio_dprintk (RIO_DEBUG_INIT, "Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid );
-
- if (RIODoAT(p, p->RIOHosts[p->RIONumHosts].PaddrP, mode)) {
- return;
- }
- else {
- rio_dprintk (RIO_DEBUG_INIT, "RIODoAT failed\n");
- p->RIOFailed++;
- }
-#endif
-
-}
-
-/*
-** RIODoAT :
-**
-** Map in a boards physical address, check that the board is there,
-** test the board and if everything is okay assign the board an entry
-** in the Rio Hosts structure.
-*/
-int
-RIODoAT(p, Base, mode)
-struct rio_info * p;
-int Base;
-int mode;
-{
-#define FOUND 1
-#define NOT_FOUND 0
-
- caddr_t cardAddr;
-
- /*
- ** Check to see if we actually have a board at this physical address.
- */
- if ((cardAddr = RIOCheckForATCard(Base)) != 0) {
- /*
- ** Now test the board to see if it is working.
- */
- if (RIOBoardTest(Base, cardAddr, RIO_AT, 0) == RIO_SUCCESS) {
- /*
- ** Fill out a slot in the Rio host structure.
- */
- if (RIOAssignAT(p, Base, cardAddr, mode)) {
- return(FOUND);
- }
- }
- RIOMapout(Base, RIO_AT_MEM_SIZE, cardAddr);
- }
- return(NOT_FOUND);
-}
-
-caddr_t
-RIOCheckForATCard(Base)
-int Base;
-{
- int off;
- struct DpRam *cardp; /* (Points at the host) */
- caddr_t virtAddr;
- unsigned char RIOSigTab[24];
-/*
-** Table of values to search for as prom signature of a host card
-*/
- strcpy(RIOSigTab, "JBJGPGGHINSMJPJR");
-
- /*
- ** Hey! Yes, You reading this code! Yo, grab a load a this:
- **
- ** IF the card is using WORD MODE rather than BYTE MODE
- ** then it will occupy 128K of PHYSICAL memory area. So,
- ** you might think that the following Mapin is wrong. Well,
- ** it isn't, because the SECOND 64K of occupied space is an
- ** EXACT COPY of the FIRST 64K. (good?), so, we need only
- ** map it in in one 64K block.
- */
- if (RIOMapin(Base, RIO_AT_MEM_SIZE, &virtAddr) == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't map the board in!\n");
- return((caddr_t)0);
- }
-
- /*
- ** virtAddr points to the DP ram of the system.
- ** We now cast this to a pointer to a RIO Host,
- ** and have a rummage about in the PROM.
- */
- cardp = (struct DpRam *)virtAddr;
-
- for (off=0; RIOSigTab[off]; off++) {
- if ((RBYTE(cardp->DpSignature[off]) & 0xFF) != RIOSigTab[off]) {
- /*
- ** Signature mismatch - card not at this address
- */
- RIOMapout(Base, RIO_AT_MEM_SIZE, virtAddr);
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't match the signature 0x%x 0x%x!\n",
- (int)cardp, off);
- return((caddr_t)0);
- }
- }
-
- /*
- ** If we get here then we must have found a valid board so return
- ** its virtual address.
- */
- return(virtAddr);
-}
-#endif
/**
** RIOAssignAT :
@@ -367,667 +153,6 @@ int mode;
rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base);
return(1);
}
-#if 0
-#ifdef FUTURE_RELEASE
-int RIOMCAinit(int Mode)
-{
- uchar SlotNumber;
- caddr_t Caddr;
- uint Paddr;
- uint Ivec;
- int Handle;
- int ret = 0;
-
- /*
- ** Valid mode information for MCA cards
- ** is only FAST LINKS
- */
- Mode = (Mode & FAST_LINKS) ? McaTpFastLinks : McaTpSlowLinks;
- rio_dprintk (RIO_DEBUG_INIT, "RIOMCAinit(%d)\n",Mode);
-
-
- /*
- ** Check out each of the slots
- */
- for (SlotNumber = 0; SlotNumber < McaMaxSlots; SlotNumber++) {
- /*
- ** Enable the slot we want to talk to
- */
- outb( McaSlotSelect, SlotNumber | McaSlotEnable );
-
- /*
- ** Read the ID word from the slot
- */
- if (((inb(McaIdHigh)<< 8)|inb(McaIdLow)) == McaRIOId)
- {
- rio_dprintk (RIO_DEBUG_INIT, "Potential MCA card in slot %d\n", SlotNumber);
-
- /*
- ** Card appears to be a RIO MCA card!
- */
- RIOMachineType |= (1<<RIO_MCA);
-
- /*
- ** Just check we haven't found too many wonderful objects
- */
- if ( RIONumHosts >= RIO_HOSTS )
- {
- Rprintf(RIOMesgTooManyCards);
- return(ret);
- }
-
- /*
- ** McaIrqEnable contains the interrupt vector, and a card
- ** enable bit.
- */
- Ivec = inb(McaIrqEnable);
-
- rio_dprintk (RIO_DEBUG_INIT, "Ivec is %x\n", Ivec);
-
- switch ( Ivec & McaIrqMask )
- {
- case McaIrq9:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ9\n");
- break;
- case McaIrq3:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ3\n");
- break;
- case McaIrq4:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ4\n");
- break;
- case McaIrq7:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ7\n");
- break;
- case McaIrq10:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ10\n");
- break;
- case McaIrq11:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ11\n");
- break;
- case McaIrq12:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ12\n");
- break;
- case McaIrq15:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ15\n");
- break;
- }
-
- /*
- ** If the card enable bit isn't set, then set it!
- */
- if ((Ivec & McaCardEnable) != McaCardEnable) {
- rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable not set - setting!\n");
- outb(McaIrqEnable,Ivec|McaCardEnable);
- } else
- rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable already set\n");
-
- /*
- ** Convert the IRQ enable mask into something useful
- */
- Ivec = RIOMcaToIvec[Ivec & McaIrqMask];
-
- /*
- ** Find the physical address
- */
- rio_dprintk (RIO_DEBUG_INIT, "inb(McaMemory) is %x\n", inb(McaMemory));
- Paddr = McaAddress(inb(McaMemory));
-
- rio_dprintk (RIO_DEBUG_INIT, "MCA card has Ivec %d Addr %x\n", Ivec, Paddr);
-
- if ( Paddr != 0 )
- {
-
- /*
- ** Tell the memory mapper that we want to talk to it
- */
- Handle = RIOMapin( Paddr, RIO_MCA_MEM_SIZE, &Caddr );
-
- if ( Handle == -1 ) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE, Paddr;
- continue;
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr);
-
- /*
- ** And check that it is actually there!
- */
- if ( RIOBoardTest( Paddr,Caddr,RIO_MCA,SlotNumber ) == RIO_SUCCESS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
- SlotNumber, RIO_MCA, Paddr, Caddr, Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[RIONumHosts].Slot = SlotNumber;
- p->RIOHosts[RIONumHosts].Ivec = Ivec;
- p->RIOHosts[RIONumHosts].Type = RIO_MCA;
- p->RIOHosts[RIONumHosts].Copy = bcopy;
- p->RIOHosts[RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[RIONumHosts].Caddr = Caddr;
- p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[RIONumHosts].Mode = Mode;
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt , 0xff);
- p->RIOHosts[RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
- RIONumHosts++;
- ret++;
- }
- else
- {
- /*
- ** It failed the test, so ignore it.
- */
- rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n");
- RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr );
- }
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d - Paddr zero!\n", SlotNumber);
- }
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber);
- }
- }
- /*
- ** Now we have checked all the slots, turn off the MCA slot selector
- */
- outb(McaSlotSelect,0);
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber);
- return ret;
-}
-
-int RIOEISAinit( int Mode )
-{
- static int EISADone = 0;
- uint Paddr;
- int PollIntMixMsgDone = 0;
- caddr_t Caddr;
- ushort Ident;
- uchar EisaSlot;
- uchar Ivec;
- int ret = 0;
-
- /*
- ** The only valid mode information for EISA hosts is fast or slow
- ** links.
- */
- Mode = (Mode & FAST_LINKS) ? EISA_TP_FAST_LINKS : EISA_TP_SLOW_LINKS;
-
- if ( EISADone )
- {
- rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit() - already done, return.\n");
- return(0);
- }
-
- EISADone++;
-
- rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit()\n");
-
-
- /*
- ** First check all cards to see if ANY are set for polled mode operation.
- ** If so, set ALL to polled.
- */
-
- for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
- {
- Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
- INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
-
- if ( Ident == RIO_EISA_IDENT )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Found Specialix product\n");
-
- if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Not Specialix RIO - Product number %x\n",
- INBZ(EisaSlot, EISA_PRODUCT_NUMBER));
- continue; /* next slot */
- }
- /*
- ** Its a Specialix RIO!
- */
- rio_dprintk (RIO_DEBUG_INIT, "RIO Revision %d\n",
- INBZ(EisaSlot, EISA_REVISION_NUMBER));
-
- RIOMachineType |= (1<<RIO_EISA);
-
- /*
- ** Just check we haven't found too many wonderful objects
- */
- if ( RIONumHosts >= RIO_HOSTS )
- {
- Rprintf(RIOMesgTooManyCards);
- return 0;
- }
-
- /*
- ** Ensure that the enable bit is set!
- */
- OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
-
- /*
- ** EISA_INTERRUPT_VEC contains the interrupt vector.
- */
- Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
-
-#ifdef RIODEBUG
- switch ( Ivec & EISA_INTERRUPT_MASK )
- {
- case EISA_IRQ_3:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 3\n");
- break;
- case EISA_IRQ_4:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 4\n");
- break;
- case EISA_IRQ_5:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 5\n");
- break;
- case EISA_IRQ_6:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 6\n");
- break;
- case EISA_IRQ_7:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 7\n");
- break;
- case EISA_IRQ_9:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 9\n");
- break;
- case EISA_IRQ_10:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 10\n");
- break;
- case EISA_IRQ_11:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 11\n");
- break;
- case EISA_IRQ_12:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 12\n");
- break;
- case EISA_IRQ_14:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 14\n");
- break;
- case EISA_IRQ_15:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 15\n");
- break;
- case EISA_POLLED:
- rio_dprintk (RIO_DEBUG_INIT, "EISA POLLED\n");
- break;
- default:
- rio_dprintk (RIO_DEBUG_INIT, NULL,DBG_INIT|DBG_FAIL,"Shagged interrupt number!\n");
- Ivec &= EISA_CONTROL_MASK;
- }
-#endif
-
- if ( (Ivec & EISA_INTERRUPT_MASK) ==
- EISA_POLLED )
- {
- RIOWillPoll = 1;
- break; /* From EisaSlot loop */
- }
- }
- }
-
- /*
- ** Do it all again now we know whether to change all cards to polled
- ** mode or not
- */
-
- for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
- {
- Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
- INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
-
- if ( Ident == RIO_EISA_IDENT )
- {
- if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
- continue; /* next slot */
-
- /*
- ** Its a Specialix RIO!
- */
-
- /*
- ** Ensure that the enable bit is set!
- */
- OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
-
- /*
- ** EISA_INTERRUPT_VEC contains the interrupt vector.
- */
- Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
-
- if ( RIOWillPoll )
- {
- /*
- ** If we are going to operate in polled mode, but this
- ** board is configured to be interrupt driven, display
- ** the message explaining the situation to the punter,
- ** assuming we haven't already done so.
- */
-
- if ( !PollIntMixMsgDone &&
- (Ivec & EISA_INTERRUPT_MASK) != EISA_POLLED )
- {
- Rprintf(RIOMesgAllPolled);
- PollIntMixMsgDone = 1;
- }
-
- /*
- ** Ungraciously ignore whatever the board reports as its
- ** interrupt vector...
- */
-
- Ivec &= ~EISA_INTERRUPT_MASK;
-
- /*
- ** ...and force it to dance to the poll tune.
- */
-
- Ivec |= EISA_POLLED;
- }
-
- /*
- ** Convert the IRQ enable mask into something useful (0-15)
- */
- Ivec = RIOEisaToIvec(Ivec);
-
- rio_dprintk (RIO_DEBUG_INIT, "EISA host in slot %d has Ivec 0x%x\n",
- EisaSlot, Ivec);
-
- /*
- ** Find the physical address
- */
- Paddr = (INBZ(EisaSlot,EISA_MEMORY_BASE_HI)<<24) |
- (INBZ(EisaSlot,EISA_MEMORY_BASE_LO)<<16);
-
- rio_dprintk (RIO_DEBUG_INIT, "EISA card has Ivec %d Addr %x\n", Ivec, Paddr);
-
- if ( Paddr == 0 )
- {
- rio_dprintk (RIO_DEBUG_INIT,
- "Board in slot %d configured for address zero!\n", EisaSlot);
- continue;
- }
-
- /*
- ** Tell the memory mapper that we want to talk to it
- */
- rio_dprintk (RIO_DEBUG_INIT, "About to map EISA card \n");
-
- if (RIOMapin( Paddr, RIO_EISA_MEM_SIZE, &Caddr) == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n",
- RIO_EISA_MEM_SIZE,Paddr);
- continue;
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr);
-
- /*
- ** And check that it is actually there!
- */
- if ( RIOBoardTest( Paddr,Caddr,RIO_EISA,EisaSlot) == RIO_SUCCESS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT,
- "Slot %d. Ivec %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
- EisaSlot,Ivec,RIO_EISA,Paddr,Caddr,Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[RIONumHosts].Slot = EisaSlot;
- p->RIOHosts[RIONumHosts].Ivec = Ivec;
- p->RIOHosts[RIONumHosts].Type = RIO_EISA;
- p->RIOHosts[RIONumHosts].Copy = bcopy;
- p->RIOHosts[RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[RIONumHosts].Caddr = Caddr;
- p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[RIONumHosts].Mode = Mode;
- /*
- ** because the EISA prom is mapped into IO space, we
- ** need to copy the unqiue number into the memory area
- ** that it would have occupied, so that the download
- ** code can determine its ID and card type.
- */
- WBYTE(p->RIOHosts[RIONumHosts].Unique[0],INBZ(EisaSlot,EISA_UNIQUE_NUM_0));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[1],INBZ(EisaSlot,EISA_UNIQUE_NUM_1));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[2],INBZ(EisaSlot,EISA_UNIQUE_NUM_2));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[3],INBZ(EisaSlot,EISA_UNIQUE_NUM_3));
- p->RIOHosts[RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
- INBZ(EisaSlot,EISA_INTERRUPT_RESET);
- RIONumHosts++;
- ret++;
- }
- else
- {
- /*
- ** It failed the test, so ignore it.
- */
- rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n");
-
- RIOMapout(Paddr, RIO_EISA_MEM_SIZE, Caddr );
- }
- }
- }
- if (RIOMachineType & RIO_EISA)
- return ret+1;
- return ret;
-}
-#endif
-
-
-#ifndef linux
-
-#define CONFIG_ADDRESS 0xcf8
-#define CONFIG_DATA 0xcfc
-#define FORWARD_REG 0xcfa
-
-
-static int
-read_config(int bus_number, int device_num, int r_number)
-{
- unsigned int cav;
- unsigned int val;
-
-/*
- Build config_address_value:
-
- 31 24 23 16 15 11 10 8 7 0
- ------------------------------------------------------
- |1| 0000000 | bus_number | device # | 000 | register |
- ------------------------------------------------------
-*/
-
- cav = r_number & 0xff;
- cav |= ((device_num & 0x1f) << 11);
- cav |= ((bus_number & 0xff) << 16);
- cav |= 0x80000000; /* Enable bit */
- outpd(CONFIG_ADDRESS,cav);
- val = inpd(CONFIG_DATA);
- outpd(CONFIG_ADDRESS,0);
- return val;
-}
-
-static
-write_config(bus_number,device_num,r_number,val)
-{
- unsigned int cav;
-
-/*
- Build config_address_value:
-
- 31 24 23 16 15 11 10 8 7 0
- ------------------------------------------------------
- |1| 0000000 | bus_number | device # | 000 | register |
- ------------------------------------------------------
-*/
-
- cav = r_number & 0xff;
- cav |= ((device_num & 0x1f) << 11);
- cav |= ((bus_number & 0xff) << 16);
- cav |= 0x80000000; /* Enable bit */
- outpd(CONFIG_ADDRESS, cav);
- outpd(CONFIG_DATA, val);
- outpd(CONFIG_ADDRESS, 0);
- return val;
-}
-#else
-/* XXX Implement these... */
-static int
-read_config(int bus_number, int device_num, int r_number)
-{
- return 0;
-}
-
-static int
-write_config(int bus_number, int device_num, int r_number)
-{
- return 0;
-}
-
-#endif
-
-int
-RIOPCIinit(p, Mode)
-struct rio_info *p;
-int Mode;
-{
- #define MAX_PCI_SLOT 32
- #define RIO_PCI_JET_CARD 0x200011CB
-
- static int slot; /* count of machine's PCI slots searched so far */
- caddr_t Caddr; /* Virtual address of the current PCI host card. */
- unsigned char Ivec; /* interrupt vector for the current PCI host */
- unsigned long Paddr; /* Physical address for the current PCI host */
- int Handle; /* Handle to Virtual memory allocated for current PCI host */
-
-
- rio_dprintk (RIO_DEBUG_INIT, "Search for a RIO PCI card - start at slot %d\n", slot);
-
- /*
- ** Initialise the search status
- */
- p->RIOLastPCISearch = RIO_FAIL;
-
- while ( (slot < MAX_PCI_SLOT) & (p->RIOLastPCISearch != RIO_SUCCESS) )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Currently testing slot %d\n", slot);
-
- if (read_config(0,slot,0) == RIO_PCI_JET_CARD) {
- p->RIOHosts[p->RIONumHosts].Ivec = 0;
- Paddr = read_config(0,slot,0x18);
- Paddr = Paddr - (Paddr & 0x1); /* Mask off the io bit */
-
- if ( (Paddr == 0) || ((Paddr & 0xffff0000) == 0xffff0000) ) {
- rio_dprintk (RIO_DEBUG_INIT, "Goofed up slot\n"); /* what! */
- slot++;
- continue;
- }
-
- p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
- Ivec = (read_config(0,slot,0x3c) & 0xff);
-
- rio_dprintk (RIO_DEBUG_INIT, "PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec);
-
- Handle = RIOMapin( Paddr, RIO_PCI_MEM_SIZE, &Caddr );
- if (Handle == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr);
- slot++;
- continue;
- }
- p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32;
- p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
- (int (*)())rio_intr, (char *)p->RIONumHosts);
- if (RIOBoardTest( Paddr, Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) {
- rio_dprintk (RIO_DEBUG_INIT, ("Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[p->RIONumHosts].Slot = 0;
- p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32;
- p->RIOHosts[p->RIONumHosts].Type = RIO_PCI;
- p->RIOHosts[p->RIONumHosts].Copy = rio_pcicopy;
- p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[p->RIONumHosts].Caddr = Caddr;
- p->RIOHosts[p->RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[p->RIONumHosts].Mode = Mode;
-
-#if 0
- WBYTE(p->RIOHosts[p->RIONumHosts].Control,
- BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
- p->RIOHosts[p->RIONumHosts].Mode |
- INTERRUPT_DISABLE );
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
- WBYTE(p->RIOHosts[p->RIONumHosts].Control,
- BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
- p->RIOHosts[p->RIONumHosts].Mode |
- INTERRUPT_DISABLE );
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
-#else
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
-#endif
- p->RIOHosts[p->RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
-
- rio_dprintk (RIO_DEBUG_INIT, "Unique no 0x%x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
-
- p->RIOLastPCISearch = RIO_SUCCESS;
- p->RIONumHosts++;
- }
- }
- slot++;
- }
-
- if ( slot >= MAX_PCI_SLOT ) {
- rio_dprintk (RIO_DEBUG_INIT, "All %d PCI slots have tested for RIO cards !!!\n",
- MAX_PCI_SLOT);
- }
-
-
- /*
- ** I don't think we want to do this anymore
- **
-
- if (!p->RIOLastPCISearch == RIO_FAIL ) {
- p->RIOFailed++;
- }
-
- **
- */
-}
-
-#ifdef FUTURE_RELEASE
-void riohalt( void )
-{
- int host;
- for ( host=0; host<p->RIONumHosts; host++ )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Stop host %d\n", host);
- (void)RIOBoardTest( p->RIOHosts[host].PaddrP, p->RIOHosts[host].Caddr, p->RIOHosts[host].Type,p->RIOHosts[host].Slot );
- }
-}
-#endif
-#endif
static uchar val[] = {
#ifdef VERY_LONG_TEST
@@ -1262,200 +387,6 @@ int size;
return RIO_SUCCESS;
}
-/*
-** try to ensure that every host is either in polled mode
-** or is in interrupt mode. Only allow interrupt mode if
-** all hosts can interrupt (why?)
-** and force into polled mode if told to. Patch up the
-** interrupt vector & salute The Queen when you've done.
-*/
-#if 0
-static void
-RIOAllocateInterrupts(p)
-struct rio_info * p;
-{
- int Host;
-
- /*
- ** Easy case - if we have been told to poll, then we poll.
- */
- if (p->mode & POLLED_MODE) {
- RIOStopInterrupts(p, 0, 0);
- return;
- }
-
- /*
- ** check - if any host has been set to polled mode, then all must be.
- */
- for (Host=0; Host<p->RIONumHosts; Host++) {
- if ( (p->RIOHosts[Host].Type != RIO_AT) &&
- (p->RIOHosts[Host].Ivec == POLLED) ) {
- RIOStopInterrupts(p, 1, Host );
- return;
- }
- }
- for (Host=0; Host<p->RIONumHosts; Host++) {
- if (p->RIOHosts[Host].Type == RIO_AT) {
- if ( (p->RIOHosts[Host].Ivec - 32) == 0) {
- RIOStopInterrupts(p, 2, Host );
- return;
- }
- }
- }
-}
-
-/*
-** something has decided that we can't be doing with these
-** new-fangled interrupt thingies. Set everything up to just
-** poll.
-*/
-static void
-RIOStopInterrupts(p, Reason, Host)
-struct rio_info * p;
-int Reason;
-int Host;
-{
-#ifdef FUTURE_RELEASE
- switch (Reason) {
- case 0: /* forced into polling by rio_polled */
- break;
- case 1: /* SCU has set 'Host' into polled mode */
- break;
- case 2: /* there aren't enough interrupt vectors for 'Host' */
- break;
- }
-#endif
-
- for (Host=0; Host<p->RIONumHosts; Host++ ) {
- struct Host *HostP = &p->RIOHosts[Host];
-
- switch (HostP->Type) {
- case RIO_AT:
- /*
- ** The AT host has it's interrupts disabled by clearing the
- ** int_enable bit.
- */
- HostP->Mode &= ~INTERRUPT_ENABLE;
- HostP->Ivec = POLLED;
- break;
-#ifdef FUTURE_RELEASE
- case RIO_EISA:
- /*
- ** The EISA host has it's interrupts disabled by setting the
- ** Ivec to zero
- */
- HostP->Ivec = POLLED;
- break;
-#endif
- case RIO_PCI:
- /*
- ** The PCI host has it's interrupts disabled by clearing the
- ** int_enable bit, like a regular host card.
- */
- HostP->Mode &= ~RIO_PCI_INT_ENABLE;
- HostP->Ivec = POLLED;
- break;
-#ifdef FUTURE_RELEASE
- case RIO_MCA:
- /*
- ** There's always one, isn't there?
- ** The MCA host card cannot have it's interrupts disabled.
- */
- RIOPatchVec(HostP);
- break;
-#endif
- }
- }
-}
-
-/*
-** This function is called at init time to setup the data structures.
-*/
-void
-RIOAllocDataStructs(p)
-struct rio_info * p;
-{
- int port,
- host,
- tm;
-
- p->RIOPortp = (struct Port *)sysbrk(RIO_PORTS * sizeof(struct Port));
- if (!p->RIOPortp) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for port structures\n");
- p->RIOFailed++;
- return;
- }
- bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS );
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for port structs\n");
- rio_dprintk (RIO_DEBUG_INIT, "First RIO port struct @0x%x, size=0x%x bytes\n",
- (int)p->RIOPortp, sizeof(struct Port));
-
- for( port=0; port<RIO_PORTS; port++ ) {
- p->RIOPortp[port].PortNum = port;
- p->RIOPortp[port].TtyP = &p->channel[port];
- sreset (p->RIOPortp[port].InUse); /* Let the first guy uses it */
- p->RIOPortp[port].portSem = -1; /* Let the first guy takes it */
- p->RIOPortp[port].ParamSem = -1; /* Let the first guy takes it */
- p->RIOPortp[port].timeout_id = 0; /* Let the first guy takes it */
- }
-
- p->RIOHosts = (struct Host *)sysbrk(RIO_HOSTS * sizeof(struct Host));
- if (!p->RIOHosts) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for host structures\n");
- p->RIOFailed++;
- return;
- }
- bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS);
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for host structs\n");
- rio_dprintk (RIO_DEBUG_INIT, "First RIO host struct @0x%x, size=0x%x bytes\n",
- (int)p->RIOHosts, sizeof(struct Host));
-
- for( host=0; host<RIO_HOSTS; host++ ) {
- spin_lock_init (&p->RIOHosts[host].HostLock);
- p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */
- }
- /*
- ** check that the buffer size is valid, round down to the next power of
- ** two if necessary; if the result is zero, then, hey, no double buffers.
- */
- for ( tm = 1; tm && tm <= p->RIOConf.BufferSize; tm <<= 1 )
- ;
- tm >>= 1;
- p->RIOBufferSize = tm;
- p->RIOBufferMask = tm ? tm - 1 : 0;
-}
-
-/*
-** this function gets called whenever the data structures need to be
-** re-setup, for example, after a riohalt (why did I ever invent it?)
-*/
-void
-RIOSetupDataStructs(p)
-struct rio_info * p;
-{
- int host, entry, rup;
-
- for ( host=0; host<RIO_HOSTS; host++ ) {
- struct Host *HostP = &p->RIOHosts[host];
- for ( entry=0; entry<LINKS_PER_UNIT; entry++ ) {
- HostP->Topology[entry].Unit = ROUTE_DISCONNECT;
- HostP->Topology[entry].Link = NO_LINK;
- }
- bcopy("HOST X", HostP->Name, 7);
- HostP->Name[5] = '1'+host;
- for (rup=0; rup<(MAX_RUP + LINKS_PER_UNIT); rup++) {
- if (rup < MAX_RUP) {
- for (entry=0; entry<LINKS_PER_UNIT; entry++ ) {
- HostP->Mapping[rup].Topology[entry].Unit = ROUTE_DISCONNECT;
- HostP->Mapping[rup].Topology[entry].Link = NO_LINK;
- }
- RIODefaultName(p, HostP, rup);
- }
- spin_lock_init(&HostP->UnixRups[rup].RupLock);
- }
- }
-}
-#endif
int
RIODefaultName(p, HostP, UnitId)
@@ -1463,10 +394,6 @@ struct rio_info * p;
struct Host * HostP;
uint UnitId;
{
-#ifdef CHECK
- CheckHost( Host );
- CheckUnitId( UnitId );
-#endif
bcopy("UNKNOWN RTA X-XX",HostP->Mapping[UnitId].Name,17);
HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
if ((UnitId+1) > 9) {
@@ -1483,33 +410,6 @@ uint UnitId;
#define RIO_RELEASE "Linux"
#define RELEASE_ID "1.0"
-#if 0
-static int
-RIOReport(p)
-struct rio_info * p;
-{
- char * RIORelease = RIO_RELEASE;
- char * RIORelID = RELEASE_ID;
- int host;
-
- rio_dprintk (RIO_DEBUG_INIT, "RIO : Release: %s ID: %s\n", RIORelease, RIORelID);
-
- if ( p->RIONumHosts==0 ) {
- rio_dprintk (RIO_DEBUG_INIT, "\nNo Hosts configured\n");
- return(0);
- }
-
- for ( host=0; host < p->RIONumHosts; host++ ) {
- struct Host *HostP = &p->RIOHosts[host];
- switch ( HostP->Type ) {
- case RIO_AT:
- rio_dprintk (RIO_DEBUG_INIT, "AT BUS : found the card at 0x%x\n", HostP->PaddrP);
- }
- }
- return 0;
-}
-#endif
-
static struct rioVersion stVersion;
struct rioVersion *
@@ -1523,27 +423,6 @@ RIOVersid(void)
return &stVersion;
}
-#if 0
-int
-RIOMapin(paddr, size, vaddr)
-paddr_t paddr;
-int size;
-caddr_t * vaddr;
-{
- *vaddr = (caddr_t)permap( (long)paddr, size);
- return ((int)*vaddr);
-}
-
-void
-RIOMapout(paddr, size, vaddr)
-paddr_t paddr;
-long size;
-caddr_t vaddr;
-{
-}
-#endif
-
-
void
RIOHostReset(Type, DpRamP, Slot)
uint Type;
@@ -1570,31 +449,6 @@ uint Slot;
WBYTE(DpRamP->DpResetTpu, 0xFF);
udelay(3);
break;
-#ifdef FUTURE_RELEASE
- case RIO_EISA:
- /*
- ** Bet this doesn't work!
- */
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RUN | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RESET | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- suspend( 3 );
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RUN | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- break;
- case RIO_MCA:
- WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable );
- WBYTE(DpRamP->DpResetTpu , 0xFF );
- suspend( 3 );
- WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable );
- WBYTE(DpRamP->DpResetTpu , 0xFF );
- suspend( 3 );
- break;
-#endif
case RIO_PCI:
rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n");
DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM;
@@ -1604,12 +458,6 @@ uint Slot;
/* for (i=0; i<6000; i++); */
/* suspend( 3 ); */
break;
-#ifdef FUTURE_RELEASE
- default:
- Rprintf(RIOMesgNoSupport,Type,DpRamP,Slot);
- return;
-#endif
-
default:
rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n");
break;
diff --git a/drivers/char/rio/riolocks.h b/drivers/char/rio/riolocks.h
deleted file mode 100644
index 0e0cdacebe0..00000000000
--- a/drivers/char/rio/riolocks.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-** Module : riolocks.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:13
-** Retrieved : 11/6/98 11:34:22
-**
-** ident @(#)riolocks.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riolocks_h__
-#define __rio_riolocks_h__
-
-#ifdef SCCS_LABELS
-static char *_riolocks_h_sccs_ = "@(#)riolocks.h 1.2";
-#endif
-
-#define LOCKB(lk) lockb(lk);
-#define UNLOCKB(lk, oldspl) unlockb(lk, oldspl);
-
-#endif
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
index 4cc7f4942bf..c622f46d6d7 100644
--- a/drivers/char/rio/rioparam.c
+++ b/drivers/char/rio/rioparam.c
@@ -195,27 +195,6 @@ int SleepFlag;
** paramed with OPEN, we want to restore the saved port termio, but
** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
*/
-#if 0
- if (PortP->FirstOpen) {
- PortP->StoredTty.iflag = TtyP->tm.c_iflag;
- PortP->StoredTty.oflag = TtyP->tm.c_oflag;
- PortP->StoredTty.cflag = TtyP->tm.c_cflag;
- PortP->StoredTty.lflag = TtyP->tm.c_lflag;
- PortP->StoredTty.line = TtyP->tm.c_line;
- for (i = 0; i < NCC + 5; i++)
- PortP->StoredTty.cc[i] = TtyP->tm.c_cc[i];
- PortP->FirstOpen = 0;
- } else if (PortP->Store || PortP->Lock) {
- rio_dprintk(RIO_DEBUG_PARAM, "OPEN: Restoring stored/locked params\n");
- TtyP->tm.c_iflag = PortP->StoredTty.iflag;
- TtyP->tm.c_oflag = PortP->StoredTty.oflag;
- TtyP->tm.c_cflag = PortP->StoredTty.cflag;
- TtyP->tm.c_lflag = PortP->StoredTty.lflag;
- TtyP->tm.c_line = PortP->StoredTty.line;
- for (i = 0; i < NCC + 5; i++)
- TtyP->tm.c_cc[i] = PortP->StoredTty.cc[i];
- }
-#endif
}
/*
@@ -273,16 +252,6 @@ int SleepFlag;
phb_param_ptr = (struct phb_param *) PacketP->data;
-#if 0
- /*
- ** COR 1
- */
- if (TtyP->tm.c_iflag & INPCK) {
- rio_dprintk(RIO_DEBUG_PARAM, "Parity checking on input enabled\n");
- Cor1 |= COR1_INPCK;
- }
-#endif
-
switch (TtyP->termios->c_cflag & CSIZE) {
case CS5:
{
@@ -524,10 +493,6 @@ int SleepFlag;
if (TtyP->termios->c_cflag & XMT1EN)
rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
#endif
-#if 0
- if (TtyP->termios->c_cflag & LOBLK)
- rio_dprintk(RIO_DEBUG_PARAM, "LOBLK - JCL output blocks when not current\n");
-#endif
if (TtyP->termios->c_lflag & ISIG)
rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
if (TtyP->termios->c_lflag & ICANON)
@@ -572,14 +537,6 @@ int SleepFlag;
rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
if (TtyP->termios->c_oflag & TABDLY)
rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
-#if 0
- if (TtyP->termios->c_oflag & BSDLY)
- rio_dprintk(RIO_DEBUG_PARAM, "Back-space delay set\n");
- if (TtyP->termios->c_oflag & VTDLY)
- rio_dprintk(RIO_DEBUG_PARAM, "Vertical tab delay set\n");
- if (TtyP->termios->c_oflag & FFDLY)
- rio_dprintk(RIO_DEBUG_PARAM, "Form-feed delay set\n");
-#endif
/*
** These things are kind of useful in a later life!
*/
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
index 0f4cd33ba64..f98888f5265 100644
--- a/drivers/char/rio/rioroute.c
+++ b/drivers/char/rio/rioroute.c
@@ -112,15 +112,6 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP)
int Lies;
unsigned long flags;
-#ifdef STACK
- RIOStackCheck("RIORouteRup");
-#endif
-#ifdef CHECK
- CheckPacketP(PacketP);
- CheckHostP(HostP);
- CheckRup(Rup);
- CheckHost(Host);
-#endif
/*
** Is this unit telling us it's current link topology?
*/
@@ -540,9 +531,6 @@ uint unit;
for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
ushort dest_port = port + 8;
-#if 0
- uint PktInt;
-#endif
WORD *TxPktP;
PKT *Pkt;
@@ -623,10 +611,6 @@ uint UnitId;
unsigned long flags;
rio_spin_lock_irqsave(&HostP->HostLock, flags);
-#ifdef CHECK
- CheckHostP(HostP);
- CheckUnitId(UnitId);
-#endif
if (RIOCheck(HostP, UnitId)) {
rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
@@ -651,10 +635,6 @@ uint UnitId;
{
uint link, unit;
-#ifdef CHECK
- CheckHostP(HostP);
- CheckUnitId(UnitId);
-#endif
UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */
if (UnitId >= MAX_RUP) /* dontcha just lurv unsigned maths! */
@@ -684,10 +664,6 @@ uint UnitId;
{
unsigned char link;
-#ifdef CHECK
- CheckHostP(HostP);
- CheckUnitId(UnitId);
-#endif
/* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
index 42c3dffcbbb..a86b216ab65 100644
--- a/drivers/char/rio/riotable.c
+++ b/drivers/char/rio/riotable.c
@@ -754,11 +754,6 @@ struct Map *HostMapP;
ushort RtaType;
unsigned long flags;
-#ifdef CHECK
- CheckHostP(HostP);
- CheckHostMapP(HostMapP);
-#endif
-
rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);
/*
@@ -784,9 +779,6 @@ struct Map *HostMapP;
rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
PortP = p->RIOPortp[SysPort];
-#if 0
- PortP->TtyP = &p->channel[SysPort];
-#endif
rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");
/*
diff --git a/drivers/char/rio/riotime.h b/drivers/char/rio/riotime.h
deleted file mode 100644
index 35e01cd103d..00000000000
--- a/drivers/char/rio/riotime.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* T I M E
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
-
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _riotime_h
-#define _riotime_h 1
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_riotime_h_sccs = "@(#)riotime.h 1.1";
-#endif
-#endif
-
-#define TWO_POWER_FIFTEEN (ushort)32768
-#define RioTime() riotime
-#define RioTimeAfter(time1,time2) ((ushort)time1 - (ushort)time2) < TWO_POWER_FIFTEEN
-#define RioTimePlus(time1,time2) ((ushort)time1 + (ushort)time2)
-
-/**************************************
- * Convert a RIO tick (1/10th second)
- * into transputer low priority ticks
- *************************************/
-#define RioTimeToLow(time) (time*(100000 / 64))
-#define RioLowToTime(time) ((time*64)/100000)
-
-#define RIOTENTHSECOND (ushort)1
-#define RIOSECOND (ushort)(RIOTENTHSECOND * 10)
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index 5894a25b011..6379816ed17 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -89,16 +89,9 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3";
#include "list.h"
#include "sam.h"
-#if 0
-static void ttyseth_pv(struct Port *, struct ttystatics *, struct termios *sg, int);
-#endif
-
static void RIOClearUp(struct Port *PortP);
int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-#if 0
-static int RIOCookMode(struct ttystatics *);
-#endif
extern int conv_vb[]; /* now defined in ttymgr.c */
extern int conv_bv[]; /* now defined in ttymgr.c */
@@ -226,33 +219,6 @@ int riotopen(struct tty_struct *tty, struct file *filp)
** until the RTA is present then we must spin here waiting for
** the RTA to boot.
*/
-#if 0
- if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
- if (PortP->WaitUntilBooted) {
- rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot\n");
- do {
- if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
- func_exit();
- return -EINTR;
- }
- if (repeat_this-- <= 0) {
- rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE);
- pseterr(EINTR);
- func_exit();
- return -EIO;
- }
- } while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
- rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
- } else {
- rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
- pseterr(ENXIO);
- func_exit();
- return 0;
- }
- }
-#else
/* I find the above code a bit hairy. I find the below code
easier to read and shorter. Now, if it works too that would
be great... -- REW
@@ -281,21 +247,10 @@ int riotopen(struct tty_struct *tty, struct file *filp)
}
}
rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
-#endif
-#if 0
- tp = PortP->TtyP; /* get tty struct */
-#endif
rio_spin_lock_irqsave(&PortP->portSem, flags);
if (p->RIOHalted) {
goto bombout;
}
-#if 0
- retval = gs_init_port(&PortP->gs);
- if (retval) {
- func_exit();
- return retval;
- }
-#endif
/*
** If the port is in the final throws of being closed,
@@ -363,11 +318,6 @@ int riotopen(struct tty_struct *tty, struct file *filp)
command piggybacks the parameters immediately.
-- REW */
RIOParam(PortP, OPEN, Modem, OK_TO_SLEEP); /* Open the port */
-#if 0
- /* This delay of 1 second was annoying. I removed it. -- REW */
- RIODelay(PortP, HUNDRED_MS * 10);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); /* Config the port */
-#endif
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
@@ -439,9 +389,6 @@ int riotopen(struct tty_struct *tty, struct file *filp)
PortP->State |= RIO_WOPEN;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL)
-#if 0
- if (sleep((caddr_t) & tp->tm.c_canqo, TTIPRI | PCATCH))
-#endif
{
/*
** ACTION: verify that this is a good thing
@@ -505,10 +452,6 @@ int riotopen(struct tty_struct *tty, struct file *filp)
*/
int riotclose(void *ptr)
{
-#if 0
- register uint SysPort = dev;
- struct ttystatics *tp; /* pointer to our ttystruct */
-#endif
struct Port *PortP = ptr; /* pointer to the port structure */
int deleted = 0;
int try = -1; /* Disable the timeouts by setting them to -1 */
@@ -534,13 +477,6 @@ int riotclose(void *ptr)
end_time = jiffies + MAX_SCHEDULE_TIMEOUT;
Modem = rio_ismodem(tty);
-#if 0
- /* What F.CKING cache? Even then, a higly idle multiprocessor,
- system with large caches this won't work . Better find out when
- this doesn't work asap, and fix the cause. -- REW */
-
- RIODelay(PortP, HUNDRED_MS * 10); /* To flush the cache */
-#endif
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
@@ -703,45 +639,6 @@ int riotclose(void *ptr)
}
-/*
-** decide if we need to use the line discipline.
-** This routine can return one of three values:
-** COOK_RAW if no processing has to be done by the line discipline or the card
-** COOK_WELL if the line discipline must be used to do the processing
-** COOK_MEDIUM if the card can do all the processing necessary.
-*/
-#if 0
-static int RIOCookMode(struct ttystatics *tp)
-{
- /*
- ** We can't handle tm.c_mstate != 0 on SCO
- ** We can't handle mapping
- ** We can't handle non-ttwrite line disc.
- ** We can't handle lflag XCASE
- ** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3)
- */
-
-#ifdef CHECK
- CheckTtyP(tp);
-#endif
- if (!(tp->tm.c_oflag & OPOST)) /* No post processing */
- return COOK_RAW; /* Raw mode o/p */
-
- if (tp->tm.c_lflag & XCASE)
- return COOK_WELL; /* Use line disc */
-
- if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3))
- return COOK_WELL; /* Use line disc for strange modes */
-
- if (tp->tm.c_oflag == OPOST) /* If only OPOST is set, do RAW */
- return COOK_RAW;
-
- /*
- ** So, we need to output process!
- */
- return COOK_MEDIUM;
-}
-#endif
static void RIOClearUp(PortP)
struct Port *PortP;
@@ -776,11 +673,6 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len
unsigned long flags;
rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");
-#ifdef CHECK
- CheckPortP(PortP);
- if (len < 1 || len > 2)
- cprintf(("STUPID LENGTH %d\n", len));
-#endif
if (PortP->State & RIO_DELETED) {
rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
@@ -852,478 +744,3 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len
}
-#if 0
-/*
-** This is an ioctl interface. This is the twentieth century. You know what
-** its all about.
-*/
-int riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
-{
- register struct Port *PortP;
- register struct ttystatics *tp;
- int current;
- int ParamSemIncremented = 0;
- int old_oflag, old_cflag, old_iflag, changed, oldcook;
- int i;
- unsigned char sio_regs[5]; /* Here be magic */
- short vpix_cflag;
- short divisor;
- int baud;
- uint SysPort = rio_minor(tty);
- int Modem = rio_ismodem(tty);
- int ioctl_processed;
-
- rio_dprintk(RIO_DEBUG_TTY, "port ioctl SysPort %d command 0x%x argument 0x%x %s\n", SysPort, cmd, arg, Modem ? "Modem" : "tty");
-
- if (SysPort >= RIO_PORTS) {
- rio_dprintk(RIO_DEBUG_TTY, "Bad port number %d\n", SysPort);
- return -ENXIO;
- }
-
- PortP = p->RIOPortp[SysPort];
- tp = PortP->TtyP;
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-#ifdef STATS
- PortP->Stat.IoctlCnt++;
-#endif
-
- if (PortP->State & RIO_DELETED) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return -EIO;
- }
-
-
- if (p->RIOHalted) {
- RIOClearUp(PortP);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return -EIO;
- }
-
- /*
- ** Count ioctls for port statistics reporting
- */
- if (PortP->statsGather)
- PortP->ioctls++;
-
- /*
- ** Specialix RIO Ioctl calls
- */
- switch (cmd) {
-
- case TCRIOTRIAD:
- if (arg)
- PortP->State |= RIO_TRIAD_MODE;
- else
- PortP->State &= ~RIO_TRIAD_MODE;
- /*
- ** Normally, when istrip is set on a port, a config is
- ** sent to the RTA instructing the CD1400 to do the
- ** stripping. In TRIAD mode, the interrupt receive routine
- ** must do the stripping instead, since it has to detect
- ** an 8 bit function key sequence. If istrip is set with
- ** TRIAD mode on(off), and 8 bit data is being read by
- ** the port, the user then turns TRIAD mode off(on), the RTA
- ** must be reconfigured (not) to do the stripping.
- ** Hence we call RIOParam here.
- */
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- return 0;
-
- case TCRIOTSTATE:
- rio_dprintk(RIO_DEBUG_TTY, "tbusy/tstop monitoring %sabled\n", arg ? "en" : "dis");
- /* MonitorTstate = 0 ; */
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- return 0;
-
- case TCRIOSTATE: /* current state of Modem input pins */
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOSTATE\n");
- if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL)
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOSTATE command failed\n");
- PortP->State |= RIO_BUSY;
- current = PortP->ModemState;
- if (copyout((caddr_t) & current, (int) arg, sizeof(current)) == COPYFAIL) {
- rio_dprintk(RIO_DEBUG_TTY, "Copyout failed\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOMBIS: /* Set modem lines */
- case TCRIOMBIC: /* Clear modem lines */
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOMBIS/TCRIOMBIC\n");
- if (cmd == TCRIOMBIS) {
- uint state;
- state = (uint) arg;
- PortP->ModemState |= (ushort) state;
- PortP->ModemLines = (ulong) arg;
- if (RIOPreemptiveCmd(p, PortP, MBIS) == RIO_FAIL)
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOMBIS command failed\n");
- } else {
- uint state;
-
- state = (uint) arg;
- PortP->ModemState &= ~(ushort) state;
- PortP->ModemLines = (ulong) arg;
- if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL)
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOMBIC command failed\n");
- }
- PortP->State |= RIO_BUSY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPON: /* set Xprint ON string */
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOXPON\n");
- if (copyin((int) arg, (caddr_t) PortP->Xprint.XpOn, MAX_XP_CTRL_LEN) == COPYFAIL) {
- rio_dprintk(RIO_DEBUG_TTY, "Copyin failed\n");
- PortP->Xprint.XpOn[0] = '\0';
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- PortP->Xprint.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
- PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn) + strlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPOFF: /* set Xprint OFF string */
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOXPOFF\n");
- if (copyin((int) arg, (caddr_t) PortP->Xprint.XpOff, MAX_XP_CTRL_LEN) == COPYFAIL) {
- rio_dprintk(RIO_DEBUG_TTY, "Copyin failed\n");
- PortP->Xprint.XpOff[0] = '\0';
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- PortP->Xprint.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
- PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn) + strlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPCPS: /* set Xprint CPS string */
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOXPCPS\n");
- if ((uint) arg > p->RIOConf.MaxXpCps || (uint) arg < p->RIOConf.MinXpCps) {
- rio_dprintk(RIO_DEBUG_TTY, "%d CPS out of range\n", arg);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EINVAL);
- return 0;
- }
- PortP->Xprint.XpCps = (uint) arg;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPRINT:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOXPRINT\n");
- if (copyout((caddr_t) & PortP->Xprint, (int) arg, sizeof(struct Xprint)) == COPYFAIL) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXANYON:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXANYON\n");
- PortP->Config |= RIO_IXANY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXANYOFF:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXANYOFF\n");
- PortP->Config &= ~RIO_IXANY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXONON:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXONON\n");
- PortP->Config |= RIO_IXON;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXONOFF:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXONOFF\n");
- PortP->Config &= ~RIO_IXON;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** Added support for CTS and RTS flow control ioctls :
-*/
- case TCRIOCTSFLOWEN:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOCTSFLOWEN\n");
- PortP->Config |= RIO_CTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- return 0;
-
- case TCRIOCTSFLOWDIS:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIOCTSFLOWDIS\n");
- PortP->Config &= ~RIO_CTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- return 0;
-
- case TCRIORTSFLOWEN:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIORTSFLOWEN\n");
- PortP->Config |= RIO_RTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- return 0;
-
- case TCRIORTSFLOWDIS:
- rio_dprintk(RIO_DEBUG_TTY, "TCRIORTSFLOWDIS\n");
- PortP->Config &= ~RIO_RTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- return 0;
-
-/* end ESIL 0761 part fix */
-
- }
-
-
- /* Lynx IOCTLS */
- switch (cmd) {
- case TIOCSETP:
- case TIOCSETN:
- case OTIOCSETP:
- case OTIOCSETN:
- ioctl_processed++;
- ttyseth(PortP, tp, (struct old_sgttyb *) arg);
- break;
- case TCSETA:
- case TCSETAW:
- case TCSETAF:
- ioctl_processed++;
- rio_dprintk(RIO_DEBUG_TTY, "NON POSIX ioctl\n");
- ttyseth_pv(PortP, tp, (struct termios *) arg, 0);
- break;
- case TCSETAP: /* posix tcsetattr() */
- case TCSETAWP: /* posix tcsetattr() */
- case TCSETAFP: /* posix tcsetattr() */
- rio_dprintk(RIO_DEBUG_TTY, "NON POSIX SYSV ioctl\n");
- ttyseth_pv(PortP, tp, (struct termios *) arg, 1);
- ioctl_processed++;
- break;
- }
-
- /*
- ** If its any of the commands that require the port to be in the
- ** non-busy state wait until all output has drained
- */
- if (!ioctl_processed)
- switch (cmd) {
- case TCSETAW:
- case TCSETAF:
- case TCSETA:
- case TCSBRK:
-#define OLD_POSIX ('x' << 8)
-#define OLD_POSIX_SETA (OLD_POSIX | 2)
-#define OLD_POSIX_SETAW (OLD_POSIX | 3)
-#define OLD_POSIX_SETAF (OLD_POSIX | 4)
-#define NEW_POSIX (('i' << 24) | ('X' << 16))
-#define NEW_POSIX_SETA (NEW_POSIX | 2)
-#define NEW_POSIX_SETAW (NEW_POSIX | 3)
-#define NEW_POSIX_SETAF (NEW_POSIX | 4)
- case OLD_POSIX_SETA:
- case OLD_POSIX_SETAW:
- case OLD_POSIX_SETAF:
- case NEW_POSIX_SETA:
- case NEW_POSIX_SETAW:
- case NEW_POSIX_SETAF:
-#ifdef TIOCSETP
- case TIOCSETP:
-#endif
- case TIOCSETD:
- case TIOCSETN:
- rio_dprintk(RIO_DEBUG_TTY, "wait for non-BUSY, semaphore set\n");
- /*
- ** Wait for drain here, at least as far as the double buffer
- ** being empty.
- */
- /* XXX Does the above comment mean that this has
- still to be implemented? -- REW */
- /* XXX Is the locking OK together with locking
- in txenable? (Deadlock?) -- REW */
-
- RIOTxEnable((char *) PortP);
- break;
- default:
- break;
- }
-
- old_cflag = tp->tm.c_cflag;
- old_iflag = tp->tm.c_iflag;
- old_oflag = tp->tm.c_oflag;
- oldcook = PortP->CookMode;
-
- if (p->RIOHalted) {
- RIOClearUp(PortP);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EIO);
- return 0;
- }
-
- PortP->FlushCmdBodge = 0;
-
- /*
- ** If the port is locked, and it is reconfigured, we want
- ** to restore the state of the tty structure so the change is NOT
- ** made.
- */
- if (PortP->Lock) {
- tp->tm.c_iflag = PortP->StoredTty.iflag;
- tp->tm.c_oflag = PortP->StoredTty.oflag;
- tp->tm.c_cflag = PortP->StoredTty.cflag;
- tp->tm.c_lflag = PortP->StoredTty.lflag;
- tp->tm.c_line = PortP->StoredTty.line;
- for (i = 0; i < NCC + 1; i++)
- tp->tm.c_cc[i] = PortP->StoredTty.cc[i];
- } else {
- /*
- ** If the port is set to store the parameters, and it is
- ** reconfigured, we want to save the current tty struct so it
- ** may be restored on the next open.
- */
- if (PortP->Store) {
- PortP->StoredTty.iflag = tp->tm.c_iflag;
- PortP->StoredTty.oflag = tp->tm.c_oflag;
- PortP->StoredTty.cflag = tp->tm.c_cflag;
- PortP->StoredTty.lflag = tp->tm.c_lflag;
- PortP->StoredTty.line = tp->tm.c_line;
- for (i = 0; i < NCC + 1; i++)
- PortP->StoredTty.cc[i] = tp->tm.c_cc[i];
- }
- }
-
- changed = (tp->tm.c_cflag != old_cflag) || (tp->tm.c_iflag != old_iflag) || (tp->tm.c_oflag != old_oflag);
-
- PortP->CookMode = RIOCookMode(tp); /* Set new cooking mode */
-
- rio_dprintk(RIO_DEBUG_TTY, "RIOIoctl changed %d newcook %d oldcook %d\n", changed, PortP->CookMode, oldcook);
-
-#ifdef MODEM_SUPPORT
- /*
- ** kludge to force CARR_ON if CLOCAL set
- */
- if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {
- tp->tm.c_state |= CARR_ON;
- wakeup((caddr_t) & tp->tm.c_canq);
- }
-#endif
-
- if (p->RIOHalted) {
- RIOClearUp(PortP);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EIO);
- return 0;
- }
- /*
- ** Re-configure if modes or cooking have changed
- */
- if (changed || oldcook != PortP->CookMode || (ioctl_processed)) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk(RIO_DEBUG_TTY, "Ioctl changing the PORT settings\n");
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- }
-
- if (p->RIOHalted) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOClearUp(PortP);
- pseterr(EIO);
- return 0;
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-}
-
-/*
- ttyseth -- set hardware dependent tty settings
-*/
-void ttyseth(PortP, s, sg)
-struct Port *PortP;
-struct ttystatics *s;
-struct old_sgttyb *sg;
-{
- struct old_sgttyb *tsg;
- struct termios *tp = &s->tm;
-
- tsg = &s->sg;
-
- if (sg->sg_flags & (EVENP | ODDP)) {
- tp->c_cflag &= PARENB;
- if (sg->sg_flags & EVENP) {
- if (sg->sg_flags & ODDP) {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= ~PARENB;
- } else {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- tp->c_cflag &= PARODD;
- }
- } else if (sg->sg_flags & ODDP) {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- tp->c_cflag &= PARODD;
- } else {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- }
- }
-/*
- * Use ispeed as the desired speed. Most implementations don't handle
- * separate input and output speeds very well. If the RIO handles this,
- * I will have to use separate sets of flags to store them in the
- * Port structure.
- */
- if (!sg->sg_ospeed)
- sg->sg_ospeed = sg->sg_ispeed;
- else
- sg->sg_ispeed = sg->sg_ospeed;
- if (sg->sg_ispeed > V_EXTB)
- sg->sg_ispeed = V_EXTB;
- if (sg->sg_ispeed < V_B0)
- sg->sg_ispeed = V_B0;
- *tsg = *sg;
- tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int) sg->sg_ispeed];
-}
-
-/*
- ttyseth_pv -- set hardware dependent tty settings using either the
- POSIX termios structure or the System V termio structure.
- sysv = 0 => (POSIX): struct termios *sg
- sysv != 0 => (System V): struct termio *sg
-*/
-static void ttyseth_pv(PortP, s, sg, sysv)
-struct Port *PortP;
-struct ttystatics *s;
-struct termios *sg;
-int sysv;
-{
- int speed;
- unsigned char csize;
- unsigned char cread;
- unsigned int lcr_flags;
- int ps;
-
- if (sysv) {
- /* sg points to a System V termio structure */
- csize = ((struct termio *) sg)->c_cflag & CSIZE;
- cread = ((struct termio *) sg)->c_cflag & CREAD;
- speed = conv_vb[((struct termio *) sg)->c_cflag & V_CBAUD];
- } else {
- /* sg points to a POSIX termios structure */
- csize = sg->c_cflag & CSIZE;
- cread = sg->c_cflag & CREAD;
- speed = conv_vb[sg->c_cflag & V_CBAUD];
- }
- if (s->sg.sg_ispeed != speed || s->sg.sg_ospeed != speed) {
- s->sg.sg_ispeed = speed;
- s->sg.sg_ospeed = speed;
- s->tm.c_cflag = (s->tm.c_cflag & ~V_CBAUD) | conv_bv[(int) s->sg.sg_ispeed];
- }
-}
-#endif
diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h
index 9b67e2468be..46084d5c7e9 100644
--- a/drivers/char/rio/riotypes.h
+++ b/drivers/char/rio/riotypes.h
@@ -43,9 +43,6 @@
#endif
#endif
-#ifdef INKERNEL
-
-#if !defined(MIPSAT)
typedef unsigned short NUMBER_ptr;
typedef unsigned short WORD_ptr;
typedef unsigned short BYTE_ptr;
@@ -65,69 +62,6 @@ typedef unsigned short RUP_ptr;
typedef unsigned short short_ptr;
typedef unsigned short u_short_ptr;
typedef unsigned short ushort_ptr;
-#else
-/* MIPSAT types */
-typedef char RIO_POINTER[8];
-typedef RIO_POINTER NUMBER_ptr;
-typedef RIO_POINTER WORD_ptr;
-typedef RIO_POINTER BYTE_ptr;
-typedef RIO_POINTER char_ptr;
-typedef RIO_POINTER Channel_ptr;
-typedef RIO_POINTER FREE_LIST_ptr_ptr;
-typedef RIO_POINTER FREE_LIST_ptr;
-typedef RIO_POINTER LPB_ptr;
-typedef RIO_POINTER Process_ptr;
-typedef RIO_POINTER PHB_ptr;
-typedef RIO_POINTER PKT_ptr;
-typedef RIO_POINTER PKT_ptr_ptr;
-typedef RIO_POINTER Q_BUF_ptr;
-typedef RIO_POINTER Q_BUF_ptr_ptr;
-typedef RIO_POINTER ROUTE_STR_ptr;
-typedef RIO_POINTER RUP_ptr;
-typedef RIO_POINTER short_ptr;
-typedef RIO_POINTER u_short_ptr;
-typedef RIO_POINTER ushort_ptr;
-#endif
-
-#else /* not INKERNEL */
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned long DWORD;
-typedef short NUMBER;
-typedef short *NUMBER_ptr;
-typedef unsigned short *WORD_ptr;
-typedef unsigned char *BYTE_ptr;
-typedef unsigned char uchar;
-typedef unsigned short ushort;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-typedef unsigned char u_char;
-typedef unsigned short u_short;
-typedef unsigned int u_int;
-typedef unsigned long u_long;
-typedef unsigned short ERROR;
-typedef unsigned long ID;
-typedef char *char_ptr;
-typedef Channel *Channel_ptr;
-typedef struct FREE_LIST *FREE_LIST_ptr;
-typedef struct FREE_LIST **FREE_LIST_ptr_ptr;
-typedef struct LPB *LPB_ptr;
-typedef struct Process *Process_ptr;
-typedef struct PHB *PHB_ptr;
-typedef struct PKT *PKT_ptr;
-typedef struct PKT **PKT_ptr_ptr;
-typedef struct Q_BUF *Q_BUF_ptr;
-typedef struct Q_BUF **Q_BUF_ptr_ptr;
-typedef struct ROUTE_STR *ROUTE_STR_ptr;
-typedef struct RUP *RUP_ptr;
-typedef short *short_ptr;
-typedef u_short *u_short_ptr;
-typedef ushort *ushort_ptr;
-typedef struct PKT PKT;
-typedef struct LPB LPB;
-typedef struct RUP RUP;
-#endif
-
#endif /* __riotypes__ */
diff --git a/drivers/char/rio/riowinif.h b/drivers/char/rio/riowinif.h
deleted file mode 100644
index f802d7593b8..00000000000
--- a/drivers/char/rio/riowinif.h
+++ /dev/null
@@ -1,1329 +0,0 @@
-/************************************************************************/
-/* */
-/* Title : RIO Shared Memory Window Inteface */
-/* */
-/* Author : N.P.Vassallo */
-/* */
-/* Creation : 7th June 1999 */
-/* */
-/* Version : 1.0.0 */
-/* */
-/* Copyright : (c) Specialix International Ltd. 1999 *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * */
-/* Description : Prototypes, structures and definitions */
-/* describing RIO host card shared memory */
-/* window interface structures: */
-/* PARMMAP */
-/* RUP */
-/* PHB */
-/* LPB */
-/* PKT */
-/* */
-/************************************************************************/
-
-/* History...
-
-1.0.0 07/06/99 NPV Creation. (based on PARMMAP.H)
-
-*/
-
-#ifndef _riowinif_h /* If RIOWINDIF.H not already defined */
-#define _riowinif_h 1
-
-/*****************************************************************************
-******************************** *********************************
-******************************** General *********************************
-******************************** *********************************
-*****************************************************************************/
-
-#define TPNULL ((_u16)(0x8000))
-
-/*****************************************************************************
-******************************** ********************************
-******************************** PARM_MAP ********************************
-******************************** ********************************
-*****************************************************************************/
-
-/* The PARM_MAP structure defines global values relating to the Host Card / RTA
- and is the main structure from which all other structures are referenced. */
-
-typedef struct _PARM_MAP {
- _u16 phb_ptr; /* 0x00 Pointer to the PHB array */
- _u16 phb_num_ptr; /* 0x02 Ptr to Number of PHB's */
- _u16 free_list; /* 0x04 Free List pointer */
- _u16 free_list_end; /* 0x06 Free List End pointer */
- _u16 q_free_list_ptr; /* 0x08 Ptr to Q_BUF variable */
- _u16 unit_id_ptr; /* 0x0A Unit Id */
- _u16 link_str_ptr; /* 0x0C Link Structure Array */
- _u16 bootloader_1; /* 0x0E 1st Stage Boot Loader */
- _u16 bootloader_2; /* 0x10 2nd Stage Boot Loader */
- _u16 port_route_map_ptr; /* 0x12 Port Route Map */
- _u16 route_ptr; /* 0x14 Route Map */
- _u16 map_present; /* 0x16 Route Map present */
- _u16 pkt_num; /* 0x18 Total number of packets */
- _u16 q_num; /* 0x1A Total number of Q packets */
- _u16 buffers_per_port; /* 0x1C Number of buffers per port */
- _u16 heap_size; /* 0x1E Initial size of heap */
- _u16 heap_left; /* 0x20 Current Heap left */
- _u16 error; /* 0x22 Error code */
- _u16 tx_max; /* 0x24 Max number of tx pkts per phb */
- _u16 rx_max; /* 0x26 Max number of rx pkts per phb */
- _u16 rx_limit; /* 0x28 For high / low watermarks */
- _u16 links; /* 0x2A Links to use */
- _u16 timer; /* 0x2C Interrupts per second */
- _u16 rups; /* 0x2E Pointer to the RUPs */
- _u16 max_phb; /* 0x30 Mostly for debugging */
- _u16 living; /* 0x32 Just increments!! */
- _u16 init_done; /* 0x34 Initialisation over */
- _u16 booting_link; /* 0x36 */
- _u16 idle_count; /* 0x38 Idle time counter */
- _u16 busy_count; /* 0x3A Busy counter */
- _u16 idle_control; /* 0x3C Control Idle Process */
- _u16 tx_intr; /* 0x3E TX interrupt pending */
- _u16 rx_intr; /* 0x40 RX interrupt pending */
- _u16 rup_intr; /* 0x42 RUP interrupt pending */
-
-} PARM_MAP;
-
-/* Same thing again, but defined as offsets... */
-
-#define PM_phb_ptr 0x00 /* 0x00 Pointer to the PHB array */
-#define PM_phb_num_ptr 0x02 /* 0x02 Ptr to Number of PHB's */
-#define PM_free_list 0x04 /* 0x04 Free List pointer */
-#define PM_free_list_end 0x06 /* 0x06 Free List End pointer */
-#define PM_q_free_list_ptr 0x08 /* 0x08 Ptr to Q_BUF variable */
-#define PM_unit_id_ptr 0x0A /* 0x0A Unit Id */
-#define PM_link_str_ptr 0x0C /* 0x0C Link Structure Array */
-#define PM_bootloader_1 0x0E /* 0x0E 1st Stage Boot Loader */
-#define PM_bootloader_2 0x10 /* 0x10 2nd Stage Boot Loader */
-#define PM_port_route_map_ptr 0x12 /* 0x12 Port Route Map */
-#define PM_route_ptr 0x14 /* 0x14 Route Map */
-#define PM_map_present 0x16 /* 0x16 Route Map present */
-#define PM_pkt_num 0x18 /* 0x18 Total number of packets */
-#define PM_q_num 0x1A /* 0x1A Total number of Q packets */
-#define PM_buffers_per_port 0x1C /* 0x1C Number of buffers per port */
-#define PM_heap_size 0x1E /* 0x1E Initial size of heap */
-#define PM_heap_left 0x20 /* 0x20 Current Heap left */
-#define PM_error 0x22 /* 0x22 Error code */
-#define PM_tx_max 0x24 /* 0x24 Max number of tx pkts per phb */
-#define PM_rx_max 0x26 /* 0x26 Max number of rx pkts per phb */
-#define PM_rx_limit 0x28 /* 0x28 For high / low watermarks */
-#define PM_links 0x2A /* 0x2A Links to use */
-#define PM_timer 0x2C /* 0x2C Interrupts per second */
-#define PM_rups 0x2E /* 0x2E Pointer to the RUPs */
-#define PM_max_phb 0x30 /* 0x30 Mostly for debugging */
-#define PM_living 0x32 /* 0x32 Just increments!! */
-#define PM_init_done 0x34 /* 0x34 Initialisation over */
-#define PM_booting_link 0x36 /* 0x36 */
-#define PM_idle_count 0x38 /* 0x38 Idle time counter */
-#define PM_busy_count 0x3A /* 0x3A Busy counter */
-#define PM_idle_control 0x3C /* 0x3C Control Idle Process */
-#define PM_tx_intr 0x3E /* 0x4E TX interrupt pending */
-#define PM_rx_intr 0x40 /* 0x40 RX interrupt pending */
-#define PM_rup_intr 0x42 /* 0x42 RUP interrupt pending */
-#define sizeof_PARM_MAP 0x44 /* structure size = 0x44 */
-
-/* PARM_MAP.error definitions... */
-#define E_NO_ERROR 0x00
-#define E_PROCESS_NOT_INIT 0x01
-#define E_LINK_TIMEOUT 0x02
-#define E_NO_ROUTE 0x03
-#define E_CONFUSED 0x04
-#define E_HOME 0x05
-#define E_CSUM_FAIL 0x06
-#define E_DISCONNECTED 0x07
-#define E_BAD_RUP 0x08
-#define E_NO_VIRGIN 0x09
-#define E_BOOT_RUP_BUSY 0x10
-#define E_CHANALLOC 0x80
-#define E_POLL_ALLOC 0x81
-#define E_LTTWAKE 0x82
-#define E_LTT_ALLOC 0x83
-#define E_LRT_ALLOC 0x84
-#define E_CIRRUS 0x85
-#define E_MONITOR 0x86
-#define E_PHB_ALLOC 0x87
-#define E_ARRAY_ALLOC 0x88
-#define E_QBUF_ALLOC 0x89
-#define E_PKT_ALLOC 0x8a
-#define E_GET_TX_Q_BUF 0x8b
-#define E_GET_RX_Q_BUF 0x8c
-#define E_MEM_OUT 0x8d
-#define E_MMU_INIT 0x8e
-#define E_LTT_INIT 0x8f
-#define E_LRT_INIT 0x90
-#define E_LINK_RUN 0x91
-#define E_MONITOR_ALLOC 0x92
-#define E_MONITOR_INIT 0x93
-#define E_POLL_INIT 0x94
-
-/* PARM_MAP.links definitions... */
-#define RIO_LINK_ENABLE 0x80FF
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** RUP ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The RUP (Remote Unit Port) structure relates to the Remote Terminal Adapters
- attached to the system and there is normally an array of MAX_RUPS (=16) structures
- in a host card, defined by PARM_MAP->rup. */
-
-typedef struct _RUP {
- _u16 txpkt; /* 0x00 Outgoing packet */
- _u16 rxpkt; /* 0x02 ncoming packet */
- _u16 link; /* 0x04 Which link to send packet down ? */
- _u8 rup_dest_unit[2]; /* 0x06 Destination Unit */
- _u16 handshake; /* 0x08 Handshaking */
- _u16 timeout; /* 0x0A Timeout */
- _u16 status; /* 0x0C Status */
- _u16 txcontrol; /* 0x0E Transmit control */
- _u16 rxcontrol; /* 0x10 Receive control */
-
-} RUP;
-
-/* Same thing again, but defined as offsets... */
-
-#define RUP_txpkt 0x00 /* 0x00 Outgoing packet */
-#define RUP_rxpkt 0x02 /* 0x02 Incoming packet */
-#define RUP_link 0x04 /* 0x04 Which link to send packet down ? */
-#define RUP_rup_dest_unit 0x06 /* 0x06 Destination Unit */
-#define RUP_handshake 0x08 /* 0x08 Handshaking */
-#define RUP_timeout 0x0A /* 0x0A Timeout */
-#define RUP_status 0x0C /* 0x0C Status */
-#define RUP_txcontrol 0x0E /* 0x0E Transmit control */
-#define RUP_rxcontrol 0x10 /* 0x10 Receive control */
-#define sizeof_RUP 0x12 /* structure size = 0x12 */
-
-#define MAX_RUP 16
-
-/* RUP.txcontrol definitions... */
-#define TX_RUP_INACTIVE 0 /* Nothing to transmit */
-#define TX_PACKET_READY 1 /* Transmit packet ready */
-#define TX_LOCK_RUP 2 /* Transmit side locked */
-
-/* RUP.txcontrol definitions... */
-#define RX_RUP_INACTIVE 0 /* Nothing received */
-#define RX_PACKET_READY 1 /* Packet received */
-
-#define RUP_NO_OWNER 0xFF /* RUP not owned by any process */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** PHB ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The PHB (Port Header Block) structure relates to the serial ports attached
- to the system and there is normally an array of MAX_PHBS (=128) structures
- in a host card, defined by PARM_MAP->phb_ptr and PARM_MAP->phb_num_ptr. */
-
-typedef struct _PHB {
- _u16 source; /* 0x00 Location of the PHB in the host card */
- _u16 handshake; /* 0x02 Used to manage receive packet flow control */
- _u16 status; /* 0x04 Internal port transmit/receive status */
- _u16 timeout; /* 0x06 Time period to wait for an ACK */
- _u16 link; /* 0x08 The host link associated with the PHB */
- _u16 destination; /* 0x0A Location of the remote port on the network */
-
- _u16 tx_start; /* 0x0C first entry in the packet array for transmit packets */
- _u16 tx_end; /* 0x0E last entry in the packet array for transmit packets */
- _u16 tx_add; /* 0x10 position in the packet array for new transmit packets */
- _u16 tx_remove; /* 0x12 current position in the packet pointer array */
-
- _u16 rx_start; /* 0x14 first entry in the packet array for receive packets */
- _u16 rx_end; /* 0x16 last entry in the packet array for receive packets */
- _u16 rx_add; /* 0x18 position in the packet array for new receive packets */
- _u16 rx_remove; /* 0x1A current position in the packet pointer array */
-
-} PHB;
-
-/* Same thing again, but defined as offsets... */
-
-#define PHB_source 0x00 /* 0x00 Location of the PHB in the host card */
-#define PHB_handshake 0x02 /* 0x02 Used to manage receive packet flow control */
-#define PHB_status 0x04 /* 0x04 Internal port transmit/receive status */
-#define PHB_timeout 0x06 /* 0x06 Time period to wait for an ACK */
-#define PHB_link 0x08 /* 0x08 The host link associated with the PHB */
-#define PHB_destination 0x0A /* 0x0A Location of the remote port on the network */
-#define PHB_tx_start 0x0C /* 0x0C first entry in the packet array for transmit packets */
-#define PHB_tx_end 0x0E /* 0x0E last entry in the packet array for transmit packets */
-#define PHB_tx_add 0x10 /* 0x10 position in the packet array for new transmit packets */
-#define PHB_tx_remove 0x12 /* 0x12 current position in the packet pointer array */
-#define PHB_rx_start 0x14 /* 0x14 first entry in the packet array for receive packets */
-#define PHB_rx_end 0x16 /* 0x16 last entry in the packet array for receive packets */
-#define PHB_rx_add 0x18 /* 0x18 position in the packet array for new receive packets */
-#define PHB_rx_remove 0x1A /* 0x1A current position in the packet pointer array */
-#define sizeof_PHB 0x1C /* structure size = 0x1C */
-
-/* PHB.handshake definitions... */
-#define PHB_HANDSHAKE_SET 0x0001 /* Set by LRT */
-#define PHB_HANDSHAKE_RESET 0x0002 /* Set by ISR / driver */
-#define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET|PHB_HANDSHAKE_SET)
- /* Reset by ltt */
-
-#define MAX_PHB 128 /* range 0-127 */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** LPB ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The LPB (Link Parameter Block) structure relates to a RIO Network Link
- and there is normally an array of MAX_LINKS (=4) structures in a host card,
- defined by PARM_MAP->link_str_ptr. */
-
-typedef struct _LPB {
- _u16 link_number; /* 0x00 Link Number */
- _u16 in_ch; /* 0x02 Link In Channel */
- _u16 out_ch; /* 0x04 Link Out Channel */
- _u8 attached_serial[4]; /* 0x06 Attached serial number */
- _u8 attached_host_serial[4]; /* 0x0A Serial number of Host who booted other end */
- _u16 descheduled; /* 0x0E Currently Descheduled */
- _u16 state; /* 0x10 Current state */
- _u16 send_poll; /* 0x12 Send a Poll Packet */
- _u16 ltt_p; /* 0x14 Process Descriptor */
- _u16 lrt_p; /* 0x16 Process Descriptor */
- _u16 lrt_status; /* 0x18 Current lrt status */
- _u16 ltt_status; /* 0x1A Current ltt status */
- _u16 timeout; /* 0x1C Timeout value */
- _u16 topology; /* 0x1E Topology bits */
- _u16 mon_ltt; /* 0x20 */
- _u16 mon_lrt; /* 0x22 */
- _u16 num_pkts; /* 0x24 */
- _u16 add_packet_list; /* 0x26 Add packets to here */
- _u16 remove_packet_list; /* 0x28 Send packets from here */
-
- _u16 lrt_fail_chan; /* 0x2A Lrt's failure channel */
- _u16 ltt_fail_chan; /* 0x2C Ltt's failure channel */
-
- RUP rup; /* 0x2E RUP structure for HOST to driver comms */
- RUP link_rup; /* 0x40 RUP for the link (POLL, topology etc.) */
- _u16 attached_link; /* 0x52 Number of attached link */
- _u16 csum_errors; /* 0x54 csum errors */
- _u16 num_disconnects; /* 0x56 number of disconnects */
- _u16 num_sync_rcvd; /* 0x58 # sync's received */
- _u16 num_sync_rqst; /* 0x5A # sync requests */
- _u16 num_tx; /* 0x5C Num pkts sent */
- _u16 num_rx; /* 0x5E Num pkts received */
- _u16 module_attached; /* 0x60 Module tpyes of attached */
- _u16 led_timeout; /* 0x62 LED timeout */
- _u16 first_port; /* 0x64 First port to service */
- _u16 last_port; /* 0x66 Last port to service */
-
-} LPB;
-
-/* Same thing again, but defined as offsets... */
-
-#define LPB_link_number 0x00 /* 0x00 Link Number */
-#define LPB_in_ch 0x02 /* 0x02 Link In Channel */
-#define LPB_out_ch 0x04 /* 0x04 Link Out Channel */
-#define LPB_attached_serial 0x06 /* 0x06 Attached serial number */
-#define LPB_attached_host_serial 0x0A /* 0x0A Serial number of Host who booted other end */
-#define LPB_descheduled 0x0E /* 0x0E Currently Descheduled */
-#define LPB_state 0x10 /* 0x10 Current state */
-#define LPB_send_poll 0x12 /* 0x12 Send a Poll Packet */
-#define LPB_ltt_p 0x14 /* 0x14 Process Descriptor */
-#define LPB_lrt_p 0x16 /* 0x16 Process Descriptor */
-#define LPB_lrt_status 0x18 /* 0x18 Current lrt status */
-#define LPB_ltt_status 0x1A /* 0x1A Current ltt status */
-#define LPB_timeout 0x1C /* 0x1C Timeout value */
-#define LPB_topology 0x1E /* 0x1E Topology bits */
-#define LPB_mon_ltt 0x20 /* 0x20 */
-#define LPB_mon_lrt 0x22 /* 0x22 */
-#define LPB_num_pkts 0x24 /* 0x24 */
-#define LPB_add_packet_list 0x26 /* 0x26 Add packets to here */
-#define LPB_remove_packet_list 0x28 /* 0x28 Send packets from here */
-#define LPB_lrt_fail_chan 0x2A /* 0x2A Lrt's failure channel */
-#define LPB_ltt_fail_chan 0x2C /* 0x2C Ltt's failure channel */
-#define LPB_rup 0x2E /* 0x2E RUP structure for HOST to driver comms */
-#define LPB_link_rup 0x40 /* 0x40 RUP for the link (POLL, topology etc.) */
-#define LPB_attached_link 0x52 /* 0x52 Number of attached link */
-#define LPB_csum_errors 0x54 /* 0x54 csum errors */
-#define LPB_num_disconnects 0x56 /* 0x56 number of disconnects */
-#define LPB_num_sync_rcvd 0x58 /* 0x58 # sync's received */
-#define LPB_num_sync_rqst 0x5A /* 0x5A # sync requests */
-#define LPB_num_tx 0x5C /* 0x5C Num pkts sent */
-#define LPB_num_rx 0x5E /* 0x5E Num pkts received */
-#define LPB_module_attached 0x60 /* 0x60 Module tpyes of attached */
-#define LPB_led_timeout 0x62 /* 0x62 LED timeout */
-#define LPB_first_port 0x64 /* 0x64 First port to service */
-#define LPB_last_port 0x66 /* 0x66 Last port to service */
-#define sizeof_LPB 0x68 /* structure size = 0x68 */
-
-#define LINKS_PER_UNIT 4 /* number of links from a host */
-
-/*****************************************************************************
-******************************** *******************************
-******************************** FREE_LIST *******************************
-******************************** *******************************
-*****************************************************************************/
-
-/* Used to overlay packet headers when allocating/freeing packets from the free list */
-
-typedef struct _FREE_LIST {
- _u16 next; /* 0x00 offset of next list item */
- _u16 prev; /* 0x02 offset of previous list item */
-
-} FREE_LIST;
-
-/* Same thing again, but defined as offsets... */
-
-#define FL_next 0x00 /* 0x00 offset of next list item */
-#define FL_prev 0x02 /* 0x02 offset of previous list item */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** PKT ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The PKT is the main unit of communication between Host Cards and RTAs across
- the RIO network. */
-
-#define PKT_MAX_DATA_LEN 72 /* Size of packet data */
-
-typedef struct _PKT {
- _u8 dest_unit; /* 0x00 Destination Unit Id */
- _u8 dest_port; /* 0x01 Destination Port */
- _u8 src_unit; /* 0x02 Source Unit Id */
- _u8 src_port; /* 0x03 Source Port */
- _u8 len; /* 0x04 Length (in bytes) of data field */
- _u8 control; /* 0x05 */
- _u8 data[PKT_MAX_DATA_LEN]; /* 0x06 Actual data */
- _u16 csum; /* 0x4E C-SUM */
-
-} PKT;
-
-/* Same thing again, but defined as offsets... */
-
-#define PKT_dest_unit 0x00 /* 0x00 Destination Unit Id */
-#define PKT_dest_port 0x01 /* 0x01 Destination Port */
-#define PKT_src_unit 0x02 /* 0x02 Source Unit Id */
-#define PKT_src_port 0x03 /* 0x03 Source Port */
-#define PKT_len 0x04 /* 0x04 Length (in bytes) of data field */
-#define PKT_control 0x05 /* 0x05 */
-#define PKT_data 0x06 /* 0x06 Actual data */
-#define PKT_csum 0x4E /* 0x4E C-SUM */
-#define sizeof_PKT 0x50 /* structure size = 0x50 */
-
-/* PKT.len definitions... */
-#define PKT_CMD_BIT 0x80
-#define PKT_CMD_DATA 0x80
-#define PKT_LEN_MASK 0x7F
-
-/* PKT.control definitions... */
-#define PKT_ACK 0x40
-#define PKT_TGL 0x20
-#define DATA_WNDW 0x10
-#define PKT_TTL_MASK 0x0F
-#define MAX_TTL 0x0F
-
-/*****************************************************************************
-***************************** ****************************
-***************************** Control Packets ****************************
-***************************** ****************************
-*****************************************************************************/
-
-/* The following definitions and structures define the control packets sent
- between the driver and RIO Ports, RTAs and Host Cards. */
-
-#define PRE_EMPTIVE 0x80 /* Pre-emptive command (sent via port's RUP) */
-
-/* "in-band" and "pre-emptive" port commands... */
-#define OPEN 0x00 /* Driver->RIO Open a port */
-#define CONFIG 0x01 /* Driver->RIO Configure a port */
-#define MOPEN 0x02 /* Driver->RIO Modem open (wait for DCD) */
-#define CLOSE 0x03 /* Driver->RIO Close a port */
-#define WFLUSH (0x04|PRE_EMPTIVE) /* Driver->RIO Write flush */
-#define RFLUSH (0x05|PRE_EMPTIVE) /* Driver->RIO Read flush */
-#define RESUME (0x06|PRE_EMPTIVE) /* Driver->RIO Behave as if XON received */
-#define SBREAK 0x07 /* Driver->RIO Start break */
-#define EBREAK 0x08 /* Driver->RIO End break */
-#define SUSPEND (0x09|PRE_EMPTIVE) /* Driver->RIO Behave as if XOFF received */
-#define FCLOSE (0x0A|PRE_EMPTIVE) /* Driver->RIO Force close */
-#define XPRINT 0x0B /* Driver->RIO Xprint packet */
-#define MBIS (0x0C|PRE_EMPTIVE) /* Driver->RIO Set modem lines */
-#define MBIC (0x0D|PRE_EMPTIVE) /* Driver->RIO Clear modem lines */
-#define MSET (0x0E|PRE_EMPTIVE) /* Driver->RIO Set modem lines */
-#define PCLOSE 0x0F /* Driver->RIO Pseudo close */
-#define MGET (0x10|PRE_EMPTIVE) /* Driver->RIO Force update of modem status */
-#define MEMDUMP (0x11|PRE_EMPTIVE) /* Driver->RIO DEBUG request for RTA memory */
-#define READ_REGISTER (0x12|PRE_EMPTIVE) /* Driver->RIO DEBUG read CD1400 register */
-
-/* Remote Unit Port (RUP) packet definitions... (specified in PKT.dest_unit and PKT.src_unit) */
-#define SYNC_RUP 0xFF /* Download internal */
-#define COMMAND_RUP 0xFE /* Command ack/status */
-#define ERROR_RUP 0xFD /* Download internal */
-#define POLL_RUP 0xFC /* Download internal */
-#define BOOT_RUP 0xFB /* Used to boot RTAs */
-#define ROUTE_RUP 0xFA /* Used to specify routing/topology */
-#define STATUS_RUP 0xF9 /* Not used */
-#define POWER_RUP 0xF8 /* Download internal */
-
-/* COMMAND_RUP definitions... */
-#define COMPLETE (0x20|PRE_EMPTIVE) /* RIO->Driver Command complete */
-#define BREAK_RECEIVED (0x21|PRE_EMPTIVE) /* RIO->Driver Break received */
-#define MODEM_STATUS (0x22|PRE_EMPTIVE) /* RIO->Driver Modem status change */
-
-/* BOOT_RUP definitions... */
-#define BOOT_REQUEST 0x00 /* RIO->Driver Request for boot */
-#define BOOT_ABORT 0x01 /* Driver->RIO Abort a boot */
-#define BOOT_SEQUENCE 0x02 /* Driver->RIO Packet with firmware details */
-#define BOOT_COMPLETED 0x03 /* RIO->Driver Boot completed */
-#define IFOAD 0x2F /* Driver->RIO Shutdown/Reboot RTA (Fall Over And Die) */
-#define IDENTIFY 0x30 /* Driver->RIO Identify RTA */
-#define ZOMBIE 0x31 /* Driver->RIO Shutdown/Flash LEDs */
-#define UFOAD 0x32 /* Driver->RIO Shutdown/Reboot neighbouring RTA */
-#define IWAIT 0x33 /* Driver->RIO Pause booting process */
-
-/* ROUTE_RUP definitions... */
-#define ROUTE_REQUEST 0x00 /* RIO->Driver Request an ID */
-#define ROUTE_FOAD 0x01 /* Driver->RIO Shutdown/reboot RTA */
-#define ROUTE_ALREADY 0x02 /* Driver->RIO Not used */
-#define ROUTE_USED 0x03 /* Driver->RIO Not used */
-#define ROUTE_ALLOCATE 0x04 /* Driver->RIO Allocate RTA RUP numbers */
-#define ROUTE_REQ_TOP 0x05 /* Driver->RIO Not used */
-#define ROUTE_TOPOLOGY 0x06 /* RIO->Driver Route/Topology status */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** OPEN **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- Sent to open a port.
- Structure of configuration info used with OPEN, CONFIG and MOPEN packets... */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_Cor1 (PKT_Data+1) /* Channel Option Register 1 */
-#define PKT_Cor2 (PKT_Data+2) /* Channel Option Register 2 */
-#define PKT_Cor4 (PKT_Data+3) /* Channel Option Register 4 */
-#define PKT_Cor5 (PKT_Data+4) /* Channel Option Register 5 */
-#define PKT_TxXon (PKT_Data+5) /* Transmit XON character */
-#define PKT_TxXoff (PKT_Data+6) /* Transmit XOFF character */
-#define PKT_RxXon (PKT_Data+7) /* Receive XON character */
-#define PKT_RxXoff (PKT_Data+8) /* Receive XOFF character */
-#define PKT_Lnext (PKT_Data+9) /* Lnext character */
-#define PKT_TxBaud (PKT_Data+10) /* Transmit baud rate */
-#define PKT_RxBaud (PKT_Data+11) /* Receive baud rate */
-
-/* COR1 definitions... */
-#define COR1_PARITY 0xE0 /* Parity mask */
-#define COR1_NONE 0x00 /* No parity */
-#define COR1_SPACE 0x20 /* Space parity */
-#define COR1_EVEN 0x40 /* Even parity */
-#define COR1_MARK 0xA0 /* Mark parity */
-#define COR1_ODD 0xC0 /* Odd parity */
-
-#define COR1_STOPBITS 0x0C /* Stop bits mask */
-#define COR1_STOP1 0x00 /* 1 stop bit */
-#define COR1_STOP1_5 0x04 /* 1.5 stop bits */
-#define COR1_STOP2 0x08 /* 2 stop bits */
-
-#define COR1_DATABITS 0x03 /* Data bits mask */
-#define COR1_DATA5 0x00 /* 5 data bits */
-#define COR1_DATA6 0x01 /* 6 data bits */
-#define COR1_DATA7 0x02 /* 7 data bits */
-#define COR1_DATA8 0x03 /* 8 data bits */
-
-/* COR2 definitions... */
-#define COR2_XON_TXFLOW 0x40 /* XON/XOFF Transmit Flow */
-#define COR2_XANY_TXFLOW 0xC0 /* XON/XANY Transmit Flow */
-#define COR2_HUPCL 0x20 /* Hang Up On Close */
-#define COR2_DSR_TXFLOW 0x08 /* DSR Transmit Flow Control */
-#define COR2_RTS_RXFLOW 0x04 /* RTS Receive Flow Control */
-#define COR2_CTS_TXFLOW 0x02 /* CTS Transmit Flow Control */
-#define COR2_XON_RXFLOW 0x01 /* XON/XOFF Receive Flow */
-
-/* COR4 definition... */
-#define COR4_IGNCR 0x80 /* Discard received CR */
-#define COR4_ICRNL 0x40 /* Map received CR -> NL */
-#define COR4_INLCR 0x20 /* Map received NL -> CR */
-#define COR4_IGNBRK 0x10 /* Ignore Received Break */
-#define COR4_NBRKINT 0x08 /* No interrupt on rx Break */
-#define COR4_IGNPAR 0x04 /* ignore rx parity error chars */
-#define COR4_PARMRK 0x02 /* Mark rx parity error chars */
-#define COR4_RAISEMOD 0x01 /* Raise modem lines on !0 baud */
-
-/* COR5 definitions... */
-#define COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */
-#define COR5_LNE 0x40 /* Enable LNEXT processing */
-#define COR5_CMOE 0x20 /* Match good & error characters */
-#define COR5_TAB3 0x10 /* TAB3 mode */
-#define COR5_TSTATE_ON 0x08 /* Enable tbusy/tstop monitoring */
-#define COR5_TSTATE_OFF 0x04 /* Disable tbusy/tstop monitoring */
-#define COR5_ONLCR 0x02 /* NL -> CR NL on output */
-#define COR5_OCRNL 0x01 /* CR -> NL on output */
-
-/* RxBaud and TxBaud definitions... */
-#define RIO_B0 0x00 /* RTS / DTR signals dropped */
-#define RIO_B50 0x01 /* 50 baud */
-#define RIO_B75 0x02 /* 75 baud */
-#define RIO_B110 0x03 /* 110 baud */
-#define RIO_B134 0x04 /* 134.5 baud */
-#define RIO_B150 0x05 /* 150 baud */
-#define RIO_B200 0x06 /* 200 baud */
-#define RIO_B300 0x07 /* 300 baud */
-#define RIO_B600 0x08 /* 600 baud */
-#define RIO_B1200 0x09 /* 1200 baud */
-#define RIO_B1800 0x0A /* 1800 baud */
-#define RIO_B2400 0x0B /* 2400 baud */
-#define RIO_B4800 0x0C /* 4800 baud */
-#define RIO_B9600 0x0D /* 9600 baud */
-#define RIO_B19200 0x0E /* 19200 baud */
-#define RIO_B38400 0x0F /* 38400 baud */
-#define RIO_B56000 0x10 /* 56000 baud */
-#define RIO_B57600 0x11 /* 57600 baud */
-#define RIO_B64000 0x12 /* 64000 baud */
-#define RIO_B115200 0x13 /* 115200 baud */
-#define RIO_B2000 0x14 /* 2000 baud */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* CONFIG *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- CONFIG is sent from the driver to configure an already opened port.
- Packet structure is same as OPEN. */
-
-/*****************************************************************************
-********************************* **********************************
-********************************* MOPEN **********************************
-********************************* **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- MOPEN is sent from the driver to open a port attached to a modem. (in-band)
- Packet structure is same as OPEN. */
-
-/*****************************************************************************
-********************************* **********************************
-********************************* CLOSE **********************************
-********************************* **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- CLOSE is sent from the driver to close a previously opened port.
- No parameters.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-/*****************************************************************************
-********************************* *********************************
-********************************* WFLUSH *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- WFLUSH is sent pre-emptively from the driver to flush the write buffers and
- packets of a port. (pre-emptive)
-
- WFLUSH is also sent in-band from the driver to a port as a marker to end
- write flushing previously started by a pre-emptive WFLUSH packet. (in-band)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* RFLUSH *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- RFLUSH is sent pre-emptively from the driver to flush the read buffers and
- packets of a port.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* RESUME *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- RESUME is sent pre-emptively from the driver to cause a port to resume
- transmission of data if blocked by XOFF. (as if XON had been received)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* SBREAK *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- SBREAK is sent in-band from the driver to a port to suspend data and start
- break signal transmission.
-
- If the break delay is 0, the break signal will be acknowledged with a
- RUP_COMMAND, COMPLETE packet and continue until an EBREAK packet is received.
-
- Otherwise, there is no acknowledgement and the break signal will last for the
- specified number of mS.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_BreakDelay (PKT_Data+1) /* Break delay in mS */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* EBREAK *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- EBREAK is sent in-band from the driver to a port to stop transmission of a
- break signal.
-
- No parameters. */
-
-/*****************************************************************************
-********************************* ********************************
-********************************* SUSPEND ********************************
-********************************* ********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- SUSPEND is sent pre-emptively from the driver to cause a port to suspend
- transmission of data. (as if XOFF had been received)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* FCLOSE *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- FCLOSE is sent pre-emptively from the driver to force close a port.
- A force close flushes receive and transmit queues, and also lowers all output
- modem signals if the COR5_HUPCL (Hang Up On Close) flag is set.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* XPRINT *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- XPRINT is sent as a normal I/O data packet except that the PKT_CMD_BIT of
- the "len" field is set, and the first "data" byte is XPRINT.
-
- The I/O data in the XPRINT packet will contain the following:
- - Transparent Print Start Sequence
- - Transparent Print Data
- - Transparent Print Stop Sequence.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MBIS **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MBIS is sent pre-emptively from the driver to set a port's modem signals.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-#define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */
-
-/* ModemSet definitions... */
-#define MBIS_RTS 0x01 /* RTS modem signal */
-#define MBIS_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MBIC **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MBIC is sent pre-emptively from the driver to clear a port's modem signals.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-#define PKT_ModemClear (PKT_Data+4) /* Modem clear signals mask */
-
-/* ModemClear definitions... */
-#define MBIC_RTS 0x01 /* RTS modem signal */
-#define MBIC_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MSET **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MSET is sent pre-emptively from the driver to set/clear a port's modem signals. */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-#define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */
-
-/* ModemSet definitions... */
-#define MSET_RTS 0x01 /* RTS modem signal */
-#define MSET_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* PCLOSE *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- PCLOSE is sent from the driver to pseudo close a previously opened port.
-
- The port will close when all data has been sent/received, however, the
- port's transmit / receive and modem signals will be left enabled and the
- port marked internally as Pseudo Closed. */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MGET **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MGET is sent pre-emptively from the driver to request the port's current modem signals. */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-
-/*****************************************************************************
-********************************* ********************************
-********************************* MEMDUMP ********************************
-********************************* ********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MEMDUMP is sent pre-emptively from the driver to request a dump of 32 bytes
- of the specified port's RTA address space.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-
-/*****************************************************************************
-****************************** *****************************
-****************************** READ_REGISTER *****************************
-****************************** *****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- READ_REGISTER is sent pre-emptively from the driver to request the contents
- of the CD1400 register specified in address.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-
-/*****************************************************************************
-************************ **************************
-************************ COMMAND_RUP - COMPLETE **************************
-************************ **************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
- packets, except MEMDUMP and READ_REGISTER.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-
-/* ModemStatus definitions... */
-#define MODEM_DSR 0x80 /* Data Set Ready modem state */
-#define MODEM_CTS 0x40 /* Clear To Send modem state */
-#define MODEM_RI 0x20 /* Ring Indicate modem state */
-#define MODEM_CD 0x10 /* Carrier Detect modem state */
-#define MODEM_TSTOP 0x08 /* Transmit Stopped state */
-#define MODEM_TEMPTY 0x04 /* Transmit Empty state */
-#define MODEM_DTR 0x02 /* DTR modem output state */
-#define MODEM_RTS 0x01 /* RTS modem output state */
-
-/* PortStatus definitions... */
-#define PORT_ISOPEN 0x01 /* Port open ? */
-#define PORT_HUPCL 0x02 /* Hangup on close? */
-#define PORT_MOPENPEND 0x04 /* Modem open pending */
-#define PORT_ISPARALLEL 0x08 /* Parallel port */
-#define PORT_BREAK 0x10 /* Port on break */
-#define PORT_STATUSPEND 0020 /* Status packet pending */
-#define PORT_BREAKPEND 0x40 /* Break packet pending */
-#define PORT_MODEMPEND 0x80 /* Modem status packet pending */
-
-/*****************************************************************************
-************************ **************************
-************************ COMMAND_RUP - COMPLETE **************************
-************************ **************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
- packets, except MEMDUMP and READ_REGISTER.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#if 0
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#endif
-
-/* ModemStatus definitions... */
-#define MODEM_DSR 0x80 /* Data Set Ready modem state */
-#define MODEM_CTS 0x40 /* Clear To Send modem state */
-#define MODEM_RI 0x20 /* Ring Indicate modem state */
-#define MODEM_CD 0x10 /* Carrier Detect modem state */
-#define MODEM_TSTOP 0x08 /* Transmit Stopped state */
-#define MODEM_TEMPTY 0x04 /* Transmit Empty state */
-#define MODEM_DTR 0x02 /* DTR modem output state */
-#define MODEM_RTS 0x01 /* RTS modem output state */
-
-/* PortStatus definitions... */
-#define PORT_ISOPEN 0x01 /* Port open ? */
-#define PORT_HUPCL 0x02 /* Hangup on close? */
-#define PORT_MOPENPEND 0x04 /* Modem open pending */
-#define PORT_ISPARALLEL 0x08 /* Parallel port */
-#define PORT_BREAK 0x10 /* Port on break */
-#define PORT_STATUSPEND 0020 /* Status packet pending */
-#define PORT_BREAKPEND 0x40 /* Break packet pending */
-#define PORT_MODEMPEND 0x80 /* Modem status packet pending */
-
-/*****************************************************************************
-******************** ********************
-******************** COMMAND_RUP - COMPLETE - MEMDUMP ********************
-******************** ********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE - MEMDUMP is sent as an acknowledgement for a MEMDUMP
- port I/O control command packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-#endif
-#define PKT_Dump (PKT_Data+8) /* 32bytes of requested dump data */
-
-/*****************************************************************************
-***************** *****************
-***************** COMMAND_RUP - COMPLETE - READ_REGISTER *****************
-***************** *****************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE - READ_REGISTER is sent as an acknowledgement for a
- READ_REGISTER port I/O control command packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /*Command code */
-#define PKT_PhbNum (PKT_Data+1) /*Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-#define PKT_RegisterValue (PKT_Data+3) /* Modem signal status */
-#if 0
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#endif
-
-/*****************************************************************************
-********************* ***********************
-********************* COMMAND_RUP - BREAK_RECEIVED ***********************
-********************* ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - BREAK_RECEIVED packets are sent when the port detects a receive BREAK signal.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-
-/*****************************************************************************
-********************* *************************
-********************* COMMAND_RUP - MODEM_STATUS *************************
-********************* *************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - MODEM_STATUS packets are sent whenever the port detects a
- change in the input modem signal states.
-
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#endif
-
-/*****************************************************************************
-************************ *************************
-************************ BOOT_RUP - BOOT_REQUEST *************************
-************************ *************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP - BOOT_REQUEST packets are sent to the Driver from RIO to request
- firmware code to load onto attached RTAs.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-
-/*****************************************************************************
-************************ ************************
-************************ BOOT_RUP - BOOT_SEQUENCE ************************
-************************ ************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - BOOT_SEQUENCE packets are sent from the Driver to RIO in response
- to a BOOT_RUP - BOOT_REQUEST packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_NumPackets (PKT_Data+2) /* Packets required to load firmware */
-#define PKT_LoadBase (PKT_Data+4) /* RTA firmware load address */
-#define PKT_CodeSize (PKT_Data+6) /* Size of firmware in bytes */
-#define PKT_CmdString (PKT_Data+8) /* Command string */
-
-/*****************************************************************************
-************************ ***********************
-************************ BOOT_RUP - BOOT_COMPLETED ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP - BOOT_COMPLETE is sent to the Driver from RIO when downloading of
- RTA firmware has completed.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_LinkNumber (PKT_Data+1) /* Link number RTA booted on */
-#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */
-
-/*****************************************************************************
-************************ ***********************
-************************ BOOT_RUP - Packet Request ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP packet without the PKT_CMD_BIT set in the PKT->len field is sent
- from RIO to the Driver as a request for a firmware boot packet. */
-
-#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** BOOT_RUP - Packet Response ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- In response to a BOOT_RUP boot packet request, the driver fills out the response
- packet with the 70 bytes of the requested sequence.
- */
-#if 0
-#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
-#endif
-#define PKT_FirmwarePacket (PKT_Data+2) /* Firmware packet */
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - IFOAD ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IFOAD packets are sent from the Driver to an RTA to cause the
- RTA to shut down and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IfoadId1 (PKT_Data+2) /* IFOAD Id 1 */
-#define PKT_IfoadId2 (PKT_Data+3) /* IFOAD Id 2 */
-
-#define IFOADID1 0xAD
-#define IFOADID2 0xF0
-
-/*****************************************************************************
-************************** ***************************
-************************** BOOT_RUP - IDENTIFY ***************************
-************************** ***************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IDENTIFY packets are sent from the Driver to an RTA to cause the
- RTA to flash its LEDs for a period of time.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IdentifyId (PKT_Data+2) /* defines pattern to flash */
-
-/*****************************************************************************
-**************************** ***************************
-**************************** BOOT_RUP - ZOMBIE ***************************
-**************************** ***************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - ZOMBIE packets are sent from the Driver to an RTA to cause the
- RTA to shut down and flash it's LEDs.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_ZombieId1 (PKT_Data+2) /* ZOMBIE Id 1 */
-#define PKT_ZombieId2 (PKT_Data+3) /* ZOMBIE Id 2 */
-
-#define ZOMBIEID1 0x52
-#define ZOMBIEID2 0x21
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - UFOAD ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - UFOAD packets are sent from the Driver to an RTA to cause the RTA
- to ask it's neighbouring RTA to shut down and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */
-#endif
-#define PKT_UfoadId1 (PKT_Data+2) /* UFOAD Id 1 */
-#define PKT_UfoadId2 (PKT_Data+3) /* UFOAD Id 2 */
-
-#define UFOADID1 0x1E
-#define UFOADID2 0x0D
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - IWAIT ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IWAIT packets are sent from the Driver to an RTA to cause the RTA
- to pause booting on the specified link for 30 seconds.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */
-#endif
-#define PKT_IwaitId1 (PKT_Data+2) /* IWAIT Id 1 */
-#define PKT_IwaitId2 (PKT_Data+3) /* IWAIT Id 2 */
-
-#define IWAITID1 0xDE
-#define IWAITID2 0xB1
-
-/*****************************************************************************
-************************ ***********************
-************************ ROUTE_RUP - ROUTE_REQUEST ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- ROUTE_RUP - ROUTE_REQUEST packets are sent from a newly booted or connected
- RTA to a Driver to request an ID (RUP or unit number).
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */
-#define PKT_ModuleTypes (PKT_Data+6) /* RTA Module types */
-
-/* ModuleTypes definitions... */
-#define MOD_BLANK 0x0F /* Blank plate attached */
-#define MOD_RS232DB25 0x00 /* RS232 DB25 connector */
-#define MOD_RS232RJ45 0x01 /* RS232 RJ45 connector */
-#define MOD_RS422DB25 0x02 /* RS422 DB25 connector */
-#define MOD_RS485DB25 0x03 /* RS485 DB25 connector */
-#define MOD_PARALLEL 0x04 /* Centronics parallel */
-
-#define MOD2 0x08 /* Set to indicate Rev2 module */
-
-/*****************************************************************************
-************************* *************************
-************************* ROUTE_RUP - ROUTE_FOAD *************************
-************************* *************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- ROUTE_RUP - ROUTE_FOAD packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
- packet to cause the RTA to "Fall Over And Die"., i.e. shutdown and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** ROUTE_RUP - ROUTE_ALLOCATE ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- ROUTE_RUP - ROUTE_ALLOCATE packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
- packet to allocate the RTA's Id number (RUP number 1..16)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IdNum (PKT_Data+1) /* RUP number for ports 1..8 */
-#if 0
-#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
-#endif
-#define PKT_IdNum2 (PKT_Data+0x17) /* RUP number for ports 9..16 */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** ROUTE_RUP - ROUTE_TOPOLOGY ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- ROUTE_RUP - ROUTE_TOPOLOGY packet is sent to inform the driver of an RTA's
- current link status.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_Link1Rup (PKT_Data+2) /* Link 1 RUP number */
-#define PKT_Link1Link (PKT_Data+3) /* Link 1 link number */
-#define PKT_Link2Rup (PKT_Data+4) /* Link 2 RUP number */
-#define PKT_Link2Link (PKT_Data+5) /* Link 2 link number */
-#define PKT_Link3Rup (PKT_Data+6) /* Link 3 RUP number */
-#define PKT_Link3Link (PKT_Data+7) /* Link 3 link number */
-#define PKT_Link4Rup (PKT_Data+8) /* Link 4 RUP number */
-#define PKT_Link4Link (PKT_Data+9) /* Link 4 link number */
-#define PKT_RtaVpdProm (PKT_Data+10) /* 32 bytes of RTA VPD PROM Contents */
-
-#endif /* _sxwinif_h */
-
-/* End of RIOWINIF.H */
diff --git a/drivers/char/rio/riscos.h b/drivers/char/rio/riscos.h
deleted file mode 100644
index 60d66d0056a..00000000000
--- a/drivers/char/rio/riscos.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-** Module : riscos.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:19
-** Retrieved : 11/6/98 11:34:22
-**
-** ident @(#)riscos.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riscos_h__
-#define __rio_riscos_h__
-
-#ifdef SCCS_LABELS
-static char *_riscos_h_sccs_ = "@(#)riscos.h 1.2";
-#endif
-
-/*
-** This module used to define all those little itsy bits required for RISC/OS
-** now it's full of null macros.
-*/
-
-/*
-** RBYTE reads a byte from a location.
-** RWORD reads a word from a location.
-** WBYTE writes a byte to a location.
-** WWORD writes a word to a location.
-** RINDW reads a word through a pointer.
-** WINDW writes a word through a pointer.
-** RIOSWAB swaps the two bytes of a word, if needed.
-*/
-
-#define RIOSWAB(N) (N)
-#define WBYTE(A,V) (A)=(uchar)(V)
-#define WWORD(A,V) (A)=(ushort)(V)
-#define RBYTE(A) (uchar)(A)
-#define RWORD(A) (ushort)(A)
-#define RINDW(A) (*(ushort *)(A))
-#define WINDW(A,V) (*(ushort *)(A)=(ushort)(V))
-
-#endif /* __rio_riscos_h__ */
diff --git a/drivers/char/rio/rtahw.h b/drivers/char/rio/rtahw.h
deleted file mode 100644
index e6c2cdfd3a1..00000000000
--- a/drivers/char/rio/rtahw.h
+++ /dev/null
@@ -1,75 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* R T A H A R D W A R E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_rtahw_h_sccs = "@(#)rtahw.h 1.5";
-#endif
-#endif
-
-#define WATCHDOG_ADDR ((unsigned short *)0x7a00)
-#define RTA_LED_ADDR ((unsigned short *)0x7c00)
-#define SERIALNUM_ADDR ((unsigned char *)0x7809)
-#define LATCH_ADDR ((unsigned char *)0x7800)
-
-/*
-** Here we define where the cd1400 chips are in memory.
-*/
-#define CD1400_ONE_ADDR (0x7300)
-#define CD1400_TWO_ADDR (0x7200)
-#define CD1400_THREE_ADDR (0x7100)
-#define CD1400_FOUR_ADDR (0x7000)
-
-/*
-** Define the different types of modules we can have
-*/
-enum module {
- MOD_BLANK = 0x0f, /* Blank plate attached */
- MOD_RS232DB25 = 0x00, /* RS232 DB25 connector */
- MOD_RS232RJ45 = 0x01, /* RS232 RJ45 connector */
- MOD_RS422DB25 = 0x02, /* RS422 DB25 connector */
- MOD_RS485DB25 = 0x03, /* RS485 DB25 connector */
- MOD_PARALLEL = 0x04 /* Centronics parallel */
-};
-
-#define TYPE_HOST 0
-#define TYPE_RTA8 1
-#define TYPE_RTA16 2
-
-#define WATCH_DOG WATCHDOG_ADDR
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h
index 8d44fec91dd..f74f67c6f70 100644
--- a/drivers/char/rio/rup.h
+++ b/drivers/char/rio/rup.h
@@ -43,12 +43,7 @@
#endif
#endif
-#if defined( HOST ) || defined( INKERNEL )
#define MAX_RUP ((short) 16)
-#endif
-#ifdef RTA
-#define MAX_RUP ((short) 1)
-#endif
#define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */
diff --git a/drivers/char/rio/rupstat.h b/drivers/char/rio/rupstat.h
deleted file mode 100644
index 56d828c63d2..00000000000
--- a/drivers/char/rio/rupstat.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* RUPSTAT
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _rupstat_h
-#define _rupstat_h
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_rupstat_h_sccs = "@(#)rupstat.h 1.1";
-#endif
-#endif
-
-#define STATUS_SYNC 0
-#define STATUS_REQ_TOP 1
-#define STATUS_TOPOLOGY 2
-
-#endif
diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h
index 31494054b21..6f754e19015 100644
--- a/drivers/char/rio/sam.h
+++ b/drivers/char/rio/sam.h
@@ -43,10 +43,6 @@
#endif
-#if !defined( HOST ) && !defined( INKERNEL )
-#define RTA 1
-#endif
-
#define NUM_FREE_LIST_UNITS 500
#ifndef FALSE
diff --git a/drivers/char/rio/selftest.h b/drivers/char/rio/selftest.h
deleted file mode 100644
index 7a3dba35232..00000000000
--- a/drivers/char/rio/selftest.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-** File: selftest.h
-**
-** Author: David Dix
-**
-** Created: 15th March 1993
-**
-** Last modified: 94/06/14
-**
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _selftests_h_
-#define _selftests_h_
-
-/*
-** Selftest identifier...
-*/
-#define SELFTEST_MAGIC 0x5a5a
-
-/*
-** This is the structure of the packet that is sent back after each
-** selftest on a booting RTA.
-*/
-typedef struct {
- short magic; /* Identifies packet type */
- int test; /* Test number, see below */
- unsigned int result; /* Result value */
- unsigned int dataIn;
- unsigned int dataOut;
-} selftestStruct;
-
-/*
-** The different tests are identified by the following data values.
-*/
-enum test {
- TESTS_COMPLETE = 0x00,
- MEMTEST_ADDR = 0x01,
- MEMTEST_BIT = 0x02,
- MEMTEST_FILL = 0x03,
- MEMTEST_DATABUS = 0x04,
- MEMTEST_ADDRBUS = 0x05,
- CD1400_INIT = 0x10,
- CD1400_LOOP = 0x11,
- CD1400_INTERRUPT = 0x12
-};
-
-enum result {
- E_PORT = 0x10,
- E_TX = 0x11,
- E_RX = 0x12,
- E_EXCEPT = 0x13,
- E_COMPARE = 0x14,
- E_MODEM = 0x15,
- E_TIMEOUT = 0x16,
- E_INTERRUPT = 0x17
-};
-#endif /* _selftests_h_ */
diff --git a/drivers/char/rio/sysmap.h b/drivers/char/rio/sysmap.h
deleted file mode 100644
index e1c6f1160df..00000000000
--- a/drivers/char/rio/sysmap.h
+++ /dev/null
@@ -1,62 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* S Y S T E M M A P H E A D E R
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_sysmap_h_sccs = "@(#)sysmap.h 1.1";
-#endif
-#endif
-
-#define SYSTEM_MAP_LEN 64 /* Len of System Map array */
-
-
-typedef struct SYS_MAP SYS_MAP;
-typedef struct SYS_MAP_LINK SYS_MAP_LINK;
-
-struct SYS_MAP_LINK {
- short id; /* Unit Id */
- short link; /* Id's Link */
- short been_here; /* Used by map_gen */
-};
-
-struct SYS_MAP {
- char serial_num[4];
- SYS_MAP_LINK link[4];
-};
-
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/timeouts.h b/drivers/char/rio/timeouts.h
deleted file mode 100644
index a8b5be3ca9b..00000000000
--- a/drivers/char/rio/timeouts.h
+++ /dev/null
@@ -1,50 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* T I M E O U T S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_defaults_h_sccs = "@(#)timeouts.h 1.3";
-#endif
-#endif
-
-#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */
-#define SECOND (int) 15625 /* Low priority ticks */
-
-#define TX_TIMEOUT (int) (200 * MILLISECOND)
-
-
-/*********** end of file ***********/
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 0949dcef069..7edc6a4dbdc 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -433,7 +433,7 @@ static void rp_do_receive(struct r_port *info,
count += ToRecv;
}
/* Push the data up to the tty layer */
- ld->receive_buf(tty, cbuf, fbuf, count);
+ ld->receive_buf(tty, chead, fhead, count);
done:
tty_ldisc_deref(ld);
}
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 80a5b840e22..fee68cc895f 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -103,6 +103,7 @@
#include <linux/serial.h>
#include <linux/generic_serial.h>
+#include <linux/tty_flip.h>
#include "ser_a2232.h"
#include "ser_a2232fw.h"
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 64bf89cb574..c2490e270f1 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -931,7 +931,7 @@ static int sx_set_real_termios (void *ptr)
case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break;
case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break;
default:
- printk (KERN_INFO "sx: Invalid wordsize: %d\n", CFLAG & CSIZE);
+ printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
break;
}
@@ -958,7 +958,7 @@ static int sx_set_real_termios (void *ptr)
} else {
set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
}
- sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
+ sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
port->gs.tty->termios->c_iflag,
I_OTHER(port->gs.tty));
@@ -973,7 +973,7 @@ static int sx_set_real_termios (void *ptr)
} else {
clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
}
- sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
+ sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
port->gs.tty->termios->c_oflag,
O_OTHER(port->gs.tty));
/* port->c_dcd = sx_get_CD (port); */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 07c9be6a6bb..a85a60a93de 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -2630,7 +2630,7 @@ static int get_interface(struct slgt_info *info, int __user *if_mode)
static int set_interface(struct slgt_info *info, int if_mode)
{
unsigned long flags;
- unsigned char val;
+ unsigned short val;
DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode));
spin_lock_irqsave(&info->lock,flags);
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5765f672e85..d58f8231885 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -243,7 +243,7 @@ static struct sysrq_key_op sysrq_term_op = {
static void moom_callback(void *ignored)
{
- out_of_memory(GFP_KERNEL, 0);
+ out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0);
}
static DECLARE_WORK(moom_work, moom_callback, NULL);
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 41a94bc79f6..eb2eb3e12d6 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -250,12 +250,17 @@ tipar_open(struct inode *inode, struct file *file)
{
unsigned int minor = iminor(inode) - TIPAR_MINOR;
- if (minor > tp_count - 1)
+ if (tp_count == 0 || minor > tp_count - 1)
return -ENXIO;
if (test_and_set_bit(minor, &opened))
return -EBUSY;
+ if (!table[minor].dev) {
+ printk(KERN_ERR "%s: NULL device for minor %u\n",
+ __FUNCTION__, minor);
+ return -ENXIO;
+ }
parport_claim_or_block(table[minor].dev);
init_ti_parallel(minor);
parport_release(table[minor].dev);
@@ -510,16 +515,20 @@ tipar_init_module(void)
err = PTR_ERR(tipar_class);
goto out_chrdev;
}
- if (parport_register_driver(&tipar_driver)) {
+ if (parport_register_driver(&tipar_driver) || tp_count == 0) {
printk(KERN_ERR "tipar: unable to register with parport\n");
err = -EIO;
- goto out;
+ goto out_class;
}
err = 0;
goto out;
+out_class:
+ class_destroy(tipar_class);
+
out_chrdev:
+ devfs_remove("ticables/par");
unregister_chrdev(TIPAR_MAJOR, "tipar");
out:
return err;
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index bc56df8a347..4c272189cd4 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -34,7 +34,6 @@
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
-#include <linux/delay.h> /* udelay */
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
@@ -156,6 +155,8 @@ This directory exports the following interfaces. There operation is
documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
alarms :
current_ref :
+received_ref_clk3a :
+received_ref_clk3b :
enable_clk3a_output :
enable_clk3b_output :
enable_clka0_output :
@@ -165,7 +166,7 @@ enable_clkb1_output :
filter_select :
hardware_switching :
hardware_switching_mode :
-interrupt_switch :
+telclock_version :
mode_select :
refalign :
reset :
@@ -173,7 +174,6 @@ select_amcb1_transmit_clock :
select_amcb2_transmit_clock :
select_redundant_clock :
select_ref_frequency :
-test_mode :
All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
has the same effect as echo 0x99 > refalign.
@@ -226,7 +226,7 @@ static int tlclk_release(struct inode *inode, struct file *filp)
return 0;
}
-ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
+static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
if (count < sizeof(struct tlclk_alarms))
@@ -242,7 +242,7 @@ ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
return sizeof(struct tlclk_alarms);
}
-ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
+static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
return 0;
@@ -278,21 +278,21 @@ static ssize_t show_current_ref(struct device *d,
static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
-static ssize_t show_interrupt_switch(struct device *d,
+static ssize_t show_telclock_version(struct device *d,
struct device_attribute *attr, char *buf)
{
unsigned long ret_val;
unsigned long flags;
spin_lock_irqsave(&event_lock, flags);
- ret_val = inb(TLCLK_REG6);
+ ret_val = inb(TLCLK_REG5);
spin_unlock_irqrestore(&event_lock, flags);
return sprintf(buf, "0x%lX\n", ret_val);
}
-static DEVICE_ATTR(interrupt_switch, S_IRUGO,
- show_interrupt_switch, NULL);
+static DEVICE_ATTR(telclock_version, S_IRUGO,
+ show_telclock_version, NULL);
static ssize_t show_alarms(struct device *d,
struct device_attribute *attr, char *buf)
@@ -309,6 +309,50 @@ static ssize_t show_alarms(struct device *d,
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static ssize_t store_received_ref_clk3a(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, ": tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG1, 0xef, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL,
+ store_received_ref_clk3a);
+
+
+static ssize_t store_received_ref_clk3b(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, ": tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG1, 0xef, val << 1);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL,
+ store_received_ref_clk3b);
+
+
static ssize_t store_enable_clk3b_output(struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -436,26 +480,6 @@ static ssize_t store_enable_clka0_output(struct device *d,
static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
store_enable_clka0_output);
-static ssize_t store_test_mode(struct device *d,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned long flags;
- unsigned long tmp;
- unsigned char val;
-
- sscanf(buf, "%lX", &tmp);
- dev_dbg(d, "tmp = 0x%lX\n", tmp);
-
- val = (unsigned char)tmp;
- spin_lock_irqsave(&event_lock, flags);
- SET_PORT_BITS(TLCLK_REG4, 0xfd, 2);
- spin_unlock_irqrestore(&event_lock, flags);
-
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(test_mode, S_IWUGO, NULL, store_test_mode);
-
static ssize_t store_select_amcb2_transmit_clock(struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -475,7 +499,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
switch (val) {
case CLK_8_592MHz:
- SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
break;
case CLK_11_184MHz:
SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
@@ -484,7 +508,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
break;
case CLK_44_736MHz:
- SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
break;
}
} else
@@ -653,9 +677,7 @@ static ssize_t store_refalign (struct device *d,
dev_dbg(d, "tmp = 0x%lX\n", tmp);
spin_lock_irqsave(&event_lock, flags);
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
- udelay(2);
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
- udelay(2);
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
spin_unlock_irqrestore(&event_lock, flags);
@@ -706,15 +728,16 @@ static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset);
static struct attribute *tlclk_sysfs_entries[] = {
&dev_attr_current_ref.attr,
- &dev_attr_interrupt_switch.attr,
+ &dev_attr_telclock_version.attr,
&dev_attr_alarms.attr,
+ &dev_attr_received_ref_clk3a.attr,
+ &dev_attr_received_ref_clk3b.attr,
&dev_attr_enable_clk3a_output.attr,
&dev_attr_enable_clk3b_output.attr,
&dev_attr_enable_clkb1_output.attr,
&dev_attr_enable_clka1_output.attr,
&dev_attr_enable_clkb0_output.attr,
&dev_attr_enable_clka0_output.attr,
- &dev_attr_test_mode.attr,
&dev_attr_select_amcb1_transmit_clock.attr,
&dev_attr_select_amcb2_transmit_clock.attr,
&dev_attr_select_redundant_clock.attr,
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index aedf7a8e6da..537aa45d8c6 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -191,7 +191,7 @@ static int get_event_name(char *dest, struct tcpa_event *event,
const char *name = "";
char data[40] = "";
int i, n_len = 0, d_len = 0;
- u32 event_id, event_data_size;
+ u32 event_id;
switch(event->event_type) {
case PREBOOT:
@@ -220,8 +220,7 @@ static int get_event_name(char *dest, struct tcpa_event *event,
}
break;
case EVENT_TAG:
- event_id = be32_to_cpu(event_entry);
- event_data_size = be32_to_cpu(&event_entry[4]);
+ event_id = be32_to_cpu(*((u32 *)event_entry));
/* ToDo Row data -> Base64 */
@@ -376,7 +375,7 @@ static int read_log(struct tpm_bios_log *log)
{
struct acpi_tcpa *buff;
acpi_status status;
- void *virt;
+ struct acpi_table_header *virt;
if (log->bios_event_log != NULL) {
printk(KERN_ERR
@@ -413,7 +412,7 @@ static int read_log(struct tpm_bios_log *log)
log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
- acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, &virt);
+ acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
memcpy(log->bios_event_log, virt, buff->log_max_len);
@@ -487,26 +486,35 @@ struct file_operations tpm_binary_bios_measurements_ops = {
.release = tpm_bios_measurements_release,
};
+static int is_bad(void *p)
+{
+ if (!p)
+ return 1;
+ if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
+ return 1;
+ return 0;
+}
+
struct dentry **tpm_bios_log_setup(char *name)
{
struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
tpm_dir = securityfs_create_dir(name, NULL);
- if (!tpm_dir)
+ if (is_bad(tpm_dir))
goto out;
bin_file =
securityfs_create_file("binary_bios_measurements",
S_IRUSR | S_IRGRP, tpm_dir, NULL,
&tpm_binary_bios_measurements_ops);
- if (!bin_file)
+ if (is_bad(bin_file))
goto out_tpm;
ascii_file =
securityfs_create_file("ascii_bios_measurements",
S_IRUSR | S_IRGRP, tpm_dir, NULL,
&tpm_ascii_bios_measurements_ops);
- if (!ascii_file)
+ if (is_bad(ascii_file))
goto out_bin;
ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
@@ -538,3 +546,4 @@ void tpm_bios_log_teardown(struct dentry **lst)
securityfs_remove(lst[i]);
}
EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 8198dbb7370..24095f6ee6d 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -33,6 +33,7 @@
static int TPM_INF_DATA;
static int TPM_INF_ADDR;
static int TPM_INF_BASE;
+static int TPM_INF_ADDR_LEN;
static int TPM_INF_PORT_LEN;
/* TPM header definitions */
@@ -195,6 +196,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
int i;
int ret;
u32 size = 0;
+ number_of_wtx = 0;
recv_begin:
/* start receiving header */
@@ -378,24 +380,35 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
!(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
TPM_INF_ADDR = pnp_port_start(dev, 0);
+ TPM_INF_ADDR_LEN = pnp_port_len(dev, 0);
TPM_INF_DATA = (TPM_INF_ADDR + 1);
TPM_INF_BASE = pnp_port_start(dev, 1);
TPM_INF_PORT_LEN = pnp_port_len(dev, 1);
- if (!TPM_INF_PORT_LEN)
- return -EINVAL;
+ if ((TPM_INF_PORT_LEN < 4) || (TPM_INF_ADDR_LEN < 2)) {
+ rc = -EINVAL;
+ goto err_last;
+ }
dev_info(&dev->dev, "Found %s with ID %s\n",
dev->name, dev_id->id);
- if (!((TPM_INF_BASE >> 8) & 0xff))
- return -EINVAL;
+ if (!((TPM_INF_BASE >> 8) & 0xff)) {
+ rc = -EINVAL;
+ goto err_last;
+ }
/* publish my base address and request region */
tpm_inf.base = TPM_INF_BASE;
if (request_region
(tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
- return -EINVAL;
+ rc = -EINVAL;
+ goto err_last;
+ }
+ if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
+ "tpm_infineon0") == NULL) {
+ rc = -EINVAL;
+ goto err_last;
}
} else {
- return -EINVAL;
+ rc = -EINVAL;
+ goto err_last;
}
/* query chip for its vendor, its version number a.s.o. */
@@ -441,10 +454,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
if ((ioh << 8 | iol) != tpm_inf.base) {
dev_err(&dev->dev,
- "Could not set IO-ports to %04x\n",
+ "Could not set IO-ports to 0x%lx\n",
tpm_inf.base);
- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
- return -EIO;
+ rc = -EIO;
+ goto err_release_region;
}
/* activate register */
@@ -471,14 +484,21 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
rc = tpm_register_hardware(&dev->dev, &tpm_inf);
if (rc < 0) {
- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_release_region;
}
return 0;
} else {
- dev_info(&dev->dev, "No Infineon TPM found!\n");
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_release_region;
}
+
+err_release_region:
+ release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
+
+err_last:
+ return rc;
}
static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
@@ -518,5 +538,5 @@ module_exit(cleanup_inf);
MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.6");
+MODULE_VERSION("1.7");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index eb8b5be4e24..e9bba94fc89 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -253,6 +253,7 @@ static void tty_buffer_free_all(struct tty_struct *tty)
static void tty_buffer_init(struct tty_struct *tty)
{
+ spin_lock_init(&tty->buf.lock);
tty->buf.head = NULL;
tty->buf.tail = NULL;
tty->buf.free = NULL;
@@ -266,6 +267,9 @@ static struct tty_buffer *tty_buffer_alloc(size_t size)
p->used = 0;
p->size = size;
p->next = NULL;
+ p->active = 0;
+ p->commit = 0;
+ p->read = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
/* printk("Flip create %p\n", p); */
@@ -296,6 +300,8 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
*tbh = t->next;
t->next = NULL;
t->used = 0;
+ t->commit = 0;
+ t->read = 0;
/* DEBUG ONLY */
memset(t->data, '*', size);
/* printk("Flip recycle %p\n", t); */
@@ -312,25 +318,37 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
- struct tty_buffer *b = tty->buf.tail, *n;
- int left = 0;
+ struct tty_buffer *b, *n;
+ int left;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->buf.lock, flags);
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
remove this conditional if its worth it. This would be invisible
to the callers */
- if(b != NULL)
+ if ((b = tty->buf.tail) != NULL) {
left = b->size - b->used;
- if(left >= size)
- return size;
- /* This is the slow path - looking for new buffers to use */
- n = tty_buffer_find(tty, size);
- if(n == NULL)
- return left;
- if(b != NULL)
- b->next = n;
- else
- tty->buf.head = n;
- tty->buf.tail = n;
+ b->active = 1;
+ } else
+ left = 0;
+
+ if (left < size) {
+ /* This is the slow path - looking for new buffers to use */
+ if ((n = tty_buffer_find(tty, size)) != NULL) {
+ if (b != NULL) {
+ b->next = n;
+ b->active = 0;
+ b->commit = b->used;
+ } else
+ tty->buf.head = n;
+ tty->buf.tail = n;
+ n->active = 1;
+ } else
+ size = left;
+ }
+
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
return size;
}
@@ -396,10 +414,12 @@ EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
{
int space = tty_buffer_request_room(tty, size);
- struct tty_buffer *tb = tty->buf.tail;
- *chars = tb->char_buf_ptr + tb->used;
- memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
- tb->used += space;
+ if (likely(space)) {
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ }
return space;
}
@@ -416,10 +436,12 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
{
int space = tty_buffer_request_room(tty, size);
- struct tty_buffer *tb = tty->buf.tail;
- *chars = tb->char_buf_ptr + tb->used;
- *flags = tb->flag_buf_ptr + tb->used;
- tb->used += space;
+ if (likely(space)) {
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ *flags = tb->flag_buf_ptr + tb->used;
+ tb->used += space;
+ }
return space;
}
@@ -1819,7 +1841,6 @@ static void release_dev(struct file * filp)
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
- up(&tty_sem);
do_sleep = 0;
if (tty_closing) {
@@ -1847,6 +1868,7 @@ static void release_dev(struct file * filp)
printk(KERN_WARNING "release_dev: %s: read/write wait queue "
"active!\n", tty_name(tty, buf));
+ up(&tty_sem);
schedule();
}
@@ -1855,8 +1877,6 @@ static void release_dev(struct file * filp)
* both sides, and we've completed the last operation that could
* block, so it's safe to proceed with closing.
*/
-
- down(&tty_sem);
if (pty_master) {
if (--o_tty->count < 0) {
printk(KERN_WARNING "release_dev: bad pty slave count "
@@ -1870,7 +1890,6 @@ static void release_dev(struct file * filp)
tty->count, tty_name(tty, buf));
tty->count = 0;
}
- up(&tty_sem);
/*
* We've decremented tty->count, so we need to remove this file
@@ -1915,6 +1934,8 @@ static void release_dev(struct file * filp)
read_unlock(&tasklist_lock);
}
+ up(&tty_sem);
+
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing))
return;
@@ -2735,6 +2756,9 @@ static void flush_to_ldisc(void *private_)
unsigned long flags;
struct tty_ldisc *disc;
struct tty_buffer *tbuf;
+ int count;
+ char *char_buf;
+ unsigned char *flag_buf;
disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
@@ -2747,20 +2771,24 @@ static void flush_to_ldisc(void *private_)
schedule_delayed_work(&tty->buf.work, 1);
goto out;
}
- spin_lock_irqsave(&tty->read_lock, flags);
+ spin_lock_irqsave(&tty->buf.lock, flags);
while((tbuf = tty->buf.head) != NULL) {
+ while ((count = tbuf->commit - tbuf->read) != 0) {
+ char_buf = tbuf->char_buf_ptr + tbuf->read;
+ flag_buf = tbuf->flag_buf_ptr + tbuf->read;
+ tbuf->read += count;
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ disc->receive_buf(tty, char_buf, flag_buf, count);
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ }
+ if (tbuf->active)
+ break;
tty->buf.head = tbuf->next;
if (tty->buf.head == NULL)
tty->buf.tail = NULL;
- spin_unlock_irqrestore(&tty->read_lock, flags);
- /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */
- disc->receive_buf(tty, tbuf->char_buf_ptr,
- tbuf->flag_buf_ptr,
- tbuf->used);
- spin_lock_irqsave(&tty->read_lock, flags);
tty_buffer_free(tty, tbuf);
}
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
out:
tty_ldisc_deref(disc);
}
@@ -2852,6 +2880,14 @@ EXPORT_SYMBOL(tty_get_baud_rate);
void tty_flip_buffer_push(struct tty_struct *tty)
{
+ unsigned long flags;
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ if (tty->buf.tail != NULL) {
+ tty->buf.tail->active = 0;
+ tty->buf.tail->commit = tty->buf.tail->used;
+ }
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+
if (tty->low_latency)
flush_to_ldisc((void *) tty);
else
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index f1d9cb7feae..0900d1dbee5 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -3213,6 +3213,7 @@ void getconsxy(struct vc_data *vc, unsigned char *p)
void putconsxy(struct vc_data *vc, unsigned char *p)
{
+ hide_cursor(vc);
gotoxy(vc, p[0], p[1]);
set_cursor(vc);
}
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 37c9e13ad3a..8d6b249ad66 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -49,29 +49,37 @@
* More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
*/
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/config.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/reboot.h>
+#include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */
+#include <linux/module.h> /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h> /* For standard types (like size_t) */
+#include <linux/errno.h> /* For the -ENODEV/... values */
+#include <linux/kernel.h> /* For printk/panic/... */
+#include <linux/delay.h> /* For mdelay function */
+#include <linux/timer.h> /* For timer related operations */
+#include <linux/jiffies.h> /* For jiffies stuff */
+#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h> /* For the watchdog specific items */
+#include <linux/notifier.h> /* For notifier support */
+#include <linux/reboot.h> /* For reboot_notifier stuff */
+#include <linux/init.h> /* For __init/__exit/... */
+#include <linux/fs.h> /* For file operations */
+#include <linux/ioport.h> /* For io-port access */
+#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
#include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/slab.h> /* For kmalloc */
-#define WD_VER "1.16 (06/12/2004)"
-#define PFX "pcwd: "
+#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
+#include <asm/io.h> /* For inb/outb/... */
+
+/* Module and version information */
+#define WATCHDOG_VERSION "1.16"
+#define WATCHDOG_DATE "03 Jan 2006"
+#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
+#define WATCHDOG_NAME "pcwd"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n"
+#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")"
/*
* It should be noted that PCWD_REVISION_B was removed because A and B
@@ -85,36 +93,38 @@
/*
* These are the defines that describe the control status bits for the
- * PC Watchdog card, revision A.
- */
+ * PCI-PC Watchdog card.
+*/
+/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
#define WD_WDRST 0x01 /* Previously reset state */
#define WD_T110 0x02 /* Temperature overheat sense */
#define WD_HRTBT 0x04 /* Heartbeat sense */
#define WD_RLY2 0x08 /* External relay triggered */
#define WD_SRLY2 0x80 /* Software external relay triggered */
-
-/*
- * These are the defines that describe the control status bits for the
- * PC Watchdog card, revision C.
- */
+/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */
#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */
#define WD_REVC_TTRP 0x04 /* Temperature Trip status */
+/* Port 2 : Control Status #2 */
+#define WD_WDIS 0x10 /* Watchdog Disabled */
+#define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */
+#define WD_SSEL 0x40 /* Watchdog Switch Select (1:SW1 <-> 0:SW2) */
+#define WD_WCMD 0x80 /* Watchdog Command Mode */
/* max. time we give an ISA watchdog card to process a command */
/* 500ms for each 4 bit response (according to spec.) */
#define ISA_COMMAND_TIMEOUT 1000
/* Watchdog's internal commands */
-#define CMD_ISA_IDLE 0x00
-#define CMD_ISA_VERSION_INTEGER 0x01
-#define CMD_ISA_VERSION_TENTH 0x02
-#define CMD_ISA_VERSION_HUNDRETH 0x03
-#define CMD_ISA_VERSION_MINOR 0x04
-#define CMD_ISA_SWITCH_SETTINGS 0x05
-#define CMD_ISA_DELAY_TIME_2SECS 0x0A
-#define CMD_ISA_DELAY_TIME_4SECS 0x0B
-#define CMD_ISA_DELAY_TIME_8SECS 0x0C
+#define CMD_ISA_IDLE 0x00
+#define CMD_ISA_VERSION_INTEGER 0x01
+#define CMD_ISA_VERSION_TENTH 0x02
+#define CMD_ISA_VERSION_HUNDRETH 0x03
+#define CMD_ISA_VERSION_MINOR 0x04
+#define CMD_ISA_SWITCH_SETTINGS 0x05
+#define CMD_ISA_DELAY_TIME_2SECS 0x0A
+#define CMD_ISA_DELAY_TIME_4SECS 0x0B
+#define CMD_ISA_DELAY_TIME_8SECS 0x0C
/*
* We are using an kernel timer to do the pinging of the watchdog
@@ -130,15 +140,17 @@ static int cards_found;
/* internal variables */
static atomic_t open_allowed = ATOMIC_INIT(1);
static char expect_close;
-static struct timer_list timer;
-static unsigned long next_heartbeat;
static int temp_panic;
-static int revision; /* The card's revision */
-static int supports_temp; /* Wether or not the card has a temperature device */
-static int command_mode; /* Wether or not the card is in command mode */
-static int initial_status; /* The card's boot status */
-static int current_readport; /* The cards I/O address */
-static spinlock_t io_lock;
+static struct { /* this is private data for each ISA-PC watchdog card */
+ int revision; /* The card's revision */
+ int supports_temp; /* Wether or not the card has a temperature device */
+ int command_mode; /* Wether or not the card is in command mode */
+ int boot_status; /* The card's boot status */
+ int io_addr; /* The cards I/O address */
+ spinlock_t io_lock; /* the lock for io operations */
+ struct timer_list timer; /* The timer that pings the watchdog */
+ unsigned long next_heartbeat; /* the next_heartbeat for the timer */
+} pcwd_private;
/* module parameters */
#define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */
@@ -161,14 +173,14 @@ static int send_isa_command(int cmd)
int port0, last_port0; /* Double read for stabilising */
/* The WCMD bit must be 1 and the command is only 4 bits in size */
- control_status = (cmd & 0x0F) | 0x80;
- outb_p(control_status, current_readport + 2);
+ control_status = (cmd & 0x0F) | WD_WCMD;
+ outb_p(control_status, pcwd_private.io_addr + 2);
udelay(ISA_COMMAND_TIMEOUT);
- port0 = inb_p(current_readport);
+ port0 = inb_p(pcwd_private.io_addr);
for (i = 0; i < 25; ++i) {
last_port0 = port0;
- port0 = inb_p(current_readport);
+ port0 = inb_p(pcwd_private.io_addr);
if (port0 == last_port0)
break; /* Data is stable */
@@ -184,7 +196,7 @@ static int set_command_mode(void)
int i, found=0, count=0;
/* Set the card into command mode */
- spin_lock(&io_lock);
+ spin_lock(&pcwd_private.io_lock);
while ((!found) && (count < 3)) {
i = send_isa_command(CMD_ISA_IDLE);
@@ -192,15 +204,15 @@ static int set_command_mode(void)
found = 1;
else if (i == 0xF3) {
/* Card does not like what we've done to it */
- outb_p(0x00, current_readport + 2);
+ outb_p(0x00, pcwd_private.io_addr + 2);
udelay(1200); /* Spec says wait 1ms */
- outb_p(0x00, current_readport + 2);
+ outb_p(0x00, pcwd_private.io_addr + 2);
udelay(ISA_COMMAND_TIMEOUT);
}
count++;
}
- spin_unlock(&io_lock);
- command_mode = found;
+ spin_unlock(&pcwd_private.io_lock);
+ pcwd_private.command_mode = found;
return(found);
}
@@ -208,12 +220,95 @@ static int set_command_mode(void)
static void unset_command_mode(void)
{
/* Set the card into normal mode */
- spin_lock(&io_lock);
- outb_p(0x00, current_readport + 2);
+ spin_lock(&pcwd_private.io_lock);
+ outb_p(0x00, pcwd_private.io_addr + 2);
udelay(ISA_COMMAND_TIMEOUT);
- spin_unlock(&io_lock);
+ spin_unlock(&pcwd_private.io_lock);
+
+ pcwd_private.command_mode = 0;
+}
+
+static inline void pcwd_check_temperature_support(void)
+{
+ if (inb(pcwd_private.io_addr) != 0xF0)
+ pcwd_private.supports_temp = 1;
+}
+
+static inline char *get_firmware(void)
+{
+ int one, ten, hund, minor;
+ char *ret;
+
+ ret = kmalloc(6, GFP_KERNEL);
+ if(ret == NULL)
+ return NULL;
+
+ if (set_command_mode()) {
+ one = send_isa_command(CMD_ISA_VERSION_INTEGER);
+ ten = send_isa_command(CMD_ISA_VERSION_TENTH);
+ hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
+ minor = send_isa_command(CMD_ISA_VERSION_MINOR);
+ sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+ }
+ else
+ sprintf(ret, "ERROR");
+
+ unset_command_mode();
+ return(ret);
+}
+
+static inline int pcwd_get_option_switches(void)
+{
+ int option_switches=0;
+
+ if (set_command_mode()) {
+ /* Get switch settings */
+ option_switches = send_isa_command(CMD_ISA_SWITCH_SETTINGS);
+ }
+
+ unset_command_mode();
+ return(option_switches);
+}
+
+static void pcwd_show_card_info(void)
+{
+ char *firmware;
+ int option_switches;
+
+ /* Get some extra info from the hardware (in command/debug/diag mode) */
+ if (pcwd_private.revision == PCWD_REVISION_A)
+ printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
+ else if (pcwd_private.revision == PCWD_REVISION_C) {
+ firmware = get_firmware();
+ printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
+ pcwd_private.io_addr, firmware);
+ kfree(firmware);
+ option_switches = pcwd_get_option_switches();
+ printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
+ option_switches,
+ ((option_switches & 0x10) ? "ON" : "OFF"),
+ ((option_switches & 0x08) ? "ON" : "OFF"));
+
+ /* Reprogram internal heartbeat to 2 seconds */
+ if (set_command_mode()) {
+ send_isa_command(CMD_ISA_DELAY_TIME_2SECS);
+ unset_command_mode();
+ }
+ }
+
+ if (pcwd_private.supports_temp)
+ printk(KERN_INFO PFX "Temperature Option Detected\n");
+
+ if (pcwd_private.boot_status & WDIOF_CARDRESET)
+ printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
+
+ if (pcwd_private.boot_status & WDIOF_OVERHEAT) {
+ printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n");
+ printk(KERN_EMERG PFX "CPU Overheat\n");
+ }
- command_mode = 0;
+ if (pcwd_private.boot_status == 0)
+ printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
}
static void pcwd_timer_ping(unsigned long data)
@@ -222,25 +317,25 @@ static void pcwd_timer_ping(unsigned long data)
/* If we got a heartbeat pulse within the WDT_INTERVAL
* we agree to ping the WDT */
- if(time_before(jiffies, next_heartbeat)) {
+ if(time_before(jiffies, pcwd_private.next_heartbeat)) {
/* Ping the watchdog */
- spin_lock(&io_lock);
- if (revision == PCWD_REVISION_A) {
+ spin_lock(&pcwd_private.io_lock);
+ if (pcwd_private.revision == PCWD_REVISION_A) {
/* Rev A cards are reset by setting the WD_WDRST bit in register 1 */
- wdrst_stat = inb_p(current_readport);
+ wdrst_stat = inb_p(pcwd_private.io_addr);
wdrst_stat &= 0x0F;
wdrst_stat |= WD_WDRST;
- outb_p(wdrst_stat, current_readport + 1);
+ outb_p(wdrst_stat, pcwd_private.io_addr + 1);
} else {
/* Re-trigger watchdog by writing to port 0 */
- outb_p(0x00, current_readport);
+ outb_p(0x00, pcwd_private.io_addr);
}
/* Re-set the timer interval */
- mod_timer(&timer, jiffies + WDT_INTERVAL);
+ mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
- spin_unlock(&io_lock);
+ spin_unlock(&pcwd_private.io_lock);
} else {
printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
}
@@ -250,19 +345,19 @@ static int pcwd_start(void)
{
int stat_reg;
- next_heartbeat = jiffies + (heartbeat * HZ);
+ pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
/* Start the timer */
- mod_timer(&timer, jiffies + WDT_INTERVAL);
+ mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
/* Enable the port */
- if (revision == PCWD_REVISION_C) {
- spin_lock(&io_lock);
- outb_p(0x00, current_readport + 3);
+ if (pcwd_private.revision == PCWD_REVISION_C) {
+ spin_lock(&pcwd_private.io_lock);
+ outb_p(0x00, pcwd_private.io_addr + 3);
udelay(ISA_COMMAND_TIMEOUT);
- stat_reg = inb_p(current_readport + 2);
- spin_unlock(&io_lock);
- if (stat_reg & 0x10) {
+ stat_reg = inb_p(pcwd_private.io_addr + 2);
+ spin_unlock(&pcwd_private.io_lock);
+ if (stat_reg & WD_WDIS) {
printk(KERN_INFO PFX "Could not start watchdog\n");
return -EIO;
}
@@ -275,18 +370,18 @@ static int pcwd_stop(void)
int stat_reg;
/* Stop the timer */
- del_timer(&timer);
+ del_timer(&pcwd_private.timer);
/* Disable the board */
- if (revision == PCWD_REVISION_C) {
- spin_lock(&io_lock);
- outb_p(0xA5, current_readport + 3);
+ if (pcwd_private.revision == PCWD_REVISION_C) {
+ spin_lock(&pcwd_private.io_lock);
+ outb_p(0xA5, pcwd_private.io_addr + 3);
udelay(ISA_COMMAND_TIMEOUT);
- outb_p(0xA5, current_readport + 3);
+ outb_p(0xA5, pcwd_private.io_addr + 3);
udelay(ISA_COMMAND_TIMEOUT);
- stat_reg = inb_p(current_readport + 2);
- spin_unlock(&io_lock);
- if ((stat_reg & 0x10) == 0) {
+ stat_reg = inb_p(pcwd_private.io_addr + 2);
+ spin_unlock(&pcwd_private.io_lock);
+ if ((stat_reg & WD_WDIS) == 0) {
printk(KERN_INFO PFX "Could not stop watchdog\n");
return -EIO;
}
@@ -297,7 +392,7 @@ static int pcwd_stop(void)
static int pcwd_keepalive(void)
{
/* user land ping */
- next_heartbeat = jiffies + (heartbeat * HZ);
+ pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
return 0;
}
@@ -315,23 +410,23 @@ static int pcwd_get_status(int *status)
int card_status;
*status=0;
- spin_lock(&io_lock);
- if (revision == PCWD_REVISION_A)
+ spin_lock(&pcwd_private.io_lock);
+ if (pcwd_private.revision == PCWD_REVISION_A)
/* Rev A cards return status information from
* the base register, which is used for the
* temperature in other cards. */
- card_status = inb(current_readport);
+ card_status = inb(pcwd_private.io_addr);
else {
/* Rev C cards return card status in the base
* address + 1 register. And use different bits
* to indicate a card initiated reset, and an
* over-temperature condition. And the reboot
* status can be reset. */
- card_status = inb(current_readport + 1);
+ card_status = inb(pcwd_private.io_addr + 1);
}
- spin_unlock(&io_lock);
+ spin_unlock(&pcwd_private.io_lock);
- if (revision == PCWD_REVISION_A) {
+ if (pcwd_private.revision == PCWD_REVISION_A) {
if (card_status & WD_WDRST)
*status |= WDIOF_CARDRESET;
@@ -360,10 +455,10 @@ static int pcwd_get_status(int *status)
static int pcwd_clear_status(void)
{
- if (revision == PCWD_REVISION_C) {
- spin_lock(&io_lock);
- outb_p(0x00, current_readport + 1); /* clear reset status */
- spin_unlock(&io_lock);
+ if (pcwd_private.revision == PCWD_REVISION_C) {
+ spin_lock(&pcwd_private.io_lock);
+ outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */
+ spin_unlock(&pcwd_private.io_lock);
}
return 0;
}
@@ -371,20 +466,20 @@ static int pcwd_clear_status(void)
static int pcwd_get_temperature(int *temperature)
{
/* check that port 0 gives temperature info and no command results */
- if (command_mode)
+ if (pcwd_private.command_mode)
return -1;
*temperature = 0;
- if (!supports_temp)
+ if (!pcwd_private.supports_temp)
return -ENODEV;
/*
* Convert celsius to fahrenheit, since this was
* the decided 'standard' for this return value.
*/
- spin_lock(&io_lock);
- *temperature = ((inb(current_readport)) * 9 / 5) + 32;
- spin_unlock(&io_lock);
+ spin_lock(&pcwd_private.io_lock);
+ *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
+ spin_unlock(&pcwd_private.io_lock);
return 0;
}
@@ -425,7 +520,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return put_user(status, argp);
case WDIOC_GETBOOTSTATUS:
- return put_user(initial_status, argp);
+ return put_user(pcwd_private.boot_status, argp);
case WDIOC_GETTEMP:
if (pcwd_get_temperature(&temperature))
@@ -434,7 +529,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return put_user(temperature, argp);
case WDIOC_SETOPTIONS:
- if (revision == PCWD_REVISION_C)
+ if (pcwd_private.revision == PCWD_REVISION_C)
{
if(copy_from_user(&rv, argp, sizeof(int)))
return -EFAULT;
@@ -550,7 +645,7 @@ static ssize_t pcwd_temp_read(struct file *file, char __user *buf, size_t count,
static int pcwd_temp_open(struct inode *inode, struct file *file)
{
- if (!supports_temp)
+ if (!pcwd_private.supports_temp)
return -ENODEV;
return nonseekable_open(inode, file);
@@ -616,68 +711,24 @@ static struct notifier_block pcwd_notifier = {
* Init & exit routines
*/
-static inline void get_support(void)
-{
- if (inb(current_readport) != 0xF0)
- supports_temp = 1;
-}
-
static inline int get_revision(void)
{
int r = PCWD_REVISION_C;
- spin_lock(&io_lock);
+ spin_lock(&pcwd_private.io_lock);
/* REV A cards use only 2 io ports; test
* presumes a floating bus reads as 0xff. */
- if ((inb(current_readport + 2) == 0xFF) ||
- (inb(current_readport + 3) == 0xFF))
+ if ((inb(pcwd_private.io_addr + 2) == 0xFF) ||
+ (inb(pcwd_private.io_addr + 3) == 0xFF))
r=PCWD_REVISION_A;
- spin_unlock(&io_lock);
+ spin_unlock(&pcwd_private.io_lock);
return r;
}
-static inline char *get_firmware(void)
-{
- int one, ten, hund, minor;
- char *ret;
-
- ret = kmalloc(6, GFP_KERNEL);
- if(ret == NULL)
- return NULL;
-
- if (set_command_mode()) {
- one = send_isa_command(CMD_ISA_VERSION_INTEGER);
- ten = send_isa_command(CMD_ISA_VERSION_TENTH);
- hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
- minor = send_isa_command(CMD_ISA_VERSION_MINOR);
- sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
- }
- else
- sprintf(ret, "ERROR");
-
- unset_command_mode();
- return(ret);
-}
-
-static inline int get_option_switches(void)
-{
- int rv=0;
-
- if (set_command_mode()) {
- /* Get switch settings */
- rv = send_isa_command(CMD_ISA_SWITCH_SETTINGS);
- }
-
- unset_command_mode();
- return(rv);
-}
-
static int __devinit pcwatchdog_init(int base_addr)
{
int ret;
- char *firmware;
- int option_switches;
cards_found++;
if (cards_found == 1)
@@ -692,104 +743,66 @@ static int __devinit pcwatchdog_init(int base_addr)
printk(KERN_ERR PFX "No I/O-Address for card detected\n");
return -ENODEV;
}
- current_readport = base_addr;
+ pcwd_private.io_addr = base_addr;
/* Check card's revision */
- revision = get_revision();
+ pcwd_private.revision = get_revision();
- if (!request_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
+ if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
- current_readport);
- current_readport = 0x0000;
+ pcwd_private.io_addr);
+ pcwd_private.io_addr = 0x0000;
return -EIO;
}
/* Initial variables */
- supports_temp = 0;
+ pcwd_private.supports_temp = 0;
temp_panic = 0;
- initial_status = 0x0000;
+ pcwd_private.boot_status = 0x0000;
/* get the boot_status */
- pcwd_get_status(&initial_status);
+ pcwd_get_status(&pcwd_private.boot_status);
/* clear the "card caused reboot" flag */
pcwd_clear_status();
- init_timer(&timer);
- timer.function = pcwd_timer_ping;
- timer.data = 0;
+ init_timer(&pcwd_private.timer);
+ pcwd_private.timer.function = pcwd_timer_ping;
+ pcwd_private.timer.data = 0;
/* Disable the board */
pcwd_stop();
/* Check whether or not the card supports the temperature device */
- get_support();
-
- /* Get some extra info from the hardware (in command/debug/diag mode) */
- if (revision == PCWD_REVISION_A)
- printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", current_readport);
- else if (revision == PCWD_REVISION_C) {
- firmware = get_firmware();
- printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
- current_readport, firmware);
- kfree(firmware);
- option_switches = get_option_switches();
- printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
- option_switches,
- ((option_switches & 0x10) ? "ON" : "OFF"),
- ((option_switches & 0x08) ? "ON" : "OFF"));
-
- /* Reprogram internal heartbeat to 2 seconds */
- if (set_command_mode()) {
- send_isa_command(CMD_ISA_DELAY_TIME_2SECS);
- unset_command_mode();
- }
- } else {
- /* Should NEVER happen, unless get_revision() fails. */
- printk(KERN_INFO PFX "Unable to get revision\n");
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
- return -1;
- }
+ pcwd_check_temperature_support();
- if (supports_temp)
- printk(KERN_INFO PFX "Temperature Option Detected\n");
-
- if (initial_status & WDIOF_CARDRESET)
- printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
-
- if (initial_status & WDIOF_OVERHEAT) {
- printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n");
- printk(KERN_EMERG PFX "CPU Overheat\n");
- }
-
- if (initial_status == 0)
- printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
+ /* Show info about the card itself */
+ pcwd_show_card_info();
/* Check that the heartbeat value is within it's range ; if not reset to the default */
- if (pcwd_set_heartbeat(heartbeat)) {
- pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
- printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n",
- WATCHDOG_HEARTBEAT);
+ if (pcwd_set_heartbeat(heartbeat)) {
+ pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
+ printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n",
+ WATCHDOG_HEARTBEAT);
}
ret = register_reboot_notifier(&pcwd_notifier);
if (ret) {
printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
ret);
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
+ release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+ pcwd_private.io_addr = 0x0000;
return ret;
}
- if (supports_temp) {
+ if (pcwd_private.supports_temp) {
ret = misc_register(&temp_miscdev);
if (ret) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
TEMP_MINOR, ret);
unregister_reboot_notifier(&pcwd_notifier);
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
+ release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+ pcwd_private.io_addr = 0x0000;
return ret;
}
}
@@ -798,11 +811,11 @@ static int __devinit pcwatchdog_init(int base_addr)
if (ret) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
- if (supports_temp)
+ if (pcwd_private.supports_temp)
misc_deregister(&temp_miscdev);
unregister_reboot_notifier(&pcwd_notifier);
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
+ release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+ pcwd_private.io_addr = 0x0000;
return ret;
}
@@ -820,11 +833,12 @@ static void __devexit pcwatchdog_exit(void)
/* Deregister */
misc_deregister(&pcwd_miscdev);
- if (supports_temp)
+ if (pcwd_private.supports_temp)
misc_deregister(&temp_miscdev);
unregister_reboot_notifier(&pcwd_notifier);
- release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
- current_readport = 0x0000;
+ release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+ pcwd_private.io_addr = 0x0000;
+ cards_found--;
}
/*
@@ -887,7 +901,7 @@ static int __init pcwd_init_module(void)
{
int i, found = 0;
- spin_lock_init(&io_lock);
+ spin_lock_init(&pcwd_private.io_lock);
for (i = 0; pcwd_ioports[i] != 0; i++) {
if (pcwd_checkcard(pcwd_ioports[i])) {
@@ -906,7 +920,7 @@ static int __init pcwd_init_module(void)
static void __exit pcwd_cleanup_module(void)
{
- if (current_readport)
+ if (pcwd_private.io_addr)
pcwatchdog_exit();
return;
}
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index b474ea52d6e..522a9370db9 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -93,23 +93,25 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
{
int ret = -ENOIOCTLCMD;
int time;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
switch (cmd) {
case WDIOC_GETSUPPORT:
- ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
+ ret = copy_to_user(argp, &ident,
sizeof(ident)) ? -EFAULT : 0;
break;
case WDIOC_GETSTATUS:
- ret = put_user(0, (int __user *)arg);
+ ret = put_user(0, p);
break;
case WDIOC_GETBOOTSTATUS:
- ret = put_user(boot_status, (int __user *)arg);
+ ret = put_user(boot_status, p);
break;
case WDIOC_SETTIMEOUT:
- ret = get_user(time, (int __user *)arg);
+ ret = get_user(time, p);
if (ret)
break;
@@ -123,7 +125,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
/*fall through*/
case WDIOC_GETTIMEOUT:
- ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg);
+ ret = put_user(pre_margin / OSCR_FREQ, p);
break;
case WDIOC_KEEPALIVE:
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
index 951764614eb..837b1ec3ffe 100644
--- a/drivers/char/watchdog/sbc_epx_c3.c
+++ b/drivers/char/watchdog/sbc_epx_c3.c
@@ -25,6 +25,7 @@
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -91,7 +92,7 @@ static int epx_c3_release(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t epx_c3_write(struct file *file, const char *data,
+static ssize_t epx_c3_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
/* Refresh the timer. */
@@ -104,6 +105,7 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int options, retval = -EINVAL;
+ int __user *argp = (void __user *)arg;
static struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
@@ -113,20 +115,19 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case WDIOC_GETSUPPORT:
- if (copy_to_user((struct watchdog_info *)arg,
- &ident, sizeof(ident)))
+ if (copy_to_user(argp, &ident, sizeof(ident)))
return -EFAULT;
return 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
- return put_user(0,(int *)arg);
+ return put_user(0, argp);
case WDIOC_KEEPALIVE:
epx_c3_pet();
return 0;
case WDIOC_GETTIMEOUT:
- return put_user(WATCHDOG_TIMEOUT,(int *)arg);
- case WDIOC_SETOPTIONS: {
- if (get_user(options, (int *)arg))
+ return put_user(WATCHDOG_TIMEOUT, argp);
+ case WDIOC_SETOPTIONS:
+ if (get_user(options, argp))
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
@@ -140,7 +141,6 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
}
return retval;
- }
default:
return -ENOIOCTLCMD;
}
@@ -181,11 +181,14 @@ static int __init watchdog_init(void)
{
int ret;
+ if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog"))
+ return -EBUSY;
+
ret = register_reboot_notifier(&epx_c3_notifier);
if (ret) {
printk(KERN_ERR PFX "cannot register reboot notifier "
"(err=%d)\n", ret);
- return ret;
+ goto out;
}
ret = misc_register(&epx_c3_miscdev);
@@ -193,18 +196,23 @@ static int __init watchdog_init(void)
printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
"(err=%d)\n", WATCHDOG_MINOR, ret);
unregister_reboot_notifier(&epx_c3_notifier);
- return ret;
+ goto out;
}
printk(banner);
return 0;
+
+out:
+ release_region(EPXC3_WATCHDOG_CTL_REG, 2);
+ return ret;
}
static void __exit watchdog_exit(void)
{
misc_deregister(&epx_c3_miscdev);
unregister_reboot_notifier(&epx_c3_notifier);
+ release_region(EPXC3_WATCHDOG_CTL_REG, 2);
}
module_init(watchdog_init);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 277a843a87a..9582de1c9ca 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/completion.h>
+#include <linux/mutex.h>
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg)
@@ -34,8 +35,8 @@
* level driver of CPUFreq support, and its spinlock. This lock
* also protects the cpufreq_cpu_data array.
*/
-static struct cpufreq_driver *cpufreq_driver;
-static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
+static struct cpufreq_driver *cpufreq_driver;
+static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
static DEFINE_SPINLOCK(cpufreq_driver_lock);
/* internal prototypes */
@@ -49,15 +50,15 @@ static void handle_update(void *data);
* changes to devices when the CPU clock speed changes.
* The mutex locks both lists.
*/
-static struct notifier_block *cpufreq_policy_notifier_list;
-static struct notifier_block *cpufreq_transition_notifier_list;
-static DECLARE_RWSEM (cpufreq_notifier_rwsem);
+static struct notifier_block *cpufreq_policy_notifier_list;
+static struct notifier_block *cpufreq_transition_notifier_list;
+static DECLARE_RWSEM (cpufreq_notifier_rwsem);
static LIST_HEAD(cpufreq_governor_list);
-static DECLARE_MUTEX (cpufreq_governor_sem);
+static DEFINE_MUTEX (cpufreq_governor_mutex);
-struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
+struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
{
struct cpufreq_policy *data;
unsigned long flags;
@@ -84,20 +85,19 @@ struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
if (!kobject_get(&data->kobj))
goto err_out_put_module;
-
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
return data;
- err_out_put_module:
+err_out_put_module:
module_put(cpufreq_driver->owner);
- err_out_unlock:
+err_out_unlock:
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
- err_out:
+err_out:
return NULL;
}
EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
+
void cpufreq_cpu_put(struct cpufreq_policy *data)
{
kobject_put(&data->kobj);
@@ -228,44 +228,53 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) {
/**
- * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
+ * cpufreq_notify_transition - call notifier chain and adjust_jiffies
+ * on frequency transition.
*
- * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
- * twice on all CPU frequency changes that have external effects.
+ * This function calls the transition notifiers and the "adjust_jiffies"
+ * function. It is called twice on all CPU frequency changes that have
+ * external effects.
*/
void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
{
+ struct cpufreq_policy *policy;
+
BUG_ON(irqs_disabled());
freqs->flags = cpufreq_driver->flags;
- dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new);
+ dprintk("notification %u of frequency transition to %u kHz\n",
+ state, freqs->new);
down_read(&cpufreq_notifier_rwsem);
+
+ policy = cpufreq_cpu_data[freqs->cpu];
switch (state) {
+
case CPUFREQ_PRECHANGE:
- /* detect if the driver reported a value as "old frequency" which
- * is not equal to what the cpufreq core thinks is "old frequency".
+ /* detect if the driver reported a value as "old frequency"
+ * which is not equal to what the cpufreq core thinks is
+ * "old frequency".
*/
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
- if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
- (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) &&
- (likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
- (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
- {
- dprintk(KERN_WARNING "Warning: CPU frequency is %u, "
- "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
- freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
+ if ((policy) && (policy->cpu == freqs->cpu) &&
+ (policy->cur) && (policy->cur != freqs->old)) {
+ dprintk(KERN_WARNING "Warning: CPU frequency is"
+ " %u, cpufreq assumed %u kHz.\n",
+ freqs->old, policy->cur);
+ freqs->old = policy->cur;
}
}
- notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
+ notifier_call_chain(&cpufreq_transition_notifier_list,
+ CPUFREQ_PRECHANGE, freqs);
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
break;
+
case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
- notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
- if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
- (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)))
- cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
+ notifier_call_chain(&cpufreq_transition_notifier_list,
+ CPUFREQ_POSTCHANGE, freqs);
+ if (likely(policy) && likely(policy->cpu == freqs->cpu))
+ policy->cur = freqs->new;
break;
}
up_read(&cpufreq_notifier_rwsem);
@@ -297,18 +306,18 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
return -EINVAL;
} else {
struct cpufreq_governor *t;
- down(&cpufreq_governor_sem);
+ mutex_lock(&cpufreq_governor_mutex);
if (!cpufreq_driver || !cpufreq_driver->target)
goto out;
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
*governor = t;
- up(&cpufreq_governor_sem);
+ mutex_unlock(&cpufreq_governor_mutex);
return 0;
}
}
- out:
- up(&cpufreq_governor_sem);
+out:
+ mutex_unlock(&cpufreq_governor_mutex);
}
return -EINVAL;
}
@@ -414,7 +423,6 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
return -EINVAL;
ret = cpufreq_set_policy(&new_policy);
-
return ret ? ret : count;
}
@@ -445,7 +453,7 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy,
goto out;
i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
}
- out:
+out:
i += sprintf(&buf[i], "\n");
return i;
}
@@ -600,7 +608,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
policy->cpu = cpu;
policy->cpus = cpumask_of_cpu(cpu);
- init_MUTEX_LOCKED(&policy->lock);
+ mutex_init(&policy->lock);
+ mutex_lock(&policy->lock);
init_completion(&policy->kobj_unregister);
INIT_WORK(&policy->update, handle_update, (void *)(long)cpu);
@@ -610,6 +619,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
ret = cpufreq_driver->init(policy);
if (ret) {
dprintk("initialization failed\n");
+ mutex_unlock(&policy->lock);
goto err_out;
}
@@ -621,9 +631,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN);
ret = kobject_register(&policy->kobj);
- if (ret)
+ if (ret) {
+ mutex_unlock(&policy->lock);
goto err_out_driver_exit;
-
+ }
/* set up files for this cpu device */
drv_attr = cpufreq_driver->attr;
while ((drv_attr) && (*drv_attr)) {
@@ -641,7 +652,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
policy->governor = NULL; /* to assure that the starting sequence is
* run in cpufreq_set_policy */
- up(&policy->lock);
+ mutex_unlock(&policy->lock);
/* set default policy */
@@ -762,10 +773,10 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
#endif
- down(&data->lock);
+ mutex_lock(&data->lock);
if (cpufreq_driver->target)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
- up(&data->lock);
+ mutex_unlock(&data->lock);
kobject_unregister(&data->kobj);
@@ -785,7 +796,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
kfree(data);
cpufreq_debug_enable_ratelimit();
-
return 0;
}
@@ -834,9 +844,9 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
unsigned int ret = 0;
if (policy) {
- down(&policy->lock);
+ mutex_lock(&policy->lock);
ret = policy->cur;
- up(&policy->lock);
+ mutex_unlock(&policy->lock);
cpufreq_cpu_put(policy);
}
@@ -862,12 +872,11 @@ unsigned int cpufreq_get(unsigned int cpu)
if (!cpufreq_driver->get)
goto out;
- down(&policy->lock);
+ mutex_lock(&policy->lock);
ret = cpufreq_driver->get(cpu);
- if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS))
- {
+ if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
/* verify no discrepancy between actual and saved value exists */
if (unlikely(ret != policy->cur)) {
cpufreq_out_of_sync(cpu, policy->cur, ret);
@@ -875,9 +884,9 @@ unsigned int cpufreq_get(unsigned int cpu)
}
}
- up(&policy->lock);
+ mutex_unlock(&policy->lock);
- out:
+out:
cpufreq_cpu_put(policy);
return (ret);
@@ -958,7 +967,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
cpu_policy->cur = cur_freq;
}
- out:
+out:
cpufreq_cpu_put(cpu_policy);
return 0;
}
@@ -1158,14 +1167,13 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
if (!policy)
return -EINVAL;
- down(&policy->lock);
+ mutex_lock(&policy->lock);
ret = __cpufreq_driver_target(policy, target_freq, relation);
- up(&policy->lock);
+ mutex_unlock(&policy->lock);
cpufreq_cpu_put(policy);
-
return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_driver_target);
@@ -1199,12 +1207,11 @@ int cpufreq_governor(unsigned int cpu, unsigned int event)
if (!policy)
return -EINVAL;
- down(&policy->lock);
+ mutex_lock(&policy->lock);
ret = __cpufreq_governor(policy, event);
- up(&policy->lock);
+ mutex_unlock(&policy->lock);
cpufreq_cpu_put(policy);
-
return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_governor);
@@ -1217,18 +1224,17 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
if (!governor)
return -EINVAL;
- down(&cpufreq_governor_sem);
+ mutex_lock(&cpufreq_governor_mutex);
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
- up(&cpufreq_governor_sem);
+ mutex_unlock(&cpufreq_governor_mutex);
return -EBUSY;
}
}
list_add(&governor->governor_list, &cpufreq_governor_list);
- up(&cpufreq_governor_sem);
-
+ mutex_unlock(&cpufreq_governor_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_register_governor);
@@ -1239,9 +1245,9 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor)
if (!governor)
return;
- down(&cpufreq_governor_sem);
+ mutex_lock(&cpufreq_governor_mutex);
list_del(&governor->governor_list);
- up(&cpufreq_governor_sem);
+ mutex_unlock(&cpufreq_governor_mutex);
return;
}
EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
@@ -1268,12 +1274,11 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
if (!cpu_policy)
return -EINVAL;
- down(&cpu_policy->lock);
+ mutex_lock(&cpu_policy->lock);
memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
- up(&cpu_policy->lock);
+ mutex_unlock(&cpu_policy->lock);
cpufreq_cpu_put(cpu_policy);
-
return 0;
}
EXPORT_SYMBOL(cpufreq_get_policy);
@@ -1287,9 +1292,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
policy->min, policy->max);
- memcpy(&policy->cpuinfo,
- &data->cpuinfo,
- sizeof(struct cpufreq_cpuinfo));
+ memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
/* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(policy);
@@ -1320,8 +1323,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
up_read(&cpufreq_notifier_rwsem);
- data->min = policy->min;
- data->max = policy->max;
+ data->min = policy->min;
+ data->max = policy->max;
dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max);
@@ -1358,7 +1361,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
}
- error_out:
+error_out:
cpufreq_debug_enable_ratelimit();
return ret;
}
@@ -1382,7 +1385,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
return -EINVAL;
/* lock this CPU */
- down(&data->lock);
+ mutex_lock(&data->lock);
ret = __cpufreq_set_policy(data, policy);
data->user_policy.min = data->min;
@@ -1390,7 +1393,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
data->user_policy.policy = data->policy;
data->user_policy.governor = data->governor;
- up(&data->lock);
+ mutex_unlock(&data->lock);
cpufreq_cpu_put(data);
return ret;
@@ -1414,20 +1417,31 @@ int cpufreq_update_policy(unsigned int cpu)
if (!data)
return -ENODEV;
- down(&data->lock);
+ mutex_lock(&data->lock);
dprintk("updating policy for CPU %u\n", cpu);
- memcpy(&policy,
- data,
- sizeof(struct cpufreq_policy));
+ memcpy(&policy, data, sizeof(struct cpufreq_policy));
policy.min = data->user_policy.min;
policy.max = data->user_policy.max;
policy.policy = data->user_policy.policy;
policy.governor = data->user_policy.governor;
+ /* BIOS might change freq behind our back
+ -> ask driver for current freq and notify governors about a change */
+ if (cpufreq_driver->get) {
+ policy.cur = cpufreq_driver->get(cpu);
+ if (!data->cur) {
+ dprintk("Driver did not initialize current freq");
+ data->cur = policy.cur;
+ } else {
+ if (data->cur != policy.cur)
+ cpufreq_out_of_sync(cpu, data->cur, policy.cur);
+ }
+ }
+
ret = __cpufreq_set_policy(data, &policy);
- up(&data->lock);
+ mutex_unlock(&data->lock);
cpufreq_cpu_put(data);
return ret;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 39543a2bed0..ac38766b258 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -28,7 +28,7 @@
#include <linux/jiffies.h>
#include <linux/kernel_stat.h>
#include <linux/percpu.h>
-
+#include <linux/mutex.h>
/*
* dbs is used in this file as a shortform for demandbased switching
* It helps to keep variable names smaller, simpler
@@ -71,7 +71,7 @@ static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
static unsigned int dbs_enable; /* number of CPUs using this policy */
-static DECLARE_MUTEX (dbs_sem);
+static DEFINE_MUTEX (dbs_mutex);
static DECLARE_WORK (dbs_work, do_dbs_timer, NULL);
struct dbs_tuners {
@@ -139,9 +139,9 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
if (ret != 1 )
return -EINVAL;
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
dbs_tuners_ins.sampling_down_factor = input;
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -153,14 +153,14 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
int ret;
ret = sscanf (buf, "%u", &input);
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) {
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return -EINVAL;
}
dbs_tuners_ins.sampling_rate = input;
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -172,16 +172,16 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
int ret;
ret = sscanf (buf, "%u", &input);
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
input < MIN_FREQUENCY_UP_THRESHOLD ||
input <= dbs_tuners_ins.down_threshold) {
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return -EINVAL;
}
dbs_tuners_ins.up_threshold = input;
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -193,16 +193,16 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused,
int ret;
ret = sscanf (buf, "%u", &input);
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD ||
input < MIN_FREQUENCY_DOWN_THRESHOLD ||
input >= dbs_tuners_ins.up_threshold) {
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return -EINVAL;
}
dbs_tuners_ins.down_threshold = input;
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -222,9 +222,9 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
if ( input > 1 )
input = 1;
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
dbs_tuners_ins.ignore_nice = input;
@@ -236,7 +236,7 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up;
}
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -257,9 +257,9 @@ static ssize_t store_freq_step(struct cpufreq_policy *policy,
/* no need to test here if freq_step is zero as the user might actually
* want this, they would be crazy though :) */
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
dbs_tuners_ins.freq_step = input;
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -444,12 +444,12 @@ static void dbs_check_cpu(int cpu)
static void do_dbs_timer(void *data)
{
int i;
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
for_each_online_cpu(i)
dbs_check_cpu(i);
schedule_delayed_work(&dbs_work,
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
}
static inline void dbs_timer_init(void)
@@ -487,7 +487,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (this_dbs_info->enable) /* Already enabled */
break;
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
for_each_cpu_mask(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -521,11 +521,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
dbs_timer_init();
}
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
break;
case CPUFREQ_GOV_STOP:
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
this_dbs_info->enable = 0;
sysfs_remove_group(&policy->kobj, &dbs_attr_group);
dbs_enable--;
@@ -536,12 +536,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (dbs_enable == 0)
dbs_timer_exit();
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
break;
case CPUFREQ_GOV_LIMITS:
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if (policy->max < this_dbs_info->cur_policy->cur)
__cpufreq_driver_target(
this_dbs_info->cur_policy,
@@ -550,7 +550,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
__cpufreq_driver_target(
this_dbs_info->cur_policy,
policy->min, CPUFREQ_RELATION_L);
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
break;
}
return 0;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index e69fd8dd1f1..9ee9411f186 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -27,6 +27,7 @@
#include <linux/jiffies.h>
#include <linux/kernel_stat.h>
#include <linux/percpu.h>
+#include <linux/mutex.h>
/*
* dbs is used in this file as a shortform for demandbased switching
@@ -70,7 +71,7 @@ static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
static unsigned int dbs_enable; /* number of CPUs using this policy */
-static DECLARE_MUTEX (dbs_sem);
+static DEFINE_MUTEX (dbs_mutex);
static DECLARE_WORK (dbs_work, do_dbs_timer, NULL);
struct dbs_tuners {
@@ -136,9 +137,9 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
if (input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
return -EINVAL;
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
dbs_tuners_ins.sampling_down_factor = input;
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -150,14 +151,14 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
int ret;
ret = sscanf (buf, "%u", &input);
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) {
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return -EINVAL;
}
dbs_tuners_ins.sampling_rate = input;
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -169,15 +170,15 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
int ret;
ret = sscanf (buf, "%u", &input);
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
input < MIN_FREQUENCY_UP_THRESHOLD) {
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return -EINVAL;
}
dbs_tuners_ins.up_threshold = input;
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -197,9 +198,9 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
if ( input > 1 )
input = 1;
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
dbs_tuners_ins.ignore_nice = input;
@@ -211,7 +212,7 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up;
}
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
return count;
}
@@ -356,12 +357,12 @@ static void dbs_check_cpu(int cpu)
static void do_dbs_timer(void *data)
{
int i;
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
for_each_online_cpu(i)
dbs_check_cpu(i);
schedule_delayed_work(&dbs_work,
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
}
static inline void dbs_timer_init(void)
@@ -399,7 +400,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (this_dbs_info->enable) /* Already enabled */
break;
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
for_each_cpu_mask(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -435,11 +436,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
dbs_timer_init();
}
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
break;
case CPUFREQ_GOV_STOP:
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
this_dbs_info->enable = 0;
sysfs_remove_group(&policy->kobj, &dbs_attr_group);
dbs_enable--;
@@ -450,12 +451,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (dbs_enable == 0)
dbs_timer_exit();
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
break;
case CPUFREQ_GOV_LIMITS:
- down(&dbs_sem);
+ mutex_lock(&dbs_mutex);
if (policy->max < this_dbs_info->cur_policy->cur)
__cpufreq_driver_target(
this_dbs_info->cur_policy,
@@ -464,7 +465,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
__cpufreq_driver_target(
this_dbs_info->cur_policy,
policy->min, CPUFREQ_RELATION_L);
- up(&dbs_sem);
+ mutex_unlock(&dbs_mutex);
break;
}
return 0;
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index d32bf3593cd..92a0be22a2a 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -1,3 +1,4 @@
+
/*
* linux/drivers/cpufreq/cpufreq_userspace.c
*
@@ -21,6 +22,7 @@
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -33,9 +35,8 @@ static unsigned int cpu_min_freq[NR_CPUS];
static unsigned int cpu_cur_freq[NR_CPUS]; /* current CPU freq */
static unsigned int cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */
static unsigned int cpu_is_managed[NR_CPUS];
-static struct cpufreq_policy current_policy[NR_CPUS];
-static DECLARE_MUTEX (userspace_sem);
+static DEFINE_MUTEX (userspace_mutex);
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
@@ -64,35 +65,34 @@ static struct notifier_block userspace_cpufreq_notifier_block = {
*
* Sets the CPU frequency to freq.
*/
-static int cpufreq_set(unsigned int freq, unsigned int cpu)
+static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy)
{
int ret = -EINVAL;
- dprintk("cpufreq_set for cpu %u, freq %u kHz\n", cpu, freq);
+ dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
- down(&userspace_sem);
- if (!cpu_is_managed[cpu])
+ mutex_lock(&userspace_mutex);
+ if (!cpu_is_managed[policy->cpu])
goto err;
- cpu_set_freq[cpu] = freq;
+ cpu_set_freq[policy->cpu] = freq;
- if (freq < cpu_min_freq[cpu])
- freq = cpu_min_freq[cpu];
- if (freq > cpu_max_freq[cpu])
- freq = cpu_max_freq[cpu];
+ if (freq < cpu_min_freq[policy->cpu])
+ freq = cpu_min_freq[policy->cpu];
+ if (freq > cpu_max_freq[policy->cpu])
+ freq = cpu_max_freq[policy->cpu];
/*
* We're safe from concurrent calls to ->target() here
- * as we hold the userspace_sem lock. If we were calling
+ * as we hold the userspace_mutex lock. If we were calling
* cpufreq_driver_target, a deadlock situation might occur:
- * A: cpufreq_set (lock userspace_sem) -> cpufreq_driver_target(lock policy->lock)
- * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_sem)
+ * A: cpufreq_set (lock userspace_mutex) -> cpufreq_driver_target(lock policy->lock)
+ * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_mutex)
*/
- ret = __cpufreq_driver_target(&current_policy[cpu], freq,
- CPUFREQ_RELATION_L);
+ ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
err:
- up(&userspace_sem);
+ mutex_unlock(&userspace_mutex);
return ret;
}
@@ -113,7 +113,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
if (ret != 1)
return -EINVAL;
- cpufreq_set(freq, policy->cpu);
+ cpufreq_set(freq, policy);
return count;
}
@@ -134,44 +134,48 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
if (!cpu_online(cpu))
return -EINVAL;
BUG_ON(!policy->cur);
- down(&userspace_sem);
+ mutex_lock(&userspace_mutex);
cpu_is_managed[cpu] = 1;
cpu_min_freq[cpu] = policy->min;
cpu_max_freq[cpu] = policy->max;
cpu_cur_freq[cpu] = policy->cur;
cpu_set_freq[cpu] = policy->cur;
sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
- memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]);
- up(&userspace_sem);
+ mutex_unlock(&userspace_mutex);
break;
case CPUFREQ_GOV_STOP:
- down(&userspace_sem);
+ mutex_lock(&userspace_mutex);
cpu_is_managed[cpu] = 0;
cpu_min_freq[cpu] = 0;
cpu_max_freq[cpu] = 0;
cpu_set_freq[cpu] = 0;
sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
dprintk("managing cpu %u stopped\n", cpu);
- up(&userspace_sem);
+ mutex_unlock(&userspace_mutex);
break;
case CPUFREQ_GOV_LIMITS:
- down(&userspace_sem);
- cpu_min_freq[cpu] = policy->min;
- cpu_max_freq[cpu] = policy->max;
- dprintk("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu], cpu_set_freq[cpu]);
+ mutex_lock(&userspace_mutex);
+ dprintk("limit event for cpu %u: %u - %u kHz,"
+ "currently %u kHz, last set to %u kHz\n",
+ cpu, policy->min, policy->max,
+ cpu_cur_freq[cpu], cpu_set_freq[cpu]);
if (policy->max < cpu_set_freq[cpu]) {
- __cpufreq_driver_target(&current_policy[cpu], policy->max,
- CPUFREQ_RELATION_H);
- } else if (policy->min > cpu_set_freq[cpu]) {
- __cpufreq_driver_target(&current_policy[cpu], policy->min,
- CPUFREQ_RELATION_L);
- } else {
- __cpufreq_driver_target(&current_policy[cpu], cpu_set_freq[cpu],
- CPUFREQ_RELATION_L);
+ __cpufreq_driver_target(policy, policy->max,
+ CPUFREQ_RELATION_H);
+ }
+ else if (policy->min > cpu_set_freq[cpu]) {
+ __cpufreq_driver_target(policy, policy->min,
+ CPUFREQ_RELATION_L);
}
- memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
- up(&userspace_sem);
+ else {
+ __cpufreq_driver_target(policy, cpu_set_freq[cpu],
+ CPUFREQ_RELATION_L);
+ }
+ cpu_min_freq[cpu] = policy->min;
+ cpu_max_freq[cpu] = policy->max;
+ cpu_cur_freq[cpu] = policy->cur;
+ mutex_unlock(&userspace_mutex);
break;
}
return 0;
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
new file mode 100644
index 00000000000..18a45565112
--- /dev/null
+++ b/drivers/edac/Kconfig
@@ -0,0 +1,101 @@
+#
+# EDAC Kconfig
+# Copyright (c) 2003 Linux Networx
+# Licensed and distributed under the GPL
+#
+# $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
+#
+
+menu 'EDAC - error detection and reporting (RAS)'
+
+config EDAC
+ tristate "EDAC core system error reporting"
+ depends on X86
+ help
+ EDAC is designed to report errors in the core system.
+ These are low-level errors that are reported in the CPU or
+ supporting chipset: memory errors, cache errors, PCI errors,
+ thermal throttling, etc.. If unsure, select 'Y'.
+
+
+comment "Reporting subsystems"
+ depends on EDAC
+
+config EDAC_DEBUG
+ bool "Debugging"
+ depends on EDAC
+ help
+ This turns on debugging information for the entire EDAC
+ sub-system. You can insert module with "debug_level=x", current
+ there're four debug levels (x=0,1,2,3 from low to high).
+ Usually you should select 'N'.
+
+config EDAC_MM_EDAC
+ tristate "Main Memory EDAC (Error Detection And Correction) reporting"
+ depends on EDAC
+ default y
+ help
+ Some systems are able to detect and correct errors in main
+ memory. EDAC can report statistics on memory error
+ detection and correction (EDAC - or commonly referred to ECC
+ errors). EDAC will also try to decode where these errors
+ occurred so that a particular failing memory module can be
+ replaced. If unsure, select 'Y'.
+
+
+config EDAC_AMD76X
+ tristate "AMD 76x (760, 762, 768)"
+ depends on EDAC_MM_EDAC && PCI && X86_32
+ help
+ Support for error detection and correction on the AMD 76x
+ series of chipsets used with the Athlon processor.
+
+config EDAC_E7XXX
+ tristate "Intel e7xxx (e7205, e7500, e7501, e7505)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ E7205, E7500, E7501 and E7505 server chipsets.
+
+config EDAC_E752X
+ tristate "Intel e752x (e7520, e7525, e7320)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ E7520, E7525, E7320 server chipsets.
+
+config EDAC_I82875P
+ tristate "Intel 82875p (D82875P, E7210)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ DP82785P and E7210 server chipsets.
+
+config EDAC_I82860
+ tristate "Intel 82860"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ 82860 chipset.
+
+config EDAC_R82600
+ tristate "Radisys 82600 embedded chipset"
+ depends on EDAC_MM_EDAC
+ help
+ Support for error detection and correction on the Radisys
+ 82600 embedded chipset.
+
+choice
+ prompt "Error detecting method"
+ depends on EDAC
+ default EDAC_POLL
+
+config EDAC_POLL
+ bool "Poll for errors"
+ depends on EDAC
+ help
+ Poll the chipset periodically to detect errors.
+
+endchoice
+
+endmenu
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
new file mode 100644
index 00000000000..93137fdab4b
--- /dev/null
+++ b/drivers/edac/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux kernel EDAC drivers.
+#
+# Copyright 02 Jul 2003, Linux Networx (http://lnxi.com)
+# This file may be distributed under the terms of the
+# GNU General Public License.
+#
+# $Id: Makefile,v 1.4.2.3 2005/07/08 22:05:38 dsp_llnl Exp $
+
+
+obj-$(CONFIG_EDAC_MM_EDAC) += edac_mc.o
+obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
+obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
+obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
+obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
+obj-$(CONFIG_EDAC_I82860) += i82860_edac.o
+obj-$(CONFIG_EDAC_R82600) += r82600_edac.o
+
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c
new file mode 100644
index 00000000000..2fcc8120b53
--- /dev/null
+++ b/drivers/edac/amd76x_edac.c
@@ -0,0 +1,356 @@
+/*
+ * AMD 76x Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * $Id: edac_amd76x.c,v 1.4.2.5 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#define AMD76X_NR_CSROWS 8
+#define AMD76X_NR_CHANS 1
+#define AMD76X_NR_DIMMS 4
+
+
+/* AMD 76x register addresses - device 0 function 0 - PCI bridge */
+#define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b)
+ *
+ * 31:16 reserved
+ * 15:14 SERR enabled: x1=ue 1x=ce
+ * 13 reserved
+ * 12 diag: disabled, enabled
+ * 11:10 mode: dis, EC, ECC, ECC+scrub
+ * 9:8 status: x1=ue 1x=ce
+ * 7:4 UE cs row
+ * 3:0 CE cs row
+ */
+#define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b)
+ *
+ * 31:26 clock disable 5 - 0
+ * 25 SDRAM init
+ * 24 reserved
+ * 23 mode register service
+ * 22:21 suspend to RAM
+ * 20 burst refresh enable
+ * 19 refresh disable
+ * 18 reserved
+ * 17:16 cycles-per-refresh
+ * 15:8 reserved
+ * 7:0 x4 mode enable 7 - 0
+ */
+#define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b)
+ *
+ * 31:23 chip-select base
+ * 22:16 reserved
+ * 15:7 chip-select mask
+ * 6:3 reserved
+ * 2:1 address mode
+ * 0 chip-select enable
+ */
+
+
+struct amd76x_error_info {
+ u32 ecc_mode_status;
+};
+
+
+enum amd76x_chips {
+ AMD761 = 0,
+ AMD762
+};
+
+
+struct amd76x_dev_info {
+ const char *ctl_name;
+};
+
+
+static const struct amd76x_dev_info amd76x_devs[] = {
+ [AMD761] = {.ctl_name = "AMD761"},
+ [AMD762] = {.ctl_name = "AMD762"},
+};
+
+
+/**
+ * amd76x_get_error_info - fetch error information
+ * @mci: Memory controller
+ * @info: Info to fill in
+ *
+ * Fetch and store the AMD76x ECC status. Clear pending status
+ * on the chip so that further errors will be reported
+ */
+
+static void amd76x_get_error_info (struct mem_ctl_info *mci,
+ struct amd76x_error_info *info)
+{
+ pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ &info->ecc_mode_status);
+
+ if (info->ecc_mode_status & BIT(8))
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ (u32) BIT(8), (u32) BIT(8));
+
+ if (info->ecc_mode_status & BIT(9))
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ (u32) BIT(9), (u32) BIT(9));
+}
+
+
+/**
+ * amd76x_process_error_info - Error check
+ * @mci: Memory controller
+ * @info: Previously fetched information from chip
+ * @handle_errors: 1 if we should do recovery
+ *
+ * Process the chip state and decide if an error has occurred.
+ * A return of 1 indicates an error. Also if handle_errors is true
+ * then attempt to handle and clean up after the error
+ */
+
+static int amd76x_process_error_info (struct mem_ctl_info *mci,
+ struct amd76x_error_info *info, int handle_errors)
+{
+ int error_found;
+ u32 row;
+
+ error_found = 0;
+
+ /*
+ * Check for an uncorrectable error
+ */
+ if (info->ecc_mode_status & BIT(8)) {
+ error_found = 1;
+
+ if (handle_errors) {
+ row = (info->ecc_mode_status >> 4) & 0xf;
+ edac_mc_handle_ue(mci,
+ mci->csrows[row].first_page, 0, row,
+ mci->ctl_name);
+ }
+ }
+
+ /*
+ * Check for a correctable error
+ */
+ if (info->ecc_mode_status & BIT(9)) {
+ error_found = 1;
+
+ if (handle_errors) {
+ row = info->ecc_mode_status & 0xf;
+ edac_mc_handle_ce(mci,
+ mci->csrows[row].first_page, 0, 0, row, 0,
+ mci->ctl_name);
+ }
+ }
+ return error_found;
+}
+
+/**
+ * amd76x_check - Poll the controller
+ * @mci: Memory controller
+ *
+ * Called by the poll handlers this function reads the status
+ * from the controller and checks for errors.
+ */
+
+static void amd76x_check(struct mem_ctl_info *mci)
+{
+ struct amd76x_error_info info;
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ amd76x_get_error_info(mci, &info);
+ amd76x_process_error_info(mci, &info, 1);
+}
+
+
+/**
+ * amd76x_probe1 - Perform set up for detected device
+ * @pdev; PCI device detected
+ * @dev_idx: Device type index
+ *
+ * We have found an AMD76x and now need to set up the memory
+ * controller status reporting. We configure and set up the
+ * memory controller reporting and claim the device.
+ */
+
+static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ enum edac_type ems_modes[] = {
+ EDAC_NONE,
+ EDAC_EC,
+ EDAC_SECDED,
+ EDAC_SECDED
+ };
+ u32 ems;
+ u32 ems_mode;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
+ ems_mode = (ems >> 10) & 0x3;
+
+ mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+ mci->pdev = pci_dev_get(pdev);
+ mci->mtype_cap = MEM_FLAG_RDDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ mci->edac_cap = ems_mode ?
+ (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.4.2.5 $";
+ mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
+ mci->edac_check = amd76x_check;
+ mci->ctl_page_to_phys = NULL;
+
+ for (index = 0; index < mci->nr_csrows; index++) {
+ struct csrow_info *csrow = &mci->csrows[index];
+ u32 mba;
+ u32 mba_base;
+ u32 mba_mask;
+ u32 dms;
+
+ /* find the DRAM Chip Select Base address and mask */
+ pci_read_config_dword(mci->pdev,
+ AMD76X_MEM_BASE_ADDR + (index * 4),
+ &mba);
+
+ if (!(mba & BIT(0)))
+ continue;
+
+ mba_base = mba & 0xff800000UL;
+ mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
+
+ pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS,
+ &dms);
+
+ csrow->first_page = mba_base >> PAGE_SHIFT;
+ csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
+ csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+ csrow->page_mask = mba_mask >> PAGE_SHIFT;
+ csrow->grain = csrow->nr_pages << PAGE_SHIFT;
+ csrow->mtype = MEM_RDDR;
+ csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
+ csrow->edac_mode = ems_modes[ems_mode];
+ }
+
+ /* clear counters */
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, (u32) (0x3 << 8),
+ (u32) (0x3 << 8));
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci) {
+ if(mci->pdev)
+ pci_dev_put(mci->pdev);
+ edac_mc_free(mci);
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit amd76x_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* don't need to call pci_device_enable() */
+ return amd76x_probe1(pdev, ent->driver_data);
+}
+
+
+/**
+ * amd76x_remove_one - driver shutdown
+ * @pdev: PCI device being handed back
+ *
+ * Called when the driver is unloaded. Find the matching mci
+ * structure for the device then delete the mci and free the
+ * resources.
+ */
+
+static void __devexit amd76x_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+ if (edac_mc_del_mc(mci))
+ return;
+ pci_dev_put(mci->pdev);
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ AMD762},
+ {PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ AMD761},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
+
+
+static struct pci_driver amd76x_driver = {
+ .name = BS_MOD_STR,
+ .probe = amd76x_init_one,
+ .remove = __devexit_p(amd76x_remove_one),
+ .id_table = amd76x_pci_tbl,
+};
+
+static int __init amd76x_init(void)
+{
+ return pci_register_driver(&amd76x_driver);
+}
+
+static void __exit amd76x_exit(void)
+{
+ pci_unregister_driver(&amd76x_driver);
+}
+
+module_init(amd76x_init);
+module_exit(amd76x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for AMD 76x memory controllers");
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
new file mode 100644
index 00000000000..c454ded2b06
--- /dev/null
+++ b/drivers/edac/e752x_edac.c
@@ -0,0 +1,1071 @@
+/*
+ * Intel e752x Memory Controller kernel module
+ * (C) 2004 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * See "enum e752x_chips" below for supported chipsets
+ *
+ * Written by Tom Zimmerman
+ *
+ * Contributors:
+ * Thayne Harbaugh at realmsys.com (?)
+ * Wang Zhenyu at intel.com
+ * Dave Jiang at mvista.com
+ *
+ * $Id: edac_e752x.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_7520_0
+#define PCI_DEVICE_ID_INTEL_7520_0 0x3590
+#endif /* PCI_DEVICE_ID_INTEL_7520_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7520_1_ERR
+#define PCI_DEVICE_ID_INTEL_7520_1_ERR 0x3591
+#endif /* PCI_DEVICE_ID_INTEL_7520_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7525_0
+#define PCI_DEVICE_ID_INTEL_7525_0 0x359E
+#endif /* PCI_DEVICE_ID_INTEL_7525_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7525_1_ERR
+#define PCI_DEVICE_ID_INTEL_7525_1_ERR 0x3593
+#endif /* PCI_DEVICE_ID_INTEL_7525_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7320_0
+#define PCI_DEVICE_ID_INTEL_7320_0 0x3592
+#endif /* PCI_DEVICE_ID_INTEL_7320_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7320_1_ERR
+#define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593
+#endif /* PCI_DEVICE_ID_INTEL_7320_1_ERR */
+
+#define E752X_NR_CSROWS 8 /* number of csrows */
+
+
+/* E752X register addresses - device 0 function 0 */
+#define E752X_DRB 0x60 /* DRAM row boundary register (8b) */
+#define E752X_DRA 0x70 /* DRAM row attribute register (8b) */
+ /*
+ * 31:30 Device width row 7
+ * 01=x8 10=x4 11=x8 DDR2
+ * 27:26 Device width row 6
+ * 23:22 Device width row 5
+ * 19:20 Device width row 4
+ * 15:14 Device width row 3
+ * 11:10 Device width row 2
+ * 7:6 Device width row 1
+ * 3:2 Device width row 0
+ */
+#define E752X_DRC 0x7C /* DRAM controller mode reg (32b) */
+ /* FIXME:IS THIS RIGHT? */
+ /*
+ * 22 Number channels 0=1,1=2
+ * 19:18 DRB Granularity 32/64MB
+ */
+#define E752X_DRM 0x80 /* Dimm mapping register */
+#define E752X_DDRCSR 0x9A /* DDR control and status reg (16b) */
+ /*
+ * 14:12 1 single A, 2 single B, 3 dual
+ */
+#define E752X_TOLM 0xC4 /* DRAM top of low memory reg (16b) */
+#define E752X_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */
+#define E752X_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */
+#define E752X_REMAPOFFSET 0xCA /* DRAM remap limit offset reg (16b) */
+
+/* E752X register addresses - device 0 function 1 */
+#define E752X_FERR_GLOBAL 0x40 /* Global first error register (32b) */
+#define E752X_NERR_GLOBAL 0x44 /* Global next error register (32b) */
+#define E752X_HI_FERR 0x50 /* Hub interface first error reg (8b) */
+#define E752X_HI_NERR 0x52 /* Hub interface next error reg (8b) */
+#define E752X_HI_ERRMASK 0x54 /* Hub interface error mask reg (8b) */
+#define E752X_HI_SMICMD 0x5A /* Hub interface SMI command reg (8b) */
+#define E752X_SYSBUS_FERR 0x60 /* System buss first error reg (16b) */
+#define E752X_SYSBUS_NERR 0x62 /* System buss next error reg (16b) */
+#define E752X_SYSBUS_ERRMASK 0x64 /* System buss error mask reg (16b) */
+#define E752X_SYSBUS_SMICMD 0x6A /* System buss SMI command reg (16b) */
+#define E752X_BUF_FERR 0x70 /* Memory buffer first error reg (8b) */
+#define E752X_BUF_NERR 0x72 /* Memory buffer next error reg (8b) */
+#define E752X_BUF_ERRMASK 0x74 /* Memory buffer error mask reg (8b) */
+#define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI command reg (8b) */
+#define E752X_DRAM_FERR 0x80 /* DRAM first error register (16b) */
+#define E752X_DRAM_NERR 0x82 /* DRAM next error register (16b) */
+#define E752X_DRAM_ERRMASK 0x84 /* DRAM error mask register (8b) */
+#define E752X_DRAM_SMICMD 0x8A /* DRAM SMI command register (8b) */
+#define E752X_DRAM_RETR_ADD 0xAC /* DRAM Retry address register (32b) */
+#define E752X_DRAM_SEC1_ADD 0xA0 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SEC2_ADD 0xC8 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_DED_ADD 0xA4 /* DRAM first uncorrectable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM first uncorrectable scrub memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SEC1_SYNDROME 0xC4 /* DRAM first correctable memory */
+ /* error syndrome register (16b) */
+#define E752X_DRAM_SEC2_SYNDROME 0xC6 /* DRAM second correctable memory */
+ /* error syndrome register (16b) */
+#define E752X_DEVPRES1 0xF4 /* Device Present 1 register (8b) */
+
+/* ICH5R register addresses - device 30 function 0 */
+#define ICH5R_PCI_STAT 0x06 /* PCI status register (16b) */
+#define ICH5R_PCI_2ND_STAT 0x1E /* PCI status secondary reg (16b) */
+#define ICH5R_PCI_BRIDGE_CTL 0x3E /* PCI bridge control register (16b) */
+
+enum e752x_chips {
+ E7520 = 0,
+ E7525 = 1,
+ E7320 = 2
+};
+
+
+struct e752x_pvt {
+ struct pci_dev *bridge_ck;
+ struct pci_dev *dev_d0f0;
+ struct pci_dev *dev_d0f1;
+ u32 tolm;
+ u32 remapbase;
+ u32 remaplimit;
+ int mc_symmetric;
+ u8 map[8];
+ int map_type;
+ const struct e752x_dev_info *dev_info;
+};
+
+
+struct e752x_dev_info {
+ u16 err_dev;
+ const char *ctl_name;
+};
+
+struct e752x_error_info {
+ u32 ferr_global;
+ u32 nerr_global;
+ u8 hi_ferr;
+ u8 hi_nerr;
+ u16 sysbus_ferr;
+ u16 sysbus_nerr;
+ u8 buf_ferr;
+ u8 buf_nerr;
+ u16 dram_ferr;
+ u16 dram_nerr;
+ u32 dram_sec1_add;
+ u32 dram_sec2_add;
+ u16 dram_sec1_syndrome;
+ u16 dram_sec2_syndrome;
+ u32 dram_ded_add;
+ u32 dram_scrb_add;
+ u32 dram_retr_add;
+};
+
+static const struct e752x_dev_info e752x_devs[] = {
+ [E7520] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
+ .ctl_name = "E7520"},
+ [E7525] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
+ .ctl_name = "E7525"},
+ [E7320] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
+ .ctl_name = "E7320"},
+};
+
+
+static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
+ unsigned long page)
+{
+ u32 remap;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (page < pvt->tolm)
+ return page;
+ if ((page >= 0x100000) && (page < pvt->remapbase))
+ return page;
+ remap = (page - pvt->tolm) + pvt->remapbase;
+ if (remap < pvt->remaplimit)
+ return remap;
+ printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+ return pvt->tolm - 1;
+}
+
+static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
+ u32 sec1_add, u16 sec1_syndrome)
+{
+ u32 page;
+ int row;
+ int channel;
+ int i;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* convert the addr to 4k page */
+ page = sec1_add >> (PAGE_SHIFT - 4);
+
+ /* FIXME - check for -1 */
+ if (pvt->mc_symmetric) {
+ /* chip select are bits 14 & 13 */
+ row = ((page >> 1) & 3);
+ printk(KERN_WARNING
+ "Test row %d Table %d %d %d %d %d %d %d %d\n",
+ row, pvt->map[0], pvt->map[1], pvt->map[2],
+ pvt->map[3], pvt->map[4], pvt->map[5],
+ pvt->map[6], pvt->map[7]);
+
+ /* test for channel remapping */
+ for (i = 0; i < 8; i++) {
+ if (pvt->map[i] == row)
+ break;
+ }
+ printk(KERN_WARNING "Test computed row %d\n", i);
+ if (i < 8)
+ row = i;
+ else
+ printk(KERN_WARNING
+ "MC%d: row %d not found in remap table\n",
+ mci->mc_idx, row);
+ } else
+ row = edac_mc_find_csrow_by_page(mci, page);
+ /* 0 = channel A, 1 = channel B */
+ channel = !(error_one & 1);
+
+ if (!pvt->map_type)
+ row = 7 - row;
+ edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel,
+ "e752x CE");
+}
+
+
+static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
+ u32 sec1_add, u16 sec1_syndrome, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ce(mci, error_one, sec1_add, sec1_syndrome);
+}
+
+static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add,
+ u32 scrb_add)
+{
+ u32 error_2b, block_page;
+ int row;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (error_one & 0x0202) {
+ error_2b = ded_add;
+ /* convert to 4k address */
+ block_page = error_2b >> (PAGE_SHIFT - 4);
+ row = pvt->mc_symmetric ?
+ /* chip select are bits 14 & 13 */
+ ((block_page >> 1) & 3) :
+ edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row,
+ "e752x UE from Read");
+ }
+ if (error_one & 0x0404) {
+ error_2b = scrb_add;
+ /* convert to 4k address */
+ block_page = error_2b >> (PAGE_SHIFT - 4);
+ row = pvt->mc_symmetric ?
+ /* chip select are bits 14 & 13 */
+ ((block_page >> 1) & 3) :
+ edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row,
+ "e752x UE from Scruber");
+ }
+}
+
+static inline void process_ue(struct mem_ctl_info *mci, u16 error_one,
+ u32 ded_add, u32 scrb_add, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ue(mci, error_one, ded_add, scrb_add);
+}
+
+static inline void process_ue_no_info_wr(struct mem_ctl_info *mci,
+ int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (!handle_error)
+ return;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ue_no_info(mci, "e752x UE log memory write");
+}
+
+static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
+ u32 retry_add)
+{
+ u32 error_1b, page;
+ int row;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ error_1b = retry_add;
+ page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
+ row = pvt->mc_symmetric ?
+ ((page >> 1) & 3) : /* chip select are bits 14 & 13 */
+ edac_mc_find_csrow_by_page(mci, page);
+ printk(KERN_WARNING
+ "MC%d: CE page 0x%lx, row %d : Memory read retry\n",
+ mci->mc_idx, (long unsigned int) page, row);
+}
+
+static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error,
+ u32 retry_add, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ded_retry(mci, error, retry_add);
+}
+
+static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
+ int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ printk(KERN_WARNING "MC%d: Memory threshold CE\n",
+ mci->mc_idx);
+}
+
+static char *global_message[11] = {
+ "PCI Express C1", "PCI Express C", "PCI Express B1",
+ "PCI Express B", "PCI Express A1", "PCI Express A",
+ "DMA Controler", "HUB Interface", "System Bus",
+ "DRAM Controler", "Internal Buffer"
+};
+
+static char *fatal_message[2] = { "Non-Fatal ", "Fatal " };
+
+static void do_global_error(int fatal, u32 errors)
+{
+ int i;
+
+ for (i = 0; i < 11; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError %s\n",
+ fatal_message[fatal], global_message[i]);
+ }
+}
+
+static inline void global_error(int fatal, u32 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_global_error(fatal, errors);
+}
+
+static char *hub_message[7] = {
+ "HI Address or Command Parity", "HI Illegal Access",
+ "HI Internal Parity", "Out of Range Access",
+ "HI Data Parity", "Enhanced Config Access",
+ "Hub Interface Target Abort"
+};
+
+static void do_hub_error(int fatal, u8 errors)
+{
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError %s\n",
+ fatal_message[fatal], hub_message[i]);
+ }
+}
+
+static inline void hub_error(int fatal, u8 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_hub_error(fatal, errors);
+}
+
+static char *membuf_message[4] = {
+ "Internal PMWB to DRAM parity",
+ "Internal PMWB to System Bus Parity",
+ "Internal System Bus or IO to PMWB Parity",
+ "Internal DRAM to PMWB Parity"
+};
+
+static void do_membuf_error(u8 errors)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "Non-Fatal Error %s\n",
+ membuf_message[i]);
+ }
+}
+
+static inline void membuf_error(u8 errors, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_membuf_error(errors);
+}
+
+#if 0
+char *sysbus_message[10] = {
+ "Addr or Request Parity",
+ "Data Strobe Glitch",
+ "Addr Strobe Glitch",
+ "Data Parity",
+ "Addr Above TOM",
+ "Non DRAM Lock Error",
+ "MCERR", "BINIT",
+ "Memory Parity",
+ "IO Subsystem Parity"
+};
+#endif /* 0 */
+
+static void do_sysbus_error(int fatal, u32 errors)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError System Bus %s\n",
+ fatal_message[fatal], global_message[i]);
+ }
+}
+
+static inline void sysbus_error(int fatal, u32 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_sysbus_error(fatal, errors);
+}
+
+static void e752x_check_hub_interface (struct e752x_error_info *info,
+ int *error_found, int handle_error)
+{
+ u8 stat8;
+
+ //pci_read_config_byte(dev,E752X_HI_FERR,&stat8);
+ stat8 = info->hi_ferr;
+ if(stat8 & 0x7f) { /* Error, so process */
+ stat8 &= 0x7f;
+ if(stat8 & 0x2b)
+ hub_error(1, stat8 & 0x2b, error_found, handle_error);
+ if(stat8 & 0x54)
+ hub_error(0, stat8 & 0x54, error_found, handle_error);
+ }
+ //pci_read_config_byte(dev,E752X_HI_NERR,&stat8);
+ stat8 = info->hi_nerr;
+ if(stat8 & 0x7f) { /* Error, so process */
+ stat8 &= 0x7f;
+ if (stat8 & 0x2b)
+ hub_error(1, stat8 & 0x2b, error_found, handle_error);
+ if(stat8 & 0x54)
+ hub_error(0, stat8 & 0x54, error_found, handle_error);
+ }
+}
+
+static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found,
+ int handle_error)
+{
+ u32 stat32, error32;
+
+ //pci_read_config_dword(dev,E752X_SYSBUS_FERR,&stat32);
+ stat32 = info->sysbus_ferr + (info->sysbus_nerr << 16);
+
+ if (stat32 == 0)
+ return; /* no errors */
+
+ error32 = (stat32 >> 16) & 0x3ff;
+ stat32 = stat32 & 0x3ff;
+ if(stat32 & 0x083)
+ sysbus_error(1, stat32 & 0x083, error_found, handle_error);
+ if(stat32 & 0x37c)
+ sysbus_error(0, stat32 & 0x37c, error_found, handle_error);
+ if(error32 & 0x083)
+ sysbus_error(1, error32 & 0x083, error_found, handle_error);
+ if(error32 & 0x37c)
+ sysbus_error(0, error32 & 0x37c, error_found, handle_error);
+}
+
+static void e752x_check_membuf (struct e752x_error_info *info, int *error_found,
+ int handle_error)
+{
+ u8 stat8;
+
+ stat8 = info->buf_ferr;
+ if (stat8 & 0x0f) { /* Error, so process */
+ stat8 &= 0x0f;
+ membuf_error(stat8, error_found, handle_error);
+ }
+ stat8 = info->buf_nerr;
+ if (stat8 & 0x0f) { /* Error, so process */
+ stat8 &= 0x0f;
+ membuf_error(stat8, error_found, handle_error);
+ }
+}
+
+static void e752x_check_dram (struct mem_ctl_info *mci,
+ struct e752x_error_info *info, int *error_found, int handle_error)
+{
+ u16 error_one, error_next;
+
+ error_one = info->dram_ferr;
+ error_next = info->dram_nerr;
+
+ /* decode and report errors */
+ if(error_one & 0x0101) /* check first error correctable */
+ process_ce(mci, error_one, info->dram_sec1_add,
+ info->dram_sec1_syndrome, error_found,
+ handle_error);
+
+ if(error_next & 0x0101) /* check next error correctable */
+ process_ce(mci, error_next, info->dram_sec2_add,
+ info->dram_sec2_syndrome, error_found,
+ handle_error);
+
+ if(error_one & 0x4040)
+ process_ue_no_info_wr(mci, error_found, handle_error);
+
+ if(error_next & 0x4040)
+ process_ue_no_info_wr(mci, error_found, handle_error);
+
+ if(error_one & 0x2020)
+ process_ded_retry(mci, error_one, info->dram_retr_add,
+ error_found, handle_error);
+
+ if(error_next & 0x2020)
+ process_ded_retry(mci, error_next, info->dram_retr_add,
+ error_found, handle_error);
+
+ if(error_one & 0x0808)
+ process_threshold_ce(mci, error_one, error_found,
+ handle_error);
+
+ if(error_next & 0x0808)
+ process_threshold_ce(mci, error_next, error_found,
+ handle_error);
+
+ if(error_one & 0x0606)
+ process_ue(mci, error_one, info->dram_ded_add,
+ info->dram_scrb_add, error_found, handle_error);
+
+ if(error_next & 0x0606)
+ process_ue(mci, error_next, info->dram_ded_add,
+ info->dram_scrb_add, error_found, handle_error);
+}
+
+static void e752x_get_error_info (struct mem_ctl_info *mci,
+ struct e752x_error_info *info)
+{
+ struct pci_dev *dev;
+ struct e752x_pvt *pvt;
+
+ memset(info, 0, sizeof(*info));
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ dev = pvt->dev_d0f1;
+
+ pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
+
+ if (info->ferr_global) {
+ pci_read_config_byte(dev, E752X_HI_FERR, &info->hi_ferr);
+ pci_read_config_word(dev, E752X_SYSBUS_FERR,
+ &info->sysbus_ferr);
+ pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr);
+ pci_read_config_word(dev, E752X_DRAM_FERR,
+ &info->dram_ferr);
+ pci_read_config_dword(dev, E752X_DRAM_SEC1_ADD,
+ &info->dram_sec1_add);
+ pci_read_config_word(dev, E752X_DRAM_SEC1_SYNDROME,
+ &info->dram_sec1_syndrome);
+ pci_read_config_dword(dev, E752X_DRAM_DED_ADD,
+ &info->dram_ded_add);
+ pci_read_config_dword(dev, E752X_DRAM_SCRB_ADD,
+ &info->dram_scrb_add);
+ pci_read_config_dword(dev, E752X_DRAM_RETR_ADD,
+ &info->dram_retr_add);
+
+ if (info->hi_ferr & 0x7f)
+ pci_write_config_byte(dev, E752X_HI_FERR,
+ info->hi_ferr);
+
+ if (info->sysbus_ferr)
+ pci_write_config_word(dev, E752X_SYSBUS_FERR,
+ info->sysbus_ferr);
+
+ if (info->buf_ferr & 0x0f)
+ pci_write_config_byte(dev, E752X_BUF_FERR,
+ info->buf_ferr);
+
+ if (info->dram_ferr)
+ pci_write_bits16(pvt->bridge_ck, E752X_DRAM_FERR,
+ info->dram_ferr, info->dram_ferr);
+
+ pci_write_config_dword(dev, E752X_FERR_GLOBAL,
+ info->ferr_global);
+ }
+
+ pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global);
+
+ if (info->nerr_global) {
+ pci_read_config_byte(dev, E752X_HI_NERR, &info->hi_nerr);
+ pci_read_config_word(dev, E752X_SYSBUS_NERR,
+ &info->sysbus_nerr);
+ pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr);
+ pci_read_config_word(dev, E752X_DRAM_NERR,
+ &info->dram_nerr);
+ pci_read_config_dword(dev, E752X_DRAM_SEC2_ADD,
+ &info->dram_sec2_add);
+ pci_read_config_word(dev, E752X_DRAM_SEC2_SYNDROME,
+ &info->dram_sec2_syndrome);
+
+ if (info->hi_nerr & 0x7f)
+ pci_write_config_byte(dev, E752X_HI_NERR,
+ info->hi_nerr);
+
+ if (info->sysbus_nerr)
+ pci_write_config_word(dev, E752X_SYSBUS_NERR,
+ info->sysbus_nerr);
+
+ if (info->buf_nerr & 0x0f)
+ pci_write_config_byte(dev, E752X_BUF_NERR,
+ info->buf_nerr);
+
+ if (info->dram_nerr)
+ pci_write_bits16(pvt->bridge_ck, E752X_DRAM_NERR,
+ info->dram_nerr, info->dram_nerr);
+
+ pci_write_config_dword(dev, E752X_NERR_GLOBAL,
+ info->nerr_global);
+ }
+}
+
+static int e752x_process_error_info (struct mem_ctl_info *mci,
+ struct e752x_error_info *info, int handle_errors)
+{
+ u32 error32, stat32;
+ int error_found;
+
+ error_found = 0;
+ error32 = (info->ferr_global >> 18) & 0x3ff;
+ stat32 = (info->ferr_global >> 4) & 0x7ff;
+
+ if (error32)
+ global_error(1, error32, &error_found, handle_errors);
+
+ if (stat32)
+ global_error(0, stat32, &error_found, handle_errors);
+
+ error32 = (info->nerr_global >> 18) & 0x3ff;
+ stat32 = (info->nerr_global >> 4) & 0x7ff;
+
+ if (error32)
+ global_error(1, error32, &error_found, handle_errors);
+
+ if (stat32)
+ global_error(0, stat32, &error_found, handle_errors);
+
+ e752x_check_hub_interface(info, &error_found, handle_errors);
+ e752x_check_sysbus(info, &error_found, handle_errors);
+ e752x_check_membuf(info, &error_found, handle_errors);
+ e752x_check_dram(mci, info, &error_found, handle_errors);
+ return error_found;
+}
+
+static void e752x_check(struct mem_ctl_info *mci)
+{
+ struct e752x_error_info info;
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ e752x_get_error_info(mci, &info);
+ e752x_process_error_info(mci, &info, 1);
+}
+
+static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ u16 pci_data, stat;
+ u32 stat32;
+ u16 stat16;
+ u8 stat8;
+ struct mem_ctl_info *mci = NULL;
+ struct e752x_pvt *pvt = NULL;
+ u16 ddrcsr;
+ u32 drc;
+ int drc_chan; /* Number of channels 0=1chan,1=2chan */
+ int drc_drbg; /* DRB granularity 0=64mb,1=128mb */
+ int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+ u32 dra;
+ unsigned long last_cumul_size;
+ struct pci_dev *pres_dev;
+ struct pci_dev *dev = NULL;
+
+ debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+ debugf0("Starting Probe1\n");
+
+ /* enable device 0 function 1 */
+ pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8);
+ stat8 |= (1 << 5);
+ pci_write_config_byte(pdev, E752X_DEVPRES1, stat8);
+
+ /* need to find out the number of channels */
+ pci_read_config_dword(pdev, E752X_DRC, &drc);
+ pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr);
+ /* FIXME: should check >>12 or 0xf, true for all? */
+ /* Dual channel = 1, Single channel = 0 */
+ drc_chan = (((ddrcsr >> 12) & 3) == 3);
+ drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */
+ drc_ddim = (drc >> 20) & 0x3;
+
+ mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->mtype_cap = MEM_FLAG_RDDR;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
+ EDAC_FLAG_S4ECD4ED;
+ /* FIXME - what if different memory types are in different csrows? */
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.11 $";
+ mci->pdev = pdev;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ pvt->dev_info = &e752x_devs[dev_idx];
+ pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
+ pvt->dev_info->err_dev,
+ pvt->bridge_ck);
+ if (pvt->bridge_ck == NULL)
+ pvt->bridge_ck = pci_scan_single_device(pdev->bus,
+ PCI_DEVFN(0, 1));
+ if (pvt->bridge_ck == NULL) {
+ printk(KERN_ERR "MC: error reporting device not found:"
+ "vendor %x device 0x%x (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
+ goto fail;
+ }
+ pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
+
+ debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+ mci->ctl_name = pvt->dev_info->ctl_name;
+ mci->edac_check = e752x_check;
+ mci->ctl_page_to_phys = ctl_page_to_phys;
+
+ /* find out the device types */
+ pci_read_config_dword(pdev, E752X_DRA, &dra);
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address for
+ * each DRAM row with a granularity of 64 or 128MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ /* mem_dev 0=x8, 1=x4 */
+ int mem_dev = (dra >> (index * 4 + 2)) & 0x3;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ mem_dev = (mem_dev == 2);
+ pci_read_config_byte(mci->pdev, E752X_DRB + index, &value);
+ /* convert a 128 or 64 MiB DRB to a page size. */
+ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
+ csrow->mtype = MEM_RDDR; /* only one type supported */
+ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
+
+ /*
+ * if single channel or x8 devices then SECDED
+ * if dual channel and x4 then S4ECD4ED
+ */
+ if (drc_ddim) {
+ if (drc_chan && mem_dev) {
+ csrow->edac_mode = EDAC_S4ECD4ED;
+ mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+ } else {
+ csrow->edac_mode = EDAC_SECDED;
+ mci->edac_cap |= EDAC_FLAG_SECDED;
+ }
+ } else
+ csrow->edac_mode = EDAC_NONE;
+ }
+
+ /* Fill in the memory map table */
+ {
+ u8 value;
+ u8 last = 0;
+ u8 row = 0;
+ for (index = 0; index < 8; index += 2) {
+
+ pci_read_config_byte(mci->pdev, E752X_DRB + index,
+ &value);
+ /* test if there is a dimm in this slot */
+ if (value == last) {
+ /* no dimm in the slot, so flag it as empty */
+ pvt->map[index] = 0xff;
+ pvt->map[index + 1] = 0xff;
+ } else { /* there is a dimm in the slot */
+ pvt->map[index] = row;
+ row++;
+ last = value;
+ /* test the next value to see if the dimm is
+ double sided */
+ pci_read_config_byte(mci->pdev,
+ E752X_DRB + index + 1,
+ &value);
+ pvt->map[index + 1] = (value == last) ?
+ 0xff : /* the dimm is single sided,
+ so flag as empty */
+ row; /* this is a double sided dimm
+ to save the next row # */
+ row++;
+ last = value;
+ }
+ }
+ }
+
+ /* set the map type. 1 = normal, 0 = reversed */
+ pci_read_config_byte(mci->pdev, E752X_DRM, &stat8);
+ pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f));
+
+ mci->edac_cap |= EDAC_FLAG_NONE;
+
+ debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
+ __func__);
+ /* load the top of low memory, remap base, and remap limit vars */
+ pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data);
+ pvt->tolm = ((u32) pci_data) << 4;
+ pci_read_config_word(mci->pdev, E752X_REMAPBASE, &pci_data);
+ pvt->remapbase = ((u32) pci_data) << 14;
+ pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data);
+ pvt->remaplimit = ((u32) pci_data) << 14;
+ printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+ pvt->remapbase, pvt->remaplimit);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ goto fail;
+ }
+
+ /* Walk through the PCI table and clear errors */
+ switch (dev_idx) {
+ case E7520:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7520_0, NULL);
+ break;
+ case E7525:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7525_0, NULL);
+ break;
+ case E7320:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7320_0, NULL);
+ break;
+ }
+
+
+ pvt->dev_d0f0 = dev;
+ for (pres_dev = dev;
+ ((struct pci_dev *) pres_dev->global_list.next != dev);
+ pres_dev = (struct pci_dev *) pres_dev->global_list.next) {
+ pci_read_config_dword(pres_dev, PCI_COMMAND, &stat32);
+ stat = (u16) (stat32 >> 16);
+ /* clear any error bits */
+ if (stat32 & ((1 << 6) + (1 << 8)))
+ pci_write_config_word(pres_dev, PCI_STATUS, stat);
+ }
+ /* find the error reporting device and clear errors */
+ dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck);
+ /* Turn off error disable & SMI in case the BIOS turned it on */
+ pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
+ pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00);
+ pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00);
+ pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
+ pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00);
+ /* clear other MCH errors */
+ pci_read_config_dword(dev, E752X_FERR_GLOBAL, &stat32);
+ pci_write_config_dword(dev, E752X_FERR_GLOBAL, stat32);
+ pci_read_config_dword(dev, E752X_NERR_GLOBAL, &stat32);
+ pci_write_config_dword(dev, E752X_NERR_GLOBAL, stat32);
+ pci_read_config_byte(dev, E752X_HI_FERR, &stat8);
+ pci_write_config_byte(dev, E752X_HI_FERR, stat8);
+ pci_read_config_byte(dev, E752X_HI_NERR, &stat8);
+ pci_write_config_byte(dev, E752X_HI_NERR, stat8);
+ pci_read_config_dword(dev, E752X_SYSBUS_FERR, &stat32);
+ pci_write_config_dword(dev, E752X_SYSBUS_FERR, stat32);
+ pci_read_config_byte(dev, E752X_BUF_FERR, &stat8);
+ pci_write_config_byte(dev, E752X_BUF_FERR, stat8);
+ pci_read_config_byte(dev, E752X_BUF_NERR, &stat8);
+ pci_write_config_byte(dev, E752X_BUF_NERR, stat8);
+ pci_read_config_word(dev, E752X_DRAM_FERR, &stat16);
+ pci_write_config_word(dev, E752X_DRAM_FERR, stat16);
+ pci_read_config_word(dev, E752X_DRAM_NERR, &stat16);
+ pci_write_config_word(dev, E752X_DRAM_NERR, stat16);
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci) {
+ if (pvt->dev_d0f0)
+ pci_dev_put(pvt->dev_d0f0);
+ if (pvt->dev_d0f1)
+ pci_dev_put(pvt->dev_d0f1);
+ if (pvt->bridge_ck)
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit e752x_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* wake up and enable device */
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ return e752x_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit e752x_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct e752x_pvt *pvt;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+
+ if (edac_mc_del_mc(mci))
+ return;
+
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ pci_dev_put(pvt->dev_d0f0);
+ pci_dev_put(pvt->dev_d0f1);
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7520},
+ {PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7525},
+ {PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7320},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, e752x_pci_tbl);
+
+
+static struct pci_driver e752x_driver = {
+ .name = BS_MOD_STR,
+ .probe = e752x_init_one,
+ .remove = __devexit_p(e752x_remove_one),
+ .id_table = e752x_pci_tbl,
+};
+
+
+static int __init e752x_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_rc = pci_register_driver(&e752x_driver);
+ return (pci_rc < 0) ? pci_rc : 0;
+}
+
+
+static void __exit e752x_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_unregister_driver(&e752x_driver);
+}
+
+
+module_init(e752x_init);
+module_exit(e752x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
+MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c
new file mode 100644
index 00000000000..d5e320dfc66
--- /dev/null
+++ b/drivers/edac/e7xxx_edac.c
@@ -0,0 +1,558 @@
+/*
+ * Intel e7xxx Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * See "enum e7xxx_chips" below for supported chipsets
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * Contributors:
+ * Eric Biederman (Linux Networx)
+ * Tom Zimmerman (Linux Networx)
+ * Jim Garlick (Lawrence Livermore National Labs)
+ * Dave Peterson (Lawrence Livermore National Labs)
+ * That One Guy (Some other place)
+ * Wang Zhenyu (intel.com)
+ *
+ * $Id: edac_e7xxx.c,v 1.5.2.9 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_7205_0
+#define PCI_DEVICE_ID_INTEL_7205_0 0x255d
+#endif /* PCI_DEVICE_ID_INTEL_7205_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7205_1_ERR
+#define PCI_DEVICE_ID_INTEL_7205_1_ERR 0x2551
+#endif /* PCI_DEVICE_ID_INTEL_7205_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7500_0
+#define PCI_DEVICE_ID_INTEL_7500_0 0x2540
+#endif /* PCI_DEVICE_ID_INTEL_7500_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7500_1_ERR
+#define PCI_DEVICE_ID_INTEL_7500_1_ERR 0x2541
+#endif /* PCI_DEVICE_ID_INTEL_7500_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7501_0
+#define PCI_DEVICE_ID_INTEL_7501_0 0x254c
+#endif /* PCI_DEVICE_ID_INTEL_7501_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7501_1_ERR
+#define PCI_DEVICE_ID_INTEL_7501_1_ERR 0x2541
+#endif /* PCI_DEVICE_ID_INTEL_7501_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7505_0
+#define PCI_DEVICE_ID_INTEL_7505_0 0x2550
+#endif /* PCI_DEVICE_ID_INTEL_7505_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7505_1_ERR
+#define PCI_DEVICE_ID_INTEL_7505_1_ERR 0x2551
+#endif /* PCI_DEVICE_ID_INTEL_7505_1_ERR */
+
+
+#define E7XXX_NR_CSROWS 8 /* number of csrows */
+#define E7XXX_NR_DIMMS 8 /* FIXME - is this correct? */
+
+
+/* E7XXX register addresses - device 0 function 0 */
+#define E7XXX_DRB 0x60 /* DRAM row boundary register (8b) */
+#define E7XXX_DRA 0x70 /* DRAM row attribute register (8b) */
+ /*
+ * 31 Device width row 7 0=x8 1=x4
+ * 27 Device width row 6
+ * 23 Device width row 5
+ * 19 Device width row 4
+ * 15 Device width row 3
+ * 11 Device width row 2
+ * 7 Device width row 1
+ * 3 Device width row 0
+ */
+#define E7XXX_DRC 0x7C /* DRAM controller mode reg (32b) */
+ /*
+ * 22 Number channels 0=1,1=2
+ * 19:18 DRB Granularity 32/64MB
+ */
+#define E7XXX_TOLM 0xC4 /* DRAM top of low memory reg (16b) */
+#define E7XXX_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */
+#define E7XXX_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */
+
+/* E7XXX register addresses - device 0 function 1 */
+#define E7XXX_DRAM_FERR 0x80 /* DRAM first error register (8b) */
+#define E7XXX_DRAM_NERR 0x82 /* DRAM next error register (8b) */
+#define E7XXX_DRAM_CELOG_ADD 0xA0 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31:28 Reserved
+ * 27:6 CE address (4k block 33:12)
+ * 5:0 Reserved
+ */
+#define E7XXX_DRAM_UELOG_ADD 0xB0 /* DRAM first uncorrectable memory */
+ /* error address register (32b) */
+ /*
+ * 31:28 Reserved
+ * 27:6 CE address (4k block 33:12)
+ * 5:0 Reserved
+ */
+#define E7XXX_DRAM_CELOG_SYNDROME 0xD0 /* DRAM first correctable memory */
+ /* error syndrome register (16b) */
+
+enum e7xxx_chips {
+ E7500 = 0,
+ E7501,
+ E7505,
+ E7205,
+};
+
+
+struct e7xxx_pvt {
+ struct pci_dev *bridge_ck;
+ u32 tolm;
+ u32 remapbase;
+ u32 remaplimit;
+ const struct e7xxx_dev_info *dev_info;
+};
+
+
+struct e7xxx_dev_info {
+ u16 err_dev;
+ const char *ctl_name;
+};
+
+
+struct e7xxx_error_info {
+ u8 dram_ferr;
+ u8 dram_nerr;
+ u32 dram_celog_add;
+ u16 dram_celog_syndrome;
+ u32 dram_uelog_add;
+};
+
+static const struct e7xxx_dev_info e7xxx_devs[] = {
+ [E7500] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR,
+ .ctl_name = "E7500"},
+ [E7501] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR,
+ .ctl_name = "E7501"},
+ [E7505] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR,
+ .ctl_name = "E7505"},
+ [E7205] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR,
+ .ctl_name = "E7205"},
+};
+
+
+/* FIXME - is this valid for both SECDED and S4ECD4ED? */
+static inline int e7xxx_find_channel(u16 syndrome)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if ((syndrome & 0xff00) == 0)
+ return 0;
+ if ((syndrome & 0x00ff) == 0)
+ return 1;
+ if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0)
+ return 0;
+ return 1;
+}
+
+
+static unsigned long
+ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page)
+{
+ u32 remap;
+ struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if ((page < pvt->tolm) ||
+ ((page >= 0x100000) && (page < pvt->remapbase)))
+ return page;
+ remap = (page - pvt->tolm) + pvt->remapbase;
+ if (remap < pvt->remaplimit)
+ return remap;
+ printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+ return pvt->tolm - 1;
+}
+
+
+static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+{
+ u32 error_1b, page;
+ u16 syndrome;
+ int row;
+ int channel;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* read the error address */
+ error_1b = info->dram_celog_add;
+ /* FIXME - should use PAGE_SHIFT */
+ page = error_1b >> 6; /* convert the address to 4k page */
+ /* read the syndrome */
+ syndrome = info->dram_celog_syndrome;
+ /* FIXME - check for -1 */
+ row = edac_mc_find_csrow_by_page(mci, page);
+ /* convert syndrome to channel */
+ channel = e7xxx_find_channel(syndrome);
+ edac_mc_handle_ce(mci, page, 0, syndrome, row, channel,
+ "e7xxx CE");
+}
+
+
+static void process_ce_no_info(struct mem_ctl_info *mci)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow");
+}
+
+
+static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+{
+ u32 error_2b, block_page;
+ int row;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* read the error address */
+ error_2b = info->dram_uelog_add;
+ /* FIXME - should use PAGE_SHIFT */
+ block_page = error_2b >> 6; /* convert to 4k address */
+ row = edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE");
+}
+
+
+static void process_ue_no_info(struct mem_ctl_info *mci)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow");
+}
+
+
+static void e7xxx_get_error_info (struct mem_ctl_info *mci,
+ struct e7xxx_error_info *info)
+{
+ struct e7xxx_pvt *pvt;
+
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR,
+ &info->dram_ferr);
+ pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR,
+ &info->dram_nerr);
+
+ if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) {
+ pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD,
+ &info->dram_celog_add);
+ pci_read_config_word(pvt->bridge_ck,
+ E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome);
+ }
+
+ if ((info->dram_ferr & 2) || (info->dram_nerr & 2))
+ pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD,
+ &info->dram_uelog_add);
+
+ if (info->dram_ferr & 3)
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03,
+ 0x03);
+
+ if (info->dram_nerr & 3)
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03,
+ 0x03);
+}
+
+
+static int e7xxx_process_error_info (struct mem_ctl_info *mci,
+ struct e7xxx_error_info *info, int handle_errors)
+{
+ int error_found;
+
+ error_found = 0;
+
+ /* decode and report errors */
+ if (info->dram_ferr & 1) { /* check first error correctable */
+ error_found = 1;
+
+ if (handle_errors)
+ process_ce(mci, info);
+ }
+
+ if (info->dram_ferr & 2) { /* check first error uncorrectable */
+ error_found = 1;
+
+ if (handle_errors)
+ process_ue(mci, info);
+ }
+
+ if (info->dram_nerr & 1) { /* check next error correctable */
+ error_found = 1;
+
+ if (handle_errors) {
+ if (info->dram_ferr & 1)
+ process_ce_no_info(mci);
+ else
+ process_ce(mci, info);
+ }
+ }
+
+ if (info->dram_nerr & 2) { /* check next error uncorrectable */
+ error_found = 1;
+
+ if (handle_errors) {
+ if (info->dram_ferr & 2)
+ process_ue_no_info(mci);
+ else
+ process_ue(mci, info);
+ }
+ }
+
+ return error_found;
+}
+
+
+static void e7xxx_check(struct mem_ctl_info *mci)
+{
+ struct e7xxx_error_info info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ e7xxx_get_error_info(mci, &info);
+ e7xxx_process_error_info(mci, &info, 1);
+}
+
+
+static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ u16 pci_data;
+ struct mem_ctl_info *mci = NULL;
+ struct e7xxx_pvt *pvt = NULL;
+ u32 drc;
+ int drc_chan = 1; /* Number of channels 0=1chan,1=2chan */
+ int drc_drbg = 1; /* DRB granularity 0=32mb,1=64mb */
+ int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+ u32 dra;
+ unsigned long last_cumul_size;
+
+
+ debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+
+ /* need to find out the number of channels */
+ pci_read_config_dword(pdev, E7XXX_DRC, &drc);
+ /* only e7501 can be single channel */
+ if (dev_idx == E7501) {
+ drc_chan = ((drc >> 22) & 0x1);
+ drc_drbg = (drc >> 18) & 0x3;
+ }
+ drc_ddim = (drc >> 20) & 0x3;
+
+ mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->mtype_cap = MEM_FLAG_RDDR;
+ mci->edac_ctl_cap =
+ EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED;
+ /* FIXME - what if different memory types are in different csrows? */
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.9 $";
+ mci->pdev = pdev;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pvt->dev_info = &e7xxx_devs[dev_idx];
+ pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
+ pvt->dev_info->err_dev,
+ pvt->bridge_ck);
+ if (!pvt->bridge_ck) {
+ printk(KERN_ERR
+ "MC: error reporting device not found:"
+ "vendor %x device 0x%x (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+ mci->ctl_name = pvt->dev_info->ctl_name;
+
+ mci->edac_check = e7xxx_check;
+ mci->ctl_page_to_phys = ctl_page_to_phys;
+
+ /* find out the device types */
+ pci_read_config_dword(pdev, E7XXX_DRA, &dra);
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address
+ * for each DRAM row with a granularity of 32 or 64MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ /* mem_dev 0=x8, 1=x4 */
+ int mem_dev = (dra >> (index * 4 + 3)) & 0x1;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value);
+ /* convert a 64 or 32 MiB DRB to a page size. */
+ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
+ csrow->mtype = MEM_RDDR; /* only one type supported */
+ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
+
+ /*
+ * if single channel or x8 devices then SECDED
+ * if dual channel and x4 then S4ECD4ED
+ */
+ if (drc_ddim) {
+ if (drc_chan && mem_dev) {
+ csrow->edac_mode = EDAC_S4ECD4ED;
+ mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+ } else {
+ csrow->edac_mode = EDAC_SECDED;
+ mci->edac_cap |= EDAC_FLAG_SECDED;
+ }
+ } else
+ csrow->edac_mode = EDAC_NONE;
+ }
+
+ mci->edac_cap |= EDAC_FLAG_NONE;
+
+ debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
+ __func__);
+ /* load the top of low memory, remap base, and remap limit vars */
+ pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data);
+ pvt->tolm = ((u32) pci_data) << 4;
+ pci_read_config_word(mci->pdev, E7XXX_REMAPBASE, &pci_data);
+ pvt->remapbase = ((u32) pci_data) << 14;
+ pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data);
+ pvt->remaplimit = ((u32) pci_data) << 14;
+ printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+ pvt->remapbase, pvt->remaplimit);
+
+ /* clear any pending errors, or initial state bits */
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03);
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03);
+
+ if (edac_mc_add_mc(mci) != 0) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci != NULL) {
+ if(pvt != NULL && pvt->bridge_ck)
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit
+e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* wake up and enable device */
+ return pci_enable_device(pdev) ?
+ -EIO : e7xxx_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct e7xxx_pvt *pvt;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) &&
+ edac_mc_del_mc(mci)) {
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+}
+
+
+static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7205},
+ {PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7500},
+ {PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7501},
+ {PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7505},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl);
+
+
+static struct pci_driver e7xxx_driver = {
+ .name = BS_MOD_STR,
+ .probe = e7xxx_init_one,
+ .remove = __devexit_p(e7xxx_remove_one),
+ .id_table = e7xxx_pci_tbl,
+};
+
+
+static int __init e7xxx_init(void)
+{
+ return pci_register_driver(&e7xxx_driver);
+}
+
+
+static void __exit e7xxx_exit(void)
+{
+ pci_unregister_driver(&e7xxx_driver);
+}
+
+module_init(e7xxx_init);
+module_exit(e7xxx_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
+ "Based on.work by Dan Hollis et al");
+MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers");
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
new file mode 100644
index 00000000000..b10ee4698b1
--- /dev/null
+++ b/drivers/edac/edac_mc.c
@@ -0,0 +1,2208 @@
+/*
+ * edac_mc kernel module
+ * (C) 2005 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * Modified by Dave Peterson and Doug Thompson
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/highmem.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/sysdev.h>
+#include <linux/ctype.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/edac.h>
+
+#include "edac_mc.h"
+
+#define EDAC_MC_VERSION "edac_mc Ver: 2.0.0 " __DATE__
+
+#ifdef CONFIG_EDAC_DEBUG
+/* Values of 0 to 4 will generate output */
+int edac_debug_level = 1;
+EXPORT_SYMBOL(edac_debug_level);
+#endif
+
+/* EDAC Controls, setable by module parameter, and sysfs */
+static int log_ue = 1;
+static int log_ce = 1;
+static int panic_on_ue = 1;
+static int poll_msec = 1000;
+
+static int check_pci_parity = 0; /* default YES check PCI parity */
+static int panic_on_pci_parity; /* default no panic on PCI Parity */
+static atomic_t pci_parity_count = ATOMIC_INIT(0);
+
+/* lock to memory controller's control array */
+static DECLARE_MUTEX(mem_ctls_mutex);
+static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
+
+/* Structure of the whitelist and blacklist arrays */
+struct edac_pci_device_list {
+ unsigned int vendor; /* Vendor ID */
+ unsigned int device; /* Deviice ID */
+};
+
+
+#define MAX_LISTED_PCI_DEVICES 32
+
+/* List of PCI devices (vendor-id:device-id) that should be skipped */
+static struct edac_pci_device_list pci_blacklist[MAX_LISTED_PCI_DEVICES];
+static int pci_blacklist_count;
+
+/* List of PCI devices (vendor-id:device-id) that should be scanned */
+static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES];
+static int pci_whitelist_count ;
+
+/* START sysfs data and methods */
+
+static const char *mem_types[] = {
+ [MEM_EMPTY] = "Empty",
+ [MEM_RESERVED] = "Reserved",
+ [MEM_UNKNOWN] = "Unknown",
+ [MEM_FPM] = "FPM",
+ [MEM_EDO] = "EDO",
+ [MEM_BEDO] = "BEDO",
+ [MEM_SDR] = "Unbuffered-SDR",
+ [MEM_RDR] = "Registered-SDR",
+ [MEM_DDR] = "Unbuffered-DDR",
+ [MEM_RDDR] = "Registered-DDR",
+ [MEM_RMBS] = "RMBS"
+};
+
+static const char *dev_types[] = {
+ [DEV_UNKNOWN] = "Unknown",
+ [DEV_X1] = "x1",
+ [DEV_X2] = "x2",
+ [DEV_X4] = "x4",
+ [DEV_X8] = "x8",
+ [DEV_X16] = "x16",
+ [DEV_X32] = "x32",
+ [DEV_X64] = "x64"
+};
+
+static const char *edac_caps[] = {
+ [EDAC_UNKNOWN] = "Unknown",
+ [EDAC_NONE] = "None",
+ [EDAC_RESERVED] = "Reserved",
+ [EDAC_PARITY] = "PARITY",
+ [EDAC_EC] = "EC",
+ [EDAC_SECDED] = "SECDED",
+ [EDAC_S2ECD2ED] = "S2ECD2ED",
+ [EDAC_S4ECD4ED] = "S4ECD4ED",
+ [EDAC_S8ECD8ED] = "S8ECD8ED",
+ [EDAC_S16ECD16ED] = "S16ECD16ED"
+};
+
+
+/* sysfs object: /sys/devices/system/edac */
+static struct sysdev_class edac_class = {
+ set_kset_name("edac"),
+};
+
+/* sysfs objects:
+ * /sys/devices/system/edac/mc
+ * /sys/devices/system/edac/pci
+ */
+static struct kobject edac_memctrl_kobj;
+static struct kobject edac_pci_kobj;
+
+/*
+ * /sys/devices/system/edac/mc;
+ * data structures and methods
+ */
+static ssize_t memctrl_string_show(void *ptr, char *buffer)
+{
+ char *value = (char*) ptr;
+ return sprintf(buffer, "%s\n", value);
+}
+
+static ssize_t memctrl_int_show(void *ptr, char *buffer)
+{
+ int *value = (int*) ptr;
+ return sprintf(buffer, "%d\n", *value);
+}
+
+static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
+{
+ int *value = (int*) ptr;
+
+ if (isdigit(*buffer))
+ *value = simple_strtoul(buffer, NULL, 0);
+
+ return count;
+}
+
+struct memctrl_dev_attribute {
+ struct attribute attr;
+ void *value;
+ ssize_t (*show)(void *,char *);
+ ssize_t (*store)(void *, const char *, size_t);
+};
+
+/* Set of show/store abstract level functions for memory control object */
+static ssize_t
+memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
+{
+ struct memctrl_dev_attribute *memctrl_dev;
+ memctrl_dev = (struct memctrl_dev_attribute*)attr;
+
+ if (memctrl_dev->show)
+ return memctrl_dev->show(memctrl_dev->value, buffer);
+ return -EIO;
+}
+
+static ssize_t
+memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct memctrl_dev_attribute *memctrl_dev;
+ memctrl_dev = (struct memctrl_dev_attribute*)attr;
+
+ if (memctrl_dev->store)
+ return memctrl_dev->store(memctrl_dev->value, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops memctrlfs_ops = {
+ .show = memctrl_dev_show,
+ .store = memctrl_dev_store
+};
+
+#define MEMCTRL_ATTR(_name,_mode,_show,_store) \
+struct memctrl_dev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = &_name, \
+ .show = _show, \
+ .store = _store, \
+};
+
+#define MEMCTRL_STRING_ATTR(_name,_data,_mode,_show,_store) \
+struct memctrl_dev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = _data, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* cwrow<id> attribute f*/
+MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL);
+
+/* csrow<id> control files */
+MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+
+
+/* Base Attributes of the memory ECC object */
+static struct memctrl_dev_attribute *memctrl_attr[] = {
+ &attr_panic_on_ue,
+ &attr_log_ue,
+ &attr_log_ce,
+ &attr_poll_msec,
+ &attr_mc_version,
+ NULL,
+};
+
+/* Main MC kobject release() function */
+static void edac_memctrl_master_release(struct kobject *kobj)
+{
+ debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_memctrl = {
+ .release = edac_memctrl_master_release,
+ .sysfs_ops = &memctrlfs_ops,
+ .default_attrs = (struct attribute **) memctrl_attr,
+};
+
+
+/* Initialize the main sysfs entries for edac:
+ * /sys/devices/system/edac
+ *
+ * and children
+ *
+ * Return: 0 SUCCESS
+ * !0 FAILURE
+ */
+static int edac_sysfs_memctrl_setup(void)
+{
+ int err=0;
+
+ debugf1("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* create the /sys/devices/system/edac directory */
+ err = sysdev_class_register(&edac_class);
+ if (!err) {
+ /* Init the MC's kobject */
+ memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj));
+ kobject_init(&edac_memctrl_kobj);
+
+ edac_memctrl_kobj.parent = &edac_class.kset.kobj;
+ edac_memctrl_kobj.ktype = &ktype_memctrl;
+
+ /* generate sysfs "..../edac/mc" */
+ err = kobject_set_name(&edac_memctrl_kobj,"mc");
+ if (!err) {
+ /* FIXME: maybe new sysdev_create_subdir() */
+ err = kobject_register(&edac_memctrl_kobj);
+ if (err) {
+ debugf1("Failed to register '.../edac/mc'\n");
+ } else {
+ debugf1("Registered '.../edac/mc' kobject\n");
+ }
+ }
+ } else {
+ debugf1(KERN_WARNING "__FILE__ %s() error=%d\n", __func__,err);
+ }
+
+ return err;
+}
+
+/*
+ * MC teardown:
+ * the '..../edac/mc' kobject followed by '..../edac' itself
+ */
+static void edac_sysfs_memctrl_teardown(void)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* Unregister the MC's kobject */
+ kobject_unregister(&edac_memctrl_kobj);
+
+ /* release the master edac mc kobject */
+ kobject_put(&edac_memctrl_kobj);
+
+ /* Unregister the 'edac' object */
+ sysdev_class_unregister(&edac_class);
+}
+
+/*
+ * /sys/devices/system/edac/pci;
+ * data structures and methods
+ */
+
+struct list_control {
+ struct edac_pci_device_list *list;
+ int *count;
+};
+
+/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */
+static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
+{
+ struct list_control *listctl;
+ struct edac_pci_device_list *list;
+ char *p = buffer;
+ int len=0;
+ int i;
+
+ listctl = ptr;
+ list = listctl->list;
+
+ for (i = 0; i < *(listctl->count); i++, list++ ) {
+ if (len > 0)
+ len += snprintf(p + len, (PAGE_SIZE-len), ",");
+
+ len += snprintf(p + len,
+ (PAGE_SIZE-len),
+ "%x:%x",
+ list->vendor,list->device);
+ }
+
+ len += snprintf(p + len,(PAGE_SIZE-len), "\n");
+
+ return (ssize_t) len;
+}
+
+/**
+ *
+ * Scan string from **s to **e looking for one 'vendor:device' tuple
+ * where each field is a hex value
+ *
+ * return 0 if an entry is NOT found
+ * return 1 if an entry is found
+ * fill in *vendor_id and *device_id with values found
+ *
+ * In both cases, make sure *s has been moved forward toward *e
+ */
+static int parse_one_device(const char **s,const char **e,
+ unsigned int *vendor_id, unsigned int *device_id)
+{
+ const char *runner, *p;
+
+ /* if null byte, we are done */
+ if (!**s) {
+ (*s)++; /* keep *s moving */
+ return 0;
+ }
+
+ /* skip over newlines & whitespace */
+ if ((**s == '\n') || isspace(**s)) {
+ (*s)++;
+ return 0;
+ }
+
+ if (!isxdigit(**s)) {
+ (*s)++;
+ return 0;
+ }
+
+ /* parse vendor_id */
+ runner = *s;
+ while (runner < *e) {
+ /* scan for vendor:device delimiter */
+ if (*runner == ':') {
+ *vendor_id = simple_strtol((char*) *s, (char**) &p, 16);
+ runner = p + 1;
+ break;
+ }
+ runner++;
+ }
+
+ if (!isxdigit(*runner)) {
+ *s = ++runner;
+ return 0;
+ }
+
+ /* parse device_id */
+ if (runner < *e) {
+ *device_id = simple_strtol((char*)runner, (char**)&p, 16);
+ runner = p;
+ }
+
+ *s = runner;
+
+ return 1;
+}
+
+static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
+ size_t count)
+{
+ struct list_control *listctl;
+ struct edac_pci_device_list *list;
+ unsigned int vendor_id, device_id;
+ const char *s, *e;
+ int *index;
+
+ s = (char*)buffer;
+ e = s + count;
+
+ listctl = ptr;
+ list = listctl->list;
+ index = listctl->count;
+
+ *index = 0;
+ while (*index < MAX_LISTED_PCI_DEVICES) {
+
+ if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
+ list[ *index ].vendor = vendor_id;
+ list[ *index ].device = device_id;
+ (*index)++;
+ }
+
+ /* check for all data consume */
+ if (s >= e)
+ break;
+ }
+
+ return count;
+}
+
+static ssize_t edac_pci_int_show(void *ptr, char *buffer)
+{
+ int *value = ptr;
+ return sprintf(buffer,"%d\n",*value);
+}
+
+static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count)
+{
+ int *value = ptr;
+
+ if (isdigit(*buffer))
+ *value = simple_strtoul(buffer,NULL,0);
+
+ return count;
+}
+
+struct edac_pci_dev_attribute {
+ struct attribute attr;
+ void *value;
+ ssize_t (*show)(void *,char *);
+ ssize_t (*store)(void *, const char *,size_t);
+};
+
+/* Set of show/store abstract level functions for PCI Parity object */
+static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct edac_pci_dev_attribute *edac_pci_dev;
+ edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
+
+ if (edac_pci_dev->show)
+ return edac_pci_dev->show(edac_pci_dev->value, buffer);
+ return -EIO;
+}
+
+static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct edac_pci_dev_attribute *edac_pci_dev;
+ edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
+
+ if (edac_pci_dev->show)
+ return edac_pci_dev->store(edac_pci_dev->value, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops edac_pci_sysfs_ops = {
+ .show = edac_pci_dev_show,
+ .store = edac_pci_dev_store
+};
+
+
+#define EDAC_PCI_ATTR(_name,_mode,_show,_store) \
+struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = &_name, \
+ .show = _show, \
+ .store = _store, \
+};
+
+#define EDAC_PCI_STRING_ATTR(_name,_data,_mode,_show,_store) \
+struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = _data, \
+ .show = _show, \
+ .store = _store, \
+};
+
+static struct list_control pci_whitelist_control = {
+ .list = pci_whitelist,
+ .count = &pci_whitelist_count
+};
+
+static struct list_control pci_blacklist_control = {
+ .list = pci_blacklist,
+ .count = &pci_blacklist_count
+};
+
+/* whitelist attribute */
+EDAC_PCI_STRING_ATTR(pci_parity_whitelist,
+ &pci_whitelist_control,
+ S_IRUGO|S_IWUSR,
+ edac_pci_list_string_show,
+ edac_pci_list_string_store);
+
+EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
+ &pci_blacklist_control,
+ S_IRUGO|S_IWUSR,
+ edac_pci_list_string_show,
+ edac_pci_list_string_store);
+
+/* PCI Parity control files */
+EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
+EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
+EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL);
+
+/* Base Attributes of the memory ECC object */
+static struct edac_pci_dev_attribute *edac_pci_attr[] = {
+ &edac_pci_attr_check_pci_parity,
+ &edac_pci_attr_panic_on_pci_parity,
+ &edac_pci_attr_pci_parity_count,
+ &edac_pci_attr_pci_parity_whitelist,
+ &edac_pci_attr_pci_parity_blacklist,
+ NULL,
+};
+
+/* No memory to release */
+static void edac_pci_release(struct kobject *kobj)
+{
+ debugf1("EDAC PCI: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_edac_pci = {
+ .release = edac_pci_release,
+ .sysfs_ops = &edac_pci_sysfs_ops,
+ .default_attrs = (struct attribute **) edac_pci_attr,
+};
+
+/**
+ * edac_sysfs_pci_setup()
+ *
+ */
+static int edac_sysfs_pci_setup(void)
+{
+ int err;
+
+ debugf1("MC: " __FILE__ ": %s()\n", __func__);
+
+ memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj));
+
+ kobject_init(&edac_pci_kobj);
+ edac_pci_kobj.parent = &edac_class.kset.kobj;
+ edac_pci_kobj.ktype = &ktype_edac_pci;
+
+ err = kobject_set_name(&edac_pci_kobj, "pci");
+ if (!err) {
+ /* Instanstiate the csrow object */
+ /* FIXME: maybe new sysdev_create_subdir() */
+ err = kobject_register(&edac_pci_kobj);
+ if (err)
+ debugf1("Failed to register '.../edac/pci'\n");
+ else
+ debugf1("Registered '.../edac/pci' kobject\n");
+ }
+ return err;
+}
+
+
+static void edac_sysfs_pci_teardown(void)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ kobject_unregister(&edac_pci_kobj);
+ kobject_put(&edac_pci_kobj);
+}
+
+/* EDAC sysfs CSROW data structures and methods */
+
+/* Set of more detailed csrow<id> attribute show/store functions */
+static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
+ csrow->channels[0].label);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
+ csrow->channels[1].label);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
+ const char *data, size_t size)
+{
+ ssize_t max_size = 0;
+
+ if (csrow->nr_channels > 0) {
+ max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
+ strncpy(csrow->channels[0].label, data, max_size);
+ csrow->channels[0].label[max_size] = '\0';
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
+ const char *data, size_t size)
+{
+ ssize_t max_size = 0;
+
+ if (csrow->nr_channels > 1) {
+ max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
+ strncpy(csrow->channels[1].label, data, max_size);
+ csrow->channels[1].label[max_size] = '\0';
+ }
+ return max_size;
+}
+
+static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", csrow->ue_count);
+}
+
+static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", csrow->ce_count);
+}
+
+static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 1) {
+ size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
+ }
+ return size;
+}
+
+static ssize_t csrow_size_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
+}
+
+static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", mem_types[csrow->mtype]);
+}
+
+static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", dev_types[csrow->dtype]);
+}
+
+static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
+}
+
+struct csrowdev_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct csrow_info *,char *);
+ ssize_t (*store)(struct csrow_info *, const char *,size_t);
+};
+
+#define to_csrow(k) container_of(k, struct csrow_info, kobj)
+#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
+
+/* Set of show/store higher level functions for csrow objects */
+static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct csrow_info *csrow = to_csrow(kobj);
+ struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
+
+ if (csrowdev_attr->show)
+ return csrowdev_attr->show(csrow, buffer);
+ return -EIO;
+}
+
+static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct csrow_info *csrow = to_csrow(kobj);
+ struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
+
+ if (csrowdev_attr->store)
+ return csrowdev_attr->store(csrow, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops csrowfs_ops = {
+ .show = csrowdev_show,
+ .store = csrowdev_store
+};
+
+#define CSROWDEV_ATTR(_name,_mode,_show,_store) \
+struct csrowdev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* cwrow<id>/attribute files */
+CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL);
+CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL);
+CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL);
+CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL);
+CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL);
+CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL);
+CSROWDEV_ATTR(ch0_ce_count,S_IRUGO,csrow_ch0_ce_count_show,NULL);
+CSROWDEV_ATTR(ch1_ce_count,S_IRUGO,csrow_ch1_ce_count_show,NULL);
+
+/* control/attribute files */
+CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
+ csrow_ch0_dimm_label_show,
+ csrow_ch0_dimm_label_store);
+CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
+ csrow_ch1_dimm_label_show,
+ csrow_ch1_dimm_label_store);
+
+
+/* Attributes of the CSROW<id> object */
+static struct csrowdev_attribute *csrow_attr[] = {
+ &attr_dev_type,
+ &attr_mem_type,
+ &attr_edac_mode,
+ &attr_size_mb,
+ &attr_ue_count,
+ &attr_ce_count,
+ &attr_ch0_ce_count,
+ &attr_ch1_ce_count,
+ &attr_ch0_dimm_label,
+ &attr_ch1_dimm_label,
+ NULL,
+};
+
+
+/* No memory to release */
+static void edac_csrow_instance_release(struct kobject *kobj)
+{
+ debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_csrow = {
+ .release = edac_csrow_instance_release,
+ .sysfs_ops = &csrowfs_ops,
+ .default_attrs = (struct attribute **) csrow_attr,
+};
+
+/* Create a CSROW object under specifed edac_mc_device */
+static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
+ struct csrow_info *csrow, int index )
+{
+ int err = 0;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ memset(&csrow->kobj, 0, sizeof(csrow->kobj));
+
+ /* generate ..../edac/mc/mc<id>/csrow<index> */
+
+ kobject_init(&csrow->kobj);
+ csrow->kobj.parent = edac_mci_kobj;
+ csrow->kobj.ktype = &ktype_csrow;
+
+ /* name this instance of csrow<id> */
+ err = kobject_set_name(&csrow->kobj,"csrow%d",index);
+ if (!err) {
+ /* Instanstiate the csrow object */
+ err = kobject_register(&csrow->kobj);
+ if (err)
+ debugf0("Failed to register CSROW%d\n",index);
+ else
+ debugf0("Registered CSROW%d\n",index);
+ }
+
+ return err;
+}
+
+/* sysfs data structures and methods for the MCI kobjects */
+
+static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
+ const char *data, size_t count )
+{
+ int row, chan;
+
+ mci->ue_noinfo_count = 0;
+ mci->ce_noinfo_count = 0;
+ mci->ue_count = 0;
+ mci->ce_count = 0;
+ for (row = 0; row < mci->nr_csrows; row++) {
+ struct csrow_info *ri = &mci->csrows[row];
+
+ ri->ue_count = 0;
+ ri->ce_count = 0;
+ for (chan = 0; chan < ri->nr_channels; chan++)
+ ri->channels[chan].ce_count = 0;
+ }
+ mci->start_time = jiffies;
+
+ return count;
+}
+
+static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ue_count);
+}
+
+static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ce_count);
+}
+
+static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ce_noinfo_count);
+}
+
+static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ue_noinfo_count);
+}
+
+static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ);
+}
+
+static ssize_t mci_mod_name_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%s %s\n", mci->mod_name, mci->mod_ver);
+}
+
+static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%s\n", mci->ctl_name);
+}
+
+static int mci_output_edac_cap(char *buf, unsigned long edac_cap)
+{
+ char *p = buf;
+ int bit_idx;
+
+ for (bit_idx = 0; bit_idx < 8 * sizeof(edac_cap); bit_idx++) {
+ if ((edac_cap >> bit_idx) & 0x1)
+ p += sprintf(p, "%s ", edac_caps[bit_idx]);
+ }
+
+ return p - buf;
+}
+
+static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
+{
+ char *p = data;
+
+ p += mci_output_edac_cap(p,mci->edac_ctl_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
+ char *data)
+{
+ char *p = data;
+
+ p += mci_output_edac_cap(p,mci->edac_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
+{
+ char *p = buf;
+ int bit_idx;
+
+ for (bit_idx = 0; bit_idx < 8 * sizeof(mtype_cap); bit_idx++) {
+ if ((mtype_cap >> bit_idx) & 0x1)
+ p += sprintf(p, "%s ", mem_types[bit_idx]);
+ }
+
+ return p - buf;
+}
+
+static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data)
+{
+ char *p = data;
+
+ p += mci_output_mtype_cap(p,mci->mtype_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
+{
+ int total_pages, csrow_idx;
+
+ for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows;
+ csrow_idx++) {
+ struct csrow_info *csrow = &mci->csrows[csrow_idx];
+
+ if (!csrow->nr_pages)
+ continue;
+ total_pages += csrow->nr_pages;
+ }
+
+ return sprintf(data,"%u\n", PAGES_TO_MiB(total_pages));
+}
+
+struct mcidev_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct mem_ctl_info *,char *);
+ ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
+};
+
+#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
+#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
+
+static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
+ struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
+
+ if (mcidev_attr->show)
+ return mcidev_attr->show(mem_ctl_info, buffer);
+ return -EIO;
+}
+
+static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
+ struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
+
+ if (mcidev_attr->store)
+ return mcidev_attr->store(mem_ctl_info, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops mci_ops = {
+ .show = mcidev_show,
+ .store = mcidev_store
+};
+
+#define MCIDEV_ATTR(_name,_mode,_show,_store) \
+struct mcidev_attribute mci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* Control file */
+MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store);
+
+/* Attribute files */
+MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL);
+MCIDEV_ATTR(module_name,S_IRUGO,mci_mod_name_show,NULL);
+MCIDEV_ATTR(edac_capability,S_IRUGO,mci_edac_capability_show,NULL);
+MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL);
+MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL);
+MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL);
+MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL);
+MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
+MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
+MCIDEV_ATTR(edac_current_capability,S_IRUGO,
+ mci_edac_current_capability_show,NULL);
+MCIDEV_ATTR(supported_mem_type,S_IRUGO,
+ mci_supported_mem_type_show,NULL);
+
+
+static struct mcidev_attribute *mci_attr[] = {
+ &mci_attr_reset_counters,
+ &mci_attr_module_name,
+ &mci_attr_mc_name,
+ &mci_attr_edac_capability,
+ &mci_attr_edac_current_capability,
+ &mci_attr_supported_mem_type,
+ &mci_attr_size_mb,
+ &mci_attr_seconds_since_reset,
+ &mci_attr_ue_noinfo_count,
+ &mci_attr_ce_noinfo_count,
+ &mci_attr_ue_count,
+ &mci_attr_ce_count,
+ NULL
+};
+
+
+/*
+ * Release of a MC controlling instance
+ */
+static void edac_mci_instance_release(struct kobject *kobj)
+{
+ struct mem_ctl_info *mci;
+ mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj);
+
+ debugf0("MC: " __FILE__ ": %s() idx=%d calling kfree\n",
+ __func__, mci->mc_idx);
+
+ kfree(mci);
+}
+
+static struct kobj_type ktype_mci = {
+ .release = edac_mci_instance_release,
+ .sysfs_ops = &mci_ops,
+ .default_attrs = (struct attribute **) mci_attr,
+};
+
+#define EDAC_DEVICE_SYMLINK "device"
+
+/*
+ * Create a new Memory Controller kobject instance,
+ * mc<id> under the 'mc' directory
+ *
+ * Return:
+ * 0 Success
+ * !0 Failure
+ */
+static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
+{
+ int i;
+ int err;
+ struct csrow_info *csrow;
+ struct kobject *edac_mci_kobj=&mci->edac_mci_kobj;
+
+ debugf0("MC: " __FILE__ ": %s() idx=%d\n", __func__, mci->mc_idx);
+
+ memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj));
+ kobject_init(edac_mci_kobj);
+
+ /* set the name of the mc<id> object */
+ err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
+ if (err)
+ return err;
+
+ /* link to our parent the '..../edac/mc' object */
+ edac_mci_kobj->parent = &edac_memctrl_kobj;
+ edac_mci_kobj->ktype = &ktype_mci;
+
+ /* register the mc<id> kobject */
+ err = kobject_register(edac_mci_kobj);
+ if (err)
+ return err;
+
+ /* create a symlink for the device */
+ err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj,
+ EDAC_DEVICE_SYMLINK);
+ if (err) {
+ kobject_unregister(edac_mci_kobj);
+ return err;
+ }
+
+ /* Make directories for each CSROW object
+ * under the mc<id> kobject
+ */
+ for (i = 0; i < mci->nr_csrows; i++) {
+
+ csrow = &mci->csrows[i];
+
+ /* Only expose populated CSROWs */
+ if (csrow->nr_pages > 0) {
+ err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
+ if (err)
+ goto fail;
+ }
+ }
+
+ /* Mark this MCI instance as having sysfs entries */
+ mci->sysfs_active = MCI_SYSFS_ACTIVE;
+
+ return 0;
+
+
+ /* CSROW error: backout what has already been registered, */
+fail:
+ for ( i--; i >= 0; i--) {
+ if (csrow->nr_pages > 0) {
+ kobject_unregister(&mci->csrows[i].kobj);
+ kobject_put(&mci->csrows[i].kobj);
+ }
+ }
+
+ kobject_unregister(edac_mci_kobj);
+ kobject_put(edac_mci_kobj);
+
+ return err;
+}
+
+/*
+ * remove a Memory Controller instance
+ */
+static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
+{
+ int i;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* remove all csrow kobjects */
+ for (i = 0; i < mci->nr_csrows; i++) {
+ if (mci->csrows[i].nr_pages > 0) {
+ kobject_unregister(&mci->csrows[i].kobj);
+ kobject_put(&mci->csrows[i].kobj);
+ }
+ }
+
+ sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
+
+ kobject_unregister(&mci->edac_mci_kobj);
+ kobject_put(&mci->edac_mci_kobj);
+}
+
+/* END OF sysfs data and methods */
+
+#ifdef CONFIG_EDAC_DEBUG
+
+EXPORT_SYMBOL(edac_mc_dump_channel);
+
+void edac_mc_dump_channel(struct channel_info *chan)
+{
+ debugf4("\tchannel = %p\n", chan);
+ debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
+ debugf4("\tchannel->ce_count = %d\n", chan->ce_count);
+ debugf4("\tchannel->label = '%s'\n", chan->label);
+ debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
+}
+
+
+EXPORT_SYMBOL(edac_mc_dump_csrow);
+
+void edac_mc_dump_csrow(struct csrow_info *csrow)
+{
+ debugf4("\tcsrow = %p\n", csrow);
+ debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx);
+ debugf4("\tcsrow->first_page = 0x%lx\n",
+ csrow->first_page);
+ debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page);
+ debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask);
+ debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages);
+ debugf4("\tcsrow->nr_channels = %d\n",
+ csrow->nr_channels);
+ debugf4("\tcsrow->channels = %p\n", csrow->channels);
+ debugf4("\tcsrow->mci = %p\n\n", csrow->mci);
+}
+
+
+EXPORT_SYMBOL(edac_mc_dump_mci);
+
+void edac_mc_dump_mci(struct mem_ctl_info *mci)
+{
+ debugf3("\tmci = %p\n", mci);
+ debugf3("\tmci->mtype_cap = %lx\n", mci->mtype_cap);
+ debugf3("\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap);
+ debugf3("\tmci->edac_cap = %lx\n", mci->edac_cap);
+ debugf4("\tmci->edac_check = %p\n", mci->edac_check);
+ debugf3("\tmci->nr_csrows = %d, csrows = %p\n",
+ mci->nr_csrows, mci->csrows);
+ debugf3("\tpdev = %p\n", mci->pdev);
+ debugf3("\tmod_name:ctl_name = %s:%s\n",
+ mci->mod_name, mci->ctl_name);
+ debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
+}
+
+
+#endif /* CONFIG_EDAC_DEBUG */
+
+/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
+ * Adjust 'ptr' so that its alignment is at least as stringent as what the
+ * compiler would provide for X and return the aligned result.
+ *
+ * If 'size' is a constant, the compiler will optimize this whole function
+ * down to either a no-op or the addition of a constant to the value of 'ptr'.
+ */
+static inline char * align_ptr (void *ptr, unsigned size)
+{
+ unsigned align, r;
+
+ /* Here we assume that the alignment of a "long long" is the most
+ * stringent alignment that the compiler will ever provide by default.
+ * As far as I know, this is a reasonable assumption.
+ */
+ if (size > sizeof(long))
+ align = sizeof(long long);
+ else if (size > sizeof(int))
+ align = sizeof(long);
+ else if (size > sizeof(short))
+ align = sizeof(int);
+ else if (size > sizeof(char))
+ align = sizeof(short);
+ else
+ return (char *) ptr;
+
+ r = size % align;
+
+ if (r == 0)
+ return (char *) ptr;
+
+ return (char *) (((unsigned long) ptr) + align - r);
+}
+
+
+EXPORT_SYMBOL(edac_mc_alloc);
+
+/**
+ * edac_mc_alloc: Allocate a struct mem_ctl_info structure
+ * @size_pvt: size of private storage needed
+ * @nr_csrows: Number of CWROWS needed for this MC
+ * @nr_chans: Number of channels for the MC
+ *
+ * Everything is kmalloc'ed as one big chunk - more efficient.
+ * Only can be used if all structures have the same lifetime - otherwise
+ * you have to allocate and initialize your own structures.
+ *
+ * Use edac_mc_free() to free mc structures allocated by this function.
+ *
+ * Returns:
+ * NULL allocation failed
+ * struct mem_ctl_info pointer
+ */
+struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
+ unsigned nr_chans)
+{
+ struct mem_ctl_info *mci;
+ struct csrow_info *csi, *csrow;
+ struct channel_info *chi, *chp, *chan;
+ void *pvt;
+ unsigned size;
+ int row, chn;
+
+ /* Figure out the offsets of the various items from the start of an mc
+ * structure. We want the alignment of each item to be at least as
+ * stringent as what the compiler would provide if we could simply
+ * hardcode everything into a single struct.
+ */
+ mci = (struct mem_ctl_info *) 0;
+ csi = (struct csrow_info *)align_ptr(&mci[1], sizeof(*csi));
+ chi = (struct channel_info *)
+ align_ptr(&csi[nr_csrows], sizeof(*chi));
+ pvt = align_ptr(&chi[nr_chans * nr_csrows], sz_pvt);
+ size = ((unsigned long) pvt) + sz_pvt;
+
+ if ((mci = kmalloc(size, GFP_KERNEL)) == NULL)
+ return NULL;
+
+ /* Adjust pointers so they point within the memory we just allocated
+ * rather than an imaginary chunk of memory located at address 0.
+ */
+ csi = (struct csrow_info *) (((char *) mci) + ((unsigned long) csi));
+ chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi));
+ pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL;
+
+ memset(mci, 0, size); /* clear all fields */
+
+ mci->csrows = csi;
+ mci->pvt_info = pvt;
+ mci->nr_csrows = nr_csrows;
+
+ for (row = 0; row < nr_csrows; row++) {
+ csrow = &csi[row];
+ csrow->csrow_idx = row;
+ csrow->mci = mci;
+ csrow->nr_channels = nr_chans;
+ chp = &chi[row * nr_chans];
+ csrow->channels = chp;
+
+ for (chn = 0; chn < nr_chans; chn++) {
+ chan = &chp[chn];
+ chan->chan_idx = chn;
+ chan->csrow = csrow;
+ }
+ }
+
+ return mci;
+}
+
+
+EXPORT_SYMBOL(edac_mc_free);
+
+/**
+ * edac_mc_free: Free a previously allocated 'mci' structure
+ * @mci: pointer to a struct mem_ctl_info structure
+ *
+ * Free up a previously allocated mci structure
+ * A MCI structure can be in 2 states after being allocated
+ * by edac_mc_alloc().
+ * 1) Allocated in a MC driver's probe, but not yet committed
+ * 2) Allocated and committed, by a call to edac_mc_add_mc()
+ * edac_mc_add_mc() is the function that adds the sysfs entries
+ * thus, this free function must determine which state the 'mci'
+ * structure is in, then either free it directly or
+ * perform kobject cleanup by calling edac_remove_sysfs_mci_device().
+ *
+ * VOID Return
+ */
+void edac_mc_free(struct mem_ctl_info *mci)
+{
+ /* only if sysfs entries for this mci instance exist
+ * do we remove them and defer the actual kfree via
+ * the kobject 'release()' callback.
+ *
+ * Otherwise, do a straight kfree now.
+ */
+ if (mci->sysfs_active == MCI_SYSFS_ACTIVE)
+ edac_remove_sysfs_mci_device(mci);
+ else
+ kfree(mci);
+}
+
+
+
+EXPORT_SYMBOL(edac_mc_find_mci_by_pdev);
+
+struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct list_head *item;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ list_for_each(item, &mc_devices) {
+ mci = list_entry(item, struct mem_ctl_info, link);
+
+ if (mci->pdev == pdev)
+ return mci;
+ }
+
+ return NULL;
+}
+
+static int add_mc_to_global_list (struct mem_ctl_info *mci)
+{
+ struct list_head *item, *insert_before;
+ struct mem_ctl_info *p;
+ int i;
+
+ if (list_empty(&mc_devices)) {
+ mci->mc_idx = 0;
+ insert_before = &mc_devices;
+ } else {
+ if (edac_mc_find_mci_by_pdev(mci->pdev)) {
+ printk(KERN_WARNING
+ "EDAC MC: %s (%s) %s %s already assigned %d\n",
+ mci->pdev->dev.bus_id, pci_name(mci->pdev),
+ mci->mod_name, mci->ctl_name, mci->mc_idx);
+ return 1;
+ }
+
+ insert_before = NULL;
+ i = 0;
+
+ list_for_each(item, &mc_devices) {
+ p = list_entry(item, struct mem_ctl_info, link);
+
+ if (p->mc_idx != i) {
+ insert_before = item;
+ break;
+ }
+
+ i++;
+ }
+
+ mci->mc_idx = i;
+
+ if (insert_before == NULL)
+ insert_before = &mc_devices;
+ }
+
+ list_add_tail_rcu(&mci->link, insert_before);
+ return 0;
+}
+
+
+
+EXPORT_SYMBOL(edac_mc_add_mc);
+
+/**
+ * edac_mc_add_mc: Insert the 'mci' structure into the mci global list
+ * @mci: pointer to the mci structure to be added to the list
+ *
+ * Return:
+ * 0 Success
+ * !0 Failure
+ */
+
+/* FIXME - should a warning be printed if no error detection? correction? */
+int edac_mc_add_mc(struct mem_ctl_info *mci)
+{
+ int rc = 1;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+#ifdef CONFIG_EDAC_DEBUG
+ if (edac_debug_level >= 3)
+ edac_mc_dump_mci(mci);
+ if (edac_debug_level >= 4) {
+ int i;
+
+ for (i = 0; i < mci->nr_csrows; i++) {
+ int j;
+ edac_mc_dump_csrow(&mci->csrows[i]);
+ for (j = 0; j < mci->csrows[i].nr_channels; j++)
+ edac_mc_dump_channel(&mci->csrows[i].
+ channels[j]);
+ }
+ }
+#endif
+ down(&mem_ctls_mutex);
+
+ if (add_mc_to_global_list(mci))
+ goto finish;
+
+ /* set load time so that error rate can be tracked */
+ mci->start_time = jiffies;
+
+ if (edac_create_sysfs_mci_device(mci)) {
+ printk(KERN_WARNING
+ "EDAC MC%d: failed to create sysfs device\n",
+ mci->mc_idx);
+ /* FIXME - should there be an error code and unwind? */
+ goto finish;
+ }
+
+ /* Report action taken */
+ printk(KERN_INFO
+ "EDAC MC%d: Giving out device to %s %s: PCI %s\n",
+ mci->mc_idx, mci->mod_name, mci->ctl_name,
+ pci_name(mci->pdev));
+
+
+ rc = 0;
+
+finish:
+ up(&mem_ctls_mutex);
+ return rc;
+}
+
+
+
+static void complete_mc_list_del (struct rcu_head *head)
+{
+ struct mem_ctl_info *mci;
+
+ mci = container_of(head, struct mem_ctl_info, rcu);
+ INIT_LIST_HEAD(&mci->link);
+ complete(&mci->complete);
+}
+
+static void del_mc_from_global_list (struct mem_ctl_info *mci)
+{
+ list_del_rcu(&mci->link);
+ init_completion(&mci->complete);
+ call_rcu(&mci->rcu, complete_mc_list_del);
+ wait_for_completion(&mci->complete);
+}
+
+EXPORT_SYMBOL(edac_mc_del_mc);
+
+/**
+ * edac_mc_del_mc: Remove the specified mci structure from global list
+ * @mci: Pointer to struct mem_ctl_info structure
+ *
+ * Returns:
+ * 0 Success
+ * 1 Failure
+ */
+int edac_mc_del_mc(struct mem_ctl_info *mci)
+{
+ int rc = 1;
+
+ debugf0("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ down(&mem_ctls_mutex);
+ del_mc_from_global_list(mci);
+ printk(KERN_INFO
+ "EDAC MC%d: Removed device %d for %s %s: PCI %s\n",
+ mci->mc_idx, mci->mc_idx, mci->mod_name, mci->ctl_name,
+ pci_name(mci->pdev));
+ rc = 0;
+ up(&mem_ctls_mutex);
+
+ return rc;
+}
+
+
+EXPORT_SYMBOL(edac_mc_scrub_block);
+
+void edac_mc_scrub_block(unsigned long page, unsigned long offset,
+ u32 size)
+{
+ struct page *pg;
+ void *virt_addr;
+ unsigned long flags = 0;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* ECC error page was not in our memory. Ignore it. */
+ if(!pfn_valid(page))
+ return;
+
+ /* Find the actual page structure then map it and fix */
+ pg = pfn_to_page(page);
+
+ if (PageHighMem(pg))
+ local_irq_save(flags);
+
+ virt_addr = kmap_atomic(pg, KM_BOUNCE_READ);
+
+ /* Perform architecture specific atomic scrub operation */
+ atomic_scrub(virt_addr + offset, size);
+
+ /* Unmap and complete */
+ kunmap_atomic(virt_addr, KM_BOUNCE_READ);
+
+ if (PageHighMem(pg))
+ local_irq_restore(flags);
+}
+
+
+/* FIXME - should return -1 */
+EXPORT_SYMBOL(edac_mc_find_csrow_by_page);
+
+int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+ unsigned long page)
+{
+ struct csrow_info *csrows = mci->csrows;
+ int row, i;
+
+ debugf1("MC%d: " __FILE__ ": %s(): 0x%lx\n", mci->mc_idx, __func__,
+ page);
+ row = -1;
+
+ for (i = 0; i < mci->nr_csrows; i++) {
+ struct csrow_info *csrow = &csrows[i];
+
+ if (csrow->nr_pages == 0)
+ continue;
+
+ debugf3("MC%d: " __FILE__
+ ": %s(): first(0x%lx) page(0x%lx)"
+ " last(0x%lx) mask(0x%lx)\n", mci->mc_idx,
+ __func__, csrow->first_page, page,
+ csrow->last_page, csrow->page_mask);
+
+ if ((page >= csrow->first_page) &&
+ (page <= csrow->last_page) &&
+ ((page & csrow->page_mask) ==
+ (csrow->first_page & csrow->page_mask))) {
+ row = i;
+ break;
+ }
+ }
+
+ if (row == -1)
+ printk(KERN_ERR
+ "EDAC MC%d: could not look up page error address %lx\n",
+ mci->mc_idx, (unsigned long) page);
+
+ return row;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ce);
+
+/* FIXME - setable log (warning/emerg) levels */
+/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
+void edac_mc_handle_ce(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ unsigned long syndrome, int row, int channel,
+ const char *msg)
+{
+ unsigned long remapped_page;
+
+ debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+
+ /* FIXME - maybe make panic on INTERNAL ERROR an option */
+ if (row >= mci->nr_csrows || row < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
+ mci->mc_idx, row, mci->nr_csrows);
+ edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+ if (channel >= mci->csrows[row].nr_channels || channel < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: channel out of range "
+ "(%d >= %d)\n",
+ mci->mc_idx, channel, mci->csrows[row].nr_channels);
+ edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+
+ if (log_ce)
+ /* FIXME - put in DIMM location */
+ printk(KERN_WARNING
+ "EDAC MC%d: CE page 0x%lx, offset 0x%lx,"
+ " grain %d, syndrome 0x%lx, row %d, channel %d,"
+ " label \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, syndrome, row, channel,
+ mci->csrows[row].channels[channel].label, msg);
+
+ mci->ce_count++;
+ mci->csrows[row].ce_count++;
+ mci->csrows[row].channels[channel].ce_count++;
+
+ if (mci->scrub_mode & SCRUB_SW_SRC) {
+ /*
+ * Some MC's can remap memory so that it is still available
+ * at a different address when PCI devices map into memory.
+ * MC's that can't do this lose the memory where PCI devices
+ * are mapped. This mapping is MC dependant and so we call
+ * back into the MC driver for it to map the MC page to
+ * a physical (CPU) page which can then be mapped to a virtual
+ * page - which can then be scrubbed.
+ */
+ remapped_page = mci->ctl_page_to_phys ?
+ mci->ctl_page_to_phys(mci, page_frame_number) :
+ page_frame_number;
+
+ edac_mc_scrub_block(remapped_page, offset_in_page,
+ mci->csrows[row].grain);
+ }
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ce_no_info);
+
+void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
+ const char *msg)
+{
+ if (log_ce)
+ printk(KERN_WARNING
+ "EDAC MC%d: CE - no information available: %s\n",
+ mci->mc_idx, msg);
+ mci->ce_noinfo_count++;
+ mci->ce_count++;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ue);
+
+void edac_mc_handle_ue(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page, int row,
+ const char *msg)
+{
+ int len = EDAC_MC_LABEL_LEN * 4;
+ char labels[len + 1];
+ char *pos = labels;
+ int chan;
+ int chars;
+
+ debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+
+ /* FIXME - maybe make panic on INTERNAL ERROR an option */
+ if (row >= mci->nr_csrows || row < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
+ mci->mc_idx, row, mci->nr_csrows);
+ edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+
+ chars = snprintf(pos, len + 1, "%s",
+ mci->csrows[row].channels[0].label);
+ len -= chars;
+ pos += chars;
+ for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
+ chan++) {
+ chars = snprintf(pos, len + 1, ":%s",
+ mci->csrows[row].channels[chan].label);
+ len -= chars;
+ pos += chars;
+ }
+
+ if (log_ue)
+ printk(KERN_EMERG
+ "EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
+ " labels \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, row, labels, msg);
+
+ if (panic_on_ue)
+ panic
+ ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
+ " labels \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, row, labels, msg);
+
+ mci->ue_count++;
+ mci->csrows[row].ue_count++;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ue_no_info);
+
+void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
+ const char *msg)
+{
+ if (panic_on_ue)
+ panic("EDAC MC%d: Uncorrected Error", mci->mc_idx);
+
+ if (log_ue)
+ printk(KERN_WARNING
+ "EDAC MC%d: UE - no information available: %s\n",
+ mci->mc_idx, msg);
+ mci->ue_noinfo_count++;
+ mci->ue_count++;
+}
+
+
+#ifdef CONFIG_PCI
+
+static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
+{
+ int where;
+ u16 status;
+
+ where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
+ pci_read_config_word(dev, where, &status);
+
+ /* If we get back 0xFFFF then we must suspect that the card has been pulled but
+ the Linux PCI layer has not yet finished cleaning up. We don't want to report
+ on such devices */
+
+ if (status == 0xFFFF) {
+ u32 sanity;
+ pci_read_config_dword(dev, 0, &sanity);
+ if (sanity == 0xFFFFFFFF)
+ return 0;
+ }
+ status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
+ PCI_STATUS_PARITY;
+
+ if (status)
+ /* reset only the bits we are interested in */
+ pci_write_config_word(dev, where, status);
+
+ return status;
+}
+
+typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
+
+/* Clear any PCI parity errors logged by this device. */
+static void edac_pci_dev_parity_clear( struct pci_dev *dev )
+{
+ u8 header_type;
+
+ get_pci_parity_status(dev, 0);
+
+ /* read the device TYPE, looking for bridges */
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE)
+ get_pci_parity_status(dev, 1);
+}
+
+/*
+ * PCI Parity polling
+ *
+ */
+static void edac_pci_dev_parity_test(struct pci_dev *dev)
+{
+ u16 status;
+ u8 header_type;
+
+ /* read the STATUS register on this device
+ */
+ status = get_pci_parity_status(dev, 0);
+
+ debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id );
+
+ /* check the status reg for errors */
+ if (status) {
+ if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Signaled System Error on %s\n",
+ pci_name (dev));
+
+ if (status & (PCI_STATUS_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Master Data Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+
+ if (status & (PCI_STATUS_DETECTED_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Detected Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+ }
+
+ /* read the device TYPE, looking for bridges */
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+ debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id );
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+ /* On bridges, need to examine secondary status register */
+ status = get_pci_parity_status(dev, 1);
+
+ debugf2("PCI SEC_STATUS= 0x%04x %s\n",
+ status, dev->dev.bus_id );
+
+ /* check the secondary status reg for errors */
+ if (status) {
+ if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Signaled System Error on %s\n",
+ pci_name (dev));
+
+ if (status & (PCI_STATUS_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Master Data Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+
+ if (status & (PCI_STATUS_DETECTED_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Detected Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+ }
+ }
+}
+
+/*
+ * check_dev_on_list: Scan for a PCI device on a white/black list
+ * @list: an EDAC &edac_pci_device_list white/black list pointer
+ * @free_index: index of next free entry on the list
+ * @pci_dev: PCI Device pointer
+ *
+ * see if list contains the device.
+ *
+ * Returns: 0 not found
+ * 1 found on list
+ */
+static int check_dev_on_list(struct edac_pci_device_list *list, int free_index,
+ struct pci_dev *dev)
+{
+ int i;
+ int rc = 0; /* Assume not found */
+ unsigned short vendor=dev->vendor;
+ unsigned short device=dev->device;
+
+ /* Scan the list, looking for a vendor/device match
+ */
+ for (i = 0; i < free_index; i++, list++ ) {
+ if ( (list->vendor == vendor ) &&
+ (list->device == device )) {
+ rc = 1;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * pci_dev parity list iterator
+ * Scan the PCI device list for one iteration, looking for SERRORs
+ * Master Parity ERRORS or Parity ERRORs on primary or secondary devices
+ */
+static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
+{
+ struct pci_dev *dev=NULL;
+
+ /* request for kernel access to the next PCI device, if any,
+ * and while we are looking at it have its reference count
+ * bumped until we are done with it
+ */
+ while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+
+ /* if whitelist exists then it has priority, so only scan those
+ * devices on the whitelist
+ */
+ if (pci_whitelist_count > 0 ) {
+ if (check_dev_on_list(pci_whitelist,
+ pci_whitelist_count, dev))
+ fn(dev);
+ } else {
+ /*
+ * if no whitelist, then check if this devices is
+ * blacklisted
+ */
+ if (!check_dev_on_list(pci_blacklist,
+ pci_blacklist_count, dev))
+ fn(dev);
+ }
+ }
+}
+
+static void do_pci_parity_check(void)
+{
+ unsigned long flags;
+ int before_count;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (!check_pci_parity)
+ return;
+
+ before_count = atomic_read(&pci_parity_count);
+
+ /* scan all PCI devices looking for a Parity Error on devices and
+ * bridges
+ */
+ local_irq_save(flags);
+ edac_pci_dev_parity_iterator(edac_pci_dev_parity_test);
+ local_irq_restore(flags);
+
+ /* Only if operator has selected panic on PCI Error */
+ if (panic_on_pci_parity) {
+ /* If the count is different 'after' from 'before' */
+ if (before_count != atomic_read(&pci_parity_count))
+ panic("EDAC: PCI Parity Error");
+ }
+}
+
+
+static inline void clear_pci_parity_errors(void)
+{
+ /* Clear any PCI bus parity errors that devices initially have logged
+ * in their registers.
+ */
+ edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
+}
+
+
+#else /* CONFIG_PCI */
+
+
+static inline void do_pci_parity_check(void)
+{
+ /* no-op */
+}
+
+
+static inline void clear_pci_parity_errors(void)
+{
+ /* no-op */
+}
+
+
+#endif /* CONFIG_PCI */
+
+/*
+ * Iterate over all MC instances and check for ECC, et al, errors
+ */
+static inline void check_mc_devices (void)
+{
+ unsigned long flags;
+ struct list_head *item;
+ struct mem_ctl_info *mci;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* during poll, have interrupts off */
+ local_irq_save(flags);
+
+ list_for_each(item, &mc_devices) {
+ mci = list_entry(item, struct mem_ctl_info, link);
+
+ if (mci->edac_check != NULL)
+ mci->edac_check(mci);
+ }
+
+ local_irq_restore(flags);
+}
+
+
+/*
+ * Check MC status every poll_msec.
+ * Check PCI status every poll_msec as well.
+ *
+ * This where the work gets done for edac.
+ *
+ * SMP safe, doesn't use NMI, and auto-rate-limits.
+ */
+static void do_edac_check(void)
+{
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ check_mc_devices();
+
+ do_pci_parity_check();
+}
+
+
+/*
+ * EDAC thread state information
+ */
+struct bs_thread_info
+{
+ struct task_struct *task;
+ struct completion *event;
+ char *name;
+ void (*run)(void);
+};
+
+static struct bs_thread_info bs_thread;
+
+/*
+ * edac_kernel_thread
+ * This the kernel thread that processes edac operations
+ * in a normal thread environment
+ */
+static int edac_kernel_thread(void *arg)
+{
+ struct bs_thread_info *thread = (struct bs_thread_info *) arg;
+
+ /* detach thread */
+ daemonize(thread->name);
+
+ current->exit_signal = SIGCHLD;
+ allow_signal(SIGKILL);
+ thread->task = current;
+
+ /* indicate to starting task we have started */
+ complete(thread->event);
+
+ /* loop forever, until we are told to stop */
+ while(thread->run != NULL) {
+ void (*run)(void);
+
+ /* call the function to check the memory controllers */
+ run = thread->run;
+ if (run)
+ run();
+
+ if (signal_pending(current))
+ flush_signals(current);
+
+ /* ensure we are interruptable */
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /* goto sleep for the interval */
+ schedule_timeout((HZ * poll_msec) / 1000);
+ try_to_freeze();
+ }
+
+ /* notify waiter that we are exiting */
+ complete(thread->event);
+
+ return 0;
+}
+
+/*
+ * edac_mc_init
+ * module initialization entry point
+ */
+static int __init edac_mc_init(void)
+{
+ int ret;
+ struct completion event;
+
+ printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n");
+
+ /*
+ * Harvest and clear any boot/initialization PCI parity errors
+ *
+ * FIXME: This only clears errors logged by devices present at time of
+ * module initialization. We should also do an initial clear
+ * of each newly hotplugged device.
+ */
+ clear_pci_parity_errors();
+
+ /* perform check for first time to harvest boot leftovers */
+ do_edac_check();
+
+ /* Create the MC sysfs entires */
+ if (edac_sysfs_memctrl_setup()) {
+ printk(KERN_ERR "EDAC MC: Error initializing sysfs code\n");
+ return -ENODEV;
+ }
+
+ /* Create the PCI parity sysfs entries */
+ if (edac_sysfs_pci_setup()) {
+ edac_sysfs_memctrl_teardown();
+ printk(KERN_ERR "EDAC PCI: Error initializing sysfs code\n");
+ return -ENODEV;
+ }
+
+ /* Create our kernel thread */
+ init_completion(&event);
+ bs_thread.event = &event;
+ bs_thread.name = "kedac";
+ bs_thread.run = do_edac_check;
+
+ /* create our kernel thread */
+ ret = kernel_thread(edac_kernel_thread, &bs_thread, CLONE_KERNEL);
+ if (ret < 0) {
+ /* remove the sysfs entries */
+ edac_sysfs_memctrl_teardown();
+ edac_sysfs_pci_teardown();
+ return -ENOMEM;
+ }
+
+ /* wait for our kernel theard ack that it is up and running */
+ wait_for_completion(&event);
+
+ return 0;
+}
+
+
+/*
+ * edac_mc_exit()
+ * module exit/termination functioni
+ */
+static void __exit edac_mc_exit(void)
+{
+ struct completion event;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ init_completion(&event);
+ bs_thread.event = &event;
+
+ /* As soon as ->run is set to NULL, the task could disappear,
+ * so we need to hold tasklist_lock until we have sent the signal
+ */
+ read_lock(&tasklist_lock);
+ bs_thread.run = NULL;
+ send_sig(SIGKILL, bs_thread.task, 1);
+ read_unlock(&tasklist_lock);
+ wait_for_completion(&event);
+
+ /* tear down the sysfs device */
+ edac_sysfs_memctrl_teardown();
+ edac_sysfs_pci_teardown();
+}
+
+
+
+
+module_init(edac_mc_init);
+module_exit(edac_mc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
+ "Based on.work by Dan Hollis et al");
+MODULE_DESCRIPTION("Core library routines for MC reporting");
+
+module_param(panic_on_ue, int, 0644);
+MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
+module_param(check_pci_parity, int, 0644);
+MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on");
+module_param(panic_on_pci_parity, int, 0644);
+MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on");
+module_param(log_ue, int, 0644);
+MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on");
+module_param(log_ce, int, 0644);
+MODULE_PARM_DESC(log_ce, "Log correctable error to console: 0=off 1=on");
+module_param(poll_msec, int, 0644);
+MODULE_PARM_DESC(poll_msec, "Polling period in milliseconds");
+#ifdef CONFIG_EDAC_DEBUG
+module_param(edac_debug_level, int, 0644);
+MODULE_PARM_DESC(edac_debug_level, "Debug level");
+#endif
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
new file mode 100644
index 00000000000..75ecf484a43
--- /dev/null
+++ b/drivers/edac/edac_mc.h
@@ -0,0 +1,448 @@
+/*
+ * MC kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * NMI handling support added by
+ * Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
+ *
+ * $Id: edac_mc.h,v 1.4.2.10 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#ifndef _EDAC_MC_H_
+#define _EDAC_MC_H_
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/nmi.h>
+#include <linux/rcupdate.h>
+#include <linux/completion.h>
+#include <linux/kobject.h>
+
+
+#define EDAC_MC_LABEL_LEN 31
+#define MC_PROC_NAME_MAX_LEN 7
+
+#if PAGE_SHIFT < 20
+#define PAGES_TO_MiB( pages ) ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
+#else /* PAGE_SHIFT > 20 */
+#define PAGES_TO_MiB( pages ) ( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#endif
+
+#ifdef CONFIG_EDAC_DEBUG
+extern int edac_debug_level;
+#define edac_debug_printk(level, fmt, args...) \
+do { if (level <= edac_debug_level) printk(KERN_DEBUG fmt, ##args); } while(0)
+#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ )
+#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ )
+#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ )
+#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ )
+#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ )
+#else /* !CONFIG_EDAC_DEBUG */
+#define debugf0( ... )
+#define debugf1( ... )
+#define debugf2( ... )
+#define debugf3( ... )
+#define debugf4( ... )
+#endif /* !CONFIG_EDAC_DEBUG */
+
+
+#define bs_xstr(s) bs_str(s)
+#define bs_str(s) #s
+#define BS_MOD_STR bs_xstr(KBUILD_BASENAME)
+
+#define BIT(x) (1 << (x))
+
+#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev
+
+/* memory devices */
+enum dev_type {
+ DEV_UNKNOWN = 0,
+ DEV_X1,
+ DEV_X2,
+ DEV_X4,
+ DEV_X8,
+ DEV_X16,
+ DEV_X32, /* Do these parts exist? */
+ DEV_X64 /* Do these parts exist? */
+};
+
+#define DEV_FLAG_UNKNOWN BIT(DEV_UNKNOWN)
+#define DEV_FLAG_X1 BIT(DEV_X1)
+#define DEV_FLAG_X2 BIT(DEV_X2)
+#define DEV_FLAG_X4 BIT(DEV_X4)
+#define DEV_FLAG_X8 BIT(DEV_X8)
+#define DEV_FLAG_X16 BIT(DEV_X16)
+#define DEV_FLAG_X32 BIT(DEV_X32)
+#define DEV_FLAG_X64 BIT(DEV_X64)
+
+/* memory types */
+enum mem_type {
+ MEM_EMPTY = 0, /* Empty csrow */
+ MEM_RESERVED, /* Reserved csrow type */
+ MEM_UNKNOWN, /* Unknown csrow type */
+ MEM_FPM, /* Fast page mode */
+ MEM_EDO, /* Extended data out */
+ MEM_BEDO, /* Burst Extended data out */
+ MEM_SDR, /* Single data rate SDRAM */
+ MEM_RDR, /* Registered single data rate SDRAM */
+ MEM_DDR, /* Double data rate SDRAM */
+ MEM_RDDR, /* Registered Double data rate SDRAM */
+ MEM_RMBS /* Rambus DRAM */
+};
+
+#define MEM_FLAG_EMPTY BIT(MEM_EMPTY)
+#define MEM_FLAG_RESERVED BIT(MEM_RESERVED)
+#define MEM_FLAG_UNKNOWN BIT(MEM_UNKNOWN)
+#define MEM_FLAG_FPM BIT(MEM_FPM)
+#define MEM_FLAG_EDO BIT(MEM_EDO)
+#define MEM_FLAG_BEDO BIT(MEM_BEDO)
+#define MEM_FLAG_SDR BIT(MEM_SDR)
+#define MEM_FLAG_RDR BIT(MEM_RDR)
+#define MEM_FLAG_DDR BIT(MEM_DDR)
+#define MEM_FLAG_RDDR BIT(MEM_RDDR)
+#define MEM_FLAG_RMBS BIT(MEM_RMBS)
+
+
+/* chipset Error Detection and Correction capabilities and mode */
+enum edac_type {
+ EDAC_UNKNOWN = 0, /* Unknown if ECC is available */
+ EDAC_NONE, /* Doesnt support ECC */
+ EDAC_RESERVED, /* Reserved ECC type */
+ EDAC_PARITY, /* Detects parity errors */
+ EDAC_EC, /* Error Checking - no correction */
+ EDAC_SECDED, /* Single bit error correction, Double detection */
+ EDAC_S2ECD2ED, /* Chipkill x2 devices - do these exist? */
+ EDAC_S4ECD4ED, /* Chipkill x4 devices */
+ EDAC_S8ECD8ED, /* Chipkill x8 devices */
+ EDAC_S16ECD16ED, /* Chipkill x16 devices */
+};
+
+#define EDAC_FLAG_UNKNOWN BIT(EDAC_UNKNOWN)
+#define EDAC_FLAG_NONE BIT(EDAC_NONE)
+#define EDAC_FLAG_PARITY BIT(EDAC_PARITY)
+#define EDAC_FLAG_EC BIT(EDAC_EC)
+#define EDAC_FLAG_SECDED BIT(EDAC_SECDED)
+#define EDAC_FLAG_S2ECD2ED BIT(EDAC_S2ECD2ED)
+#define EDAC_FLAG_S4ECD4ED BIT(EDAC_S4ECD4ED)
+#define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED)
+#define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED)
+
+
+/* scrubbing capabilities */
+enum scrub_type {
+ SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */
+ SCRUB_NONE, /* No scrubber */
+ SCRUB_SW_PROG, /* SW progressive (sequential) scrubbing */
+ SCRUB_SW_SRC, /* Software scrub only errors */
+ SCRUB_SW_PROG_SRC, /* Progressive software scrub from an error */
+ SCRUB_SW_TUNABLE, /* Software scrub frequency is tunable */
+ SCRUB_HW_PROG, /* HW progressive (sequential) scrubbing */
+ SCRUB_HW_SRC, /* Hardware scrub only errors */
+ SCRUB_HW_PROG_SRC, /* Progressive hardware scrub from an error */
+ SCRUB_HW_TUNABLE /* Hardware scrub frequency is tunable */
+};
+
+#define SCRUB_FLAG_SW_PROG BIT(SCRUB_SW_PROG)
+#define SCRUB_FLAG_SW_SRC BIT(SCRUB_SW_SRC_CORR)
+#define SCRUB_FLAG_SW_PROG_SRC BIT(SCRUB_SW_PROG_SRC_CORR)
+#define SCRUB_FLAG_SW_TUN BIT(SCRUB_SW_SCRUB_TUNABLE)
+#define SCRUB_FLAG_HW_PROG BIT(SCRUB_HW_PROG)
+#define SCRUB_FLAG_HW_SRC BIT(SCRUB_HW_SRC_CORR)
+#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR)
+#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE)
+
+enum mci_sysfs_status {
+ MCI_SYSFS_INACTIVE = 0, /* sysfs entries NOT registered */
+ MCI_SYSFS_ACTIVE /* sysfs entries ARE registered */
+};
+
+/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
+
+/*
+ * There are several things to be aware of that aren't at all obvious:
+ *
+ *
+ * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
+ *
+ * These are some of the many terms that are thrown about that don't always
+ * mean what people think they mean (Inconceivable!). In the interest of
+ * creating a common ground for discussion, terms and their definitions
+ * will be established.
+ *
+ * Memory devices: The individual chip on a memory stick. These devices
+ * commonly output 4 and 8 bits each. Grouping several
+ * of these in parallel provides 64 bits which is common
+ * for a memory stick.
+ *
+ * Memory Stick: A printed circuit board that agregates multiple
+ * memory devices in parallel. This is the atomic
+ * memory component that is purchaseable by Joe consumer
+ * and loaded into a memory socket.
+ *
+ * Socket: A physical connector on the motherboard that accepts
+ * a single memory stick.
+ *
+ * Channel: Set of memory devices on a memory stick that must be
+ * grouped in parallel with one or more additional
+ * channels from other memory sticks. This parallel
+ * grouping of the output from multiple channels are
+ * necessary for the smallest granularity of memory access.
+ * Some memory controllers are capable of single channel -
+ * which means that memory sticks can be loaded
+ * individually. Other memory controllers are only
+ * capable of dual channel - which means that memory
+ * sticks must be loaded as pairs (see "socket set").
+ *
+ * Chip-select row: All of the memory devices that are selected together.
+ * for a single, minimum grain of memory access.
+ * This selects all of the parallel memory devices across
+ * all of the parallel channels. Common chip-select rows
+ * for single channel are 64 bits, for dual channel 128
+ * bits.
+ *
+ * Single-Ranked stick: A Single-ranked stick has 1 chip-select row of memmory.
+ * Motherboards commonly drive two chip-select pins to
+ * a memory stick. A single-ranked stick, will occupy
+ * only one of those rows. The other will be unused.
+ *
+ * Double-Ranked stick: A double-ranked stick has two chip-select rows which
+ * access different sets of memory devices. The two
+ * rows cannot be accessed concurrently.
+ *
+ * Double-sided stick: DEPRECATED TERM, see Double-Ranked stick.
+ * A double-sided stick has two chip-select rows which
+ * access different sets of memory devices. The two
+ * rows cannot be accessed concurrently. "Double-sided"
+ * is irrespective of the memory devices being mounted
+ * on both sides of the memory stick.
+ *
+ * Socket set: All of the memory sticks that are required for for
+ * a single memory access or all of the memory sticks
+ * spanned by a chip-select row. A single socket set
+ * has two chip-select rows and if double-sided sticks
+ * are used these will occupy those chip-select rows.
+ *
+ * Bank: This term is avoided because it is unclear when
+ * needing to distinguish between chip-select rows and
+ * socket sets.
+ *
+ * Controller pages:
+ *
+ * Physical pages:
+ *
+ * Virtual pages:
+ *
+ *
+ * STRUCTURE ORGANIZATION AND CHOICES
+ *
+ *
+ *
+ * PS - I enjoyed writing all that about as much as you enjoyed reading it.
+ */
+
+
+struct channel_info {
+ int chan_idx; /* channel index */
+ u32 ce_count; /* Correctable Errors for this CHANNEL */
+ char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
+ struct csrow_info *csrow; /* the parent */
+};
+
+
+struct csrow_info {
+ unsigned long first_page; /* first page number in dimm */
+ unsigned long last_page; /* last page number in dimm */
+ unsigned long page_mask; /* used for interleaving -
+ 0UL for non intlv */
+ u32 nr_pages; /* number of pages in csrow */
+ u32 grain; /* granularity of reported error in bytes */
+ int csrow_idx; /* the chip-select row */
+ enum dev_type dtype; /* memory device type */
+ u32 ue_count; /* Uncorrectable Errors for this csrow */
+ u32 ce_count; /* Correctable Errors for this csrow */
+ enum mem_type mtype; /* memory csrow type */
+ enum edac_type edac_mode; /* EDAC mode for this csrow */
+ struct mem_ctl_info *mci; /* the parent */
+
+ struct kobject kobj; /* sysfs kobject for this csrow */
+
+ /* FIXME the number of CHANNELs might need to become dynamic */
+ u32 nr_channels;
+ struct channel_info *channels;
+};
+
+
+struct mem_ctl_info {
+ struct list_head link; /* for global list of mem_ctl_info structs */
+ unsigned long mtype_cap; /* memory types supported by mc */
+ unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */
+ unsigned long edac_cap; /* configuration capabilities - this is
+ closely related to edac_ctl_cap. The
+ difference is that the controller
+ may be capable of s4ecd4ed which would
+ be listed in edac_ctl_cap, but if
+ channels aren't capable of s4ecd4ed then the
+ edac_cap would not have that capability. */
+ unsigned long scrub_cap; /* chipset scrub capabilities */
+ enum scrub_type scrub_mode; /* current scrub mode */
+
+ enum mci_sysfs_status sysfs_active; /* status of sysfs */
+
+ /* pointer to edac checking routine */
+ void (*edac_check) (struct mem_ctl_info * mci);
+ /*
+ * Remaps memory pages: controller pages to physical pages.
+ * For most MC's, this will be NULL.
+ */
+ /* FIXME - why not send the phys page to begin with? */
+ unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
+ unsigned long page);
+ int mc_idx;
+ int nr_csrows;
+ struct csrow_info *csrows;
+ /*
+ * FIXME - what about controllers on other busses? - IDs must be
+ * unique. pdev pointer should be sufficiently unique, but
+ * BUS:SLOT.FUNC numbers may not be unique.
+ */
+ struct pci_dev *pdev;
+ const char *mod_name;
+ const char *mod_ver;
+ const char *ctl_name;
+ char proc_name[MC_PROC_NAME_MAX_LEN + 1];
+ void *pvt_info;
+ u32 ue_noinfo_count; /* Uncorrectable Errors w/o info */
+ u32 ce_noinfo_count; /* Correctable Errors w/o info */
+ u32 ue_count; /* Total Uncorrectable Errors for this MC */
+ u32 ce_count; /* Total Correctable Errors for this MC */
+ unsigned long start_time; /* mci load start time (in jiffies) */
+
+ /* this stuff is for safe removal of mc devices from global list while
+ * NMI handlers may be traversing list
+ */
+ struct rcu_head rcu;
+ struct completion complete;
+
+ /* edac sysfs device control */
+ struct kobject edac_mci_kobj;
+};
+
+
+
+/* write all or some bits in a byte-register*/
+static inline void pci_write_bits8(struct pci_dev *pdev, int offset,
+ u8 value, u8 mask)
+{
+ if (mask != 0xff) {
+ u8 buf;
+ pci_read_config_byte(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_byte(pdev, offset, value);
+}
+
+
+/* write all or some bits in a word-register*/
+static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
+ u16 value, u16 mask)
+{
+ if (mask != 0xffff) {
+ u16 buf;
+ pci_read_config_word(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_word(pdev, offset, value);
+}
+
+
+/* write all or some bits in a dword-register*/
+static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
+ u32 value, u32 mask)
+{
+ if (mask != 0xffff) {
+ u32 buf;
+ pci_read_config_dword(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_dword(pdev, offset, value);
+}
+
+
+#ifdef CONFIG_EDAC_DEBUG
+void edac_mc_dump_channel(struct channel_info *chan);
+void edac_mc_dump_mci(struct mem_ctl_info *mci);
+void edac_mc_dump_csrow(struct csrow_info *csrow);
+#endif /* CONFIG_EDAC_DEBUG */
+
+extern int edac_mc_add_mc(struct mem_ctl_info *mci);
+extern int edac_mc_del_mc(struct mem_ctl_info *mci);
+
+extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+ unsigned long page);
+
+extern struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev
+ *pdev);
+
+extern void edac_mc_scrub_block(unsigned long page,
+ unsigned long offset, u32 size);
+
+/*
+ * The no info errors are used when error overflows are reported.
+ * There are a limited number of error logging registers that can
+ * be exausted. When all registers are exhausted and an additional
+ * error occurs then an error overflow register records that an
+ * error occured and the type of error, but doesn't have any
+ * further information. The ce/ue versions make for cleaner
+ * reporting logic and function interface - reduces conditional
+ * statement clutter and extra function arguments.
+ */
+extern void edac_mc_handle_ce(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ unsigned long syndrome,
+ int row, int channel, const char *msg);
+
+extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
+ const char *msg);
+
+extern void edac_mc_handle_ue(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ int row, const char *msg);
+
+extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
+ const char *msg);
+
+/*
+ * This kmalloc's and initializes all the structures.
+ * Can't be used if all structures don't have the same lifetime.
+ */
+extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt,
+ unsigned nr_csrows, unsigned nr_chans);
+
+/* Free an mc previously allocated by edac_mc_alloc() */
+extern void edac_mc_free(struct mem_ctl_info *mci);
+
+
+#endif /* _EDAC_MC_H_ */
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c
new file mode 100644
index 00000000000..52596e75f9c
--- /dev/null
+++ b/drivers/edac/i82860_edac.c
@@ -0,0 +1,299 @@
+/*
+ * Intel 82860 Memory Controller kernel module
+ * (C) 2005 Red Hat (http://www.redhat.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Ben Woodard <woodard@redhat.com>
+ * shamelessly copied from and based upon the edac_i82875 driver
+ * by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_82860_0
+#define PCI_DEVICE_ID_INTEL_82860_0 0x2531
+#endif /* PCI_DEVICE_ID_INTEL_82860_0 */
+
+#define I82860_MCHCFG 0x50
+#define I82860_GBA 0x60
+#define I82860_GBA_MASK 0x7FF
+#define I82860_GBA_SHIFT 24
+#define I82860_ERRSTS 0xC8
+#define I82860_EAP 0xE4
+#define I82860_DERRCTL_STS 0xE2
+
+enum i82860_chips {
+ I82860 = 0,
+};
+
+struct i82860_dev_info {
+ const char *ctl_name;
+};
+
+struct i82860_error_info {
+ u16 errsts;
+ u32 eap;
+ u16 derrsyn;
+ u16 errsts2;
+};
+
+static const struct i82860_dev_info i82860_devs[] = {
+ [I82860] = {
+ .ctl_name = "i82860"},
+};
+
+static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
+ has already registered driver */
+
+static int i82860_registered = 1;
+
+static void i82860_get_error_info (struct mem_ctl_info *mci,
+ struct i82860_error_info *info)
+{
+ /*
+ * This is a mess because there is no atomic way to read all the
+ * registers at once and the registers can transition from CE being
+ * overwritten by UE.
+ */
+ pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts);
+ pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
+ pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, &info->derrsyn);
+ pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts2);
+
+ pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+
+ /*
+ * If the error is the same for both reads then the first set of reads
+ * is valid. If there is a change then there is a CE no info and the
+ * second set of reads is valid and should be UE info.
+ */
+ if (!(info->errsts2 & 0x0003))
+ return;
+ if ((info->errsts ^ info->errsts2) & 0x0003) {
+ pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
+ pci_read_config_word(mci->pdev, I82860_DERRCTL_STS,
+ &info->derrsyn);
+ }
+}
+
+static int i82860_process_error_info (struct mem_ctl_info *mci,
+ struct i82860_error_info *info, int handle_errors)
+{
+ int row;
+
+ if (!(info->errsts2 & 0x0003))
+ return 0;
+
+ if (!handle_errors)
+ return 1;
+
+ if ((info->errsts ^ info->errsts2) & 0x0003) {
+ edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
+ info->errsts = info->errsts2;
+ }
+
+ info->eap >>= PAGE_SHIFT;
+ row = edac_mc_find_csrow_by_page(mci, info->eap);
+
+ if (info->errsts & 0x0002)
+ edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
+ else
+ edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+ 0, "i82860 UE");
+
+ return 1;
+}
+
+static void i82860_check(struct mem_ctl_info *mci)
+{
+ struct i82860_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ i82860_get_error_info(mci, &info);
+ i82860_process_error_info(mci, &info, 1);
+}
+
+static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ unsigned long last_cumul_size;
+
+ u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+
+ /* RDRAM has channels but these don't map onto the abstractions that
+ edac uses.
+ The device groups from the GRA registers seem to map reasonably
+ well onto the notion of a chip select row.
+ There are 16 GRA registers and since the name is associated with
+ the channel and the GRA registers map to physical devices so we are
+ going to make 1 channel for group.
+ */
+ mci = edac_mc_alloc(0, 16, 1);
+ if (!mci)
+ return -ENOMEM;
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_DDR;
+
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ /* I"m not sure about this but I think that all RDRAM is SECDED */
+ mci->edac_cap = EDAC_FLAG_SECDED;
+ /* adjust FLAGS */
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.1.2.6 $";
+ mci->ctl_name = i82860_devs[dev_idx].ctl_name;
+ mci->edac_check = i82860_check;
+ mci->ctl_page_to_phys = NULL;
+
+ pci_read_config_word(mci->pdev, I82860_MCHCFG, &mchcfg_ddim);
+ mchcfg_ddim = mchcfg_ddim & 0x180;
+
+ /*
+ * The group row boundary (GRA) reg values are boundary address
+ * for each DRAM row with a granularity of 16MB. GRA regs are
+ * cumulative; therefore GRA15 will contain the total memory contained
+ * in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u16 value;
+ u32 cumul_size;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ pci_read_config_word(mci->pdev, I82860_GBA + index * 2,
+ &value);
+
+ cumul_size = (value & I82860_GBA_MASK) <<
+ (I82860_GBA_SHIFT - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
+ csrow->mtype = MEM_RMBS;
+ csrow->dtype = DEV_UNKNOWN;
+ csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
+ }
+
+ /* clear counters */
+ pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ edac_mc_free(mci);
+ } else {
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ rc = 0;
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit i82860_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ printk(KERN_INFO "i82860 init one\n");
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ rc = i82860_probe1(pdev, ent->driver_data);
+ if(rc == 0)
+ mci_pdev = pci_dev_get(pdev);
+ return rc;
+}
+
+static void __devexit i82860_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ mci = edac_mc_find_mci_by_pdev(pdev);
+ if ((mci != NULL) && (edac_mc_del_mc(mci) == 0))
+ edac_mc_free(mci);
+}
+
+static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ I82860},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
+
+static struct pci_driver i82860_driver = {
+ .name = BS_MOD_STR,
+ .probe = i82860_init_one,
+ .remove = __devexit_p(i82860_remove_one),
+ .id_table = i82860_pci_tbl,
+};
+
+static int __init i82860_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
+ return pci_rc;
+
+ if (!mci_pdev) {
+ i82860_registered = 0;
+ mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82860_0, NULL);
+ if (mci_pdev == NULL) {
+ debugf0("860 pci_get_device fail\n");
+ return -ENODEV;
+ }
+ pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
+ if (pci_rc < 0) {
+ debugf0("860 init fail\n");
+ pci_dev_put(mci_pdev);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+static void __exit i82860_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_unregister_driver(&i82860_driver);
+ if (!i82860_registered) {
+ i82860_remove_one(mci_pdev);
+ pci_dev_put(mci_pdev);
+ }
+}
+
+module_init(i82860_init);
+module_exit(i82860_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR
+ ("Red Hat Inc. (http://www.redhat.com.com) Ben Woodard <woodard@redhat.com>");
+MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
new file mode 100644
index 00000000000..1991f94af75
--- /dev/null
+++ b/drivers/edac/i82875p_edac.c
@@ -0,0 +1,532 @@
+/*
+ * Intel D82875P Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Contributors:
+ * Wang Zhenyu at intel.com
+ *
+ * $Id: edac_i82875p.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_82875_0
+#define PCI_DEVICE_ID_INTEL_82875_0 0x2578
+#endif /* PCI_DEVICE_ID_INTEL_82875_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_82875_6
+#define PCI_DEVICE_ID_INTEL_82875_6 0x257e
+#endif /* PCI_DEVICE_ID_INTEL_82875_6 */
+
+
+/* four csrows in dual channel, eight in single channel */
+#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans))
+
+
+/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */
+#define I82875P_EAP 0x58 /* Error Address Pointer (32b)
+ *
+ * 31:12 block address
+ * 11:0 reserved
+ */
+
+#define I82875P_DERRSYN 0x5c /* DRAM Error Syndrome (8b)
+ *
+ * 7:0 DRAM ECC Syndrome
+ */
+
+#define I82875P_DES 0x5d /* DRAM Error Status (8b)
+ *
+ * 7:1 reserved
+ * 0 Error channel 0/1
+ */
+
+#define I82875P_ERRSTS 0xc8 /* Error Status Register (16b)
+ *
+ * 15:10 reserved
+ * 9 non-DRAM lock error (ndlock)
+ * 8 Sftwr Generated SMI
+ * 7 ECC UE
+ * 6 reserved
+ * 5 MCH detects unimplemented cycle
+ * 4 AGP access outside GA
+ * 3 Invalid AGP access
+ * 2 Invalid GA translation table
+ * 1 Unsupported AGP command
+ * 0 ECC CE
+ */
+
+#define I82875P_ERRCMD 0xca /* Error Command (16b)
+ *
+ * 15:10 reserved
+ * 9 SERR on non-DRAM lock
+ * 8 SERR on ECC UE
+ * 7 SERR on ECC CE
+ * 6 target abort on high exception
+ * 5 detect unimplemented cyc
+ * 4 AGP access outside of GA
+ * 3 SERR on invalid AGP access
+ * 2 invalid translation table
+ * 1 SERR on unsupported AGP command
+ * 0 reserved
+ */
+
+
+/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */
+#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b)
+ *
+ * 15:10 reserved
+ * 9 fast back-to-back - ro 0
+ * 8 SERR enable - ro 0
+ * 7 addr/data stepping - ro 0
+ * 6 parity err enable - ro 0
+ * 5 VGA palette snoop - ro 0
+ * 4 mem wr & invalidate - ro 0
+ * 3 special cycle - ro 0
+ * 2 bus master - ro 0
+ * 1 mem access dev6 - 0(dis),1(en)
+ * 0 IO access dev3 - 0(dis),1(en)
+ */
+
+#define I82875P_BAR6 0x10 /* Mem Delays Base ADDR Reg (32b)
+ *
+ * 31:12 mem base addr [31:12]
+ * 11:4 address mask - ro 0
+ * 3 prefetchable - ro 0(non),1(pre)
+ * 2:1 mem type - ro 0
+ * 0 mem space - ro 0
+ */
+
+/* Intel 82875p MMIO register space - device 0 function 0 - MMR space */
+
+#define I82875P_DRB_SHIFT 26 /* 64MiB grain */
+#define I82875P_DRB 0x00 /* DRAM Row Boundary (8b x 8)
+ *
+ * 7 reserved
+ * 6:0 64MiB row boundary addr
+ */
+
+#define I82875P_DRA 0x10 /* DRAM Row Attribute (4b x 8)
+ *
+ * 7 reserved
+ * 6:4 row attr row 1
+ * 3 reserved
+ * 2:0 row attr row 0
+ *
+ * 000 = 4KiB
+ * 001 = 8KiB
+ * 010 = 16KiB
+ * 011 = 32KiB
+ */
+
+#define I82875P_DRC 0x68 /* DRAM Controller Mode (32b)
+ *
+ * 31:30 reserved
+ * 29 init complete
+ * 28:23 reserved
+ * 22:21 nr chan 00=1,01=2
+ * 20 reserved
+ * 19:18 Data Integ Mode 00=none,01=ecc
+ * 17:11 reserved
+ * 10:8 refresh mode
+ * 7 reserved
+ * 6:4 mode select
+ * 3:2 reserved
+ * 1:0 DRAM type 01=DDR
+ */
+
+
+enum i82875p_chips {
+ I82875P = 0,
+};
+
+
+struct i82875p_pvt {
+ struct pci_dev *ovrfl_pdev;
+ void __iomem *ovrfl_window;
+};
+
+
+struct i82875p_dev_info {
+ const char *ctl_name;
+};
+
+
+struct i82875p_error_info {
+ u16 errsts;
+ u32 eap;
+ u8 des;
+ u8 derrsyn;
+ u16 errsts2;
+};
+
+
+static const struct i82875p_dev_info i82875p_devs[] = {
+ [I82875P] = {
+ .ctl_name = "i82875p"},
+};
+
+static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
+ has already registered driver */
+static int i82875p_registered = 1;
+
+static void i82875p_get_error_info (struct mem_ctl_info *mci,
+ struct i82875p_error_info *info)
+{
+ /*
+ * This is a mess because there is no atomic way to read all the
+ * registers at once and the registers can transition from CE being
+ * overwritten by UE.
+ */
+ pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts);
+ pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
+ pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
+ pci_read_config_byte(mci->pdev, I82875P_DERRSYN, &info->derrsyn);
+ pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts2);
+
+ pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+
+ /*
+ * If the error is the same then we can for both reads then
+ * the first set of reads is valid. If there is a change then
+ * there is a CE no info and the second set of reads is valid
+ * and should be UE info.
+ */
+ if (!(info->errsts2 & 0x0081))
+ return;
+ if ((info->errsts ^ info->errsts2) & 0x0081) {
+ pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
+ pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
+ pci_read_config_byte(mci->pdev, I82875P_DERRSYN,
+ &info->derrsyn);
+ }
+}
+
+static int i82875p_process_error_info (struct mem_ctl_info *mci,
+ struct i82875p_error_info *info, int handle_errors)
+{
+ int row, multi_chan;
+
+ multi_chan = mci->csrows[0].nr_channels - 1;
+
+ if (!(info->errsts2 & 0x0081))
+ return 0;
+
+ if (!handle_errors)
+ return 1;
+
+ if ((info->errsts ^ info->errsts2) & 0x0081) {
+ edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
+ info->errsts = info->errsts2;
+ }
+
+ info->eap >>= PAGE_SHIFT;
+ row = edac_mc_find_csrow_by_page(mci, info->eap);
+
+ if (info->errsts & 0x0080)
+ edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE");
+ else
+ edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+ multi_chan ? (info->des & 0x1) : 0,
+ "i82875p CE");
+
+ return 1;
+}
+
+
+static void i82875p_check(struct mem_ctl_info *mci)
+{
+ struct i82875p_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ i82875p_get_error_info(mci, &info);
+ i82875p_process_error_info(mci, &info, 1);
+}
+
+
+#ifdef CONFIG_PROC_FS
+extern int pci_proc_attach_device(struct pci_dev *);
+#endif
+
+static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ struct i82875p_pvt *pvt = NULL;
+ unsigned long last_cumul_size;
+ struct pci_dev *ovrfl_pdev;
+ void __iomem *ovrfl_window = NULL;
+
+ u32 drc;
+ u32 drc_chan; /* Number of channels 0=1chan,1=2chan */
+ u32 nr_chans;
+ u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ ovrfl_pdev = pci_find_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
+
+ if (!ovrfl_pdev) {
+ /*
+ * Intel tells BIOS developers to hide device 6 which
+ * configures the overflow device access containing
+ * the DRBs - this is where we expose device 6.
+ * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
+ */
+ pci_write_bits8(pdev, 0xf4, 0x2, 0x2);
+ ovrfl_pdev =
+ pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
+ if (!ovrfl_pdev)
+ goto fail;
+ }
+#ifdef CONFIG_PROC_FS
+ if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to attach overflow device\n",
+ __func__);
+ goto fail;
+ }
+#endif /* CONFIG_PROC_FS */
+ if (pci_enable_device(ovrfl_pdev)) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to enable overflow device\n",
+ __func__);
+ goto fail;
+ }
+
+ if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) {
+#ifdef CORRECT_BIOS
+ goto fail;
+#endif
+ }
+ /* cache is irrelevant for PCI bus reads/writes */
+ ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0),
+ pci_resource_len(ovrfl_pdev, 0));
+
+ if (!ovrfl_window) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to ioremap bar6\n", __func__);
+ goto fail;
+ }
+
+ /* need to find out the number of channels */
+ drc = readl(ovrfl_window + I82875P_DRC);
+ drc_chan = ((drc >> 21) & 0x1);
+ nr_chans = drc_chan + 1;
+ drc_ddim = (drc >> 18) & 0x1;
+
+ mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
+ nr_chans);
+
+ if (!mci) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_DDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ mci->edac_cap = EDAC_FLAG_UNKNOWN;
+ /* adjust FLAGS */
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.11 $";
+ mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
+ mci->edac_check = i82875p_check;
+ mci->ctl_page_to_phys = NULL;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+
+ pvt = (struct i82875p_pvt *) mci->pvt_info;
+ pvt->ovrfl_pdev = ovrfl_pdev;
+ pvt->ovrfl_window = ovrfl_window;
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address
+ * for each DRAM row with a granularity of 32 or 64MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ value = readb(ovrfl_window + I82875P_DRB + index);
+ cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
+ csrow->mtype = MEM_DDR;
+ csrow->dtype = DEV_UNKNOWN;
+ csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
+ }
+
+ /* clear counters */
+ pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+ fail:
+ if (mci)
+ edac_mc_free(mci);
+
+ if (ovrfl_window)
+ iounmap(ovrfl_window);
+
+ if (ovrfl_pdev) {
+ pci_release_regions(ovrfl_pdev);
+ pci_disable_device(ovrfl_pdev);
+ }
+
+ /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */
+ return rc;
+}
+
+
+/* returns count (>= 0), or negative on error */
+static int __devinit i82875p_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ printk(KERN_INFO "i82875p init one\n");
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ rc = i82875p_probe1(pdev, ent->driver_data);
+ if (mci_pdev == NULL)
+ mci_pdev = pci_dev_get(pdev);
+ return rc;
+}
+
+
+static void __devexit i82875p_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct i82875p_pvt *pvt = NULL;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+
+ pvt = (struct i82875p_pvt *) mci->pvt_info;
+ if (pvt->ovrfl_window)
+ iounmap(pvt->ovrfl_window);
+
+ if (pvt->ovrfl_pdev) {
+#ifdef CORRECT_BIOS
+ pci_release_regions(pvt->ovrfl_pdev);
+#endif /*CORRECT_BIOS */
+ pci_disable_device(pvt->ovrfl_pdev);
+ pci_dev_put(pvt->ovrfl_pdev);
+ }
+
+ if (edac_mc_del_mc(mci))
+ return;
+
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ I82875P},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl);
+
+
+static struct pci_driver i82875p_driver = {
+ .name = BS_MOD_STR,
+ .probe = i82875p_init_one,
+ .remove = __devexit_p(i82875p_remove_one),
+ .id_table = i82875p_pci_tbl,
+};
+
+
+static int __init i82875p_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_rc = pci_register_driver(&i82875p_driver);
+ if (pci_rc < 0)
+ return pci_rc;
+ if (mci_pdev == NULL) {
+ i82875p_registered = 0;
+ mci_pdev =
+ pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82875_0, NULL);
+ if (!mci_pdev) {
+ debugf0("875p pci_get_device fail\n");
+ return -ENODEV;
+ }
+ pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl);
+ if (pci_rc < 0) {
+ debugf0("875p init fail\n");
+ pci_dev_put(mci_pdev);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+
+static void __exit i82875p_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_unregister_driver(&i82875p_driver);
+ if (!i82875p_registered) {
+ i82875p_remove_one(mci_pdev);
+ pci_dev_put(mci_pdev);
+ }
+}
+
+
+module_init(i82875p_init);
+module_exit(i82875p_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c
new file mode 100644
index 00000000000..e90892831b9
--- /dev/null
+++ b/drivers/edac/r82600_edac.c
@@ -0,0 +1,407 @@
+/*
+ * Radisys 82600 Embedded chipset Memory Controller kernel module
+ * (C) 2005 EADS Astrium
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Tim Small <tim@buttersideup.com>, based on work by Thayne
+ * Harbaugh, Dan Hollis <goemon at anime dot net> and others.
+ *
+ * $Id: edac_r82600.c,v 1.1.2.6 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ * Written with reference to 82600 High Integration Dual PCI System
+ * Controller Data Book:
+ * http://www.radisys.com/files/support_downloads/007-01277-0002.82600DataBook.pdf
+ * references to this document given in []
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+/* Radisys say "The 82600 integrates a main memory SDRAM controller that
+ * supports up to four banks of memory. The four banks can support a mix of
+ * sizes of 64 bit wide (72 bits with ECC) Synchronous DRAM (SDRAM) DIMMs,
+ * each of which can be any size from 16MB to 512MB. Both registered (control
+ * signals buffered) and unbuffered DIMM types are supported. Mixing of
+ * registered and unbuffered DIMMs as well as mixing of ECC and non-ECC DIMMs
+ * is not allowed. The 82600 SDRAM interface operates at the same frequency as
+ * the CPU bus, 66MHz, 100MHz or 133MHz."
+ */
+
+#define R82600_NR_CSROWS 4
+#define R82600_NR_CHANS 1
+#define R82600_NR_DIMMS 4
+
+#define R82600_BRIDGE_ID 0x8200
+
+/* Radisys 82600 register addresses - device 0 function 0 - PCI bridge */
+#define R82600_DRAMC 0x57 /* Various SDRAM related control bits
+ * all bits are R/W
+ *
+ * 7 SDRAM ISA Hole Enable
+ * 6 Flash Page Mode Enable
+ * 5 ECC Enable: 1=ECC 0=noECC
+ * 4 DRAM DIMM Type: 1=
+ * 3 BIOS Alias Disable
+ * 2 SDRAM BIOS Flash Write Enable
+ * 1:0 SDRAM Refresh Rate: 00=Disabled
+ * 01=7.8usec (256Mbit SDRAMs)
+ * 10=15.6us 11=125usec
+ */
+
+#define R82600_SDRAMC 0x76 /* "SDRAM Control Register"
+ * More SDRAM related control bits
+ * all bits are R/W
+ *
+ * 15:8 Reserved.
+ *
+ * 7:5 Special SDRAM Mode Select
+ *
+ * 4 Force ECC
+ *
+ * 1=Drive ECC bits to 0 during
+ * write cycles (i.e. ECC test mode)
+ *
+ * 0=Normal ECC functioning
+ *
+ * 3 Enhanced Paging Enable
+ *
+ * 2 CAS# Latency 0=3clks 1=2clks
+ *
+ * 1 RAS# to CAS# Delay 0=3 1=2
+ *
+ * 0 RAS# Precharge 0=3 1=2
+ */
+
+#define R82600_EAP 0x80 /* ECC Error Address Pointer Register
+ *
+ * 31 Disable Hardware Scrubbing (RW)
+ * 0=Scrub on corrected read
+ * 1=Don't scrub on corrected read
+ *
+ * 30:12 Error Address Pointer (RO)
+ * Upper 19 bits of error address
+ *
+ * 11:4 Syndrome Bits (RO)
+ *
+ * 3 BSERR# on multibit error (RW)
+ * 1=enable 0=disable
+ *
+ * 2 NMI on Single Bit Eror (RW)
+ * 1=NMI triggered by SBE n.b. other
+ * prerequeists
+ * 0=NMI not triggered
+ *
+ * 1 MBE (R/WC)
+ * read 1=MBE at EAP (see above)
+ * read 0=no MBE, or SBE occurred first
+ * write 1=Clear MBE status (must also
+ * clear SBE)
+ * write 0=NOP
+ *
+ * 1 SBE (R/WC)
+ * read 1=SBE at EAP (see above)
+ * read 0=no SBE, or MBE occurred first
+ * write 1=Clear SBE status (must also
+ * clear MBE)
+ * write 0=NOP
+ */
+
+#define R82600_DRBA 0x60 /* + 0x60..0x63 SDRAM Row Boundry Address
+ * Registers
+ *
+ * 7:0 Address lines 30:24 - upper limit of
+ * each row [p57]
+ */
+
+struct r82600_error_info {
+ u32 eapr;
+};
+
+
+static unsigned int disable_hardware_scrub = 0;
+
+
+static void r82600_get_error_info (struct mem_ctl_info *mci,
+ struct r82600_error_info *info)
+{
+ pci_read_config_dword(mci->pdev, R82600_EAP, &info->eapr);
+
+ if (info->eapr & BIT(0))
+ /* Clear error to allow next error to be reported [p.62] */
+ pci_write_bits32(mci->pdev, R82600_EAP,
+ ((u32) BIT(0) & (u32) BIT(1)),
+ ((u32) BIT(0) & (u32) BIT(1)));
+
+ if (info->eapr & BIT(1))
+ /* Clear error to allow next error to be reported [p.62] */
+ pci_write_bits32(mci->pdev, R82600_EAP,
+ ((u32) BIT(0) & (u32) BIT(1)),
+ ((u32) BIT(0) & (u32) BIT(1)));
+}
+
+
+static int r82600_process_error_info (struct mem_ctl_info *mci,
+ struct r82600_error_info *info, int handle_errors)
+{
+ int error_found;
+ u32 eapaddr, page;
+ u32 syndrome;
+
+ error_found = 0;
+
+ /* bits 30:12 store the upper 19 bits of the 32 bit error address */
+ eapaddr = ((info->eapr >> 12) & 0x7FFF) << 13;
+ /* Syndrome in bits 11:4 [p.62] */
+ syndrome = (info->eapr >> 4) & 0xFF;
+
+ /* the R82600 reports at less than page *
+ * granularity (upper 19 bits only) */
+ page = eapaddr >> PAGE_SHIFT;
+
+ if (info->eapr & BIT(0)) { /* CE? */
+ error_found = 1;
+
+ if (handle_errors)
+ edac_mc_handle_ce(
+ mci, page, 0, /* not avail */
+ syndrome,
+ edac_mc_find_csrow_by_page(mci, page),
+ 0, /* channel */
+ mci->ctl_name);
+ }
+
+ if (info->eapr & BIT(1)) { /* UE? */
+ error_found = 1;
+
+ if (handle_errors)
+ /* 82600 doesn't give enough info */
+ edac_mc_handle_ue(mci, page, 0,
+ edac_mc_find_csrow_by_page(mci, page),
+ mci->ctl_name);
+ }
+
+ return error_found;
+}
+
+static void r82600_check(struct mem_ctl_info *mci)
+{
+ struct r82600_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ r82600_get_error_info(mci, &info);
+ r82600_process_error_info(mci, &info, 1);
+}
+
+static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ u8 dramcr;
+ u32 ecc_on;
+ u32 reg_sdram;
+ u32 eapr;
+ u32 scrub_disabled;
+ u32 sdram_refresh_rate;
+ u32 row_high_limit_last = 0;
+ u32 eap_init_bits;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+
+ pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
+ pci_read_config_dword(pdev, R82600_EAP, &eapr);
+
+ ecc_on = dramcr & BIT(5);
+ reg_sdram = dramcr & BIT(4);
+ scrub_disabled = eapr & BIT(31);
+ sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
+
+ debugf2("MC: " __FILE__ ": %s(): sdram refresh rate = %#0x\n",
+ __func__, sdram_refresh_rate);
+
+ debugf2("MC: " __FILE__ ": %s(): DRAMC register = %#0x\n", __func__,
+ dramcr);
+
+ mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ /* FIXME try to work out if the chip leads have been *
+ * used for COM2 instead on this board? [MA6?] MAYBE: */
+
+ /* On the R82600, the pins for memory bits 72:65 - i.e. the *
+ * EC bits are shared with the pins for COM2 (!), so if COM2 *
+ * is enabled, we assume COM2 is wired up, and thus no EDAC *
+ * is possible. */
+ mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ if (ecc_on) {
+ if (scrub_disabled)
+ debugf3("MC: " __FILE__ ": %s(): mci = %p - "
+ "Scrubbing disabled! EAP: %#0x\n", __func__,
+ mci, eapr);
+ } else
+ mci->edac_cap = EDAC_FLAG_NONE;
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.1.2.6 $";
+ mci->ctl_name = "R82600";
+ mci->edac_check = r82600_check;
+ mci->ctl_page_to_phys = NULL;
+
+ for (index = 0; index < mci->nr_csrows; index++) {
+ struct csrow_info *csrow = &mci->csrows[index];
+ u8 drbar; /* sDram Row Boundry Address Register */
+ u32 row_high_limit;
+ u32 row_base;
+
+ /* find the DRAM Chip Select Base address and mask */
+ pci_read_config_byte(mci->pdev, R82600_DRBA + index, &drbar);
+
+ debugf1("MC%d: " __FILE__ ": %s() Row=%d DRBA = %#0x\n",
+ mci->mc_idx, __func__, index, drbar);
+
+ row_high_limit = ((u32) drbar << 24);
+/* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */
+
+ debugf1("MC%d: " __FILE__ ": %s() Row=%d, "
+ "Boundry Address=%#0x, Last = %#0x \n",
+ mci->mc_idx, __func__, index, row_high_limit,
+ row_high_limit_last);
+
+ /* Empty row [p.57] */
+ if (row_high_limit == row_high_limit_last)
+ continue;
+
+ row_base = row_high_limit_last;
+
+ csrow->first_page = row_base >> PAGE_SHIFT;
+ csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
+ csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
+ /* Error address is top 19 bits - so granularity is *
+ * 14 bits */
+ csrow->grain = 1 << 14;
+ csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
+ /* FIXME - check that this is unknowable with this chipset */
+ csrow->dtype = DEV_UNKNOWN;
+
+ /* Mode is global on 82600 */
+ csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
+ row_high_limit_last = row_high_limit;
+ }
+
+ /* clear counters */
+ /* FIXME should we? */
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+
+ /* Clear error flags to allow next error to be reported [p.62] */
+ /* Test systems seem to always have the UE flag raised on boot */
+
+ eap_init_bits = BIT(0) & BIT(1);
+ if (disable_hardware_scrub) {
+ eap_init_bits |= BIT(31);
+ debugf3("MC: " __FILE__ ": %s(): Disabling Hardware Scrub "
+ "(scrub on error)\n", __func__);
+ }
+
+ pci_write_bits32(mci->pdev, R82600_EAP, eap_init_bits,
+ eap_init_bits);
+
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci)
+ edac_mc_free(mci);
+
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit r82600_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* don't need to call pci_device_enable() */
+ return r82600_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit r82600_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) &&
+ !edac_mc_del_mc(mci))
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id r82600_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
+
+
+static struct pci_driver r82600_driver = {
+ .name = BS_MOD_STR,
+ .probe = r82600_init_one,
+ .remove = __devexit_p(r82600_remove_one),
+ .id_table = r82600_pci_tbl,
+};
+
+
+static int __init r82600_init(void)
+{
+ return pci_register_driver(&r82600_driver);
+}
+
+
+static void __exit r82600_exit(void)
+{
+ pci_unregister_driver(&r82600_driver);
+}
+
+
+module_init(r82600_init);
+module_exit(r82600_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
+ "on behalf of EADS Astrium");
+MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
+
+module_param(disable_hardware_scrub, bool, 0644);
+MODULE_PARM_DESC(disable_hardware_scrub,
+ "If set, disable the chipset's automatic scrub for CEs");
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 5c8943509cc..66d03f242d3 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -1053,7 +1053,7 @@ static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len)
int i;
fcmd = &_fcmd;
- memset(fcmd, 0, sizeof(fcmd));
+ memset(fcmd, 0, sizeof(fcp_cmnd));
FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa))
fch = &fcmd->fch;
FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c5829591436..7230d4e0819 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -113,6 +113,16 @@ config SENSORS_DS1621
This driver can also be built as a module. If so, the module
will be called ds1621.
+config SENSORS_F71805F
+ tristate "Fintek F71805F/FG"
+ depends on HWMON && EXPERIMENTAL
+ help
+ If you say yes here you get support for hardware monitoring
+ features of the Fintek F71805F/FG chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called f71805f.
+
config SENSORS_FSCHER
tristate "FSC Hermes"
depends on HWMON && I2C && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 06d4a1d1410..fbdb8d911a7 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
+obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
new file mode 100644
index 00000000000..e029e0a94ec
--- /dev/null
+++ b/drivers/hwmon/f71805f.c
@@ -0,0 +1,908 @@
+/*
+ * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
+ * hardware monitoring features
+ * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+ *
+ * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
+ * complete hardware monitoring features: voltage, fan and temperature
+ * sensors, and manual and automatic fan speed control.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <asm/io.h>
+
+static struct platform_device *pdev;
+
+#define DRVNAME "f71805f"
+
+/*
+ * Super-I/O constants and functions
+ */
+
+#define F71805F_LD_HWM 0x04
+
+#define SIO_REG_LDSEL 0x07 /* Logical device select */
+#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
+#define SIO_REG_DEVREV 0x22 /* Device revision */
+#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
+#define SIO_REG_ENABLE 0x30 /* Logical device enable */
+#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
+
+#define SIO_FINTEK_ID 0x1934
+#define SIO_F71805F_ID 0x0406
+
+static inline int
+superio_inb(int base, int reg)
+{
+ outb(reg, base);
+ return inb(base + 1);
+}
+
+static int
+superio_inw(int base, int reg)
+{
+ int val;
+ outb(reg++, base);
+ val = inb(base + 1) << 8;
+ outb(reg, base);
+ val |= inb(base + 1);
+ return val;
+}
+
+static inline void
+superio_select(int base, int ld)
+{
+ outb(SIO_REG_LDSEL, base);
+ outb(ld, base + 1);
+}
+
+static inline void
+superio_enter(int base)
+{
+ outb(0x87, base);
+ outb(0x87, base);
+}
+
+static inline void
+superio_exit(int base)
+{
+ outb(0xaa, base);
+}
+
+/*
+ * ISA constants
+ */
+
+#define REGION_LENGTH 2
+#define ADDR_REG_OFFSET 0
+#define DATA_REG_OFFSET 1
+
+static struct resource f71805f_resource __initdata = {
+ .flags = IORESOURCE_IO,
+};
+
+/*
+ * Registers
+ */
+
+/* in nr from 0 to 8 (8-bit values) */
+#define F71805F_REG_IN(nr) (0x10 + (nr))
+#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr))
+#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr))
+/* fan nr from 0 to 2 (12-bit values, two registers) */
+#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
+#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
+#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
+/* temp nr from 0 to 2 (8-bit values) */
+#define F71805F_REG_TEMP(nr) (0x1B + (nr))
+#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
+#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr))
+#define F71805F_REG_TEMP_MODE 0x01
+
+#define F71805F_REG_START 0x00
+/* status nr from 0 to 2 */
+#define F71805F_REG_STATUS(nr) (0x36 + (nr))
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct f71805f_data {
+ unsigned short addr;
+ const char *name;
+ struct semaphore lock;
+ struct class_device *class_dev;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+ unsigned long last_limits; /* In jiffies */
+
+ /* Register values */
+ u8 in[9];
+ u8 in_high[9];
+ u8 in_low[9];
+ u16 fan[3];
+ u16 fan_low[3];
+ u8 fan_enabled; /* Read once at init time */
+ u8 temp[3];
+ u8 temp_high[3];
+ u8 temp_hyst[3];
+ u8 temp_mode;
+ u8 alarms[3];
+};
+
+static inline long in_from_reg(u8 reg)
+{
+ return (reg * 8);
+}
+
+/* The 2 least significant bits are not used */
+static inline u8 in_to_reg(long val)
+{
+ if (val <= 0)
+ return 0;
+ if (val >= 2016)
+ return 0xfc;
+ return (((val + 16) / 32) << 2);
+}
+
+/* in0 is downscaled by a factor 2 internally */
+static inline long in0_from_reg(u8 reg)
+{
+ return (reg * 16);
+}
+
+static inline u8 in0_to_reg(long val)
+{
+ if (val <= 0)
+ return 0;
+ if (val >= 4032)
+ return 0xfc;
+ return (((val + 32) / 64) << 2);
+}
+
+/* The 4 most significant bits are not used */
+static inline long fan_from_reg(u16 reg)
+{
+ reg &= 0xfff;
+ if (!reg || reg == 0xfff)
+ return 0;
+ return (1500000 / reg);
+}
+
+static inline u16 fan_to_reg(long rpm)
+{
+ /* If the low limit is set below what the chip can measure,
+ store the largest possible 12-bit value in the registers,
+ so that no alarm will ever trigger. */
+ if (rpm < 367)
+ return 0xfff;
+ return (1500000 / rpm);
+}
+
+static inline long temp_from_reg(u8 reg)
+{
+ return (reg * 1000);
+}
+
+static inline u8 temp_to_reg(long val)
+{
+ if (val < 0)
+ val = 0;
+ else if (val > 1000 * 0xff)
+ val = 0xff;
+ return ((val + 500) / 1000);
+}
+
+/*
+ * Device I/O access
+ */
+
+static u8 f71805f_read8(struct f71805f_data *data, u8 reg)
+{
+ u8 val;
+
+ down(&data->lock);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ val = inb(data->addr + DATA_REG_OFFSET);
+ up(&data->lock);
+
+ return val;
+}
+
+static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
+{
+ down(&data->lock);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ outb(val, data->addr + DATA_REG_OFFSET);
+ up(&data->lock);
+}
+
+/* It is important to read the MSB first, because doing so latches the
+ value of the LSB, so we are sure both bytes belong to the same value. */
+static u16 f71805f_read16(struct f71805f_data *data, u8 reg)
+{
+ u16 val;
+
+ down(&data->lock);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ val = inb(data->addr + DATA_REG_OFFSET) << 8;
+ outb(++reg, data->addr + ADDR_REG_OFFSET);
+ val |= inb(data->addr + DATA_REG_OFFSET);
+ up(&data->lock);
+
+ return val;
+}
+
+static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
+{
+ down(&data->lock);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ outb(val >> 8, data->addr + DATA_REG_OFFSET);
+ outb(++reg, data->addr + ADDR_REG_OFFSET);
+ outb(val & 0xff, data->addr + DATA_REG_OFFSET);
+ up(&data->lock);
+}
+
+static struct f71805f_data *f71805f_update_device(struct device *dev)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ int nr;
+
+ down(&data->update_lock);
+
+ /* Limit registers cache is refreshed after 60 seconds */
+ if (time_after(jiffies, data->last_updated + 60 * HZ)
+ || !data->valid) {
+ for (nr = 0; nr < 9; nr++) {
+ data->in_high[nr] = f71805f_read8(data,
+ F71805F_REG_IN_HIGH(nr));
+ data->in_low[nr] = f71805f_read8(data,
+ F71805F_REG_IN_LOW(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ if (data->fan_enabled & (1 << nr))
+ data->fan_low[nr] = f71805f_read16(data,
+ F71805F_REG_FAN_LOW(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ data->temp_high[nr] = f71805f_read8(data,
+ F71805F_REG_TEMP_HIGH(nr));
+ data->temp_hyst[nr] = f71805f_read8(data,
+ F71805F_REG_TEMP_HYST(nr));
+ }
+ data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE);
+
+ data->last_limits = jiffies;
+ }
+
+ /* Measurement registers cache is refreshed after 1 second */
+ if (time_after(jiffies, data->last_updated + HZ)
+ || !data->valid) {
+ for (nr = 0; nr < 9; nr++) {
+ data->in[nr] = f71805f_read8(data,
+ F71805F_REG_IN(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ if (data->fan_enabled & (1 << nr))
+ data->fan[nr] = f71805f_read16(data,
+ F71805F_REG_FAN(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ data->temp[nr] = f71805f_read8(data,
+ F71805F_REG_TEMP(nr));
+ }
+ for (nr = 0; nr < 3; nr++) {
+ data->alarms[nr] = f71805f_read8(data,
+ F71805F_REG_STATUS(nr));
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+/*
+ * Sysfs interface
+ */
+
+static ssize_t show_in0(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in[0]));
+}
+
+static ssize_t show_in0_max(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0]));
+}
+
+static ssize_t show_in0_min(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0]));
+}
+
+static ssize_t set_in0_max(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_high[0] = in0_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t set_in0_min(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_low[0] = in0_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
+static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
+static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+
+static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", in_from_reg(data->in[nr]));
+}
+
+static ssize_t show_in_max(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr]));
+}
+
+static ssize_t show_in_min(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr]));
+}
+
+static ssize_t set_in_max(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_high[nr] = in_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t set_in_min(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_low[nr] = in_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+#define sysfs_in(offset) \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+ show_in, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, set_in_min, offset)
+
+sysfs_in(1);
+sysfs_in(2);
+sysfs_in(3);
+sysfs_in(4);
+sysfs_in(5);
+sysfs_in(6);
+sysfs_in(7);
+sysfs_in(8);
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->fan_low[nr] = fan_to_reg(val);
+ f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+#define sysfs_fan(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_fan, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, offset - 1)
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr]));
+}
+
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr]));
+}
+
+static ssize_t show_temp_type(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ /* 3 is diode, 4 is thermistor */
+ return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4);
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_high[nr] = temp_to_reg(val);
+ f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_hyst[nr] = temp_to_reg(val);
+ f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+#define sysfs_temp(offset) \
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_temp, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
+ show_temp_max, set_temp_max, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
+ show_temp_hyst, set_temp_hyst, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \
+ show_temp_type, NULL, offset - 1)
+
+sysfs_temp(1);
+sysfs_temp(2);
+sysfs_temp(3);
+
+static ssize_t show_alarms_in(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%d\n", data->alarms[0] |
+ ((data->alarms[1] & 0x01) << 8));
+}
+
+static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%d\n", data->alarms[2] & 0x07);
+}
+
+static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+
+ return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
+}
+
+static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
+static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
+static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", data->name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+/*
+ * Device registration and initialization
+ */
+
+static void __devinit f71805f_init_device(struct f71805f_data *data)
+{
+ u8 reg;
+ int i;
+
+ reg = f71805f_read8(data, F71805F_REG_START);
+ if ((reg & 0x41) != 0x01) {
+ printk(KERN_DEBUG DRVNAME ": Starting monitoring "
+ "operations\n");
+ f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
+ }
+
+ /* Fan monitoring can be disabled. If it is, we won't be polling
+ the register values, and won't create the related sysfs files. */
+ for (i = 0; i < 3; i++) {
+ reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i));
+ if (!(reg & 0x80))
+ data->fan_enabled |= (1 << i);
+ }
+}
+
+static int __devinit f71805f_probe(struct platform_device *pdev)
+{
+ struct f71805f_data *data;
+ struct resource *res;
+ int err;
+
+ if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Out of memory\n");
+ goto exit;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ data->addr = res->start;
+ init_MUTEX(&data->lock);
+ data->name = "f71805f";
+ init_MUTEX(&data->update_lock);
+
+ platform_set_drvdata(pdev, data);
+
+ data->class_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
+ goto exit_free;
+ }
+
+ /* Initialize the F71805F chip */
+ f71805f_init_device(data);
+
+ /* Register sysfs interface files */
+ device_create_file(&pdev->dev, &dev_attr_in0_input);
+ device_create_file(&pdev->dev, &dev_attr_in0_max);
+ device_create_file(&pdev->dev, &dev_attr_in0_min);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr);
+ if (data->fan_enabled & (1 << 0)) {
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan1_min.dev_attr);
+ }
+ if (data->fan_enabled & (1 << 1)) {
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan2_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan2_min.dev_attr);
+ }
+ if (data->fan_enabled & (1 << 2)) {
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan3_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_fan3_min.dev_attr);
+ }
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp3_input.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_max_hyst.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp2_max_hyst.dev_attr);
+ device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp3_max_hyst.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr);
+ device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr);
+ device_create_file(&pdev->dev, &dev_attr_alarms_in);
+ device_create_file(&pdev->dev, &dev_attr_alarms_fan);
+ device_create_file(&pdev->dev, &dev_attr_alarms_temp);
+ device_create_file(&pdev->dev, &dev_attr_name);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int __devexit f71805f_remove(struct platform_device *pdev)
+{
+ struct f71805f_data *data = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ hwmon_device_unregister(data->class_dev);
+ kfree(data);
+
+ return 0;
+}
+
+static struct platform_driver f71805f_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .probe = f71805f_probe,
+ .remove = __devexit_p(f71805f_remove),
+};
+
+static int __init f71805f_device_add(unsigned short address)
+{
+ int err;
+
+ pdev = platform_device_alloc(DRVNAME, address);
+ if (!pdev) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+ goto exit;
+ }
+
+ f71805f_resource.start = address;
+ f71805f_resource.end = address + REGION_LENGTH - 1;
+ f71805f_resource.name = pdev->name;
+ err = platform_device_add_resources(pdev, &f71805f_resource, 1);
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Device resource addition failed "
+ "(%d)\n", err);
+ goto exit_device_put;
+ }
+
+ err = platform_device_add(pdev);
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+ err);
+ goto exit_device_put;
+ }
+
+ return 0;
+
+exit_device_put:
+ platform_device_put(pdev);
+exit:
+ return err;
+}
+
+static int __init f71805f_find(int sioaddr, unsigned short *address)
+{
+ int err = -ENODEV;
+ u16 devid;
+
+ superio_enter(sioaddr);
+
+ devid = superio_inw(sioaddr, SIO_REG_MANID);
+ if (devid != SIO_FINTEK_ID)
+ goto exit;
+
+ devid = superio_inw(sioaddr, SIO_REG_DEVID);
+ if (devid != SIO_F71805F_ID) {
+ printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
+ "skipping\n");
+ goto exit;
+ }
+
+ superio_select(sioaddr, F71805F_LD_HWM);
+ if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+ printk(KERN_WARNING DRVNAME ": Device not activated, "
+ "skipping\n");
+ goto exit;
+ }
+
+ *address = superio_inw(sioaddr, SIO_REG_ADDR);
+ if (*address == 0) {
+ printk(KERN_WARNING DRVNAME ": Base address not set, "
+ "skipping\n");
+ goto exit;
+ }
+
+ err = 0;
+ printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
+ *address, superio_inb(sioaddr, SIO_REG_DEVREV));
+
+exit:
+ superio_exit(sioaddr);
+ return err;
+}
+
+static int __init f71805f_init(void)
+{
+ int err;
+ unsigned short address;
+
+ if (f71805f_find(0x2e, &address)
+ && f71805f_find(0x4e, &address))
+ return -ENODEV;
+
+ err = platform_driver_register(&f71805f_driver);
+ if (err)
+ goto exit;
+
+ /* Sets global pdev as a side effect */
+ err = f71805f_device_add(address);
+ if (err)
+ goto exit_driver;
+
+ return 0;
+
+exit_driver:
+ platform_driver_unregister(&f71805f_driver);
+exit:
+ return err;
+}
+
+static void __exit f71805f_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&f71805f_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("F71805F hardware monitoring driver");
+
+module_init(f71805f_init);
+module_exit(f71805f_exit);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 0da7c9c508c..d7a9401600b 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -45,8 +45,7 @@
/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
- 0x2e, 0x2f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
static unsigned short isa_address;
/* Insmod parameters */
@@ -830,6 +829,11 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
if ((err = i2c_attach_client(new_client)))
goto ERROR2;
+ if (!is_isa)
+ dev_info(&new_client->dev, "The I2C interface to IT87xxF "
+ "hardware monitoring chips is deprecated. Please "
+ "report if you still rely on it.\n");
+
/* Check PWM configuration */
enable_pwm_interface = it87_check_pwm(new_client);
@@ -1182,7 +1186,8 @@ static int __init sm_it87_init(void)
static void __exit sm_it87_exit(void)
{
- i2c_isa_del_driver(&it87_isa_driver);
+ if (isa_address)
+ i2c_isa_del_driver(&it87_isa_driver);
i2c_del_driver(&it87_driver);
}
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index a2f420d01fb..df9e02aaa70 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -87,15 +87,15 @@ static struct i2c_driver lm77_driver = {
/* In the temperature registers, the low 3 bits are not part of the
temperature values; they are the status bits. */
-static inline u16 LM77_TEMP_TO_REG(int temp)
+static inline s16 LM77_TEMP_TO_REG(int temp)
{
int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX);
- return (u16)((ntemp / 500) * 8);
+ return (ntemp / 500) * 8;
}
-static inline int LM77_TEMP_FROM_REG(u16 reg)
+static inline int LM77_TEMP_FROM_REG(s16 reg)
{
- return ((int)reg / 8) * 500;
+ return (reg / 8) * 500;
}
/* sysfs stuff */
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 3eb08f004c0..271e9cb9532 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -437,12 +437,12 @@ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
show_temp, NULL, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
show_temp_max, set_temp_max, offset - 1); \
-static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
+static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
show_temp_min, set_temp_min, offset - 1)
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL);
static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max);
-static DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
define_temperature_sysfs(2);
define_temperature_sysfs(3);
@@ -451,7 +451,7 @@ define_temperature_sysfs(5);
define_temperature_sysfs(6);
#define CFG_INFO_TEMP(id) { &sensor_dev_attr_temp##id##_input.dev_attr, \
- &sensor_dev_attr_temp##id##_min.dev_attr, \
+ &sensor_dev_attr_temp##id##_max_hyst.dev_attr, \
&sensor_dev_attr_temp##id##_max.dev_attr }
#define CFG_INFO_VOLT(id) { &sensor_dev_attr_in##id##_input.dev_attr, \
&sensor_dev_attr_in##id##_min.dev_attr, \
@@ -464,7 +464,7 @@ struct str_device_attr_table {
};
static struct str_device_attr_table cfg_info_temp[] = {
- { &dev_attr_temp1_input, &dev_attr_temp1_min, &dev_attr_temp1_max },
+ { &dev_attr_temp1_input, &dev_attr_temp1_max_hyst, &dev_attr_temp1_max },
CFG_INFO_TEMP(2),
CFG_INFO_TEMP(3),
CFG_INFO_TEMP(4),
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 557114872f3..64c1f8af5bb 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -95,11 +95,16 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
(0x39)))
#define W83781D_REG_CONFIG 0x40
+
+/* Interrupt status (W83781D, AS99127F) */
#define W83781D_REG_ALARM1 0x41
#define W83781D_REG_ALARM2 0x42
-#define W83781D_REG_ALARM3 0x450 /* not on W83781D */
-#define W83781D_REG_IRQ 0x4C
+/* Real-time status (W83782D, W83783S, W83627HF) */
+#define W83782D_REG_ALARM1 0x459
+#define W83782D_REG_ALARM2 0x45A
+#define W83782D_REG_ALARM3 0x45B
+
#define W83781D_REG_BEEP_CONFIG 0x4D
#define W83781D_REG_BEEP_INTS1 0x56
#define W83781D_REG_BEEP_INTS2 0x57
@@ -1513,15 +1518,6 @@ w83781d_init_client(struct i2c_client *client)
W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
}
}
-
- if (type != w83781d) {
- /* enable comparator mode for temp2 and temp3 so
- alarm indication will work correctly */
- i = w83781d_read_value(client, W83781D_REG_IRQ);
- if (!(i & 0x40))
- w83781d_write_value(client, W83781D_REG_IRQ,
- i | 0x40);
- }
}
/* Start monitoring */
@@ -1612,14 +1608,25 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
data->fan_div[1] |= (i >> 4) & 0x04;
data->fan_div[2] |= (i >> 5) & 0x04;
}
- data->alarms =
- w83781d_read_value(client,
- W83781D_REG_ALARM1) +
- (w83781d_read_value(client, W83781D_REG_ALARM2) << 8);
if ((data->type == w83782d) || (data->type == w83627hf)) {
- data->alarms |=
- w83781d_read_value(client,
- W83781D_REG_ALARM3) << 16;
+ data->alarms = w83781d_read_value(client,
+ W83782D_REG_ALARM1)
+ | (w83781d_read_value(client,
+ W83782D_REG_ALARM2) << 8)
+ | (w83781d_read_value(client,
+ W83782D_REG_ALARM3) << 16);
+ } else if (data->type == w83783s) {
+ data->alarms = w83781d_read_value(client,
+ W83782D_REG_ALARM1)
+ | (w83781d_read_value(client,
+ W83782D_REG_ALARM2) << 8);
+ } else {
+ /* No real-time status registers, fall back to
+ interrupt status registers */
+ data->alarms = w83781d_read_value(client,
+ W83781D_REG_ALARM1)
+ | (w83781d_read_value(client,
+ W83781D_REG_ALARM2) << 8);
}
i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2);
data->beep_enable = i >> 7;
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index b176bf0c4c7..a2f6bb67623 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -303,10 +303,6 @@ struct w83792d_data {
static int w83792d_attach_adapter(struct i2c_adapter *adapter);
static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind);
static int w83792d_detach_client(struct i2c_client *client);
-
-static int w83792d_read_value(struct i2c_client *client, u8 register);
-static int w83792d_write_value(struct i2c_client *client, u8 register,
- u8 value);
static struct w83792d_data *w83792d_update_device(struct device *dev);
#ifdef DEBUG
@@ -329,6 +325,20 @@ static inline long in_count_from_reg(int nr, struct w83792d_data *data)
return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03));
}
+/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
+ but the driver only accesses registers in bank 0, so we don't have
+ to switch banks and lock access between switches. */
+static inline int w83792d_read_value(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static inline int
+w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
/* following are the sysfs callback functions */
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1386,19 +1396,6 @@ w83792d_detach_client(struct i2c_client *client)
return 0;
}
-/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
- but the driver only accesses registers in bank 0, so we don't have
- to switch banks and lock access between switches. */
-static int w83792d_read_value(struct i2c_client *client, u8 reg)
-{
- return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
-{
- return i2c_smbus_write_byte_data(client, reg, value);
-}
-
static void
w83792d_init_client(struct i2c_client *client)
{
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index 938848ae162..3df3f09995c 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -202,7 +202,7 @@ EXPORT_SYMBOL(i2c_sibyte_del_bus);
#ifdef MODULE
MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
-MODULE_PARM(bit_scan, "i");
+module_param(bit_scan, int, 0);
MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 08d5b8fed2d..ff92735c7c8 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -124,6 +124,7 @@ config I2C_I801
ICH6
ICH7
ESB2
+ ICH8
This driver can also be built as a module. If so, the module
will be called i2c-i801.
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 1c752ddc10e..8e0f3158215 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -32,6 +32,7 @@
ICH6 266A
ICH7 27DA
ESB2 269B
+ ICH8 283E
This driver supports several versions of Intel's I/O Controller Hubs (ICH).
For SMBus support, they are similar to the PIIX4 and are part
of Intel's '810' and other chipsets.
@@ -527,6 +528,7 @@ static struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 9f2ffef4d81..4344ae6b1fc 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -72,16 +72,6 @@ static ssize_t show_adapter_name(struct device *dev,
}
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
-static int i2c_isa_device_probe(struct device *dev)
-{
- return -ENODEV;
-}
-
-static int i2c_isa_device_remove(struct device *dev)
-{
- return 0;
-}
-
/* We implement an interface which resembles i2c_{add,del}_driver,
but for i2c-isa drivers. We don't have to remember and handle lists
@@ -93,8 +83,6 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
/* Add the driver to the list of i2c drivers in the driver core */
driver->driver.bus = &i2c_bus_type;
- driver->driver.probe = i2c_isa_device_probe;
- driver->driver.remove = i2c_isa_device_remove;
res = driver_register(&driver->driver);
if (res)
return res;
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 3e5eba9fcac..c63025a4c86 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -121,14 +121,11 @@ static struct i2c_adapter parport_adapter = {
static int __init i2c_parport_init(void)
{
- int type_count;
-
- type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
- if (type < 0 || type >= type_count) {
+ if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
type = 0;
}
-
+
if (base == 0) {
printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
base = DEFAULT_BASE;
@@ -152,7 +149,7 @@ static int __init i2c_parport_init(void)
release_region(base, 3);
return -ENODEV;
}
-
+
return 0;
}
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 2854d858fc9..7e2e8cd1c14 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -241,14 +241,11 @@ static struct parport_driver i2c_parport_driver = {
static int __init i2c_parport_init(void)
{
- int type_count;
-
- type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
- if (type < 0 || type >= type_count) {
+ if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
type = 0;
}
-
+
return parport_register_driver(&i2c_parport_driver);
}
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 86e2234faf8..7579f4b256a 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -861,7 +861,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *r
decode_ISR(isr);
}
- if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32))
+ if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog))
i2c->isrlog[i2c->irqlogidx++] = isr;
show_state(i2c);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 0ce58b50604..1a2c9ab5d9e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -946,6 +946,20 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val
}
}
+s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
+ u8 length, u8 *values)
+{
+ union i2c_smbus_data data;
+
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ length = I2C_SMBUS_BLOCK_MAX;
+ data.block[0] = length;
+ memcpy(data.block + 1, values, length);
+ return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_I2C_BLOCK_DATA, &data);
+}
+
/* Simulate a SMBus command using the i2c protocol
No checking of parameters is done! */
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
@@ -1150,6 +1164,7 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data);
EXPORT_SYMBOL(i2c_smbus_write_word_data);
EXPORT_SYMBOL(i2c_smbus_write_block_data);
EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
+EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus main module");
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 1c81174595b..d633081fa4c 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -52,9 +52,9 @@ config IDE
if IDE
-config IDE_MAX_HWIFS
+config IDE_MAX_HWIFS
int "Max IDE interfaces"
- depends on ALPHA || SUPERH
+ depends on ALPHA || SUPERH || IA64
default 4
help
This is the maximum number of IDE hardware interfaces that will
@@ -162,8 +162,8 @@ config BLK_DEV_IDECS
tristate "PCMCIA IDE support"
depends on PCMCIA
help
- Support for outboard IDE disks, tape drives, and CD-ROM drives
- connected through a PCMCIA card.
+ Support for Compact Flash cards, outboard IDE disks, tape drives,
+ and CD-ROM drives connected through a PCMCIA card.
config BLK_DEV_IDECD
tristate "Include IDE/ATAPI CDROM support"
@@ -267,7 +267,7 @@ config IDE_TASK_IOCTL
help
This is a direct raw access to the media. It is a complex but
elegant solution to test and validate the domain of the hardware and
- perform below the driver data recover if needed. This is the most
+ perform below the driver data recovery if needed. This is the most
basic form of media-forensics.
If you are unsure, say N here.
@@ -525,7 +525,7 @@ config BLK_DEV_CS5520
tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)"
depends on EXPERIMENTAL
help
- Include support for PIO tuning an virtual DMA on the Cyrix MediaGX
+ Include support for PIO tuning and virtual DMA on the Cyrix MediaGX
5510/5520 chipset. This will automatically be detected and
configured if found.
@@ -662,7 +662,7 @@ config PDC202XX_BURST
It was originally designed for the PDC20246/Ultra33, whose BIOS will
only setup UDMA on the first two PDC20246 cards. It has also been
- used succesfully on a PDC20265/Ultra100, allowing use of UDMA modes
+ used successfully on a PDC20265/Ultra100, allowing use of UDMA modes
when the PDC20265 BIOS has been disabled (for faster boot up).
Please read the comments at the top of
@@ -673,13 +673,6 @@ config PDC202XX_BURST
config BLK_DEV_PDC202XX_NEW
tristate "PROMISE PDC202{68|69|70|71|75|76|77} support"
-# FIXME - probably wants to be one for old and for new
-config PDC202XX_FORCE
- bool "Enable controller even if disabled by BIOS"
- depends on BLK_DEV_PDC202XX_NEW
- help
- Enable the PDC202xx controller even if it has been disabled in the BIOS setup.
-
config BLK_DEV_SVWKS
tristate "ServerWorks OSB4/CSB5/CSB6 chipsets support"
help
@@ -722,7 +715,7 @@ config BLK_DEV_SIS5513
config BLK_DEV_SLC90E66
tristate "SLC90E66 chipset support"
help
- This driver ensures (U)DMA support for Victroy66 SouthBridges for
+ This driver ensures (U)DMA support for Victory66 SouthBridges for
SMsC with Intel NorthBridges. This is an Ultra66 based chipset.
The nice thing about it is that you can mix Ultra/DMA/PIO devices
and it will handle timing cycles. Since this is an improved
@@ -1060,7 +1053,7 @@ config IDEDMA_IVB
in that mode with an 80c ribbon.
If you are experiencing compatibility or performance problems, you
- MAY try to answering Y here. However, it does not necessarily solve
+ MAY try to answer Y here. However, it does not necessarily solve
any of your problems, it could even cause more of them.
It is normally safe to answer Y; however, the default is N.
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index ca25f9e3d0f..09086b8b648 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -190,7 +190,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
if (lba48) {
task_ioreg_t tasklets[10];
- pr_debug("%s: LBA=0x%012llx\n", drive->name, block);
+ pr_debug("%s: LBA=0x%012llx\n", drive->name,
+ (unsigned long long)block);
tasklets[0] = 0;
tasklets[1] = 0;
@@ -317,7 +318,8 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
- block, rq->nr_sectors, (unsigned long)rq->buffer);
+ (unsigned long long)block, rq->nr_sectors,
+ (unsigned long)rq->buffer);
if (hwif->rw_disk)
hwif->rw_disk(drive, rq);
@@ -776,7 +778,7 @@ static void update_ordered(ide_drive_t *drive)
ide_id_has_flush_cache_ext(id));
printk(KERN_INFO "%s: cache flushes %ssupported\n",
- drive->name, barrier ? "" : "not");
+ drive->name, barrier ? "" : "not ");
if (barrier) {
ordered = QUEUE_ORDERED_DRAIN_FLUSH;
@@ -889,11 +891,7 @@ static void idedisk_setup (ide_drive_t *drive)
if (drive->id_read == 0)
return;
- /*
- * CompactFlash cards and their brethern look just like hard drives
- * to us, but they are removable and don't have a doorlock mechanism.
- */
- if (drive->removable && !(drive->is_flash)) {
+ if (drive->removable) {
/*
* Removable disks (eg. SYQUEST); ignore 'WD' drives
*/
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 8d50df4526a..c01615dec20 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -55,8 +55,8 @@
#include <asm/io.h>
#include <asm/bitops.h>
-int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
- int nr_sectors)
+static int __ide_end_request(ide_drive_t *drive, struct request *rq,
+ int uptodate, int nr_sectors)
{
int ret = 1;
@@ -91,7 +91,6 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
return ret;
}
-EXPORT_SYMBOL(__ide_end_request);
/**
* ide_end_request - complete an IDE I/O
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index af7af958ab3..b72dde70840 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -1243,6 +1243,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
*/
if (stat == 0xff)
return -ENODEV;
+ touch_softlockup_watchdog();
}
return -EBUSY;
}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index e7425546b4b..427d1c20417 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -125,45 +125,6 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
}
/**
- * drive_is_flashcard - check for compact flash
- * @drive: drive to check
- *
- * CompactFlash cards and their brethern pretend to be removable
- * hard disks, except:
- * (1) they never have a slave unit, and
- * (2) they don't have doorlock mechanisms.
- * This test catches them, and is invoked elsewhere when setting
- * appropriate config bits.
- *
- * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD)
- * devices, so in linux 2.3.x we should change this to just treat all
- * PCMCIA drives this way, and get rid of the model-name tests below
- * (too big of an interface change for 2.4.x).
- * At that time, we might also consider parameterizing the timeouts and
- * retries, since these are MUCH faster than mechanical drives. -M.Lord
- */
-
-static inline int drive_is_flashcard (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
-
- if (drive->removable) {
- if (id->config == 0x848a) return 1; /* CompactFlash */
- if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
- || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
- || !strncmp(id->model, "SunDisk SDCFB", 13) /* old SanDisk */
- || !strncmp(id->model, "SanDisk SDCFB", 13) /* SanDisk */
- || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */
- || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */
- || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */
- {
- return 1; /* yes, it is a flash memory card */
- }
- }
- return 0; /* no, it is not a flash memory card */
-}
-
-/**
* do_identify - identify a drive
* @drive: drive to identify
* @cmd: command used
@@ -278,13 +239,17 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
/*
* Not an ATAPI device: looks like a "regular" hard disk
*/
- if (id->config & (1<<7))
+
+ /*
+ * 0x848a = CompactFlash device
+ * These are *not* removable in Linux definition of the term
+ */
+
+ if ((id->config != 0x848a) && (id->config & (1<<7)))
drive->removable = 1;
- if (drive_is_flashcard(drive))
- drive->is_flash = 1;
drive->media = ide_disk;
- printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" );
+ printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
QUIRK_LIST(drive);
return;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 9834dce4e20..0606bd2f602 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -34,6 +34,7 @@
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
+#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
@@ -314,6 +315,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
if (rq->bio) /* fs request */
rq->errors = 0;
+ touch_softlockup_watchdog();
+
switch (drive->hwif->data_phase) {
case TASKFILE_MULTI_IN:
case TASKFILE_MULTI_OUT:
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index afeb02bbb72..b2cc43702f6 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -242,7 +242,6 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
drive->name[2] = 'a' + (index * MAX_DRIVES) + unit;
drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
drive->using_dma = 0;
- drive->is_flash = 0;
drive->vdma = 0;
INIT_LIST_HEAD(&drive->list);
init_completion(&drive->gendev_rel_comp);
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index a21b1e11eef..c743e68c33a 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -262,6 +262,21 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch
else
pci_set_drvdata(dev, (void *) aec6xxx_34_base);
+ /* These are necessary to get AEC6280 Macintosh cards to work */
+ if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
+ (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
+ u8 reg49h = 0, reg4ah = 0;
+ /* Clear reset and test bits. */
+ pci_read_config_byte(dev, 0x49, &reg49h);
+ pci_write_config_byte(dev, 0x49, reg49h & ~0x30);
+ /* Enable chip interrupt output. */
+ pci_read_config_byte(dev, 0x4a, &reg4ah);
+ pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01);
+ /* Enable burst mode. */
+ pci_read_config_byte(dev, 0x4a, &reg4ah);
+ pci_write_config_byte(dev, 0x4a, reg4ah | 0x80);
+ }
+
return dev->irq;
}
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 7b589d948bf..940bdd4c578 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1288,6 +1288,10 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
goto init_hpt37X_done;
}
}
+ if (!pci_get_drvdata(dev)) {
+ printk("No Clock Stabilization!!!\n");
+ return;
+ }
pll_recal:
if (adjust & 1)
pll -= (adjust >> 1);
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 108fda83fea..38f41b377ff 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -733,7 +733,7 @@ static void __devinit it8212_disable_raid(struct pci_dev *dev)
pci_write_config_dword(dev,0x4C, 0x02040204);
pci_write_config_byte(dev, 0x42, 0x36);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
}
static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name)
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index fe06ebb0e5b..acd63173199 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -420,9 +420,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = {
.init_hwif = init_hwif_pdc202new,
.channels = 2,
.autodma = AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
- .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
.bootable = OFF_BOARD,
},{ /* 3 */
.name = "PDC20271",
@@ -447,9 +444,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = {
.init_hwif = init_hwif_pdc202new,
.channels = 2,
.autodma = AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
- .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
.bootable = OFF_BOARD,
},{ /* 6 */
.name = "PDC20277",
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index ad9d95817f9..6f8f8645b02 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -786,9 +786,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.init_dma = init_dma_pdc202xx,
.channels = 2,
.autodma = AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
- .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
.bootable = OFF_BOARD,
.extra = 16,
},{ /* 1 */
@@ -799,9 +796,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.init_dma = init_dma_pdc202xx,
.channels = 2,
.autodma = AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
- .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
.bootable = OFF_BOARD,
.extra = 48,
.flags = IDEPCI_FLAG_FORCE_PDC,
@@ -813,9 +807,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.init_dma = init_dma_pdc202xx,
.channels = 2,
.autodma = AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
- .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
.bootable = OFF_BOARD,
.extra = 48,
},{ /* 3 */
@@ -826,9 +817,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.init_dma = init_dma_pdc202xx,
.channels = 2,
.autodma = AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
- .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
.bootable = OFF_BOARD,
.extra = 48,
.flags = IDEPCI_FLAG_FORCE_PDC,
@@ -840,9 +828,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.init_dma = init_dma_pdc202xx,
.channels = 2,
.autodma = AUTODMA,
-#ifndef CONFIG_PDC202XX_FORCE
- .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}},
-#endif
.bootable = OFF_BOARD,
.extra = 48,
}
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index b3e77df63ce..e9b83e1a302 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -135,6 +135,7 @@ static u8 piix_ratemask (ide_drive_t *drive)
case PCI_DEVICE_ID_INTEL_ICH6_19:
case PCI_DEVICE_ID_INTEL_ICH7_21:
case PCI_DEVICE_ID_INTEL_ESB2_18:
+ case PCI_DEVICE_ID_INTEL_ICH8_6:
mode = 3;
break;
/* UDMA 66 capable */
@@ -449,6 +450,7 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char
case PCI_DEVICE_ID_INTEL_ICH6_19:
case PCI_DEVICE_ID_INTEL_ICH7_21:
case PCI_DEVICE_ID_INTEL_ESB2_18:
+ case PCI_DEVICE_ID_INTEL_ICH8_6:
{
unsigned int extra = 0;
pci_read_config_dword(dev, 0x54, &extra);
@@ -575,6 +577,7 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = {
/* 21 */ DECLARE_PIIX_DEV("ICH7"),
/* 22 */ DECLARE_PIIX_DEV("ICH4"),
/* 23 */ DECLARE_PIIX_DEV("ESB2"),
+ /* 24 */ DECLARE_PIIX_DEV("ICH8M"),
};
/**
@@ -651,6 +654,7 @@ static struct pci_device_id piix_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 23},
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 24},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 4ee597d0879..43b96e29836 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -13,11 +13,6 @@
* License along with this program; if not, write the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan
@@ -510,7 +505,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
drive->name);
goto use_pio_instead;
} else {
- u32 xcount, bcount =
+ u32 bcount =
0x10000 - (cur_addr & 0xffff);
if (bcount > cur_len)
@@ -525,8 +520,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
*table = 0x0;
table++;
- xcount = bcount & 0xffff;
- *table = cpu_to_be32(xcount);
+ *table = cpu_to_be32(bcount);
table++;
cur_addr += bcount;
@@ -680,7 +674,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
return -EIO;
/* Create /proc/ide entries */
- create_proc_ide_interfaces();
+ create_proc_ide_interfaces();
return 0;
}
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index d393b504bf2..c82f47a66e4 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -665,7 +665,15 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
struct ib_wc mad_wc;
struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
- if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) {
+ /*
+ * Directed route handling starts if the initial LID routed part of
+ * a request or the ending LID routed part of a response is empty.
+ * If we are at the start of the LID routed part, don't update the
+ * hop_ptr or hop_cnt. See section 14.2.2, Vol 1 IB spec.
+ */
+ if ((ib_get_smp_direction(smp) ? smp->dr_dlid : smp->dr_slid) ==
+ IB_LID_PERMISSIVE &&
+ !smi_handle_dr_smp_send(smp, device->node_type, port_num)) {
ret = -EINVAL;
printk(KERN_ERR PFX "Invalid directed route\n");
goto out;
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index acda7d63d6f..501cc054cb3 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -956,6 +956,8 @@ static void ib_sa_remove_one(struct ib_device *device)
ib_unregister_event_handler(&sa_dev->event_handler);
+ flush_scheduled_work();
+
for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
ib_unregister_mad_agent(sa_dev->port[i].agent);
kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index e95c4293a49..f6a05965a4e 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1319,15 +1319,6 @@ static struct class ucm_class = {
.release = ib_ucm_release_class_dev
};
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
- struct ib_ucm_device *dev;
-
- dev = container_of(class_dev, struct ib_ucm_device, class_dev);
- return print_dev_t(buf, dev->dev.dev);
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
{
struct ib_ucm_device *dev;
@@ -1364,15 +1355,13 @@ static void ib_ucm_add_one(struct ib_device *device)
ucm_dev->class_dev.class = &ucm_class;
ucm_dev->class_dev.dev = device->dma_device;
+ ucm_dev->class_dev.devt = ucm_dev->dev.dev;
snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
ucm_dev->devnum);
if (class_device_register(&ucm_dev->class_dev))
goto err_cdev;
if (class_device_create_file(&ucm_dev->class_dev,
- &class_device_attr_dev))
- goto err_class;
- if (class_device_create_file(&ucm_dev->class_dev,
&class_device_attr_ibdev))
goto err_class;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 96ea79b63df..903f85a4bc0 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -902,6 +902,7 @@ static void __exit ib_uverbs_cleanup(void)
unregister_filesystem(&uverbs_event_fs);
class_destroy(uverbs_class);
unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+ flush_scheduled_work();
idr_destroy(&ib_uverbs_pd_idr);
idr_destroy(&ib_uverbs_mr_idr);
idr_destroy(&ib_uverbs_mw_idr);
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index a14eed08a0f..a19e0ed03d7 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -184,7 +184,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff);
ib_get_cached_gid(&dev->ib_dev,
be32_to_cpu(ah->av->port_pd) >> 24,
- ah->av->gid_index,
+ ah->av->gid_index % dev->limits.gid_table_len,
&header->grh.source_gid);
memcpy(header->grh.destination_gid.raw,
ah->av->dgid, 16);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index be1791be627..2825615ce81 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -199,8 +199,7 @@ static int mthca_cmd_post(struct mthca_dev *dev,
{
int err = 0;
- if (down_interruptible(&dev->cmd.hcr_sem))
- return -EINTR;
+ mutex_lock(&dev->cmd.hcr_mutex);
if (event) {
unsigned long end = jiffies + GO_BIT_TIMEOUT;
@@ -238,7 +237,7 @@ static int mthca_cmd_post(struct mthca_dev *dev,
op), dev->hcr + 6 * 4);
out:
- up(&dev->cmd.hcr_sem);
+ mutex_unlock(&dev->cmd.hcr_mutex);
return err;
}
@@ -255,8 +254,7 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
int err = 0;
unsigned long end;
- if (down_interruptible(&dev->cmd.poll_sem))
- return -EINTR;
+ down(&dev->cmd.poll_sem);
err = mthca_cmd_post(dev, in_param,
out_param ? *out_param : 0,
@@ -333,8 +331,7 @@ static int mthca_cmd_wait(struct mthca_dev *dev,
int err = 0;
struct mthca_cmd_context *context;
- if (down_interruptible(&dev->cmd.event_sem))
- return -EINTR;
+ down(&dev->cmd.event_sem);
spin_lock(&dev->cmd.context_lock);
BUG_ON(dev->cmd.free_head < 0);
@@ -438,7 +435,7 @@ static int mthca_cmd_imm(struct mthca_dev *dev,
int mthca_cmd_init(struct mthca_dev *dev)
{
- sema_init(&dev->cmd.hcr_sem, 1);
+ mutex_init(&dev->cmd.hcr_mutex);
sema_init(&dev->cmd.poll_sem, 1);
dev->cmd.use_events = 0;
@@ -1032,25 +1029,6 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
MTHCA_GET(size, outbox, QUERY_DEV_LIM_UAR_ENTRY_SZ_OFFSET);
dev_lim->uar_scratch_entry_sz = size;
- mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
- dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
- mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
- dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
- mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
- dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
- mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
- dev_lim->max_eqs, dev_lim->reserved_eqs, dev_lim->eqc_entry_sz);
- mthca_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
- dev_lim->reserved_mrws, dev_lim->reserved_mtts);
- mthca_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
- dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);
- mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
- dev_lim->max_pds, dev_lim->reserved_mgms);
- mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
- dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);
-
- mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
-
if (mthca_is_memfree(dev)) {
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
dev_lim->max_srq_sz = 1 << field;
@@ -1096,6 +1074,25 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE;
}
+ mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
+ dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
+ mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
+ dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
+ mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
+ dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
+ mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
+ dev_lim->max_eqs, dev_lim->reserved_eqs, dev_lim->eqc_entry_sz);
+ mthca_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
+ dev_lim->reserved_mrws, dev_lim->reserved_mtts);
+ mthca_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
+ dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);
+ mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
+ dev_lim->max_pds, dev_lim->reserved_mgms);
+ mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
+ dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);
+
+ mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
+
out:
mthca_free_mailbox(dev, mailbox);
return err;
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index a104ab041ea..e481037288d 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -44,6 +44,8 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/timer.h>
+#include <linux/mutex.h>
+
#include <asm/semaphore.h>
#include "mthca_provider.h"
@@ -51,8 +53,8 @@
#define DRV_NAME "ib_mthca"
#define PFX DRV_NAME ": "
-#define DRV_VERSION "0.06"
-#define DRV_RELDATE "June 23, 2005"
+#define DRV_VERSION "0.07"
+#define DRV_RELDATE "February 13, 2006"
enum {
MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
@@ -111,7 +113,7 @@ enum {
struct mthca_cmd {
struct pci_pool *pool;
int use_events;
- struct semaphore hcr_sem;
+ struct mutex hcr_mutex;
struct semaphore poll_sem;
struct semaphore event_sem;
int max_cmds;
@@ -256,7 +258,7 @@ struct mthca_av_table {
};
struct mthca_mcg_table {
- struct semaphore sem;
+ struct mutex mutex;
struct mthca_alloc alloc;
struct mthca_icm_table *table;
};
@@ -301,7 +303,7 @@ struct mthca_dev {
u64 ddr_end;
MTHCA_DECLARE_DOORBELL_LOCK(doorbell_lock)
- struct semaphore cap_mask_mutex;
+ struct mutex cap_mask_mutex;
void __iomem *hcr;
void __iomem *kar;
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 8b00d9a0f6f..9c849d27b06 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -155,6 +155,13 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
return -ENODEV;
}
+ if (dev_lim->uar_size > pci_resource_len(mdev->pdev, 2)) {
+ mthca_err(mdev, "HCA reported UAR size of 0x%x bigger than "
+ "PCI resource 2 size of 0x%lx, aborting.\n",
+ dev_lim->uar_size, pci_resource_len(mdev->pdev, 2));
+ return -ENODEV;
+ }
+
mdev->limits.num_ports = dev_lim->num_ports;
mdev->limits.vl_cap = dev_lim->max_vl;
mdev->limits.mtu_cap = dev_lim->max_mtu;
@@ -976,8 +983,7 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
err = -ENODEV;
goto err_disable_pdev;
}
- if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) ||
- pci_resource_len(pdev, 2) != 1 << 23) {
+ if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
dev_err(&pdev->dev, "Missing UAR, aborting.\n");
err = -ENODEV;
goto err_disable_pdev;
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 77bc6c746f4..321f11e707f 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -154,10 +154,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return PTR_ERR(mailbox);
mgm = mailbox->buf;
- if (down_interruptible(&dev->mcg_table.sem)) {
- err = -EINTR;
- goto err_sem;
- }
+ mutex_lock(&dev->mcg_table.mutex);
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
@@ -241,8 +238,8 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
BUG_ON(index < dev->limits.num_mgms);
mthca_free(&dev->mcg_table.alloc, index);
}
- up(&dev->mcg_table.sem);
- err_sem:
+ mutex_unlock(&dev->mcg_table.mutex);
+
mthca_free_mailbox(dev, mailbox);
return err;
}
@@ -263,10 +260,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return PTR_ERR(mailbox);
mgm = mailbox->buf;
- if (down_interruptible(&dev->mcg_table.sem)) {
- err = -EINTR;
- goto err_sem;
- }
+ mutex_lock(&dev->mcg_table.mutex);
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
@@ -371,8 +365,8 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
}
out:
- up(&dev->mcg_table.sem);
- err_sem:
+ mutex_unlock(&dev->mcg_table.mutex);
+
mthca_free_mailbox(dev, mailbox);
return err;
}
@@ -389,7 +383,7 @@ int __devinit mthca_init_mcg_table(struct mthca_dev *dev)
if (err)
return err;
- init_MUTEX(&dev->mcg_table.sem);
+ mutex_init(&dev->mcg_table.mutex);
return 0;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 9fb985a016e..d709cb162a7 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -50,7 +50,7 @@ enum {
};
struct mthca_user_db_table {
- struct semaphore mutex;
+ struct mutex mutex;
struct {
u64 uvirt;
struct scatterlist mem;
@@ -158,7 +158,7 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
int ret = 0;
u8 status;
- down(&table->mutex);
+ mutex_lock(&table->mutex);
if (table->icm[i]) {
++table->icm[i]->refcount;
@@ -184,7 +184,7 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
++table->icm[i]->refcount;
out:
- up(&table->mutex);
+ mutex_unlock(&table->mutex);
return ret;
}
@@ -198,7 +198,7 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o
i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
- down(&table->mutex);
+ mutex_lock(&table->mutex);
if (--table->icm[i]->refcount == 0) {
mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
@@ -207,7 +207,7 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o
table->icm[i] = NULL;
}
- up(&table->mutex);
+ mutex_unlock(&table->mutex);
}
void *mthca_table_find(struct mthca_icm_table *table, int obj)
@@ -220,7 +220,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj)
if (!table->lowmem)
return NULL;
- down(&table->mutex);
+ mutex_lock(&table->mutex);
idx = (obj & (table->num_obj - 1)) * table->obj_size;
icm = table->icm[idx / MTHCA_TABLE_CHUNK_SIZE];
@@ -240,7 +240,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj)
}
out:
- up(&table->mutex);
+ mutex_unlock(&table->mutex);
return page ? lowmem_page_address(page) + offset : NULL;
}
@@ -301,7 +301,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
table->num_obj = nobj;
table->obj_size = obj_size;
table->lowmem = use_lowmem;
- init_MUTEX(&table->mutex);
+ mutex_init(&table->mutex);
for (i = 0; i < num_icm; ++i)
table->icm[i] = NULL;
@@ -380,7 +380,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
if (index < 0 || index > dev->uar_table.uarc_size / 8)
return -EINVAL;
- down(&db_tab->mutex);
+ mutex_lock(&db_tab->mutex);
i = index / MTHCA_DB_REC_PER_PAGE;
@@ -424,7 +424,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
db_tab->page[i].refcount = 1;
out:
- up(&db_tab->mutex);
+ mutex_unlock(&db_tab->mutex);
return ret;
}
@@ -439,11 +439,11 @@ void mthca_unmap_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
* pages until we clean up the whole db table.
*/
- down(&db_tab->mutex);
+ mutex_lock(&db_tab->mutex);
--db_tab->page[index / MTHCA_DB_REC_PER_PAGE].refcount;
- up(&db_tab->mutex);
+ mutex_unlock(&db_tab->mutex);
}
struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev)
@@ -460,7 +460,7 @@ struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev)
if (!db_tab)
return ERR_PTR(-ENOMEM);
- init_MUTEX(&db_tab->mutex);
+ mutex_init(&db_tab->mutex);
for (i = 0; i < npages; ++i) {
db_tab->page[i].refcount = 0;
db_tab->page[i].uvirt = 0;
@@ -499,7 +499,7 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
int ret = 0;
u8 status;
- down(&dev->db_tab->mutex);
+ mutex_lock(&dev->db_tab->mutex);
switch (type) {
case MTHCA_DB_TYPE_CQ_ARM:
@@ -585,7 +585,7 @@ found:
*db = (__be32 *) &page->db_rec[j];
out:
- up(&dev->db_tab->mutex);
+ mutex_unlock(&dev->db_tab->mutex);
return ret;
}
@@ -601,7 +601,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
page = dev->db_tab->page + i;
- down(&dev->db_tab->mutex);
+ mutex_lock(&dev->db_tab->mutex);
page->db_rec[j] = 0;
if (i >= dev->db_tab->min_group2)
@@ -624,7 +624,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
++dev->db_tab->min_group2;
}
- up(&dev->db_tab->mutex);
+ mutex_unlock(&dev->db_tab->mutex);
}
int mthca_init_db_tab(struct mthca_dev *dev)
@@ -638,7 +638,7 @@ int mthca_init_db_tab(struct mthca_dev *dev)
if (!dev->db_tab)
return -ENOMEM;
- init_MUTEX(&dev->db_tab->mutex);
+ mutex_init(&dev->db_tab->mutex);
dev->db_tab->npages = dev->uar_table.uarc_size / 4096;
dev->db_tab->max_group1 = 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index 4fdca26eea8..36f1141a08a 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -39,8 +39,7 @@
#include <linux/list.h>
#include <linux/pci.h>
-
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#define MTHCA_ICM_CHUNK_LEN \
((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \
@@ -64,7 +63,7 @@ struct mthca_icm_table {
int num_obj;
int obj_size;
int lowmem;
- struct semaphore mutex;
+ struct mutex mutex;
struct mthca_icm *icm[0];
};
@@ -147,7 +146,7 @@ struct mthca_db_table {
int max_group1;
int min_group2;
struct mthca_db_page *page;
- struct semaphore mutex;
+ struct mutex mutex;
};
enum mthca_db_type {
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 484a7e6b7f8..e88e39aef85 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -185,7 +185,7 @@ static int mthca_modify_port(struct ib_device *ibdev,
int err;
u8 status;
- if (down_interruptible(&to_mdev(ibdev)->cap_mask_mutex))
+ if (mutex_lock_interruptible(&to_mdev(ibdev)->cap_mask_mutex))
return -ERESTARTSYS;
err = mthca_query_port(ibdev, port, &attr);
@@ -207,7 +207,7 @@ static int mthca_modify_port(struct ib_device *ibdev,
}
out:
- up(&to_mdev(ibdev)->cap_mask_mutex);
+ mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex);
return err;
}
@@ -1185,7 +1185,7 @@ int mthca_register_device(struct mthca_dev *dev)
dev->ib_dev.post_recv = mthca_tavor_post_receive;
}
- init_MUTEX(&dev->cap_mask_mutex);
+ mutex_init(&dev->cap_mask_mutex);
ret = ib_register_device(&dev->ib_dev);
if (ret)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index e0a5412b7e6..2f85a9a831b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -78,6 +78,7 @@ enum {
IPOIB_FLAG_SUBINTERFACE = 4,
IPOIB_MCAST_RUN = 5,
IPOIB_STOP_REAPER = 6,
+ IPOIB_MCAST_STARTED = 7,
IPOIB_MAX_BACKOFF_SECONDS = 16,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fd3f5c862a5..c3b5f79d116 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -505,7 +505,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
list_add_tail(&neigh->list, &path->neigh_list);
- if (path->pathrec.dlid) {
+ if (path->ah) {
kref_get(&path->ah->ref);
neigh->ah = path->ah;
@@ -591,7 +591,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
return;
}
- if (path->pathrec.dlid) {
+ if (path->ah) {
ipoib_dbg(priv, "Send unicast ARP to %04x\n",
be16_to_cpu(path->pathrec.dlid));
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 98039da0caf..a2408d7ec59 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -97,6 +97,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh, *tmp;
unsigned long flags;
+ int tx_dropped = 0;
ipoib_dbg_mcast(netdev_priv(dev),
"deleting multicast group " IPOIB_GID_FMT "\n",
@@ -123,8 +124,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
if (mcast->ah)
ipoib_put_ah(mcast->ah);
- while (!skb_queue_empty(&mcast->pkt_queue))
+ while (!skb_queue_empty(&mcast->pkt_queue)) {
+ ++tx_dropped;
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
+ }
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ priv->stats.tx_dropped += tx_dropped;
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
kfree(mcast);
}
@@ -276,8 +283,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
}
/* actually send any queued packets */
+ spin_lock_irq(&priv->tx_lock);
while (!skb_queue_empty(&mcast->pkt_queue)) {
struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
+ spin_unlock_irq(&priv->tx_lock);
skb->dev = dev;
@@ -288,7 +297,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
if (dev_queue_xmit(skb))
ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
+ spin_lock_irq(&priv->tx_lock);
}
+ spin_unlock_irq(&priv->tx_lock);
return 0;
}
@@ -300,6 +311,7 @@ ipoib_mcast_sendonly_join_complete(int status,
{
struct ipoib_mcast *mcast = mcast_ptr;
struct net_device *dev = mcast->dev;
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
if (!status)
ipoib_mcast_join_finish(mcast, mcmember);
@@ -310,8 +322,12 @@ ipoib_mcast_sendonly_join_complete(int status,
IPOIB_GID_ARG(mcast->mcmember.mgid), status);
/* Flush out any queued packets */
- while (!skb_queue_empty(&mcast->pkt_queue))
+ spin_lock_irq(&priv->tx_lock);
+ while (!skb_queue_empty(&mcast->pkt_queue)) {
+ ++priv->stats.tx_dropped;
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
+ }
+ spin_unlock_irq(&priv->tx_lock);
/* Clear the busy flag so we try again */
clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
@@ -517,8 +533,10 @@ void ipoib_mcast_join_task(void *dev_ptr)
}
if (!priv->broadcast) {
- priv->broadcast = ipoib_mcast_alloc(dev, 1);
- if (!priv->broadcast) {
+ struct ipoib_mcast *broadcast;
+
+ broadcast = ipoib_mcast_alloc(dev, 1);
+ if (!broadcast) {
ipoib_warn(priv, "failed to allocate broadcast group\n");
mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
@@ -528,10 +546,11 @@ void ipoib_mcast_join_task(void *dev_ptr)
return;
}
- memcpy(priv->broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
+ spin_lock_irq(&priv->lock);
+ memcpy(broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
sizeof (union ib_gid));
+ priv->broadcast = broadcast;
- spin_lock_irq(&priv->lock);
__ipoib_mcast_add(dev, priv->broadcast);
spin_unlock_irq(&priv->lock);
}
@@ -585,6 +604,10 @@ int ipoib_mcast_start_thread(struct net_device *dev)
queue_work(ipoib_workqueue, &priv->mcast_task);
mutex_unlock(&mcast_mutex);
+ spin_lock_irq(&priv->lock);
+ set_bit(IPOIB_MCAST_STARTED, &priv->flags);
+ spin_unlock_irq(&priv->lock);
+
return 0;
}
@@ -595,6 +618,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
ipoib_dbg_mcast(priv, "stopping multicast thread\n");
+ spin_lock_irq(&priv->lock);
+ clear_bit(IPOIB_MCAST_STARTED, &priv->flags);
+ spin_unlock_irq(&priv->lock);
+
mutex_lock(&mcast_mutex);
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
cancel_delayed_work(&priv->mcast_task);
@@ -677,6 +704,14 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
*/
spin_lock(&priv->lock);
+ if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags) ||
+ !priv->broadcast ||
+ !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
+ ++priv->stats.tx_dropped;
+ dev_kfree_skb_any(skb);
+ goto unlock;
+ }
+
mcast = __ipoib_mcast_find(dev, mgid);
if (!mcast) {
/* Let's create a new send only group now */
@@ -687,6 +722,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
if (!mcast) {
ipoib_warn(priv, "unable to allocate memory for "
"multicast structure\n");
+ ++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
goto out;
}
@@ -700,8 +736,10 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
if (!mcast->ah) {
if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
skb_queue_tail(&mcast->pkt_queue, skb);
- else
+ else {
+ ++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
+ }
if (mcast->query)
ipoib_dbg_mcast(priv, "no address vector, "
@@ -735,6 +773,7 @@ out:
ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
}
+unlock:
spin_unlock(&priv->lock);
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 31207e66414..2d2d4ac3525 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -357,9 +357,9 @@ static void srp_remove_work(void *target_ptr)
target->state = SRP_TARGET_REMOVED;
spin_unlock_irq(target->scsi_host->host_lock);
- down(&target->srp_host->target_mutex);
+ mutex_lock(&target->srp_host->target_mutex);
list_del(&target->list);
- up(&target->srp_host->target_mutex);
+ mutex_unlock(&target->srp_host->target_mutex);
scsi_remove_host(target->scsi_host);
ib_destroy_cm_id(target->cm_id);
@@ -1254,9 +1254,9 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
if (scsi_add_host(target->scsi_host, host->dev->dma_device))
return -ENODEV;
- down(&host->target_mutex);
+ mutex_lock(&host->target_mutex);
list_add_tail(&target->list, &host->target_list);
- up(&host->target_mutex);
+ mutex_unlock(&host->target_mutex);
target->state = SRP_TARGET_LIVE;
@@ -1525,7 +1525,7 @@ static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
return NULL;
INIT_LIST_HEAD(&host->target_list);
- init_MUTEX(&host->target_mutex);
+ mutex_init(&host->target_mutex);
init_completion(&host->released);
host->dev = device;
host->port = port;
@@ -1626,7 +1626,7 @@ static void srp_remove_one(struct ib_device *device)
* Mark all target ports as removed, so we stop queueing
* commands and don't try to reconnect.
*/
- down(&host->target_mutex);
+ mutex_lock(&host->target_mutex);
list_for_each_entry_safe(target, tmp_target,
&host->target_list, list) {
spin_lock_irqsave(target->scsi_host->host_lock, flags);
@@ -1634,7 +1634,7 @@ static void srp_remove_one(struct ib_device *device)
target->state = SRP_TARGET_REMOVED;
spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
}
- up(&host->target_mutex);
+ mutex_unlock(&host->target_mutex);
/*
* Wait for any reconnection tasks that may have
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index b564f18caf7..4e7727df32f 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -37,8 +37,7 @@
#include <linux/types.h>
#include <linux/list.h>
-
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
@@ -85,7 +84,7 @@ struct srp_host {
struct ib_mr *mr;
struct class_device class_dev;
struct list_head target_list;
- struct semaphore target_mutex;
+ struct mutex target_mutex;
struct completion released;
struct list_head list;
};
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index 4571ea3a4b9..4612d13ea75 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -57,7 +57,7 @@ static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "
struct a3d {
struct gameport *gameport;
struct gameport *adc;
- struct input_dev dev;
+ struct input_dev *dev;
int axes[4];
int buttons;
int mode;
@@ -115,7 +115,7 @@ static int a3d_csum(char *data, int count)
static void a3d_read(struct a3d *a3d, unsigned char *data)
{
- struct input_dev *dev = &a3d->dev;
+ struct input_dev *dev = a3d->dev;
switch (a3d->mode) {
@@ -265,14 +265,20 @@ static void a3d_close(struct input_dev *dev)
static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct a3d *a3d;
+ struct input_dev *input_dev;
struct gameport *adc;
unsigned char data[A3D_MAX_LENGTH];
int i;
int err;
- if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL)))
- return -ENOMEM;
+ a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!a3d || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+ a3d->dev = input_dev;
a3d->gameport = gameport;
gameport_set_drvdata(gameport, a3d);
@@ -302,42 +308,48 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
sprintf(a3d->phys, "%s/input0", gameport->phys);
+ input_dev->name = a3d_names[a3d->mode];
+ input_dev->phys = a3d->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
+ input_dev->id.product = a3d->mode;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = a3d;
+ input_dev->open = a3d_open;
+ input_dev->close = a3d_close;
+
if (a3d->mode == A3D_MODE_PXL) {
int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
a3d->length = 33;
- init_input_dev(&a3d->dev);
-
- a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
- a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
- a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
- | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
-
- a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
- | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-
- a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE);
+ input_dev->evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y);
+ input_dev->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
+ | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
+ input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
+ | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+ input_dev->keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP)
+ | BIT(BTN_PINKIE);
a3d_read(a3d, data);
for (i = 0; i < 4; i++) {
if (i < 2)
- input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8);
+ input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8);
else
- input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0);
- input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
}
} else {
a3d->length = 29;
- init_input_dev(&a3d->dev);
-
- a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
- a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
- a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
+ input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y);
+ input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
a3d_read(a3d, data);
@@ -358,24 +370,17 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
}
}
- a3d->dev.private = a3d;
- a3d->dev.open = a3d_open;
- a3d->dev.close = a3d_close;
-
- a3d->dev.name = a3d_names[a3d->mode];
- a3d->dev.phys = a3d->phys;
- a3d->dev.id.bustype = BUS_GAMEPORT;
- a3d->dev.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
- a3d->dev.id.product = a3d->mode;
- a3d->dev.id.version = 0x0100;
-
- input_register_device(&a3d->dev);
- printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);
+ err = input_register_device(a3d->dev);
+ if (err)
+ goto fail3;
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: if (a3d->adc)
+ gameport_unregister_port(a3d->adc);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
+ input_free_device(input_dev);
kfree(a3d);
return err;
}
@@ -384,11 +389,9 @@ static void a3d_disconnect(struct gameport *gameport)
{
struct a3d *a3d = gameport_get_drvdata(gameport);
- input_unregister_device(&a3d->dev);
- if (a3d->adc) {
+ input_unregister_device(a3d->dev);
+ if (a3d->adc)
gameport_unregister_port(a3d->adc);
- a3d->adc = NULL;
- }
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(a3d);
@@ -397,6 +400,7 @@ static void a3d_disconnect(struct gameport *gameport)
static struct gameport_driver a3d_drv = {
.driver = {
.name = "adc",
+ .owner = THIS_MODULE,
},
.description = DRIVER_DESC,
.connect = a3d_connect,
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 499344c7275..dcffc34f30c 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -275,68 +275,70 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char
/*
* db9_saturn_report() analyzes packet and reports.
*/
-static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *dev, int n, int max_pads)
+static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *devs[], int n, int max_pads)
{
+ struct input_dev *dev;
int tmp, i, j;
tmp = (id == 0x41) ? 60 : 10;
- for (j = 0; (j < tmp) && (n < max_pads); j += 10, n++) {
+ for (j = 0; j < tmp && n < max_pads; j += 10, n++) {
+ dev = devs[n];
switch (data[j]) {
case 0x16: /* multi controller (analog 4 axis) */
- input_report_abs(dev + n, db9_abs[5], data[j + 6]);
+ input_report_abs(dev, db9_abs[5], data[j + 6]);
case 0x15: /* mission stick (analog 3 axis) */
- input_report_abs(dev + n, db9_abs[3], data[j + 4]);
- input_report_abs(dev + n, db9_abs[4], data[j + 5]);
+ input_report_abs(dev, db9_abs[3], data[j + 4]);
+ input_report_abs(dev, db9_abs[4], data[j + 5]);
case 0x13: /* racing controller (analog 1 axis) */
- input_report_abs(dev + n, db9_abs[2], data[j + 3]);
+ input_report_abs(dev, db9_abs[2], data[j + 3]);
case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
case 0x02: /* digital pad (digital 2 axis + buttons) */
- input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
- input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
+ input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
+ input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
for (i = 0; i < 9; i++)
- input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
+ input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
break;
case 0x19: /* mission stick x2 (analog 6 axis + buttons) */
- input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
- input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
+ input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
+ input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
for (i = 0; i < 9; i++)
- input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
- input_report_abs(dev + n, db9_abs[2], data[j + 3]);
- input_report_abs(dev + n, db9_abs[3], data[j + 4]);
- input_report_abs(dev + n, db9_abs[4], data[j + 5]);
+ input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
+ input_report_abs(dev, db9_abs[2], data[j + 3]);
+ input_report_abs(dev, db9_abs[3], data[j + 4]);
+ input_report_abs(dev, db9_abs[4], data[j + 5]);
/*
- input_report_abs(dev + n, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
- input_report_abs(dev + n, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
+ input_report_abs(dev, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
+ input_report_abs(dev, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
*/
- input_report_abs(dev + n, db9_abs[6], data[j + 7]);
- input_report_abs(dev + n, db9_abs[7], data[j + 8]);
- input_report_abs(dev + n, db9_abs[5], data[j + 9]);
+ input_report_abs(dev, db9_abs[6], data[j + 7]);
+ input_report_abs(dev, db9_abs[7], data[j + 8]);
+ input_report_abs(dev, db9_abs[5], data[j + 9]);
break;
case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */
- input_report_key(dev + n, BTN_A, data[j + 3] & 0x80);
- input_report_abs(dev + n, db9_abs[2], data[j + 3] & 0x7f);
+ input_report_key(dev, BTN_A, data[j + 3] & 0x80);
+ input_report_abs(dev, db9_abs[2], data[j + 3] & 0x7f);
break;
case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */
- input_report_key(dev + n, BTN_START, data[j + 1] & 0x08);
- input_report_key(dev + n, BTN_A, data[j + 1] & 0x04);
- input_report_key(dev + n, BTN_C, data[j + 1] & 0x02);
- input_report_key(dev + n, BTN_B, data[j + 1] & 0x01);
- input_report_abs(dev + n, db9_abs[2], data[j + 2] ^ 0x80);
- input_report_abs(dev + n, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
+ input_report_key(dev, BTN_START, data[j + 1] & 0x08);
+ input_report_key(dev, BTN_A, data[j + 1] & 0x04);
+ input_report_key(dev, BTN_C, data[j + 1] & 0x02);
+ input_report_key(dev, BTN_B, data[j + 1] & 0x01);
+ input_report_abs(dev, db9_abs[2], data[j + 2] ^ 0x80);
+ input_report_abs(dev, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
break;
case 0xff:
default: /* no pad */
- input_report_abs(dev + n, db9_abs[0], 0);
- input_report_abs(dev + n, db9_abs[1], 0);
+ input_report_abs(dev, db9_abs[0], 0);
+ input_report_abs(dev, db9_abs[1], 0);
for (i = 0; i < 9; i++)
- input_report_key(dev + n, db9_cd32_btn[i], 0);
+ input_report_key(dev, db9_cd32_btn[i], 0);
break;
}
}
return n;
}
-static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
+static int db9_saturn(int mode, struct parport *port, struct input_dev *devs[])
{
unsigned char id, data[60];
int type, n, max_pads;
@@ -361,7 +363,7 @@ static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
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);
+ tmp = db9_saturn_report(id, data, devs, tmp, max_pads);
}
return 0;
}
@@ -489,7 +491,7 @@ static void db9_timer(unsigned long private)
case DB9_SATURN_DPP:
case DB9_SATURN_DPP_2:
- db9_saturn(db9->mode, port, dev);
+ db9_saturn(db9->mode, port, db9->dev);
break;
case DB9_CD32_PAD:
@@ -614,7 +616,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
if (!input_dev) {
printk(KERN_ERR "db9.c: Not enough memory for input device\n");
err = -ENOMEM;
- goto err_free_devs;
+ goto err_unreg_devs;
}
sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
@@ -640,13 +642,17 @@ static struct db9 __init *db9_probe(int parport, int mode)
input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
}
- input_register_device(input_dev);
+ err = input_register_device(input_dev);
+ if (err)
+ goto err_free_dev;
}
parport_put_port(pp);
return db9;
- err_free_devs:
+ err_free_dev:
+ input_free_device(db9->dev[i]);
+ err_unreg_devs:
while (--i >= 0)
input_unregister_device(db9->dev[i]);
kfree(db9);
@@ -658,7 +664,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
return ERR_PTR(err);
}
-static void __exit db9_remove(struct db9 *db9)
+static void db9_remove(struct db9 *db9)
{
int i;
@@ -696,7 +702,8 @@ static int __init db9_init(void)
if (err) {
while (--i >= 0)
- db9_remove(db9_base[i]);
+ if (db9_base[i])
+ db9_remove(db9_base[i]);
return err;
}
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 7df2d82f2c8..900587acdb4 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -159,6 +159,48 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
}
+static void gc_n64_process_packet(struct gc *gc)
+{
+ unsigned char data[GC_N64_LENGTH];
+ signed char axes[2];
+ struct input_dev *dev;
+ int i, j, s;
+
+ gc_n64_read_packet(gc, data);
+
+ for (i = 0; i < GC_MAX_DEVICES; i++) {
+
+ dev = gc->dev[i];
+ if (!dev)
+ continue;
+
+ s = gc_status_bit[i];
+
+ if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
+
+ axes[0] = axes[1] = 0;
+
+ for (j = 0; j < 8; j++) {
+ if (data[23 - j] & s)
+ axes[0] |= 1 << j;
+ if (data[31 - j] & s)
+ axes[1] |= 1 << j;
+ }
+
+ input_report_abs(dev, ABS_X, axes[0]);
+ input_report_abs(dev, ABS_Y, -axes[1]);
+
+ input_report_abs(dev, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
+ input_report_abs(dev, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
+
+ for (j = 0; j < 10; j++)
+ input_report_key(dev, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
+
+ input_sync(dev);
+ }
+ }
+}
+
/*
* NES/SNES support.
*/
@@ -198,6 +240,39 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
}
}
+static void gc_nes_process_packet(struct gc *gc)
+{
+ unsigned char data[GC_SNES_LENGTH];
+ struct input_dev *dev;
+ int i, j, s;
+
+ gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
+
+ for (i = 0; i < GC_MAX_DEVICES; i++) {
+
+ dev = gc->dev[i];
+ if (!dev)
+ continue;
+
+ s = gc_status_bit[i];
+
+ if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
+ input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7]));
+ input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5]));
+ }
+
+ if (s & gc->pads[GC_NES])
+ for (j = 0; j < 4; j++)
+ input_report_key(dev, 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, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
+
+ input_sync(dev);
+ }
+}
+
/*
* Multisystem joystick support
*/
@@ -219,6 +294,35 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
}
}
+static void gc_multi_process_packet(struct gc *gc)
+{
+ unsigned char data[GC_MULTI2_LENGTH];
+ struct input_dev *dev;
+ int i, s;
+
+ gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
+
+ for (i = 0; i < GC_MAX_DEVICES; i++) {
+
+ dev = gc->dev[i];
+ if (!dev)
+ continue;
+
+ s = gc_status_bit[i];
+
+ if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
+ input_report_abs(dev, ABS_X, !(s & data[2]) - !(s & data[3]));
+ input_report_abs(dev, ABS_Y, !(s & data[0]) - !(s & data[1]));
+ input_report_key(dev, BTN_TRIGGER, s & data[4]);
+ }
+
+ if (s & gc->pads[GC_MULTI2])
+ input_report_key(dev, BTN_THUMB, s & data[5]);
+
+ input_sync(dev);
+ }
+}
+
/*
* PSX support
*
@@ -263,10 +367,11 @@ static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
* the psx pad.
*/
-static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
+static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_MAX_DEVICES])
{
int i, j, cmd, read;
- for (i = 0; i < 5; i++)
+
+ for (i = 0; i < GC_MAX_DEVICES; i++)
data[i] = 0;
for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
@@ -274,7 +379,7 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
udelay(gc_psx_delay);
read = parport_read_status(gc->pd->port) ^ 0x80;
- for (j = 0; j < 5; j++)
+ for (j = 0; j < GC_MAX_DEVICES; j++)
data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0;
parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
udelay(gc_psx_delay);
@@ -286,11 +391,12 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
* device identifier code.
*/
-static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5])
+static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES],
+ unsigned char id[GC_MAX_DEVICES])
{
int i, j, max_len = 0;
unsigned long flags;
- unsigned char data2[5];
+ unsigned char data2[GC_MAX_DEVICES];
parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */
udelay(gc_psx_delay);
@@ -303,7 +409,7 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
gc_psx_command(gc, 0x42, id); /* Get device ids */
gc_psx_command(gc, 0, data2); /* Dump status */
- for (i =0; i < 5; i++) /* Find the longest pad */
+ for (i =0; i < GC_MAX_DEVICES; i++) /* Find the longest pad */
if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
&& (GC_PSX_LEN(id[i]) > max_len)
&& (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
@@ -311,7 +417,7 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
for (i = 0; i < max_len; i++) { /* Read in all the data */
gc_psx_command(gc, 0, data2);
- for (j = 0; j < 5; j++)
+ for (j = 0; j < GC_MAX_DEVICES; j++)
data[j][i] = data2[j];
}
@@ -319,185 +425,124 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
- for(i = 0; i < 5; i++) /* Set id's to the real value */
+ for(i = 0; i < GC_MAX_DEVICES; i++) /* Set id's to the real value */
id[i] = GC_PSX_ID(id[i]);
}
-/*
- * gc_timer() reads and analyzes console pads data.
- */
+static void gc_psx_process_packet(struct gc *gc)
+{
+ unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES];
+ unsigned char id[GC_MAX_DEVICES];
+ struct input_dev *dev;
+ int i, j;
-#define GC_MAX_LENGTH GC_N64_LENGTH
+ gc_psx_read_packet(gc, data, id);
-static void gc_timer(unsigned long private)
-{
- struct gc *gc = (void *) private;
- unsigned char data[GC_MAX_LENGTH];
- unsigned char data_psx[5][GC_PSX_BYTES];
- int i, j, s;
+ for (i = 0; i < GC_MAX_DEVICES; i++) {
-/*
- * N64 pads - must be read first, any read confuses them for 200 us
- */
+ dev = gc->dev[i];
+ if (!dev)
+ continue;
- if (gc->pads[GC_N64]) {
+ switch (id[i]) {
- gc_n64_read_packet(gc, data);
+ case GC_PSX_RUMBLE:
- for (i = 0; i < 5; i++) {
+ input_report_key(dev, BTN_THUMBL, ~data[i][0] & 0x04);
+ input_report_key(dev, BTN_THUMBR, ~data[i][0] & 0x02);
- s = gc_status_bit[i];
+ case GC_PSX_NEGCON:
+ case GC_PSX_ANALOG:
- if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
+ if (gc->pads[GC_DDR] & gc_status_bit[i]) {
+ for(j = 0; j < 4; j++)
+ input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j));
+ } else {
+ for (j = 0; j < 4; j++)
+ input_report_abs(dev, gc_psx_abs[j + 2], data[i][j + 2]);
- signed char axes[2];
- axes[0] = axes[1] = 0;
+ input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128);
+ input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128);
+ }
- for (j = 0; j < 8; j++) {
- if (data[23 - j] & s) axes[0] |= 1 << j;
- if (data[31 - j] & s) axes[1] |= 1 << j;
+ for (j = 0; j < 8; j++)
+ input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j));
+
+ input_report_key(dev, BTN_START, ~data[i][0] & 0x08);
+ input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01);
+
+ input_sync(dev);
+
+ break;
+
+ case GC_PSX_NORMAL:
+ if (gc->pads[GC_DDR] & gc_status_bit[i]) {
+ for(j = 0; j < 4; j++)
+ input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j));
+ } else {
+ input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128);
+ input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[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, gc_psx_abs[j + 2], 128);
+ * This needs to be debugged properly,
+ * maybe fuzz processing needs to be done in input_sync()
+ * --vojtech
+ */
}
- input_report_abs(gc->dev[i], ABS_X, axes[0]);
- input_report_abs(gc->dev[i], ABS_Y, -axes[1]);
+ for (j = 0; j < 8; j++)
+ input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j));
+
+ input_report_key(dev, BTN_START, ~data[i][0] & 0x08);
+ input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01);
- 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]));
+ input_sync(dev);
- for (j = 0; j < 10; j++)
- input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
+ break;
- input_sync(gc->dev[i]);
- }
+ case 0: /* not a pad, ignore */
+ break;
}
}
+}
/*
- * NES and SNES pads
+ * gc_timer() initiates reads of console pads data.
*/
- if (gc->pads[GC_NES] || gc->pads[GC_SNES]) {
-
- gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
-
- for (i = 0; i < 5; i++) {
-
- s = gc_status_bit[i];
+static void gc_timer(unsigned long private)
+{
+ struct gc *gc = (void *) private;
- if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
- 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]));
- }
+/*
+ * N64 pads - must be read first, any read confuses them for 200 us
+ */
- if (s & gc->pads[GC_NES])
- for (j = 0; j < 4; j++)
- input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
+ if (gc->pads[GC_N64])
+ gc_n64_process_packet(gc);
- if (s & gc->pads[GC_SNES])
- for (j = 0; j < 8; j++)
- input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
+/*
+ * NES and SNES pads
+ */
- input_sync(gc->dev[i]);
- }
- }
+ if (gc->pads[GC_NES] || gc->pads[GC_SNES])
+ gc_nes_process_packet(gc);
/*
* Multi and Multi2 joysticks
*/
- if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) {
-
- gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
-
- for (i = 0; i < 5; i++) {
-
- s = gc_status_bit[i];
-
- if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
- 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(gc->dev[i], BTN_THUMB, s & data[5]);
-
- input_sync(gc->dev[i]);
- }
- }
+ if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2])
+ gc_multi_process_packet(gc);
/*
* PSX controllers
*/
- if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {
-
- gc_psx_read_packet(gc, data_psx, data);
-
- for (i = 0; i < 5; i++) {
- switch (data[i]) {
-
- case GC_PSX_RUMBLE:
-
- 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]) {
- for(j = 0; j < 4; 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(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);
-
- 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(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
-
- 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(gc->dev[i]);
-
- break;
-
- case GC_PSX_NORMAL:
- if (gc->pads[GC_DDR] & gc_status_bit[i]) {
- for(j = 0; j < 4; j++)
- input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
- } else {
- 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(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
- */
- }
-
- for (j = 0; j < 8; j++)
- input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
-
- 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(gc->dev[i]);
-
- break;
-
- case 0: /* not a pad, ignore */
- break;
- }
- }
- }
+ if (gc->pads[GC_PSX] || gc->pads[GC_DDR])
+ gc_psx_process_packet(gc);
mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
}
@@ -654,16 +699,18 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
gc->timer.data = (long) gc;
gc->timer.function = gc_timer;
- for (i = 0; i < n_pads; i++) {
+ for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) {
if (!pads[i])
continue;
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;
+ goto err_unreg_devs;
- input_register_device(gc->dev[i]);
+ err = input_register_device(gc->dev[i]);
+ if (err)
+ goto err_free_dev;
}
if (!gc->pads[0]) {
@@ -675,9 +722,12 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
parport_put_port(pp);
return gc;
- err_free_devs:
+ err_free_dev:
+ input_free_device(gc->dev[i]);
+ err_unreg_devs:
while (--i >= 0)
- input_unregister_device(gc->dev[i]);
+ if (gc->dev[i])
+ input_unregister_device(gc->dev[i]);
err_free_gc:
kfree(gc);
err_unreg_pardev:
@@ -688,7 +738,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
return ERR_PTR(err);
}
-static void __exit gc_remove(struct gc *gc)
+static void gc_remove(struct gc *gc)
{
int i;
@@ -726,7 +776,8 @@ static int __init gc_init(void)
if (err) {
while (--i >= 0)
- gc_remove(gc_base[i]);
+ if (gc_base[i])
+ gc_remove(gc_base[i]);
return err;
}
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index a936e7aedb1..20cb98ac2d7 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -192,6 +192,9 @@ static void grip_poll(struct gameport *gameport)
for (i = 0; i < 2; i++) {
dev = grip->dev[i];
+ if (!dev)
+ continue;
+
grip->reads++;
switch (grip->mode[i]) {
@@ -381,12 +384,15 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
if (t > 0)
set_bit(t, input_dev->keybit);
- input_register_device(grip->dev[i]);
+ err = input_register_device(grip->dev[i]);
+ if (err)
+ goto fail4;
}
return 0;
- fail3: for (i = 0; i < 2; i++)
+ fail4: input_free_device(grip->dev[i]);
+ fail3: while (--i >= 0)
if (grip->dev[i])
input_unregister_device(grip->dev[i]);
fail2: gameport_close(gameport);
@@ -411,6 +417,7 @@ static void grip_disconnect(struct gameport *gameport)
static struct gameport_driver grip_drv = {
.driver = {
.name = "grip",
+ .owner = THIS_MODULE,
},
.description = DRIVER_DESC,
.connect = grip_connect,
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 64b9c31c47f..b6bc0499804 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -345,7 +345,7 @@ int iforce_init_device(struct iforce *iforce)
int i;
input_dev = input_allocate_device();
- if (input_dev)
+ if (!input_dev)
return -ENOMEM;
init_waitqueue_head(&iforce->wait);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 4a2629243e1..76cb1f88f4e 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -167,9 +167,9 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
iforce->expect_packet = 0;
iforce->ecmd = cmd;
memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
- wake_up(&iforce->wait);
}
#endif
+ wake_up(&iforce->wait);
if (!iforce->type) {
being_used--;
@@ -264,7 +264,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
wait_event_interruptible_timeout(iforce->wait,
iforce->ctrl->status != -EINPROGRESS, HZ);
- if (iforce->ctrl->status != -EINPROGRESS) {
+ if (iforce->ctrl->status) {
usb_unlink_urb(iforce->ctrl);
return -1;
}
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index bc2fce60f9f..fe79d158456 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -95,7 +95,6 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
- wake_up(&iforce->wait);
iforce_process_packet(iforce,
(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 78dd163cd70..2b2ec1057de 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -736,7 +736,7 @@ 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);
- input_dev = input_allocate_device();
+ sw->dev[i] = input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
goto fail3;
@@ -771,12 +771,15 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
- input_register_device(sw->dev[i]);
+ err = input_register_device(sw->dev[i]);
+ if (err)
+ goto fail4;
}
return 0;
- fail3: while (--i >= 0)
+ fail4: input_free_device(sw->dev[i]);
+ fail3: while (--i >= 0)
input_unregister_device(sw->dev[i]);
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
@@ -801,6 +804,7 @@ static void sw_disconnect(struct gameport *gameport)
static struct gameport_driver sw_drv = {
.driver = {
.name = "sidewinder",
+ .owner = THIS_MODULE,
},
.description = DRIVER_DESC,
.connect = sw_connect,
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 60e2aac7d06..bb23ed2a04a 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -284,13 +284,13 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
struct tmdc_port *port;
struct input_dev *input_dev;
int i, j, b = 0;
+ int err;
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;
+ err = -ENOMEM;
+ goto fail;
}
port->mode = data[TMDC_BYTE_ID];
@@ -347,9 +347,15 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
b += port->btnc[i];
}
- input_register_device(port->dev);
+ err = input_register_device(port->dev);
+ if (err)
+ goto fail;
return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(port);
+ return err;
}
/*
@@ -424,6 +430,7 @@ static void tmdc_disconnect(struct gameport *gameport)
static struct gameport_driver tmdc_drv = {
.driver = {
.name = "tmdc",
+ .owner = THIS_MODULE,
},
.description = DRIVER_DESC,
.connect = tmdc_connect,
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 7e9764937d0..b154938e88a 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -204,14 +204,14 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
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;
+ goto err_unreg_devs;
}
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;
+ goto err_unreg_devs;
}
tgfx->sticks |= (1 << i);
@@ -238,7 +238,9 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
for (j = 0; j < n_buttons[i]; j++)
set_bit(tgfx_buttons[j], input_dev->keybit);
- input_register_device(tgfx->dev[i]);
+ err = input_register_device(tgfx->dev[i]);
+ if (err)
+ goto err_free_dev;
}
if (!tgfx->sticks) {
@@ -249,9 +251,12 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
return tgfx;
- err_free_devs:
+ err_free_dev:
+ input_free_device(tgfx->dev[i]);
+ err_unreg_devs:
while (--i >= 0)
- input_unregister_device(tgfx->dev[i]);
+ if (tgfx->dev[i])
+ input_unregister_device(tgfx->dev[i]);
err_free_tgfx:
kfree(tgfx);
err_unreg_pardev:
@@ -262,7 +267,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
return ERR_PTR(err);
}
-static void __exit tgfx_remove(struct tgfx *tgfx)
+static void tgfx_remove(struct tgfx *tgfx)
{
int i;
@@ -300,7 +305,8 @@ static int __init tgfx_init(void)
if (err) {
while (--i >= 0)
- tgfx_remove(tgfx_base[i]);
+ if (tgfx_base[i])
+ tgfx_remove(tgfx_base[i]);
return err;
}
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index cd3a1e742a3..7f8b0093c5b 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -265,13 +265,13 @@ static struct serio_driver twidjoy_drv = {
* The functions for inserting/removing us as a module.
*/
-int __init twidjoy_init(void)
+static int __init twidjoy_init(void)
{
serio_register_driver(&twidjoy_drv);
return 0;
}
-void __exit twidjoy_exit(void)
+static void __exit twidjoy_exit(void)
{
serio_unregister_driver(&twidjoy_drv);
}
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 6e0afbb2238..2708167ba17 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
-obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index e08dbe08f46..4bad588d0e5 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -50,6 +50,18 @@ config INPUT_WISTRON_BTNS
To compile this driver as a module, choose M here: the module will
be called wistron_btns.
+config INPUT_IXP4XX_BEEPER
+ tristate "IXP4XX Beeper support"
+ depends on ARCH_IXP4XX
+ help
+ If you say yes here, you can connect a beeper to the
+ ixp4xx gpio pins. This is used by the LinkSys NSLU2.
+
+ If unsure, say Y.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ixp4xx-beeper.
+
config INPUT_UINPUT
tristate "User level driver support"
help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index ce44cce0128..415c4917898 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -7,7 +7,7 @@
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
-obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
+obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
new file mode 100644
index 00000000000..3a6ae85cd69
--- /dev/null
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -0,0 +1,184 @@
+/*
+ * Generic IXP4xx beeper driver
+ *
+ * Copyright (C) 2005 Tower Technologies
+ *
+ * based on nslu2-io.c
+ * Copyright (C) 2004 Karen Spearel
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <asm/hardware.h>
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("ixp4xx beeper driver");
+MODULE_LICENSE("GPL");
+
+static DEFINE_SPINLOCK(beep_lock);
+
+static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&beep_lock, flags);
+
+ if (count) {
+ gpio_line_config(pin, IXP4XX_GPIO_OUT);
+ gpio_line_set(pin, IXP4XX_GPIO_LOW);
+
+ *IXP4XX_OSRT2 = (count & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
+ } else {
+ gpio_line_config(pin, IXP4XX_GPIO_IN);
+ gpio_line_set(pin, IXP4XX_GPIO_HIGH);
+
+ *IXP4XX_OSRT2 = 0;
+ }
+
+ spin_unlock_irqrestore(&beep_lock, flags);
+}
+
+static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+ unsigned int pin = (unsigned int) dev->private;
+ unsigned int count = 0;
+
+ if (type != EV_SND)
+ return -1;
+
+ switch (code) {
+ case SND_BELL:
+ if (value)
+ value = 1000;
+ case SND_TONE:
+ break;
+ default:
+ return -1;
+ }
+
+ if (value > 20 && value < 32767)
+#ifndef FREQ
+ count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1;
+#else
+ count = (FREQ / (value * 4)) - 1;
+#endif
+
+ ixp4xx_spkr_control(pin, count);
+
+ return 0;
+}
+
+static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* clear interrupt */
+ *IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND;
+
+ /* flip the beeper output */
+ *IXP4XX_GPIO_GPOUTR ^= (1 << (unsigned int) dev_id);
+
+ return IRQ_HANDLED;
+}
+
+static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
+{
+ struct input_dev *input_dev;
+ int err;
+
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->private = (void *) dev->id;
+ input_dev->name = "ixp4xx beeper",
+ input_dev->phys = "ixp4xx/gpio";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x001f;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &dev->dev;
+
+ input_dev->evbit[0] = BIT(EV_SND);
+ input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ input_dev->event = ixp4xx_spkr_event;
+
+ err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
+ SA_INTERRUPT | SA_TIMER, "ixp4xx-beeper", (void *) dev->id);
+ if (err)
+ goto err_free_device;
+
+ err = input_register_device(input_dev);
+ if (err)
+ goto err_free_irq;
+
+ platform_set_drvdata(dev, input_dev);
+
+ return 0;
+
+ err_free_irq:
+ free_irq(IRQ_IXP4XX_TIMER2, dev);
+ err_free_device:
+ input_free_device(input_dev);
+
+ return err;
+}
+
+static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
+{
+ struct input_dev *input_dev = platform_get_drvdata(dev);
+ unsigned int pin = (unsigned int) input_dev->private;
+
+ input_unregister_device(input_dev);
+ platform_set_drvdata(dev, NULL);
+
+ /* turn the speaker off */
+ disable_irq(IRQ_IXP4XX_TIMER2);
+ ixp4xx_spkr_control(pin, 0);
+
+ free_irq(IRQ_IXP4XX_TIMER2, dev);
+
+ return 0;
+}
+
+static void ixp4xx_spkr_shutdown(struct platform_device *dev)
+{
+ struct input_dev *input_dev = platform_get_drvdata(dev);
+ unsigned int pin = (unsigned int) input_dev->private;
+
+ /* turn off the speaker */
+ disable_irq(IRQ_IXP4XX_TIMER2);
+ ixp4xx_spkr_control(pin, 0);
+}
+
+static struct platform_driver ixp4xx_spkr_platform_driver = {
+ .driver = {
+ .name = "ixp4xx-beeper",
+ .owner = THIS_MODULE,
+ },
+ .probe = ixp4xx_spkr_probe,
+ .remove = __devexit_p(ixp4xx_spkr_remove),
+ .shutdown = ixp4xx_spkr_shutdown,
+};
+
+static int __init ixp4xx_spkr_init(void)
+{
+ return platform_driver_register(&ixp4xx_spkr_platform_driver);
+}
+
+static void __exit ixp4xx_spkr_exit(void)
+{
+ platform_driver_unregister(&ixp4xx_spkr_platform_driver);
+}
+
+module_init(ixp4xx_spkr_init);
+module_exit(ixp4xx_spkr_exit);
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index c88520d3d13..40333d61093 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -232,6 +232,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
+ { 99, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 100, PS2PP_KIND_MX, /* MX510 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 7665fd9ce55..19b1b012172 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -403,6 +403,7 @@ static int genius_detect(struct psmouse *psmouse, int set_properties)
set_bit(REL_WHEEL, psmouse->dev->relbit);
psmouse->vendor = "Genius";
+ psmouse->name = "Mouse";
psmouse->pktsize = 4;
}
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index b4898d8a68e..6d9ec9ab1b9 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -68,15 +68,19 @@ struct trackpoint_attr_data {
size_t field_offset;
unsigned char command;
unsigned char mask;
+ unsigned char inverted;
};
static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf)
{
struct trackpoint_data *tp = psmouse->private;
struct trackpoint_attr_data *attr = data;
- unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+ unsigned char value = *(unsigned char *)((char *)tp + attr->field_offset);
+
+ if (attr->inverted)
+ value = !value;
- return sprintf(buf, "%u\n", *field);
+ return sprintf(buf, "%u\n", value);
}
static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
@@ -120,6 +124,9 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
if (*rest || value > 1)
return -EINVAL;
+ if (attr->inverted)
+ value = !value;
+
if (*field != value) {
*field = value;
trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask);
@@ -129,11 +136,12 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
}
-#define TRACKPOINT_BIT_ATTR(_name, _command, _mask) \
+#define TRACKPOINT_BIT_ATTR(_name, _command, _mask, _inv) \
static struct trackpoint_attr_data trackpoint_attr_##_name = { \
.field_offset = offsetof(struct trackpoint_data, _name), \
.command = _command, \
.mask = _mask, \
+ .inverted = _inv, \
}; \
PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
&trackpoint_attr_##_name, \
@@ -150,9 +158,9 @@ TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH);
TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME);
TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV);
-TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON);
-TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
-TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, 0);
+TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK, 0);
+TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV, 1);
static struct attribute *trackpoint_attrs[] = {
&psmouse_attr_sensitivity.dattr.attr,
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index 9857d8b6ad6..050298b1a09 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -78,7 +78,7 @@
#define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */
#define TP_MASK_MB 0x01
-#define TP_TOGGLE_EXT_DEV 0x23 /* Toggle external device */
+#define TP_TOGGLE_EXT_DEV 0x23 /* Disable external device */
#define TP_MASK_EXT_DEV 0x02
#define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */
#define TP_MASK_DRIFT 0x80
@@ -125,7 +125,7 @@
#define TP_DEF_MB 0x00
#define TP_DEF_PTSON 0x00
#define TP_DEF_SKIPBACK 0x00
-#define TP_DEF_EXT_DEV 0x01
+#define TP_DEF_EXT_DEV 0x00 /* 0 means enabled */
#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd))
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 81fd7a97a93..9abed18d2ec 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -356,7 +356,7 @@ static void mousedev_free(struct mousedev *mousedev)
kfree(mousedev);
}
-static int mixdev_release(void)
+static void mixdev_release(void)
{
struct input_handle *handle;
@@ -370,8 +370,6 @@ static int mixdev_release(void)
mousedev_free(mousedev);
}
}
-
- return 0;
}
static int mousedev_release(struct inode * inode, struct file * file)
@@ -384,9 +382,8 @@ static int mousedev_release(struct inode * inode, struct file * file)
if (!--list->mousedev->open) {
if (list->mousedev->minor == MOUSEDEV_MIX)
- return mixdev_release();
-
- if (!mousedev_mix.open) {
+ mixdev_release();
+ else if (!mousedev_mix.open) {
if (list->mousedev->exist)
input_close_device(&list->mousedev->handle);
else
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 678a8599f9f..4155197867a 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o
obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
-obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
obj-$(CONFIG_HP_SDC) += hp_sdc.o
obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 2c674023a6a..b1b14f8d4dd 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -98,7 +98,7 @@ config TOUCHSCREEN_MK712
config TOUCHSCREEN_HP600
tristate "HP Jornada 680/690 touchscreen"
- depends on SH_HP600 && SH_ADC
+ depends on SH_HP6XX && SH_ADC
help
Say Y here if you have a HP Jornada 680 or 690 and want to
support the built-in touchscreen.
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index dd8c6a9ffc7..8c12a974b41 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -29,9 +29,6 @@
#ifdef CONFIG_ARCH_OMAP
#include <asm/arch/gpio.h>
#endif
-
-#else
-#define set_irq_type(irq,type) do{}while(0)
#endif
@@ -51,10 +48,13 @@
#define TS_POLL_PERIOD msecs_to_jiffies(10)
+/* this driver doesn't aim at the peak continuous sample rate */
+#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
+
struct ts_event {
/* For portability, we can't read 12 bit values using SPI (which
* would make the controller deliver them as native byteorder u16
- * with msbs zeroed). Instead, we read them as two 8-byte values,
+ * with msbs zeroed). Instead, we read them as two 8-bit values,
* which need byteswapping then range adjustment.
*/
__be16 x;
@@ -63,7 +63,7 @@ struct ts_event {
};
struct ads7846 {
- struct input_dev input;
+ struct input_dev *input;
char phys[32];
struct spi_device *spi;
@@ -71,6 +71,7 @@ struct ads7846 {
u16 vref_delay_usecs;
u16 x_plate_ohms;
+ u8 read_x, read_y, read_z1, read_z2;
struct ts_event tc;
struct spi_transfer xfer[8];
@@ -120,10 +121,10 @@ struct ads7846 {
#define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \
| ADS_12_BIT | ADS_DFR)
-static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON;
-static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON;
-static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON;
-static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */
+#define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON)
+#define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON)
+#define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON)
+#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_PDOWN) /* LAST */
/* single-ended samples need to first power up reference voltage;
* we leave both ADC and VREF powered
@@ -131,8 +132,8 @@ static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */
#define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
| ADS_12_BIT | ADS_SER)
-static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON;
-static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN;
+#define REF_ON (READ_12BIT_DFR(x) | ADS_PD10_ALL_ON)
+#define REF_OFF (READ_12BIT_DFR(y) | ADS_PD10_PDOWN)
/*--------------------------------------------------------------------------*/
@@ -141,7 +142,9 @@ static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN;
*/
struct ser_req {
+ u8 ref_on;
u8 command;
+ u8 ref_off;
u16 scratch;
__be16 sample;
struct spi_message msg;
@@ -155,7 +158,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL);
int status;
int sample;
- int i;
+ int i;
if (!req)
return -ENOMEM;
@@ -163,7 +166,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
INIT_LIST_HEAD(&req->msg.transfers);
/* activate reference, so it has time to settle; */
- req->xfer[0].tx_buf = &ref_on;
+ req->ref_on = REF_ON;
+ req->xfer[0].tx_buf = &req->ref_on;
req->xfer[0].len = 1;
req->xfer[1].rx_buf = &req->scratch;
req->xfer[1].len = 2;
@@ -185,7 +189,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
/* REVISIT: take a few more samples, and compare ... */
/* turn off reference */
- req->xfer[4].tx_buf = &ref_off;
+ req->ref_off = REF_OFF;
+ req->xfer[4].tx_buf = &req->ref_off;
req->xfer[4].len = 1;
req->xfer[5].rx_buf = &req->scratch;
req->xfer[5].len = 2;
@@ -239,11 +244,12 @@ SHOW(vbatt)
static void ads7846_rx(void *ads)
{
- struct ads7846 *ts = ads;
- unsigned Rt;
- unsigned sync = 0;
- u16 x, y, z1, z2;
- unsigned long flags;
+ struct ads7846 *ts = ads;
+ struct input_dev *input_dev = ts->input;
+ unsigned Rt;
+ unsigned sync = 0;
+ u16 x, y, z1, z2;
+ unsigned long flags;
/* adjust: 12 bit samples (left aligned), built from
* two 8 bit values writen msb-first.
@@ -279,21 +285,21 @@ static void ads7846_rx(void *ads)
* won't notice that, even if nPENIRQ never fires ...
*/
if (!ts->pendown && Rt != 0) {
- input_report_key(&ts->input, BTN_TOUCH, 1);
+ input_report_key(input_dev, BTN_TOUCH, 1);
sync = 1;
} else if (ts->pendown && Rt == 0) {
- input_report_key(&ts->input, BTN_TOUCH, 0);
+ input_report_key(input_dev, BTN_TOUCH, 0);
sync = 1;
}
if (Rt) {
- input_report_abs(&ts->input, ABS_X, x);
- input_report_abs(&ts->input, ABS_Y, y);
- input_report_abs(&ts->input, ABS_PRESSURE, Rt);
+ input_report_abs(input_dev, ABS_X, x);
+ input_report_abs(input_dev, ABS_Y, y);
+ input_report_abs(input_dev, ABS_PRESSURE, Rt);
sync = 1;
}
if (sync)
- input_sync(&ts->input);
+ input_sync(input_dev);
#ifdef VERBOSE
if (Rt || ts->pendown)
@@ -399,9 +405,10 @@ static int ads7846_resume(struct spi_device *spi)
static int __devinit ads7846_probe(struct spi_device *spi)
{
struct ads7846 *ts;
+ struct input_dev *input_dev;
struct ads7846_platform_data *pdata = spi->dev.platform_data;
struct spi_transfer *x;
- int i;
+ int err;
if (!spi->irq) {
dev_dbg(&spi->dev, "no IRQ?\n");
@@ -414,9 +421,9 @@ static int __devinit ads7846_probe(struct spi_device *spi)
}
/* don't exceed max specified sample rate */
- if (spi->max_speed_hz > (125000 * 16)) {
+ if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
- (spi->max_speed_hz/16)/1000);
+ (spi->max_speed_hz/SAMPLE_BITS)/1000);
return -EINVAL;
}
@@ -426,13 +433,18 @@ static int __devinit ads7846_probe(struct spi_device *spi)
* to discard the four garbage LSBs.
*/
- if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL)))
- return -ENOMEM;
+ ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ts || !input_dev) {
+ err = -ENOMEM;
+ goto err_free_mem;
+ }
dev_set_drvdata(&spi->dev, ts);
+ spi->dev.power.power_state = PMSG_ON;
ts->spi = spi;
- spi->dev.power.power_state = PMSG_ON;
+ ts->input = input_dev;
init_timer(&ts->timer);
ts->timer.data = (unsigned long) ts;
@@ -442,81 +454,90 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
- init_input_dev(&ts->input);
+ snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
- ts->input.dev = &spi->dev;
- ts->input.name = "ADS784x Touchscreen";
- snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id);
- ts->input.phys = ts->phys;
+ input_dev->name = "ADS784x Touchscreen";
+ input_dev->phys = ts->phys;
+ input_dev->cdev.dev = &spi->dev;
- ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_set_abs_params(&ts->input, ABS_X,
+ 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,
pdata->x_min ? : 0,
pdata->x_max ? : MAX_12BIT,
0, 0);
- input_set_abs_params(&ts->input, ABS_Y,
+ input_set_abs_params(input_dev, ABS_Y,
pdata->y_min ? : 0,
pdata->y_max ? : MAX_12BIT,
0, 0);
- input_set_abs_params(&ts->input, ABS_PRESSURE,
+ input_set_abs_params(input_dev, ABS_PRESSURE,
pdata->pressure_min, pdata->pressure_max, 0, 0);
- input_register_device(&ts->input);
-
/* set up the transfers to read touchscreen state; this assumes we
* use formula #2 for pressure, not #3.
*/
+ INIT_LIST_HEAD(&ts->msg.transfers);
x = ts->xfer;
/* y- still on; turn on only y+ (and ADC) */
- x->tx_buf = &read_y;
+ ts->read_y = READ_Y;
+ x->tx_buf = &ts->read_y;
x->len = 1;
+ spi_message_add_tail(x, &ts->msg);
+
x++;
x->rx_buf = &ts->tc.y;
x->len = 2;
- x++;
+ spi_message_add_tail(x, &ts->msg);
/* turn y+ off, x- on; we'll use formula #2 */
if (ts->model == 7846) {
- x->tx_buf = &read_z1;
+ x++;
+ ts->read_z1 = READ_Z1;
+ x->tx_buf = &ts->read_z1;
x->len = 1;
+ spi_message_add_tail(x, &ts->msg);
+
x++;
x->rx_buf = &ts->tc.z1;
x->len = 2;
- x++;
+ spi_message_add_tail(x, &ts->msg);
- x->tx_buf = &read_z2;
+ x++;
+ ts->read_z2 = READ_Z2;
+ x->tx_buf = &ts->read_z2;
x->len = 1;
+ spi_message_add_tail(x, &ts->msg);
+
x++;
x->rx_buf = &ts->tc.z2;
x->len = 2;
- x++;
+ spi_message_add_tail(x, &ts->msg);
}
/* turn y- off, x+ on, then leave in lowpower */
- x->tx_buf = &read_x;
+ x++;
+ ts->read_x = READ_X;
+ x->tx_buf = &ts->read_x;
x->len = 1;
+ spi_message_add_tail(x, &ts->msg);
+
x++;
x->rx_buf = &ts->tc.x;
x->len = 2;
- x++;
-
- CS_CHANGE(x[-1]);
+ CS_CHANGE(*x);
+ spi_message_add_tail(x, &ts->msg);
- for (i = 0; i < x - ts->xfer; i++)
- spi_message_add_tail(&ts->xfer[i], &ts->msg);
ts->msg.complete = ads7846_rx;
ts->msg.context = ts;
- if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM,
- spi->dev.bus_id, ts)) {
+ if (request_irq(spi->irq, ads7846_irq,
+ SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
+ spi->dev.bus_id, ts)) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
- input_unregister_device(&ts->input);
- kfree(ts);
- return -EBUSY;
+ err = -EBUSY;
+ goto err_free_mem;
}
- set_irq_type(spi->irq, IRQT_FALLING);
dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
@@ -537,7 +558,18 @@ static int __devinit ads7846_probe(struct spi_device *spi)
device_create_file(&spi->dev, &dev_attr_vbatt);
device_create_file(&spi->dev, &dev_attr_vaux);
+ err = input_register_device(input_dev);
+ if (err)
+ goto err_free_irq;
+
return 0;
+
+ err_free_irq:
+ free_irq(spi->irq, ts);
+ err_free_mem:
+ input_free_device(input_dev);
+ kfree(ts);
+ return err;
}
static int __devexit ads7846_remove(struct spi_device *spi)
@@ -557,7 +589,7 @@ static int __devexit ads7846_remove(struct spi_device *spi)
device_remove_file(&spi->dev, &dev_attr_vbatt);
device_remove_file(&spi->dev, &dev_attr_vaux);
- input_unregister_device(&ts->input);
+ input_unregister_device(ts->input);
kfree(ts);
dev_dbg(&spi->dev, "unregistered touchscreen\n");
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
index 4844d250a5e..3226830eea0 100644
--- a/drivers/input/touchscreen/mk712.c
+++ b/drivers/input/touchscreen/mk712.c
@@ -154,7 +154,7 @@ static void mk712_close(struct input_dev *dev)
spin_unlock_irqrestore(&mk712_lock, flags);
}
-int __init mk712_init(void)
+static int __init mk712_init(void)
{
int err;
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index 0ef560144be..6dfc94122dd 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -351,7 +351,7 @@ config HISAX_ENTERNOW_PCI
config HISAX_AMD7930
bool "Am7930 (EXPERIMENTAL)"
- depends on EXPERIMENTAL && SPARC
+ depends on EXPERIMENTAL && SPARC && BROKEN
help
This enables HiSax support for the AMD7930 chips on some SPARCs.
This code is not finished yet.
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 1b85ce166af..11fe537e2f6 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -216,7 +216,7 @@ struct Layer1 {
#define GROUP_TEI 127
#define TEI_SAPI 63
#define CTRL_SAPI 0
-#define PACKET_NOACK 250
+#define PACKET_NOACK 7
/* Layer2 Flags */
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index f190a99604f..393633681f4 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -2359,8 +2359,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
/* use queue instead of direct, if online and */
/* data is in queue or buffer is full */
- if ((info->online && tty_buffer_request_room(tty, l) < l) ||
- (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
+ if (info->online && ((tty_buffer_request_room(tty, l) < l) ||
+ !skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
skb = alloc_skb(l, GFP_ATOMIC);
if (!skb) {
spin_unlock_irqrestore(&info->readlock, flags);
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index 3314a5a1985..94c9afb7017 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -71,14 +71,14 @@ int sc_ioctl(int card, scs_ioctl *data)
/*
* Get the SRec from user space
*/
- if (copy_from_user(srec, data->dataptr, sizeof(srec))) {
+ if (copy_from_user(srec, data->dataptr, SCIOC_SRECSIZE)) {
kfree(rcvmsg);
kfree(srec);
return -EFAULT;
}
status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc,
- 0, sizeof(srec), srec, rcvmsg, SAR_TIMEOUT);
+ 0, SCIOC_SRECSIZE, srec, rcvmsg, SAR_TIMEOUT);
kfree(rcvmsg);
kfree(srec);
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 7d4a0ac28c0..12ad462737b 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -187,6 +187,14 @@ config WINDFARM_PM91
This driver provides thermal control for the PowerMac9,1
which is the recent (SMU based) single CPU desktop G5
+config WINDFARM_PM112
+ tristate "Support for thermal management on PowerMac11,2"
+ depends on WINDFARM && I2C && PMAC_SMU
+ select I2C_POWERMAC
+ help
+ This driver provides thermal control for the PowerMac11,2
+ which are the recent dual and quad G5 machines using the
+ 970MP dual-core processor.
config ANSLCD
tristate "Support for ANS LCD display"
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index f4657aa81fb..6081acdea40 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -35,3 +35,8 @@ obj-$(CONFIG_WINDFARM_PM91) += windfarm_smu_controls.o \
windfarm_smu_sensors.o \
windfarm_lm75_sensor.o windfarm_pid.o \
windfarm_cpufreq_clamp.o windfarm_pm91.o
+obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
+ windfarm_smu_controls.o \
+ windfarm_smu_sensors.o \
+ windfarm_max6690_sensor.o \
+ windfarm_lm75_sensor.o windfarm_pid.o
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index ed6d3174d66..69596f6438e 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -140,10 +140,9 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp,
{
struct macio_dev * macio_dev;
struct of_device * of;
- char *scratch, *compat;
+ char *scratch, *compat, *compat2;
int i = 0;
- int length = 0;
- int cplen, seen = 0;
+ int length, cplen, cplen2, seen = 0;
if (!dev)
return -ENODEV;
@@ -153,23 +152,22 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp,
return -ENODEV;
of = &macio_dev->ofdev;
- scratch = buffer;
/* stuff we want to pass to /sbin/hotplug */
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "OF_NAME=%s",
- of->node->name);
- if ((buffer_size - length <= 0) || (i >= num_envp))
- return -ENOMEM;
+ envp[i++] = scratch = buffer;
+ length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name);
++length;
+ buffer_size -= length;
+ if ((buffer_size <= 0) || (i >= num_envp))
+ return -ENOMEM;
scratch += length;
envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "OF_TYPE=%s",
- of->node->type);
- if ((buffer_size - length <= 0) || (i >= num_envp))
- return -ENOMEM;
+ length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type);
++length;
+ buffer_size -= length;
+ if ((buffer_size <= 0) || (i >= num_envp))
+ return -ENOMEM;
scratch += length;
/* Since the compatible field can contain pretty much anything
@@ -177,29 +175,55 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp,
* up using a number of environment variables instead. */
compat = (char *) get_property(of->node, "compatible", &cplen);
+ compat2 = compat;
+ cplen2= cplen;
while (compat && cplen > 0) {
- int l;
envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length,
+ length = scnprintf (scratch, buffer_size,
"OF_COMPATIBLE_%d=%s", seen, compat);
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ ++length;
+ buffer_size -= length;
+ if ((buffer_size <= 0) || (i >= num_envp))
return -ENOMEM;
- length++;
scratch += length;
- l = strlen (compat) + 1;
- compat += l;
- cplen -= l;
+ length = strlen (compat) + 1;
+ compat += length;
+ cplen -= length;
seen++;
}
envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length,
- "OF_COMPATIBLE_N=%d", seen);
- if ((buffer_size - length <= 0) || (i >= num_envp))
- return -ENOMEM;
+ length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen);
++length;
+ buffer_size -= length;
+ if ((buffer_size <= 0) || (i >= num_envp))
+ return -ENOMEM;
+ scratch += length;
+
+ envp[i++] = scratch;
+ length = scnprintf (scratch, buffer_size, "MODALIAS=of:N%sT%s",
+ of->node->name, of->node->type);
+ /* overwrite '\0' */
+ buffer_size -= length;
+ if ((buffer_size <= 0) || (i >= num_envp))
+ return -ENOMEM;
scratch += length;
+ if (!compat2) {
+ compat2 = "";
+ cplen2 = 1;
+ }
+ while (cplen2 > 0) {
+ length = snprintf (scratch, buffer_size, "C%s", compat2);
+ buffer_size -= length;
+ if (buffer_size <= 0)
+ return -ENOMEM;
+ scratch += length;
+ length = strlen (compat2) + 1;
+ compat2 += length;
+ cplen2 -= length;
+ }
+
envp[i] = NULL;
return 0;
diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h
index 3f0cb0312ea..7a2482cc26a 100644
--- a/drivers/macintosh/windfarm.h
+++ b/drivers/macintosh/windfarm.h
@@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/notifier.h>
+#include <linux/device.h>
/* Display a 16.16 fixed point value */
#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16)
@@ -39,6 +40,7 @@ struct wf_control {
char *name;
int type;
struct kref ref;
+ struct device_attribute attr;
};
#define WF_CONTROL_TYPE_GENERIC 0
@@ -87,6 +89,7 @@ struct wf_sensor {
struct wf_sensor_ops *ops;
char *name;
struct kref ref;
+ struct device_attribute attr;
};
/* Same lifetime rules as controls */
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 6c2a471ea6c..bb8d5efe19b 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -33,6 +33,7 @@
#include <linux/reboot.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/mutex.h>
#include "windfarm.h"
@@ -48,13 +49,17 @@
static LIST_HEAD(wf_controls);
static LIST_HEAD(wf_sensors);
-static DECLARE_MUTEX(wf_lock);
+static DEFINE_MUTEX(wf_lock);
static struct notifier_block *wf_client_list;
static int wf_client_count;
static unsigned int wf_overtemp;
static unsigned int wf_overtemp_counter;
struct task_struct *wf_thread;
+static struct platform_device wf_platform_device = {
+ .name = "windfarm",
+};
+
/*
* Utilities & tick thread
*/
@@ -156,26 +161,67 @@ static void wf_control_release(struct kref *kref)
kfree(ct);
}
+static ssize_t wf_show_control(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
+ s32 val = 0;
+ int err;
+
+ err = ctrl->ops->get_value(ctrl, &val);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%d\n", val);
+}
+
+/* This is really only for debugging... */
+static ssize_t wf_store_control(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
+ int val;
+ int err;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ while (endp < buf + count && (*endp == ' ' || *endp == '\n'))
+ ++endp;
+ if (endp - buf < count)
+ return -EINVAL;
+ err = ctrl->ops->set_value(ctrl, val);
+ if (err < 0)
+ return err;
+ return count;
+}
+
int wf_register_control(struct wf_control *new_ct)
{
struct wf_control *ct;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_for_each_entry(ct, &wf_controls, link) {
if (!strcmp(ct->name, new_ct->name)) {
printk(KERN_WARNING "windfarm: trying to register"
" duplicate control %s\n", ct->name);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return -EEXIST;
}
}
kref_init(&new_ct->ref);
list_add(&new_ct->link, &wf_controls);
+ new_ct->attr.attr.name = new_ct->name;
+ new_ct->attr.attr.owner = THIS_MODULE;
+ new_ct->attr.attr.mode = 0644;
+ new_ct->attr.show = wf_show_control;
+ new_ct->attr.store = wf_store_control;
+ device_create_file(&wf_platform_device.dev, &new_ct->attr);
+
DBG("wf: Registered control %s\n", new_ct->name);
wf_notify(WF_EVENT_NEW_CONTROL, new_ct);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return 0;
}
@@ -183,9 +229,9 @@ EXPORT_SYMBOL_GPL(wf_register_control);
void wf_unregister_control(struct wf_control *ct)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_del(&ct->link);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
DBG("wf: Unregistered control %s\n", ct->name);
@@ -197,16 +243,16 @@ struct wf_control * wf_find_control(const char *name)
{
struct wf_control *ct;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_for_each_entry(ct, &wf_controls, link) {
if (!strcmp(ct->name, name)) {
if (wf_get_control(ct))
ct = NULL;
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return ct;
}
}
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return NULL;
}
EXPORT_SYMBOL_GPL(wf_find_control);
@@ -246,26 +292,46 @@ static void wf_sensor_release(struct kref *kref)
kfree(sr);
}
+static ssize_t wf_show_sensor(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr);
+ s32 val = 0;
+ int err;
+
+ err = sens->ops->get_value(sens, &val);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val));
+}
+
int wf_register_sensor(struct wf_sensor *new_sr)
{
struct wf_sensor *sr;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_for_each_entry(sr, &wf_sensors, link) {
if (!strcmp(sr->name, new_sr->name)) {
printk(KERN_WARNING "windfarm: trying to register"
" duplicate sensor %s\n", sr->name);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return -EEXIST;
}
}
kref_init(&new_sr->ref);
list_add(&new_sr->link, &wf_sensors);
+ new_sr->attr.attr.name = new_sr->name;
+ new_sr->attr.attr.owner = THIS_MODULE;
+ new_sr->attr.attr.mode = 0444;
+ new_sr->attr.show = wf_show_sensor;
+ new_sr->attr.store = NULL;
+ device_create_file(&wf_platform_device.dev, &new_sr->attr);
+
DBG("wf: Registered sensor %s\n", new_sr->name);
wf_notify(WF_EVENT_NEW_SENSOR, new_sr);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return 0;
}
@@ -273,9 +339,9 @@ EXPORT_SYMBOL_GPL(wf_register_sensor);
void wf_unregister_sensor(struct wf_sensor *sr)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_del(&sr->link);
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
DBG("wf: Unregistered sensor %s\n", sr->name);
@@ -287,16 +353,16 @@ struct wf_sensor * wf_find_sensor(const char *name)
{
struct wf_sensor *sr;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
list_for_each_entry(sr, &wf_sensors, link) {
if (!strcmp(sr->name, name)) {
if (wf_get_sensor(sr))
sr = NULL;
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return sr;
}
}
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return NULL;
}
EXPORT_SYMBOL_GPL(wf_find_sensor);
@@ -329,7 +395,7 @@ int wf_register_client(struct notifier_block *nb)
struct wf_control *ct;
struct wf_sensor *sr;
- down(&wf_lock);
+ mutex_lock(&wf_lock);
rc = notifier_chain_register(&wf_client_list, nb);
if (rc != 0)
goto bail;
@@ -341,19 +407,19 @@ int wf_register_client(struct notifier_block *nb)
if (wf_client_count == 1)
wf_start_thread();
bail:
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return rc;
}
EXPORT_SYMBOL_GPL(wf_register_client);
int wf_unregister_client(struct notifier_block *nb)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
notifier_chain_unregister(&wf_client_list, nb);
wf_client_count++;
if (wf_client_count == 0)
wf_stop_thread();
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return 0;
}
@@ -361,23 +427,23 @@ EXPORT_SYMBOL_GPL(wf_unregister_client);
void wf_set_overtemp(void)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
wf_overtemp++;
if (wf_overtemp == 1) {
printk(KERN_WARNING "windfarm: Overtemp condition detected !\n");
wf_overtemp_counter = 0;
wf_notify(WF_EVENT_OVERTEMP, NULL);
}
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
}
EXPORT_SYMBOL_GPL(wf_set_overtemp);
void wf_clear_overtemp(void)
{
- down(&wf_lock);
+ mutex_lock(&wf_lock);
WARN_ON(wf_overtemp == 0);
if (wf_overtemp == 0) {
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
return;
}
wf_overtemp--;
@@ -385,7 +451,7 @@ void wf_clear_overtemp(void)
printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n");
wf_notify(WF_EVENT_NORMALTEMP, NULL);
}
- up(&wf_lock);
+ mutex_unlock(&wf_lock);
}
EXPORT_SYMBOL_GPL(wf_clear_overtemp);
@@ -395,10 +461,6 @@ int wf_is_overtemp(void)
}
EXPORT_SYMBOL_GPL(wf_is_overtemp);
-static struct platform_device wf_platform_device = {
- .name = "windfarm",
-};
-
static int __init windfarm_core_init(void)
{
DBG("wf: core loaded\n");
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
new file mode 100644
index 00000000000..5b9ad6ca7cb
--- /dev/null
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -0,0 +1,169 @@
+/*
+ * Windfarm PowerMac thermal control. MAX6690 sensor.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ *
+ * Use and redistribute under the terms of the GNU GPL v2.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/prom.h>
+#include <asm/pmac_low_i2c.h>
+
+#include "windfarm.h"
+
+#define VERSION "0.1"
+
+/* This currently only exports the external temperature sensor,
+ since that's all the control loops need. */
+
+/* Some MAX6690 register numbers */
+#define MAX6690_INTERNAL_TEMP 0
+#define MAX6690_EXTERNAL_TEMP 1
+
+struct wf_6690_sensor {
+ struct i2c_client i2c;
+ struct wf_sensor sens;
+};
+
+#define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens)
+#define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c)
+
+static int wf_max6690_attach(struct i2c_adapter *adapter);
+static int wf_max6690_detach(struct i2c_client *client);
+
+static struct i2c_driver wf_max6690_driver = {
+ .driver = {
+ .name = "wf_max6690",
+ },
+ .attach_adapter = wf_max6690_attach,
+ .detach_client = wf_max6690_detach,
+};
+
+static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
+{
+ struct wf_6690_sensor *max = wf_to_6690(sr);
+ s32 data;
+
+ if (max->i2c.adapter == NULL)
+ return -ENODEV;
+
+ /* chip gets initialized by firmware */
+ data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP);
+ if (data < 0)
+ return data;
+ *value = data << 16;
+ return 0;
+}
+
+static void wf_max6690_release(struct wf_sensor *sr)
+{
+ struct wf_6690_sensor *max = wf_to_6690(sr);
+
+ if (max->i2c.adapter) {
+ i2c_detach_client(&max->i2c);
+ max->i2c.adapter = NULL;
+ }
+ kfree(max);
+}
+
+static struct wf_sensor_ops wf_max6690_ops = {
+ .get_value = wf_max6690_get,
+ .release = wf_max6690_release,
+ .owner = THIS_MODULE,
+};
+
+static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
+{
+ struct wf_6690_sensor *max;
+ char *name = "u4-temp";
+
+ max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
+ if (max == NULL) {
+ printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
+ "no memory\n", name);
+ return;
+ }
+
+ max->sens.ops = &wf_max6690_ops;
+ max->sens.name = name;
+ max->i2c.addr = addr >> 1;
+ max->i2c.adapter = adapter;
+ max->i2c.driver = &wf_max6690_driver;
+ strncpy(max->i2c.name, name, I2C_NAME_SIZE-1);
+
+ if (i2c_attach_client(&max->i2c)) {
+ printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
+ goto fail;
+ }
+
+ if (wf_register_sensor(&max->sens)) {
+ i2c_detach_client(&max->i2c);
+ goto fail;
+ }
+
+ return;
+
+ fail:
+ kfree(max);
+}
+
+static int wf_max6690_attach(struct i2c_adapter *adapter)
+{
+ struct device_node *busnode, *dev = NULL;
+ struct pmac_i2c_bus *bus;
+ const char *loc;
+ u32 *reg;
+
+ bus = pmac_i2c_adapter_to_bus(adapter);
+ if (bus == NULL)
+ return -ENODEV;
+ busnode = pmac_i2c_get_bus_node(bus);
+
+ while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+ if (!device_is_compatible(dev, "max6690"))
+ continue;
+ loc = get_property(dev, "hwsensor-location", NULL);
+ reg = (u32 *) get_property(dev, "reg", NULL);
+ if (!loc || !reg)
+ continue;
+ printk("found max6690, loc=%s reg=%x\n", loc, *reg);
+ if (strcmp(loc, "BACKSIDE"))
+ continue;
+ wf_max6690_create(adapter, *reg);
+ }
+
+ return 0;
+}
+
+static int wf_max6690_detach(struct i2c_client *client)
+{
+ struct wf_6690_sensor *max = i2c_to_6690(client);
+
+ max->i2c.adapter = NULL;
+ wf_unregister_sensor(&max->sens);
+
+ return 0;
+}
+
+static int __init wf_max6690_sensor_init(void)
+{
+ return i2c_add_driver(&wf_max6690_driver);
+}
+
+static void __exit wf_max6690_sensor_exit(void)
+{
+ i2c_del_driver(&wf_max6690_driver);
+}
+
+module_init(wf_max6690_sensor_init);
+module_exit(wf_max6690_sensor_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_pid.c b/drivers/macintosh/windfarm_pid.c
index 2e803b36875..0842432e27a 100644
--- a/drivers/macintosh/windfarm_pid.c
+++ b/drivers/macintosh/windfarm_pid.c
@@ -88,8 +88,8 @@ EXPORT_SYMBOL_GPL(wf_cpu_pid_init);
s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
{
- s64 error, integ, deriv, prop;
- s32 target, sval, adj;
+ s64 integ, deriv, prop;
+ s32 error, target, sval, adj;
int i, hlen = st->param.history_len;
/* Calculate error term */
@@ -117,7 +117,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
integ += st->errors[(st->index + hlen - i) % hlen];
integ *= st->param.interval;
integ *= st->param.gr;
- sval = st->param.tmax - ((integ >> 20) & 0xffffffff);
+ sval = st->param.tmax - (s32)(integ >> 20);
adj = min(st->param.ttarget, sval);
DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj);
@@ -129,7 +129,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
deriv *= st->param.gd;
/* Calculate proportional term */
- prop = (new_temp - adj);
+ prop = st->last_delta = (new_temp - adj);
prop *= st->param.gp;
DBG("deriv: %lx, prop: %lx\n", deriv, prop);
diff --git a/drivers/macintosh/windfarm_pid.h b/drivers/macintosh/windfarm_pid.h
index a364c2a2499..bbccc22d42b 100644
--- a/drivers/macintosh/windfarm_pid.h
+++ b/drivers/macintosh/windfarm_pid.h
@@ -72,6 +72,7 @@ struct wf_cpu_pid_state {
int index; /* index of current power */
int tindex; /* index of current temp */
s32 target; /* current target value */
+ s32 last_delta; /* last Tactual - Ttarget */
s32 powers[WF_PID_MAX_HISTORY]; /* power history buffer */
s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */
s32 temps[2]; /* temp. history buffer */
diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
new file mode 100644
index 00000000000..c2a4e689c78
--- /dev/null
+++ b/drivers/macintosh/windfarm_pm112.c
@@ -0,0 +1,698 @@
+/*
+ * Windfarm PowerMac thermal control.
+ * Control loops for machines with SMU and PPC970MP processors.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Use and redistribute under the terms of the GNU GPL v2.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <asm/prom.h>
+#include <asm/smu.h>
+
+#include "windfarm.h"
+#include "windfarm_pid.h"
+
+#define VERSION "0.2"
+
+#define DEBUG
+#undef LOTSA_DEBUG
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while(0)
+#endif
+
+#ifdef LOTSA_DEBUG
+#define DBG_LOTS(args...) printk(args)
+#else
+#define DBG_LOTS(args...) do { } while(0)
+#endif
+
+/* define this to force CPU overtemp to 60 degree, useful for testing
+ * the overtemp code
+ */
+#undef HACKED_OVERTEMP
+
+/* We currently only handle 2 chips, 4 cores... */
+#define NR_CHIPS 2
+#define NR_CORES 4
+#define NR_CPU_FANS 3 * NR_CHIPS
+
+/* Controls and sensors */
+static struct wf_sensor *sens_cpu_temp[NR_CORES];
+static struct wf_sensor *sens_cpu_power[NR_CORES];
+static struct wf_sensor *hd_temp;
+static struct wf_sensor *slots_power;
+static struct wf_sensor *u4_temp;
+
+static struct wf_control *cpu_fans[NR_CPU_FANS];
+static char *cpu_fan_names[NR_CPU_FANS] = {
+ "cpu-rear-fan-0",
+ "cpu-rear-fan-1",
+ "cpu-front-fan-0",
+ "cpu-front-fan-1",
+ "cpu-pump-0",
+ "cpu-pump-1",
+};
+static struct wf_control *cpufreq_clamp;
+
+/* Second pump isn't required (and isn't actually present) */
+#define CPU_FANS_REQD (NR_CPU_FANS - 2)
+#define FIRST_PUMP 4
+#define LAST_PUMP 5
+
+/* We keep a temperature history for average calculation of 180s */
+#define CPU_TEMP_HIST_SIZE 180
+
+/* Scale factor for fan speed, *100 */
+static int cpu_fan_scale[NR_CPU_FANS] = {
+ 100,
+ 100,
+ 97, /* inlet fans run at 97% of exhaust fan */
+ 97,
+ 100, /* updated later */
+ 100, /* updated later */
+};
+
+static struct wf_control *backside_fan;
+static struct wf_control *slots_fan;
+static struct wf_control *drive_bay_fan;
+
+/* PID loop state */
+static struct wf_cpu_pid_state cpu_pid[NR_CORES];
+static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
+static int cpu_thist_pt;
+static s64 cpu_thist_total;
+static s32 cpu_all_tmax = 100 << 16;
+static int cpu_last_target;
+static struct wf_pid_state backside_pid;
+static int backside_tick;
+static struct wf_pid_state slots_pid;
+static int slots_started;
+static struct wf_pid_state drive_bay_pid;
+static int drive_bay_tick;
+
+static int nr_cores;
+static int have_all_controls;
+static int have_all_sensors;
+static int started;
+
+static int failure_state;
+#define FAILURE_SENSOR 1
+#define FAILURE_FAN 2
+#define FAILURE_PERM 4
+#define FAILURE_LOW_OVERTEMP 8
+#define FAILURE_HIGH_OVERTEMP 16
+
+/* Overtemp values */
+#define LOW_OVER_AVERAGE 0
+#define LOW_OVER_IMMEDIATE (10 << 16)
+#define LOW_OVER_CLEAR ((-10) << 16)
+#define HIGH_OVER_IMMEDIATE (14 << 16)
+#define HIGH_OVER_AVERAGE (10 << 16)
+#define HIGH_OVER_IMMEDIATE (14 << 16)
+
+
+/* Implementation... */
+static int create_cpu_loop(int cpu)
+{
+ int chip = cpu / 2;
+ int core = cpu & 1;
+ struct smu_sdbp_header *hdr;
+ struct smu_sdbp_cpupiddata *piddata;
+ struct wf_cpu_pid_param pid;
+ struct wf_control *main_fan = cpu_fans[0];
+ s32 tmax;
+ int fmin;
+
+ /* Get PID params from the appropriate SAT */
+ hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL);
+ if (hdr == NULL) {
+ printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n");
+ return -EINVAL;
+ }
+ piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
+
+ /* Get FVT params to get Tmax; if not found, assume default */
+ hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL);
+ if (hdr) {
+ struct smu_sdbp_fvt *fvt = (struct smu_sdbp_fvt *)&hdr[1];
+ tmax = fvt->maxtemp << 16;
+ } else
+ tmax = 95 << 16; /* default to 95 degrees C */
+
+ /* We keep a global tmax for overtemp calculations */
+ if (tmax < cpu_all_tmax)
+ cpu_all_tmax = tmax;
+
+ /*
+ * Darwin has a minimum fan speed of 1000 rpm for the 4-way and
+ * 515 for the 2-way. That appears to be overkill, so for now,
+ * impose a minimum of 750 or 515.
+ */
+ fmin = (nr_cores > 2) ? 750 : 515;
+
+ /* Initialize PID loop */
+ pid.interval = 1; /* seconds */
+ pid.history_len = piddata->history_len;
+ pid.gd = piddata->gd;
+ pid.gp = piddata->gp;
+ pid.gr = piddata->gr / piddata->history_len;
+ pid.pmaxadj = (piddata->max_power << 16) - (piddata->power_adj << 8);
+ pid.ttarget = tmax - (piddata->target_temp_delta << 16);
+ pid.tmax = tmax;
+ pid.min = main_fan->ops->get_min(main_fan);
+ pid.max = main_fan->ops->get_max(main_fan);
+ if (pid.min < fmin)
+ pid.min = fmin;
+
+ wf_cpu_pid_init(&cpu_pid[cpu], &pid);
+ return 0;
+}
+
+static void cpu_max_all_fans(void)
+{
+ int i;
+
+ /* We max all CPU fans in case of a sensor error. We also do the
+ * cpufreq clamping now, even if it's supposedly done later by the
+ * generic code anyway, we do it earlier here to react faster
+ */
+ if (cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ for (i = 0; i < NR_CPU_FANS; ++i)
+ if (cpu_fans[i])
+ wf_control_set_max(cpu_fans[i]);
+}
+
+static int cpu_check_overtemp(s32 temp)
+{
+ int new_state = 0;
+ s32 t_avg, t_old;
+
+ /* First check for immediate overtemps */
+ if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
+ new_state |= FAILURE_LOW_OVERTEMP;
+ if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
+ " temperature !\n");
+ }
+ if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
+ new_state |= FAILURE_HIGH_OVERTEMP;
+ if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Critical overtemp due to"
+ " immediate CPU temperature !\n");
+ }
+
+ /* We calculate a history of max temperatures and use that for the
+ * overtemp management
+ */
+ t_old = cpu_thist[cpu_thist_pt];
+ cpu_thist[cpu_thist_pt] = temp;
+ cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
+ cpu_thist_total -= t_old;
+ cpu_thist_total += temp;
+ t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
+
+ DBG_LOTS("t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
+ FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
+
+ /* Now check for average overtemps */
+ if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
+ new_state |= FAILURE_LOW_OVERTEMP;
+ if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Overtemp due to average CPU"
+ " temperature !\n");
+ }
+ if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
+ new_state |= FAILURE_HIGH_OVERTEMP;
+ if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
+ printk(KERN_ERR "windfarm: Critical overtemp due to"
+ " average CPU temperature !\n");
+ }
+
+ /* Now handle overtemp conditions. We don't currently use the windfarm
+ * overtemp handling core as it's not fully suited to the needs of those
+ * new machine. This will be fixed later.
+ */
+ if (new_state) {
+ /* High overtemp -> immediate shutdown */
+ if (new_state & FAILURE_HIGH_OVERTEMP)
+ machine_power_off();
+ if ((failure_state & new_state) != new_state)
+ cpu_max_all_fans();
+ failure_state |= new_state;
+ } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
+ (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
+ printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
+ failure_state &= ~FAILURE_LOW_OVERTEMP;
+ }
+
+ return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
+}
+
+static void cpu_fans_tick(void)
+{
+ int err, cpu;
+ s32 greatest_delta = 0;
+ s32 temp, power, t_max = 0;
+ int i, t, target = 0;
+ struct wf_sensor *sr;
+ struct wf_control *ct;
+ struct wf_cpu_pid_state *sp;
+
+ DBG_LOTS(KERN_DEBUG);
+ for (cpu = 0; cpu < nr_cores; ++cpu) {
+ /* Get CPU core temperature */
+ sr = sens_cpu_temp[cpu];
+ err = sr->ops->get_value(sr, &temp);
+ if (err) {
+ DBG("\n");
+ printk(KERN_WARNING "windfarm: CPU %d temperature "
+ "sensor error %d\n", cpu, err);
+ failure_state |= FAILURE_SENSOR;
+ cpu_max_all_fans();
+ return;
+ }
+
+ /* Keep track of highest temp */
+ t_max = max(t_max, temp);
+
+ /* Get CPU power */
+ sr = sens_cpu_power[cpu];
+ err = sr->ops->get_value(sr, &power);
+ if (err) {
+ DBG("\n");
+ printk(KERN_WARNING "windfarm: CPU %d power "
+ "sensor error %d\n", cpu, err);
+ failure_state |= FAILURE_SENSOR;
+ cpu_max_all_fans();
+ return;
+ }
+
+ /* Run PID */
+ sp = &cpu_pid[cpu];
+ t = wf_cpu_pid_run(sp, power, temp);
+
+ if (cpu == 0 || sp->last_delta > greatest_delta) {
+ greatest_delta = sp->last_delta;
+ target = t;
+ }
+ DBG_LOTS("[%d] P=%d.%.3d T=%d.%.3d ",
+ cpu, FIX32TOPRINT(power), FIX32TOPRINT(temp));
+ }
+ DBG_LOTS("fans = %d, t_max = %d.%03d\n", target, FIX32TOPRINT(t_max));
+
+ /* Darwin limits decrease to 20 per iteration */
+ if (target < (cpu_last_target - 20))
+ target = cpu_last_target - 20;
+ cpu_last_target = target;
+ for (cpu = 0; cpu < nr_cores; ++cpu)
+ cpu_pid[cpu].target = target;
+
+ /* Handle possible overtemps */
+ if (cpu_check_overtemp(t_max))
+ return;
+
+ /* Set fans */
+ for (i = 0; i < NR_CPU_FANS; ++i) {
+ ct = cpu_fans[i];
+ if (ct == NULL)
+ continue;
+ err = ct->ops->set_value(ct, target * cpu_fan_scale[i] / 100);
+ if (err) {
+ printk(KERN_WARNING "windfarm: fan %s reports "
+ "error %d\n", ct->name, err);
+ failure_state |= FAILURE_FAN;
+ break;
+ }
+ }
+}
+
+/* Backside/U4 fan */
+static struct wf_pid_param backside_param = {
+ .interval = 5,
+ .history_len = 2,
+ .gd = 48 << 20,
+ .gp = 5 << 20,
+ .gr = 0,
+ .itarget = 64 << 16,
+ .additive = 1,
+};
+
+static void backside_fan_tick(void)
+{
+ s32 temp;
+ int speed;
+ int err;
+
+ if (!backside_fan || !u4_temp)
+ return;
+ if (!backside_tick) {
+ /* first time; initialize things */
+ backside_param.min = backside_fan->ops->get_min(backside_fan);
+ backside_param.max = backside_fan->ops->get_max(backside_fan);
+ wf_pid_init(&backside_pid, &backside_param);
+ backside_tick = 1;
+ }
+ if (--backside_tick > 0)
+ return;
+ backside_tick = backside_pid.param.interval;
+
+ err = u4_temp->ops->get_value(u4_temp, &temp);
+ if (err) {
+ printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n",
+ err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(backside_fan);
+ return;
+ }
+ speed = wf_pid_run(&backside_pid, temp);
+ DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(temp), speed);
+
+ err = backside_fan->ops->set_value(backside_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+/* Drive bay fan */
+static struct wf_pid_param drive_bay_prm = {
+ .interval = 5,
+ .history_len = 2,
+ .gd = 30 << 20,
+ .gp = 5 << 20,
+ .gr = 0,
+ .itarget = 40 << 16,
+ .additive = 1,
+};
+
+static void drive_bay_fan_tick(void)
+{
+ s32 temp;
+ int speed;
+ int err;
+
+ if (!drive_bay_fan || !hd_temp)
+ return;
+ if (!drive_bay_tick) {
+ /* first time; initialize things */
+ drive_bay_prm.min = drive_bay_fan->ops->get_min(drive_bay_fan);
+ drive_bay_prm.max = drive_bay_fan->ops->get_max(drive_bay_fan);
+ wf_pid_init(&drive_bay_pid, &drive_bay_prm);
+ drive_bay_tick = 1;
+ }
+ if (--drive_bay_tick > 0)
+ return;
+ drive_bay_tick = drive_bay_pid.param.interval;
+
+ err = hd_temp->ops->get_value(hd_temp, &temp);
+ if (err) {
+ printk(KERN_WARNING "windfarm: drive bay temp sensor "
+ "error %d\n", err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(drive_bay_fan);
+ return;
+ }
+ speed = wf_pid_run(&drive_bay_pid, temp);
+ DBG_LOTS("drive_bay PID temp=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(temp), speed);
+
+ err = drive_bay_fan->ops->set_value(drive_bay_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+/* PCI slots area fan */
+/* This makes the fan speed proportional to the power consumed */
+static struct wf_pid_param slots_param = {
+ .interval = 1,
+ .history_len = 2,
+ .gd = 0,
+ .gp = 0,
+ .gr = 0x1277952,
+ .itarget = 0,
+ .min = 1560,
+ .max = 3510,
+};
+
+static void slots_fan_tick(void)
+{
+ s32 power;
+ int speed;
+ int err;
+
+ if (!slots_fan || !slots_power)
+ return;
+ if (!slots_started) {
+ /* first time; initialize things */
+ wf_pid_init(&slots_pid, &slots_param);
+ slots_started = 1;
+ }
+
+ err = slots_power->ops->get_value(slots_power, &power);
+ if (err) {
+ printk(KERN_WARNING "windfarm: slots power sensor error %d\n",
+ err);
+ failure_state |= FAILURE_SENSOR;
+ wf_control_set_max(slots_fan);
+ return;
+ }
+ speed = wf_pid_run(&slots_pid, power);
+ DBG_LOTS("slots PID power=%d.%.3d speed=%d\n",
+ FIX32TOPRINT(power), speed);
+
+ err = slots_fan->ops->set_value(slots_fan, speed);
+ if (err) {
+ printk(KERN_WARNING "windfarm: slots fan error %d\n", err);
+ failure_state |= FAILURE_FAN;
+ }
+}
+
+static void set_fail_state(void)
+{
+ int i;
+
+ if (cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ for (i = 0; i < NR_CPU_FANS; ++i)
+ if (cpu_fans[i])
+ wf_control_set_max(cpu_fans[i]);
+ if (backside_fan)
+ wf_control_set_max(backside_fan);
+ if (slots_fan)
+ wf_control_set_max(slots_fan);
+ if (drive_bay_fan)
+ wf_control_set_max(drive_bay_fan);
+}
+
+static void pm112_tick(void)
+{
+ int i, last_failure;
+
+ if (!started) {
+ started = 1;
+ for (i = 0; i < nr_cores; ++i) {
+ if (create_cpu_loop(i) < 0) {
+ failure_state = FAILURE_PERM;
+ set_fail_state();
+ break;
+ }
+ }
+ DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
+
+#ifdef HACKED_OVERTEMP
+ cpu_all_tmax = 60 << 16;
+#endif
+ }
+
+ /* Permanent failure, bail out */
+ if (failure_state & FAILURE_PERM)
+ return;
+ /* Clear all failure bits except low overtemp which will be eventually
+ * cleared by the control loop itself
+ */
+ last_failure = failure_state;
+ failure_state &= FAILURE_LOW_OVERTEMP;
+ cpu_fans_tick();
+ backside_fan_tick();
+ slots_fan_tick();
+ drive_bay_fan_tick();
+
+ DBG_LOTS("last_failure: 0x%x, failure_state: %x\n",
+ last_failure, failure_state);
+
+ /* Check for failures. Any failure causes cpufreq clamping */
+ if (failure_state && last_failure == 0 && cpufreq_clamp)
+ wf_control_set_max(cpufreq_clamp);
+ if (failure_state == 0 && last_failure && cpufreq_clamp)
+ wf_control_set_min(cpufreq_clamp);
+
+ /* That's it for now, we might want to deal with other failures
+ * differently in the future though
+ */
+}
+
+static void pm112_new_control(struct wf_control *ct)
+{
+ int i, max_exhaust;
+
+ if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
+ if (wf_get_control(ct) == 0)
+ cpufreq_clamp = ct;
+ }
+
+ for (i = 0; i < NR_CPU_FANS; ++i) {
+ if (!strcmp(ct->name, cpu_fan_names[i])) {
+ if (cpu_fans[i] == NULL && wf_get_control(ct) == 0)
+ cpu_fans[i] = ct;
+ break;
+ }
+ }
+ if (i >= NR_CPU_FANS) {
+ /* not a CPU fan, try the others */
+ if (!strcmp(ct->name, "backside-fan")) {
+ if (backside_fan == NULL && wf_get_control(ct) == 0)
+ backside_fan = ct;
+ } else if (!strcmp(ct->name, "slots-fan")) {
+ if (slots_fan == NULL && wf_get_control(ct) == 0)
+ slots_fan = ct;
+ } else if (!strcmp(ct->name, "drive-bay-fan")) {
+ if (drive_bay_fan == NULL && wf_get_control(ct) == 0)
+ drive_bay_fan = ct;
+ }
+ return;
+ }
+
+ for (i = 0; i < CPU_FANS_REQD; ++i)
+ if (cpu_fans[i] == NULL)
+ return;
+
+ /* work out pump scaling factors */
+ max_exhaust = cpu_fans[0]->ops->get_max(cpu_fans[0]);
+ for (i = FIRST_PUMP; i <= LAST_PUMP; ++i)
+ if ((ct = cpu_fans[i]) != NULL)
+ cpu_fan_scale[i] =
+ ct->ops->get_max(ct) * 100 / max_exhaust;
+
+ have_all_controls = 1;
+}
+
+static void pm112_new_sensor(struct wf_sensor *sr)
+{
+ unsigned int i;
+
+ if (have_all_sensors)
+ return;
+ if (!strncmp(sr->name, "cpu-temp-", 9)) {
+ i = sr->name[9] - '0';
+ if (sr->name[10] == 0 && i < NR_CORES &&
+ sens_cpu_temp[i] == NULL && wf_get_sensor(sr) == 0)
+ sens_cpu_temp[i] = sr;
+
+ } else if (!strncmp(sr->name, "cpu-power-", 10)) {
+ i = sr->name[10] - '0';
+ if (sr->name[11] == 0 && i < NR_CORES &&
+ sens_cpu_power[i] == NULL && wf_get_sensor(sr) == 0)
+ sens_cpu_power[i] = sr;
+ } else if (!strcmp(sr->name, "hd-temp")) {
+ if (hd_temp == NULL && wf_get_sensor(sr) == 0)
+ hd_temp = sr;
+ } else if (!strcmp(sr->name, "slots-power")) {
+ if (slots_power == NULL && wf_get_sensor(sr) == 0)
+ slots_power = sr;
+ } else if (!strcmp(sr->name, "u4-temp")) {
+ if (u4_temp == NULL && wf_get_sensor(sr) == 0)
+ u4_temp = sr;
+ } else
+ return;
+
+ /* check if we have all the sensors we need */
+ for (i = 0; i < nr_cores; ++i)
+ if (sens_cpu_temp[i] == NULL || sens_cpu_power[i] == NULL)
+ return;
+
+ have_all_sensors = 1;
+}
+
+static int pm112_wf_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ switch (event) {
+ case WF_EVENT_NEW_SENSOR:
+ pm112_new_sensor(data);
+ break;
+ case WF_EVENT_NEW_CONTROL:
+ pm112_new_control(data);
+ break;
+ case WF_EVENT_TICK:
+ if (have_all_controls && have_all_sensors)
+ pm112_tick();
+ }
+ return 0;
+}
+
+static struct notifier_block pm112_events = {
+ .notifier_call = pm112_wf_notify,
+};
+
+static int wf_pm112_probe(struct device *dev)
+{
+ wf_register_client(&pm112_events);
+ return 0;
+}
+
+static int wf_pm112_remove(struct device *dev)
+{
+ wf_unregister_client(&pm112_events);
+ /* should release all sensors and controls */
+ return 0;
+}
+
+static struct device_driver wf_pm112_driver = {
+ .name = "windfarm",
+ .bus = &platform_bus_type,
+ .probe = wf_pm112_probe,
+ .remove = wf_pm112_remove,
+};
+
+static int __init wf_pm112_init(void)
+{
+ struct device_node *cpu;
+
+ if (!machine_is_compatible("PowerMac11,2"))
+ return -ENODEV;
+
+ /* Count the number of CPU cores */
+ nr_cores = 0;
+ for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
+ ++nr_cores;
+
+ printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n");
+ driver_register(&wf_pm112_driver);
+ return 0;
+}
+
+static void __exit wf_pm112_exit(void)
+{
+ driver_unregister(&wf_pm112_driver);
+}
+
+module_init(wf_pm112_init);
+module_exit(wf_pm112_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index eb69a601e76..f1df6efcbe6 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -538,45 +538,6 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
}
}
-
-/*
- * ****** Attributes ******
- *
- */
-
-#define BUILD_SHOW_FUNC_FIX(name, data) \
-static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- ssize_t r; \
- s32 val = 0; \
- data->ops->get_value(data, &val); \
- r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \
- return r; \
-} \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-
-#define BUILD_SHOW_FUNC_INT(name, data) \
-static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- s32 val = 0; \
- data->ops->get_value(data, &val); \
- return sprintf(buf, "%d", val); \
-} \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main);
-BUILD_SHOW_FUNC_INT(sys_fan, fan_system);
-BUILD_SHOW_FUNC_INT(hd_fan, fan_hd);
-
-BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp);
-BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power);
-BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp);
-
/*
* ****** Setup / Init / Misc ... ******
*
@@ -654,17 +615,13 @@ static void wf_smu_new_control(struct wf_control *ct)
return;
if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_cpu_main = ct;
- device_create_file(wf_smu_dev, &dev_attr_cpu_fan);
- }
}
if (fan_system == NULL && !strcmp(ct->name, "system-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_system = ct;
- device_create_file(wf_smu_dev, &dev_attr_sys_fan);
- }
}
if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
@@ -683,10 +640,8 @@ static void wf_smu_new_control(struct wf_control *ct)
}
if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_hd = ct;
- device_create_file(wf_smu_dev, &dev_attr_hd_fan);
- }
}
if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp)
@@ -699,24 +654,18 @@ static void wf_smu_new_sensor(struct wf_sensor *sr)
return;
if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_cpu_power = sr;
- device_create_file(wf_smu_dev, &dev_attr_cpu_power);
- }
}
if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_cpu_temp = sr;
- device_create_file(wf_smu_dev, &dev_attr_cpu_temp);
- }
}
if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_hd_temp = sr;
- device_create_file(wf_smu_dev, &dev_attr_hd_temp);
- }
}
if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp)
@@ -794,32 +743,20 @@ static int wf_smu_remove(struct device *ddev)
* with that except by adding locks all over... I'll do that
* eventually but heh, who ever rmmod this module anyway ?
*/
- if (sensor_cpu_power) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_power);
+ if (sensor_cpu_power)
wf_put_sensor(sensor_cpu_power);
- }
- if (sensor_cpu_temp) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_temp);
+ if (sensor_cpu_temp)
wf_put_sensor(sensor_cpu_temp);
- }
- if (sensor_hd_temp) {
- device_remove_file(wf_smu_dev, &dev_attr_hd_temp);
+ if (sensor_hd_temp)
wf_put_sensor(sensor_hd_temp);
- }
/* Release all controls */
- if (fan_cpu_main) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_fan);
+ if (fan_cpu_main)
wf_put_control(fan_cpu_main);
- }
- if (fan_hd) {
- device_remove_file(wf_smu_dev, &dev_attr_hd_fan);
+ if (fan_hd)
wf_put_control(fan_hd);
- }
- if (fan_system) {
- device_remove_file(wf_smu_dev, &dev_attr_sys_fan);
+ if (fan_system)
wf_put_control(fan_system);
- }
if (cpufreq_clamp)
wf_put_control(cpufreq_clamp);
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
index 43243cf7410..0d6372e96d3 100644
--- a/drivers/macintosh/windfarm_pm91.c
+++ b/drivers/macintosh/windfarm_pm91.c
@@ -458,45 +458,6 @@ static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st)
/*
- * ****** Attributes ******
- *
- */
-
-#define BUILD_SHOW_FUNC_FIX(name, data) \
-static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- ssize_t r; \
- s32 val = 0; \
- data->ops->get_value(data, &val); \
- r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \
- return r; \
-} \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-
-#define BUILD_SHOW_FUNC_INT(name, data) \
-static ssize_t show_##name(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- s32 val = 0; \
- data->ops->get_value(data, &val); \
- return sprintf(buf, "%d", val); \
-} \
-static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL);
-
-BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main);
-BUILD_SHOW_FUNC_INT(hd_fan, fan_hd);
-BUILD_SHOW_FUNC_INT(slots_fan, fan_slots);
-
-BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp);
-BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power);
-BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp);
-BUILD_SHOW_FUNC_FIX(slots_power, sensor_slots_power);
-
-/*
* ****** Setup / Init / Misc ... ******
*
*/
@@ -581,10 +542,8 @@ static void wf_smu_new_control(struct wf_control *ct)
return;
if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-rear-fan-0")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_cpu_main = ct;
- device_create_file(wf_smu_dev, &dev_attr_cpu_fan);
- }
}
if (fan_cpu_second == NULL && !strcmp(ct->name, "cpu-rear-fan-1")) {
@@ -603,17 +562,13 @@ static void wf_smu_new_control(struct wf_control *ct)
}
if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_hd = ct;
- device_create_file(wf_smu_dev, &dev_attr_hd_fan);
- }
}
if (fan_slots == NULL && !strcmp(ct->name, "slots-fan")) {
- if (wf_get_control(ct) == 0) {
+ if (wf_get_control(ct) == 0)
fan_slots = ct;
- device_create_file(wf_smu_dev, &dev_attr_slots_fan);
- }
}
if (fan_cpu_main && (fan_cpu_second || fan_cpu_third) && fan_hd &&
@@ -627,31 +582,23 @@ static void wf_smu_new_sensor(struct wf_sensor *sr)
return;
if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_cpu_power = sr;
- device_create_file(wf_smu_dev, &dev_attr_cpu_power);
- }
}
if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_cpu_temp = sr;
- device_create_file(wf_smu_dev, &dev_attr_cpu_temp);
- }
}
if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_hd_temp = sr;
- device_create_file(wf_smu_dev, &dev_attr_hd_temp);
- }
}
if (sensor_slots_power == NULL && !strcmp(sr->name, "slots-power")) {
- if (wf_get_sensor(sr) == 0) {
+ if (wf_get_sensor(sr) == 0)
sensor_slots_power = sr;
- device_create_file(wf_smu_dev, &dev_attr_slots_power);
- }
}
if (sensor_cpu_power && sensor_cpu_temp &&
@@ -720,40 +667,26 @@ static int wf_smu_remove(struct device *ddev)
* with that except by adding locks all over... I'll do that
* eventually but heh, who ever rmmod this module anyway ?
*/
- if (sensor_cpu_power) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_power);
+ if (sensor_cpu_power)
wf_put_sensor(sensor_cpu_power);
- }
- if (sensor_cpu_temp) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_temp);
+ if (sensor_cpu_temp)
wf_put_sensor(sensor_cpu_temp);
- }
- if (sensor_hd_temp) {
- device_remove_file(wf_smu_dev, &dev_attr_hd_temp);
+ if (sensor_hd_temp)
wf_put_sensor(sensor_hd_temp);
- }
- if (sensor_slots_power) {
- device_remove_file(wf_smu_dev, &dev_attr_slots_power);
+ if (sensor_slots_power)
wf_put_sensor(sensor_slots_power);
- }
/* Release all controls */
- if (fan_cpu_main) {
- device_remove_file(wf_smu_dev, &dev_attr_cpu_fan);
+ if (fan_cpu_main)
wf_put_control(fan_cpu_main);
- }
if (fan_cpu_second)
wf_put_control(fan_cpu_second);
if (fan_cpu_third)
wf_put_control(fan_cpu_third);
- if (fan_hd) {
- device_remove_file(wf_smu_dev, &dev_attr_hd_fan);
+ if (fan_hd)
wf_put_control(fan_hd);
- }
- if (fan_slots) {
- device_remove_file(wf_smu_dev, &dev_attr_slots_fan);
+ if (fan_slots)
wf_put_control(fan_slots);
- }
if (cpufreq_clamp)
wf_put_control(cpufreq_clamp);
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 4d811600bda..a9e88edc0c7 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -24,7 +24,7 @@
#include "windfarm.h"
-#define VERSION "0.3"
+#define VERSION "0.4"
#undef DEBUG
@@ -34,6 +34,8 @@
#define DBG(args...) do { } while(0)
#endif
+static int smu_supports_new_fans_ops = 1;
+
/*
* SMU fans control object
*/
@@ -59,23 +61,49 @@ static int smu_set_fan(int pwm, u8 id, u16 value)
/* Fill SMU command structure */
cmd.cmd = SMU_CMD_FAN_COMMAND;
- cmd.data_len = 14;
+
+ /* The SMU has an "old" and a "new" way of setting the fan speed
+ * Unfortunately, I found no reliable way to know which one works
+ * on a given machine model. After some investigations it appears
+ * that MacOS X just tries the new one, and if it fails fallbacks
+ * to the old ones ... Ugh.
+ */
+ retry:
+ if (smu_supports_new_fans_ops) {
+ buffer[0] = 0x30;
+ buffer[1] = id;
+ *((u16 *)(&buffer[2])) = value;
+ cmd.data_len = 4;
+ } else {
+ if (id > 7)
+ return -EINVAL;
+ /* Fill argument buffer */
+ memset(buffer, 0, 16);
+ buffer[0] = pwm ? 0x10 : 0x00;
+ buffer[1] = 0x01 << id;
+ *((u16 *)&buffer[2 + id * 2]) = value;
+ cmd.data_len = 14;
+ }
+
cmd.reply_len = 16;
cmd.data_buf = cmd.reply_buf = buffer;
cmd.status = 0;
cmd.done = smu_done_complete;
cmd.misc = &comp;
- /* Fill argument buffer */
- memset(buffer, 0, 16);
- buffer[0] = pwm ? 0x10 : 0x00;
- buffer[1] = 0x01 << id;
- *((u16 *)&buffer[2 + id * 2]) = value;
-
rc = smu_queue_cmd(&cmd);
if (rc)
return rc;
wait_for_completion(&comp);
+
+ /* Handle fallback (see coment above) */
+ if (cmd.status != 0 && smu_supports_new_fans_ops) {
+ printk(KERN_WARNING "windfarm: SMU failed new fan command "
+ "falling back to old method\n");
+ smu_supports_new_fans_ops = 0;
+ goto retry;
+ }
+
return cmd.status;
}
@@ -158,19 +186,29 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
/* Names used on desktop models */
if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") ||
- !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan"))
+ !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan") ||
+ !strcmp(l, "CPU A EXHAUST"))
fct->ctrl.name = "cpu-rear-fan-0";
- else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1"))
+ else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1") ||
+ !strcmp(l, "CPU B EXHAUST"))
fct->ctrl.name = "cpu-rear-fan-1";
else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") ||
- !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan"))
+ !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan") ||
+ !strcmp(l, "CPU A INTAKE"))
fct->ctrl.name = "cpu-front-fan-0";
- else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1"))
+ else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1") ||
+ !strcmp(l, "CPU B INTAKE"))
fct->ctrl.name = "cpu-front-fan-1";
- else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan"))
+ else if (!strcmp(l, "CPU A PUMP"))
+ fct->ctrl.name = "cpu-pump-0";
+ else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") ||
+ !strcmp(l, "EXPANSION SLOTS INTAKE"))
fct->ctrl.name = "slots-fan";
- else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay"))
+ else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay") ||
+ !strcmp(l, "DRIVE BAY A INTAKE"))
fct->ctrl.name = "drive-bay-fan";
+ else if (!strcmp(l, "BACKSIDE"))
+ fct->ctrl.name = "backside-fan";
/* Names used on iMac models */
if (!strcmp(l, "System Fan") || !strcmp(l, "System fan"))
@@ -223,7 +261,8 @@ static int __init smu_controls_init(void)
/* Look for RPM fans */
for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;)
- if (!strcmp(fans->name, "rpm-fans"))
+ if (!strcmp(fans->name, "rpm-fans") ||
+ device_is_compatible(fans, "smu-rpm-fans"))
break;
for (fan = NULL;
fans && (fan = of_get_next_child(fans, fan)) != NULL;) {
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
new file mode 100644
index 00000000000..24e51d5e97f
--- /dev/null
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -0,0 +1,419 @@
+/*
+ * Windfarm PowerMac thermal control. SMU "satellite" controller sensors.
+ *
+ * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ *
+ * Released under the terms of the GNU GPL v2.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/semaphore.h>
+#include <asm/prom.h>
+#include <asm/smu.h>
+#include <asm/pmac_low_i2c.h>
+
+#include "windfarm.h"
+
+#define VERSION "0.2"
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...) do { } while(0)
+#endif
+
+/* If the cache is older than 800ms we'll refetch it */
+#define MAX_AGE msecs_to_jiffies(800)
+
+struct wf_sat {
+ int nr;
+ atomic_t refcnt;
+ struct semaphore mutex;
+ unsigned long last_read; /* jiffies when cache last updated */
+ u8 cache[16];
+ struct i2c_client i2c;
+ struct device_node *node;
+};
+
+static struct wf_sat *sats[2];
+
+struct wf_sat_sensor {
+ int index;
+ int index2; /* used for power sensors */
+ int shift;
+ struct wf_sat *sat;
+ struct wf_sensor sens;
+};
+
+#define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens)
+#define i2c_to_sat(c) container_of(c, struct wf_sat, i2c)
+
+static int wf_sat_attach(struct i2c_adapter *adapter);
+static int wf_sat_detach(struct i2c_client *client);
+
+static struct i2c_driver wf_sat_driver = {
+ .driver = {
+ .name = "wf_smu_sat",
+ },
+ .attach_adapter = wf_sat_attach,
+ .detach_client = wf_sat_detach,
+};
+
+/*
+ * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested
+ * length down to the low-level driver, so we use this, which
+ * works well enough with the SMU i2c driver code...
+ */
+static int sat_read_block(struct i2c_client *client, u8 command,
+ u8 *values, int len)
+{
+ union i2c_smbus_data data;
+ int err;
+
+ data.block[0] = len;
+ err = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA,
+ &data);
+ if (!err)
+ memcpy(values, data.block, len);
+ return err;
+}
+
+struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
+ unsigned int *size)
+{
+ struct wf_sat *sat;
+ int err;
+ unsigned int i, len;
+ u8 *buf;
+ u8 data[4];
+
+ /* TODO: Add the resulting partition to the device-tree */
+
+ if (sat_id > 1 || (sat = sats[sat_id]) == NULL)
+ return NULL;
+
+ err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8);
+ if (err) {
+ printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err);
+ return NULL;
+ }
+
+ len = i2c_smbus_read_word_data(&sat->i2c, 9);
+ if (len < 0) {
+ printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n");
+ return NULL;
+ }
+ if (len == 0) {
+ printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id);
+ return NULL;
+ }
+
+ len = le16_to_cpu(len);
+ len = (len + 3) & ~3;
+ buf = kmalloc(len, GFP_KERNEL);
+ if (buf == NULL)
+ return NULL;
+
+ for (i = 0; i < len; i += 4) {
+ err = sat_read_block(&sat->i2c, 0xa, data, 4);
+ if (err) {
+ printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
+ err);
+ goto fail;
+ }
+ buf[i] = data[1];
+ buf[i+1] = data[0];
+ buf[i+2] = data[3];
+ buf[i+3] = data[2];
+ }
+#ifdef DEBUG
+ DBG(KERN_DEBUG "sat %d partition %x:", sat_id, id);
+ for (i = 0; i < len; ++i)
+ DBG(" %x", buf[i]);
+ DBG("\n");
+#endif
+
+ if (size)
+ *size = len;
+ return (struct smu_sdbp_header *) buf;
+
+ fail:
+ kfree(buf);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(smu_sat_get_sdb_partition);
+
+/* refresh the cache */
+static int wf_sat_read_cache(struct wf_sat *sat)
+{
+ int err;
+
+ err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16);
+ if (err)
+ return err;
+ sat->last_read = jiffies;
+#ifdef LOTSA_DEBUG
+ {
+ int i;
+ DBG(KERN_DEBUG "wf_sat_get: data is");
+ for (i = 0; i < 16; ++i)
+ DBG(" %.2x", sat->cache[i]);
+ DBG("\n");
+ }
+#endif
+ return 0;
+}
+
+static int wf_sat_get(struct wf_sensor *sr, s32 *value)
+{
+ struct wf_sat_sensor *sens = wf_to_sat(sr);
+ struct wf_sat *sat = sens->sat;
+ int i, err;
+ s32 val;
+
+ if (sat->i2c.adapter == NULL)
+ return -ENODEV;
+
+ down(&sat->mutex);
+ if (time_after(jiffies, (sat->last_read + MAX_AGE))) {
+ err = wf_sat_read_cache(sat);
+ if (err)
+ goto fail;
+ }
+
+ i = sens->index * 2;
+ val = ((sat->cache[i] << 8) + sat->cache[i+1]) << sens->shift;
+ if (sens->index2 >= 0) {
+ i = sens->index2 * 2;
+ /* 4.12 * 8.8 -> 12.20; shift right 4 to get 16.16 */
+ val = (val * ((sat->cache[i] << 8) + sat->cache[i+1])) >> 4;
+ }
+
+ *value = val;
+ err = 0;
+
+ fail:
+ up(&sat->mutex);
+ return err;
+}
+
+static void wf_sat_release(struct wf_sensor *sr)
+{
+ struct wf_sat_sensor *sens = wf_to_sat(sr);
+ struct wf_sat *sat = sens->sat;
+
+ if (atomic_dec_and_test(&sat->refcnt)) {
+ if (sat->i2c.adapter) {
+ i2c_detach_client(&sat->i2c);
+ sat->i2c.adapter = NULL;
+ }
+ if (sat->nr >= 0)
+ sats[sat->nr] = NULL;
+ kfree(sat);
+ }
+ kfree(sens);
+}
+
+static struct wf_sensor_ops wf_sat_ops = {
+ .get_value = wf_sat_get,
+ .release = wf_sat_release,
+ .owner = THIS_MODULE,
+};
+
+static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
+{
+ struct wf_sat *sat;
+ struct wf_sat_sensor *sens;
+ u32 *reg;
+ char *loc, *type;
+ u8 addr, chip, core;
+ struct device_node *child;
+ int shift, cpu, index;
+ char *name;
+ int vsens[2], isens[2];
+
+ reg = (u32 *) get_property(dev, "reg", NULL);
+ if (reg == NULL)
+ return;
+ addr = *reg;
+ DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
+
+ sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL);
+ if (sat == NULL)
+ return;
+ sat->nr = -1;
+ sat->node = of_node_get(dev);
+ atomic_set(&sat->refcnt, 0);
+ init_MUTEX(&sat->mutex);
+ sat->i2c.addr = (addr >> 1) & 0x7f;
+ sat->i2c.adapter = adapter;
+ sat->i2c.driver = &wf_sat_driver;
+ strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1);
+
+ if (i2c_attach_client(&sat->i2c)) {
+ printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
+ goto fail;
+ }
+
+ vsens[0] = vsens[1] = -1;
+ isens[0] = isens[1] = -1;
+ child = NULL;
+ while ((child = of_get_next_child(dev, child)) != NULL) {
+ reg = (u32 *) get_property(child, "reg", NULL);
+ type = get_property(child, "device_type", NULL);
+ loc = get_property(child, "location", NULL);
+ if (reg == NULL || loc == NULL)
+ continue;
+
+ /* the cooked sensors are between 0x30 and 0x37 */
+ if (*reg < 0x30 || *reg > 0x37)
+ continue;
+ index = *reg - 0x30;
+
+ /* expect location to be CPU [AB][01] ... */
+ if (strncmp(loc, "CPU ", 4) != 0)
+ continue;
+ chip = loc[4] - 'A';
+ core = loc[5] - '0';
+ if (chip > 1 || core > 1) {
+ printk(KERN_ERR "wf_sat_create: don't understand "
+ "location %s for %s\n", loc, child->full_name);
+ continue;
+ }
+ cpu = 2 * chip + core;
+ if (sat->nr < 0)
+ sat->nr = chip;
+ else if (sat->nr != chip) {
+ printk(KERN_ERR "wf_sat_create: can't cope with "
+ "multiple CPU chips on one SAT (%s)\n", loc);
+ continue;
+ }
+
+ if (strcmp(type, "voltage-sensor") == 0) {
+ name = "cpu-voltage";
+ shift = 4;
+ vsens[core] = index;
+ } else if (strcmp(type, "current-sensor") == 0) {
+ name = "cpu-current";
+ shift = 8;
+ isens[core] = index;
+ } else if (strcmp(type, "temp-sensor") == 0) {
+ name = "cpu-temp";
+ shift = 10;
+ } else
+ continue; /* hmmm shouldn't happen */
+
+ /* the +16 is enough for "cpu-voltage-n" */
+ sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL);
+ if (sens == NULL) {
+ printk(KERN_ERR "wf_sat_create: couldn't create "
+ "%s sensor %d (no memory)\n", name, cpu);
+ continue;
+ }
+ sens->index = index;
+ sens->index2 = -1;
+ sens->shift = shift;
+ sens->sat = sat;
+ atomic_inc(&sat->refcnt);
+ sens->sens.ops = &wf_sat_ops;
+ sens->sens.name = (char *) (sens + 1);
+ snprintf(sens->sens.name, 16, "%s-%d", name, cpu);
+
+ if (wf_register_sensor(&sens->sens)) {
+ atomic_dec(&sat->refcnt);
+ kfree(sens);
+ }
+ }
+
+ /* make the power sensors */
+ for (core = 0; core < 2; ++core) {
+ if (vsens[core] < 0 || isens[core] < 0)
+ continue;
+ cpu = 2 * sat->nr + core;
+ sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL);
+ if (sens == NULL) {
+ printk(KERN_ERR "wf_sat_create: couldn't create power "
+ "sensor %d (no memory)\n", cpu);
+ continue;
+ }
+ sens->index = vsens[core];
+ sens->index2 = isens[core];
+ sens->shift = 0;
+ sens->sat = sat;
+ atomic_inc(&sat->refcnt);
+ sens->sens.ops = &wf_sat_ops;
+ sens->sens.name = (char *) (sens + 1);
+ snprintf(sens->sens.name, 16, "cpu-power-%d", cpu);
+
+ if (wf_register_sensor(&sens->sens)) {
+ atomic_dec(&sat->refcnt);
+ kfree(sens);
+ }
+ }
+
+ if (sat->nr >= 0)
+ sats[sat->nr] = sat;
+
+ return;
+
+ fail:
+ kfree(sat);
+}
+
+static int wf_sat_attach(struct i2c_adapter *adapter)
+{
+ struct device_node *busnode, *dev = NULL;
+ struct pmac_i2c_bus *bus;
+
+ bus = pmac_i2c_adapter_to_bus(adapter);
+ if (bus == NULL)
+ return -ENODEV;
+ busnode = pmac_i2c_get_bus_node(bus);
+
+ while ((dev = of_get_next_child(busnode, dev)) != NULL)
+ if (device_is_compatible(dev, "smu-sat"))
+ wf_sat_create(adapter, dev);
+ return 0;
+}
+
+static int wf_sat_detach(struct i2c_client *client)
+{
+ struct wf_sat *sat = i2c_to_sat(client);
+
+ /* XXX TODO */
+
+ sat->i2c.adapter = NULL;
+ return 0;
+}
+
+static int __init sat_sensors_init(void)
+{
+ int err;
+
+ err = i2c_add_driver(&wf_sat_driver);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static void __exit sat_sensors_exit(void)
+{
+ i2c_del_driver(&wf_sat_driver);
+}
+
+module_init(sat_sensors_init);
+/*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c
index 1a00d9c75a2..bed25dcf8a1 100644
--- a/drivers/macintosh/windfarm_smu_sensors.c
+++ b/drivers/macintosh/windfarm_smu_sensors.c
@@ -220,14 +220,29 @@ static struct smu_ad_sensor *smu_ads_create(struct device_node *node)
!strcmp(l, "CPU T-Diode")) {
ads->sens.ops = &smu_cputemp_ops;
ads->sens.name = "cpu-temp";
+ if (cpudiode == NULL) {
+ DBG("wf: cpudiode partition (%02x) not found\n",
+ SMU_SDB_CPUDIODE_ID);
+ goto fail;
+ }
} else if (!strcmp(c, "current-sensor") &&
!strcmp(l, "CPU Current")) {
ads->sens.ops = &smu_cpuamp_ops;
ads->sens.name = "cpu-current";
+ if (cpuvcp == NULL) {
+ DBG("wf: cpuvcp partition (%02x) not found\n",
+ SMU_SDB_CPUVCP_ID);
+ goto fail;
+ }
} else if (!strcmp(c, "voltage-sensor") &&
!strcmp(l, "CPU Voltage")) {
ads->sens.ops = &smu_cpuvolt_ops;
ads->sens.name = "cpu-voltage";
+ if (cpuvcp == NULL) {
+ DBG("wf: cpuvcp partition (%02x) not found\n",
+ SMU_SDB_CPUVCP_ID);
+ goto fail;
+ }
} else if (!strcmp(c, "power-sensor") &&
!strcmp(l, "Slots Power")) {
ads->sens.ops = &smu_slotspow_ops;
@@ -365,29 +380,22 @@ smu_cpu_power_create(struct wf_sensor *volts, struct wf_sensor *amps)
return NULL;
}
-static int smu_fetch_param_partitions(void)
+static void smu_fetch_param_partitions(void)
{
struct smu_sdbp_header *hdr;
/* Get CPU voltage/current/power calibration data */
hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL);
- if (hdr == NULL) {
- DBG("wf: cpuvcp partition (%02x) not found\n",
- SMU_SDB_CPUVCP_ID);
- return -ENODEV;
+ if (hdr != NULL) {
+ cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1];
+ /* Keep version around */
+ cpuvcp_version = hdr->version;
}
- cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1];
- /* Keep version around */
- cpuvcp_version = hdr->version;
/* Get CPU diode calibration data */
hdr = smu_get_sdb_partition(SMU_SDB_CPUDIODE_ID, NULL);
- if (hdr == NULL) {
- DBG("wf: cpudiode partition (%02x) not found\n",
- SMU_SDB_CPUDIODE_ID);
- return -ENODEV;
- }
- cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1];
+ if (hdr != NULL)
+ cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1];
/* Get slots power calibration data if any */
hdr = smu_get_sdb_partition(SMU_SDB_SLOTSPOW_ID, NULL);
@@ -398,23 +406,18 @@ static int smu_fetch_param_partitions(void)
hdr = smu_get_sdb_partition(SMU_SDB_DEBUG_SWITCHES_ID, NULL);
if (hdr != NULL)
debugswitches = (u8 *)&hdr[1];
-
- return 0;
}
static int __init smu_sensors_init(void)
{
struct device_node *smu, *sensors, *s;
struct smu_ad_sensor *volt_sensor = NULL, *curr_sensor = NULL;
- int rc;
if (!smu_present())
return -ENODEV;
/* Get parameters partitions */
- rc = smu_fetch_param_partitions();
- if (rc)
- return rc;
+ smu_fetch_param_partitions();
smu = of_find_node_by_type(NULL, "smu");
if (smu == NULL)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 1235135b384..442e2be6052 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1359,16 +1359,11 @@ static int ctl_ioctl(struct inode *inode, struct file *file,
* Copy the parameters into kernel space.
*/
r = copy_params(user, &param);
- if (r) {
- current->flags &= ~PF_MEMALLOC;
- return r;
- }
- /*
- * FIXME: eventually we will remove the PF_MEMALLOC flag
- * here. However the tools still do nasty things like
- * 'load' while a device is suspended.
- */
+ current->flags &= ~PF_MEMALLOC;
+
+ if (r)
+ return r;
r = validate_params(cmd, param);
if (r)
@@ -1386,7 +1381,6 @@ static int ctl_ioctl(struct inode *inode, struct file *file,
out:
free_params(param);
- current->flags &= ~PF_MEMALLOC;
return r;
}
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index efe4adf7853..d73779a4241 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -112,7 +112,7 @@ void dm_destroy_dirty_log(struct dirty_log *log)
/*
* The on-disk version of the metadata.
*/
-#define MIRROR_DISK_VERSION 1
+#define MIRROR_DISK_VERSION 2
#define LOG_OFFSET 2
struct log_header {
@@ -157,7 +157,6 @@ struct log_c {
struct log_header *disk_header;
struct io_region bits_location;
- uint32_t *disk_bits;
};
/*
@@ -166,20 +165,20 @@ struct log_c {
*/
static inline int log_test_bit(uint32_t *bs, unsigned bit)
{
- return test_bit(bit, (unsigned long *) bs) ? 1 : 0;
+ return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0;
}
static inline void log_set_bit(struct log_c *l,
uint32_t *bs, unsigned bit)
{
- set_bit(bit, (unsigned long *) bs);
+ ext2_set_bit(bit, (unsigned long *) bs);
l->touched = 1;
}
static inline void log_clear_bit(struct log_c *l,
uint32_t *bs, unsigned bit)
{
- clear_bit(bit, (unsigned long *) bs);
+ ext2_clear_bit(bit, (unsigned long *) bs);
l->touched = 1;
}
@@ -219,6 +218,11 @@ static int read_header(struct log_c *log)
log->header.nr_regions = 0;
}
+#ifdef __LITTLE_ENDIAN
+ if (log->header.version == 1)
+ log->header.version = 2;
+#endif
+
if (log->header.version != MIRROR_DISK_VERSION) {
DMWARN("incompatible disk log version");
return -EINVAL;
@@ -239,45 +243,24 @@ static inline int write_header(struct log_c *log)
/*----------------------------------------------------------------
* Bits IO
*--------------------------------------------------------------*/
-static inline void bits_to_core(uint32_t *core, uint32_t *disk, unsigned count)
-{
- unsigned i;
-
- for (i = 0; i < count; i++)
- core[i] = le32_to_cpu(disk[i]);
-}
-
-static inline void bits_to_disk(uint32_t *core, uint32_t *disk, unsigned count)
-{
- unsigned i;
-
- /* copy across the clean/dirty bitset */
- for (i = 0; i < count; i++)
- disk[i] = cpu_to_le32(core[i]);
-}
-
static int read_bits(struct log_c *log)
{
int r;
unsigned long ebits;
r = dm_io_sync_vm(1, &log->bits_location, READ,
- log->disk_bits, &ebits);
+ log->clean_bits, &ebits);
if (r)
return r;
- bits_to_core(log->clean_bits, log->disk_bits,
- log->bitset_uint32_count);
return 0;
}
static int write_bits(struct log_c *log)
{
unsigned long ebits;
- bits_to_disk(log->clean_bits, log->disk_bits,
- log->bitset_uint32_count);
return dm_io_sync_vm(1, &log->bits_location, WRITE,
- log->disk_bits, &ebits);
+ log->clean_bits, &ebits);
}
/*----------------------------------------------------------------
@@ -433,11 +416,6 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t),
1 << SECTOR_SHIFT);
lc->bits_location.count = size >> SECTOR_SHIFT;
- lc->disk_bits = vmalloc(size);
- if (!lc->disk_bits) {
- vfree(lc->disk_header);
- goto bad;
- }
return 0;
bad:
@@ -451,7 +429,6 @@ static void disk_dtr(struct dirty_log *log)
struct log_c *lc = (struct log_c *) log->context;
dm_put_device(lc->ti, lc->log_dev);
vfree(lc->disk_header);
- vfree(lc->disk_bits);
core_dtr(log);
}
@@ -568,7 +545,8 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
return 0;
do {
- *region = find_next_zero_bit((unsigned long *) lc->sync_bits,
+ *region = ext2_find_next_zero_bit(
+ (unsigned long *) lc->sync_bits,
lc->region_count,
lc->sync_search);
lc->sync_search = *region + 1;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 87727d84dbb..f3759dd7828 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -373,16 +373,11 @@ static inline ulong round_up(ulong n, ulong size)
static void read_snapshot_metadata(struct dm_snapshot *s)
{
- if (s->have_metadata)
- return;
-
if (s->store.read_metadata(&s->store)) {
down_write(&s->lock);
s->valid = 0;
up_write(&s->lock);
}
-
- s->have_metadata = 1;
}
/*
@@ -471,7 +466,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
s->chunk_shift = ffs(chunk_size) - 1;
s->valid = 1;
- s->have_metadata = 0;
+ s->active = 0;
s->last_percent = 0;
init_rwsem(&s->lock);
s->table = ti->table;
@@ -506,7 +501,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad5;
}
+ /* Metadata must only be loaded into one table at once */
+ read_snapshot_metadata(s);
+
/* Add snapshot to the list of snapshots for this origin */
+ /* Exceptions aren't triggered till snapshot_resume() is called */
if (register_snapshot(s)) {
r = -EINVAL;
ti->error = "Cannot register snapshot origin";
@@ -793,6 +792,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
if (!s->valid)
return -EIO;
+ if (unlikely(bio_barrier(bio)))
+ return -EOPNOTSUPP;
+
/*
* Write to snapshot - higher level takes care of RW/RO
* flags so we should only get this if we are
@@ -862,7 +864,9 @@ static void snapshot_resume(struct dm_target *ti)
{
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
- read_snapshot_metadata(s);
+ down_write(&s->lock);
+ s->active = 1;
+ up_write(&s->lock);
}
static int snapshot_status(struct dm_target *ti, status_type_t type,
@@ -932,8 +936,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
/* Do all the snapshots on this origin */
list_for_each_entry (snap, snapshots, list) {
- /* Only deal with valid snapshots */
- if (!snap->valid)
+ /* Only deal with valid and active snapshots */
+ if (!snap->valid || !snap->active)
continue;
/* Nothing to do if writing beyond end of snapshot */
@@ -1057,6 +1061,9 @@ static int origin_map(struct dm_target *ti, struct bio *bio,
struct dm_dev *dev = (struct dm_dev *) ti->private;
bio->bi_bdev = dev->bdev;
+ if (unlikely(bio_barrier(bio)))
+ return -EOPNOTSUPP;
+
/* Only tell snapshots if this is a write */
return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1;
}
@@ -1104,7 +1111,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result,
static struct target_type origin_target = {
.name = "snapshot-origin",
- .version = {1, 0, 1},
+ .version = {1, 1, 0},
.module = THIS_MODULE,
.ctr = origin_ctr,
.dtr = origin_dtr,
@@ -1115,7 +1122,7 @@ static struct target_type origin_target = {
static struct target_type snapshot_target = {
.name = "snapshot",
- .version = {1, 0, 1},
+ .version = {1, 1, 0},
.module = THIS_MODULE,
.ctr = snapshot_ctr,
.dtr = snapshot_dtr,
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 375aa24d4d7..fdec1e2dc87 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -99,7 +99,9 @@ struct dm_snapshot {
/* You can't use a snapshot if this is 0 (e.g. if full) */
int valid;
- int have_metadata;
+
+ /* Origin writes don't trigger exceptions until this is set */
+ int active;
/* Used for display of table */
char type;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a6f2dc66c3d..9b1e2f5ca63 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -508,7 +508,7 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
if (q->merge_bvec_fn)
rs->max_sectors =
min_not_zero(rs->max_sectors,
- (unsigned short)(PAGE_SIZE >> 9));
+ (unsigned int) (PAGE_SIZE >> 9));
rs->max_phys_segments =
min_not_zero(rs->max_phys_segments,
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 8c16359f8b0..e9adeb9d172 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -31,6 +31,7 @@ struct dm_io {
int error;
struct bio *bio;
atomic_t io_count;
+ unsigned long start_time;
};
/*
@@ -244,6 +245,36 @@ static inline void free_tio(struct mapped_device *md, struct target_io *tio)
mempool_free(tio, md->tio_pool);
}
+static void start_io_acct(struct dm_io *io)
+{
+ struct mapped_device *md = io->md;
+
+ io->start_time = jiffies;
+
+ preempt_disable();
+ disk_round_stats(dm_disk(md));
+ preempt_enable();
+ dm_disk(md)->in_flight = atomic_inc_return(&md->pending);
+}
+
+static int end_io_acct(struct dm_io *io)
+{
+ struct mapped_device *md = io->md;
+ struct bio *bio = io->bio;
+ unsigned long duration = jiffies - io->start_time;
+ int pending;
+ int rw = bio_data_dir(bio);
+
+ preempt_disable();
+ disk_round_stats(dm_disk(md));
+ preempt_enable();
+ dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending);
+
+ disk_stat_add(dm_disk(md), ticks[rw], duration);
+
+ return !pending;
+}
+
/*
* Add the bio to the list of deferred io.
*/
@@ -299,7 +330,7 @@ static void dec_pending(struct dm_io *io, int error)
io->error = error;
if (atomic_dec_and_test(&io->io_count)) {
- if (atomic_dec_and_test(&io->md->pending))
+ if (end_io_acct(io))
/* nudge anyone waiting on suspend queue */
wake_up(&io->md->wait);
@@ -554,7 +585,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio)
ci.sector_count = bio_sectors(bio);
ci.idx = bio->bi_idx;
- atomic_inc(&md->pending);
+ start_io_acct(ci.io);
while (ci.sector_count)
__clone_and_map(&ci);
@@ -573,10 +604,14 @@ static void __split_bio(struct mapped_device *md, struct bio *bio)
static int dm_request(request_queue_t *q, struct bio *bio)
{
int r;
+ int rw = bio_data_dir(bio);
struct mapped_device *md = q->queuedata;
down_read(&md->io_lock);
+ disk_stat_inc(dm_disk(md), ios[rw]);
+ disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio));
+
/*
* If we're suspended we have to queue
* this io for later.
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index ca99979c868..8b3515f394a 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -8,6 +8,7 @@
* completion notification.
*/
+#include <asm/types.h>
#include <asm/atomic.h>
#include <linux/blkdev.h>
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 1778104e106..d05e3125d29 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1024,7 +1024,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
rdev-> sb_size = (rdev->sb_size | bmask)+1;
if (refdev == 0)
- return 1;
+ ret = 1;
else {
__u64 ev1, ev2;
struct mdp_superblock_1 *refsb =
@@ -1044,7 +1044,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
ev2 = le64_to_cpu(refsb->events);
if (ev1 > ev2)
- return 1;
+ ret = 1;
+ else
+ ret = 0;
}
if (minor_version)
rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2;
@@ -1058,7 +1060,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
if (le32_to_cpu(sb->size) > rdev->size*2)
return -EINVAL;
- return 0;
+ return ret;
}
static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
@@ -1081,7 +1083,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->size = le64_to_cpu(sb->size)/2;
mddev->events = le64_to_cpu(sb->events);
mddev->bitmap_offset = 0;
- mddev->default_bitmap_offset = 1024;
+ mddev->default_bitmap_offset = 1024 >> 9;
mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
memcpy(mddev->uuid, sb->set_uuid, 16);
@@ -1161,6 +1163,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors);
+ sb->raid_disks = cpu_to_le32(mddev->raid_disks);
+ sb->size = cpu_to_le64(mddev->size<<1);
+
if (mddev->bitmap && mddev->bitmap_file == NULL) {
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
@@ -2686,14 +2691,6 @@ static int do_md_stop(mddev_t * mddev, int ro)
set_disk_ro(disk, 1);
}
- bitmap_destroy(mddev);
- if (mddev->bitmap_file) {
- atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
- fput(mddev->bitmap_file);
- mddev->bitmap_file = NULL;
- }
- mddev->bitmap_offset = 0;
-
/*
* Free resources if final stop
*/
@@ -2703,6 +2700,14 @@ static int do_md_stop(mddev_t * mddev, int ro)
struct gendisk *disk;
printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
+ bitmap_destroy(mddev);
+ if (mddev->bitmap_file) {
+ atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
+ fput(mddev->bitmap_file);
+ mddev->bitmap_file = NULL;
+ }
+ mddev->bitmap_offset = 0;
+
ITERATE_RDEV(mddev,rdev,tmp)
if (rdev->raid_disk >= 0) {
char nm[20];
@@ -2939,6 +2944,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
info.ctime = mddev->ctime;
info.level = mddev->level;
info.size = mddev->size;
+ if (info.size != mddev->size) /* overflow */
+ info.size = -1;
info.nr_disks = nr;
info.raid_disks = mddev->raid_disks;
info.md_minor = mddev->md_minor;
@@ -3395,6 +3402,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
mddev->ctime = get_seconds();
mddev->level = info->level;
+ mddev->clevel[0] = 0;
mddev->size = info->size;
mddev->raid_disks = info->raid_disks;
/* don't set md_minor, it is determined by which /dev/md* was
@@ -3464,7 +3472,7 @@ static int update_size(mddev_t *mddev, unsigned long size)
bdev = bdget_disk(mddev->gendisk, 0);
if (bdev) {
mutex_lock(&bdev->bd_inode->i_mutex);
- i_size_write(bdev->bd_inode, mddev->array_size << 10);
+ i_size_write(bdev->bd_inode, (loff_t)mddev->array_size << 10);
mutex_unlock(&bdev->bd_inode->i_mutex);
bdput(bdev);
}
@@ -3484,17 +3492,6 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks)
if (mddev->sync_thread)
return -EBUSY;
rv = mddev->pers->reshape(mddev, raid_disks);
- if (!rv) {
- struct block_device *bdev;
-
- bdev = bdget_disk(mddev->gendisk, 0);
- if (bdev) {
- mutex_lock(&bdev->bd_inode->i_mutex);
- i_size_write(bdev->bd_inode, mddev->array_size << 10);
- mutex_unlock(&bdev->bd_inode->i_mutex);
- bdput(bdev);
- }
- }
return rv;
}
@@ -3530,7 +3527,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
)
return -EINVAL;
/* Check there is only one change */
- if (mddev->size != info->size) cnt++;
+ if (info->size >= 0 && mddev->size != info->size) cnt++;
if (mddev->raid_disks != info->raid_disks) cnt++;
if (mddev->layout != info->layout) cnt++;
if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++;
@@ -3547,7 +3544,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
else
return mddev->pers->reconfig(mddev, info->layout, -1);
}
- if (mddev->size != info->size)
+ if (info->size >= 0 && mddev->size != info->size)
rv = update_size(mddev, info->size);
if (mddev->raid_disks != info->raid_disks)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index d03f99cf4b7..678f4dbbea1 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -372,7 +372,7 @@ out_free_conf:
kfree(conf);
mddev->private = NULL;
out:
- return 1;
+ return -ENOMEM;
}
static int raid0_stop (mddev_t *mddev)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9130d051b47..ab90a6d1202 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -565,6 +565,8 @@ rb_out:
if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL)
atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
+ else
+ disk = -1;
rcu_read_unlock();
return disk;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 25976bfb6f9..2dba305daf3 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -350,7 +350,8 @@ static void shrink_stripes(raid5_conf_t *conf)
while (drop_one_stripe(conf))
;
- kmem_cache_destroy(conf->slab_cache);
+ if (conf->slab_cache)
+ kmem_cache_destroy(conf->slab_cache);
conf->slab_cache = NULL;
}
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index f618a53b98b..cd477ebf2ee 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -115,7 +115,7 @@ static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
list_add_tail(&sh->lru, &conf->inactive_list);
atomic_dec(&conf->active_stripes);
if (!conf->inactive_blocked ||
- atomic_read(&conf->active_stripes) < (NR_STRIPES*3/4))
+ atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4))
wake_up(&conf->wait_for_stripe);
}
}
@@ -273,7 +273,8 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
conf->inactive_blocked = 1;
wait_event_lock_irq(conf->wait_for_stripe,
!list_empty(&conf->inactive_list) &&
- (atomic_read(&conf->active_stripes) < (NR_STRIPES *3/4)
+ (atomic_read(&conf->active_stripes)
+ < (conf->max_nr_stripes *3/4)
|| !conf->inactive_blocked),
conf->device_lock,
unplug_slaves(conf->mddev);
@@ -302,9 +303,31 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
return sh;
}
-static int grow_stripes(raid6_conf_t *conf, int num)
+static int grow_one_stripe(raid6_conf_t *conf)
{
struct stripe_head *sh;
+ sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
+ if (!sh)
+ return 0;
+ memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
+ sh->raid_conf = conf;
+ spin_lock_init(&sh->lock);
+
+ if (grow_buffers(sh, conf->raid_disks)) {
+ shrink_buffers(sh, conf->raid_disks);
+ kmem_cache_free(conf->slab_cache, sh);
+ return 0;
+ }
+ /* we just created an active stripe so... */
+ atomic_set(&sh->count, 1);
+ atomic_inc(&conf->active_stripes);
+ INIT_LIST_HEAD(&sh->lru);
+ release_stripe(sh);
+ return 1;
+}
+
+static int grow_stripes(raid6_conf_t *conf, int num)
+{
kmem_cache_t *sc;
int devs = conf->raid_disks;
@@ -316,45 +339,35 @@ static int grow_stripes(raid6_conf_t *conf, int num)
if (!sc)
return 1;
conf->slab_cache = sc;
- while (num--) {
- sh = kmem_cache_alloc(sc, GFP_KERNEL);
- if (!sh)
- return 1;
- memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev));
- sh->raid_conf = conf;
- spin_lock_init(&sh->lock);
-
- if (grow_buffers(sh, conf->raid_disks)) {
- shrink_buffers(sh, conf->raid_disks);
- kmem_cache_free(sc, sh);
+ while (num--)
+ if (!grow_one_stripe(conf))
return 1;
- }
- /* we just created an active stripe so... */
- atomic_set(&sh->count, 1);
- atomic_inc(&conf->active_stripes);
- INIT_LIST_HEAD(&sh->lru);
- release_stripe(sh);
- }
return 0;
}
-static void shrink_stripes(raid6_conf_t *conf)
+static int drop_one_stripe(raid6_conf_t *conf)
{
struct stripe_head *sh;
+ spin_lock_irq(&conf->device_lock);
+ sh = get_free_stripe(conf);
+ spin_unlock_irq(&conf->device_lock);
+ if (!sh)
+ return 0;
+ if (atomic_read(&sh->count))
+ BUG();
+ shrink_buffers(sh, conf->raid_disks);
+ kmem_cache_free(conf->slab_cache, sh);
+ atomic_dec(&conf->active_stripes);
+ return 1;
+}
- while (1) {
- spin_lock_irq(&conf->device_lock);
- sh = get_free_stripe(conf);
- spin_unlock_irq(&conf->device_lock);
- if (!sh)
- break;
- if (atomic_read(&sh->count))
- BUG();
- shrink_buffers(sh, conf->raid_disks);
- kmem_cache_free(conf->slab_cache, sh);
- atomic_dec(&conf->active_stripes);
- }
- kmem_cache_destroy(conf->slab_cache);
+static void shrink_stripes(raid6_conf_t *conf)
+{
+ while (drop_one_stripe(conf))
+ ;
+
+ if (conf->slab_cache)
+ kmem_cache_destroy(conf->slab_cache);
conf->slab_cache = NULL;
}
@@ -1912,6 +1925,74 @@ static void raid6d (mddev_t *mddev)
PRINTK("--- raid6d inactive\n");
}
+static ssize_t
+raid6_show_stripe_cache_size(mddev_t *mddev, char *page)
+{
+ raid6_conf_t *conf = mddev_to_conf(mddev);
+ if (conf)
+ return sprintf(page, "%d\n", conf->max_nr_stripes);
+ else
+ return 0;
+}
+
+static ssize_t
+raid6_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
+{
+ raid6_conf_t *conf = mddev_to_conf(mddev);
+ char *end;
+ int new;
+ if (len >= PAGE_SIZE)
+ return -EINVAL;
+ if (!conf)
+ return -ENODEV;
+
+ new = simple_strtoul(page, &end, 10);
+ if (!*page || (*end && *end != '\n') )
+ return -EINVAL;
+ if (new <= 16 || new > 32768)
+ return -EINVAL;
+ while (new < conf->max_nr_stripes) {
+ if (drop_one_stripe(conf))
+ conf->max_nr_stripes--;
+ else
+ break;
+ }
+ while (new > conf->max_nr_stripes) {
+ if (grow_one_stripe(conf))
+ conf->max_nr_stripes++;
+ else break;
+ }
+ return len;
+}
+
+static struct md_sysfs_entry
+raid6_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR,
+ raid6_show_stripe_cache_size,
+ raid6_store_stripe_cache_size);
+
+static ssize_t
+stripe_cache_active_show(mddev_t *mddev, char *page)
+{
+ raid6_conf_t *conf = mddev_to_conf(mddev);
+ if (conf)
+ return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
+ else
+ return 0;
+}
+
+static struct md_sysfs_entry
+raid6_stripecache_active = __ATTR_RO(stripe_cache_active);
+
+static struct attribute *raid6_attrs[] = {
+ &raid6_stripecache_size.attr,
+ &raid6_stripecache_active.attr,
+ NULL,
+};
+static struct attribute_group raid6_attrs_group = {
+ .name = NULL,
+ .attrs = raid6_attrs,
+};
+
static int run(mddev_t *mddev)
{
raid6_conf_t *conf;
@@ -2095,6 +2176,7 @@ static int stop (mddev_t *mddev)
shrink_stripes(conf);
kfree(conf->stripe_hashtbl);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
+ sysfs_remove_group(&mddev->kobj, &raid6_attrs_group);
kfree(conf);
mddev->private = NULL;
return 0;
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 2583a865a58..2963605c0ec 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -4,7 +4,7 @@ config DVB_B2C2_FLEXCOP
select DVB_STV0299
select DVB_MT352
select DVB_MT312
- select DVB_NXT2002
+ select DVB_NXT200X
select DVB_STV0297
select DVB_BCM3510
select DVB_LGDT330X
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 344a3c89846..7d7e1613c5a 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -116,11 +116,9 @@ void flexcop_dma_free(struct flexcop_dma *dma);
int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
-int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx);
int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff);
int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles);
-int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets);
/* from flexcop-eeprom.c */
/* the PCI part uses this call to get the MAC address, the USB part has its own */
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
index cf4ed1df608..6f592bc32d2 100644
--- a/drivers/media/dvb/b2c2/flexcop-dma.c
+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -169,38 +169,3 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
}
EXPORT_SYMBOL(flexcop_dma_config_timer);
-/* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */
-int flexcop_dma_control_packet_irq(struct flexcop_device *fc,
- flexcop_dma_index_t no,
- int onoff)
-{
- flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
-
- deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
- if (no & FC_DMA_1)
- v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
-
- if (no & FC_DMA_2)
- v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
-
- fc->write_ibi_reg(fc,ctrl_208,v);
- deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
-
- return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
-
-int flexcop_dma_config_packet_count(struct flexcop_device *fc,
- flexcop_dma_index_t dma_idx,
- u8 packets)
-{
- flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
- flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
-
- flexcop_dma_remap(fc,dma_idx,1);
-
- v.dma_0x4_remap.DMA_maxpackets = packets;
- fc->write_ibi_reg(fc,r,v);
- return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_config_packet_count);
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 0b940e152b7..390cc3a99ce 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -9,7 +9,7 @@
#include "stv0299.h"
#include "mt352.h"
-#include "nxt2002.h"
+#include "nxt200x.h"
#include "bcm3510.h"
#include "stv0297.h"
#include "mt312.h"
@@ -343,9 +343,10 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.clock_polarity_flip = 1,
};
-static struct nxt2002_config samsung_tbmv_config = {
+static struct nxt200x_config samsung_tbmv_config = {
.demod_address = 0x0a,
- .request_firmware = flexcop_fe_request_firmware,
+ .pll_address = 0xc2,
+ .pll_desc = &dvb_pll_samsung_tbmv,
};
static struct bcm3510_config air2pc_atsc_first_gen_config = {
@@ -505,7 +506,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
} else
/* try the air atsc 2nd generation (nxt2002) */
- if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+ if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC2;
info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
} else
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index 62282d8dbfa..167583bf062 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -36,14 +36,14 @@ void flexcop_determine_revision(struct flexcop_device *fc)
/* bus parts have to decide if hw pid filtering is used or not. */
}
-const char *flexcop_revision_names[] = {
+static const char *flexcop_revision_names[] = {
"Unkown chip",
"FlexCopII",
"FlexCopIIb",
"FlexCopIII",
};
-const char *flexcop_device_names[] = {
+static const char *flexcop_device_names[] = {
"Unkown device",
"Air2PC/AirStar 2 DVB-T",
"Air2PC/AirStar 2 ATSC 1st generation",
@@ -54,7 +54,7 @@ const char *flexcop_device_names[] = {
"Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
};
-const char *flexcop_bus_names[] = {
+static const char *flexcop_bus_names[] = {
"USB",
"PCI",
};
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
index 2f76eb3fea4..9bc40bdcc28 100644
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -161,8 +161,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs)
fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
- deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ",
- jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos);
+ deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ",
+ jiffies_to_usecs(jiffies - fc_pci->last_irq),
+ v.raw, (unsigned long long)cur_addr, cur_pos,
+ fc_pci->last_dma1_cur_pos);
fc_pci->last_irq = jiffies;
/* buffer end was reached, restarted from the beginning
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 3153f9513c6..491f9bd6e19 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -16,8 +16,6 @@ typedef enum {
FLEXCOP_III,
} flexcop_revision_t;
-extern const char *flexcop_revision_names[];
-
typedef enum {
FC_UNK = 0,
FC_AIR_DVB,
@@ -34,8 +32,6 @@ typedef enum {
FC_PCI,
} flexcop_bus_t;
-extern const char *flexcop_device_names[];
-
/* FlexCop IBI Registers */
#if defined(__LITTLE_ENDIAN)
#include "flexcop_ibi_value_le.h"
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index f2957145003..34c3189a1a3 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -381,6 +381,23 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *
EXPORT_SYMBOL(bt878_device_control);
+
+struct cards card_list[] __devinitdata = {
+
+ { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
+ { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
+ { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" },
+ { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" },
+ { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" },
+ { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
+ { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
+ { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
+ { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
+ { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"},
+ { 0, -1, NULL }
+};
+
+
/***********************/
/* PCI device handling */
/***********************/
@@ -388,18 +405,41 @@ EXPORT_SYMBOL(bt878_device_control);
static int __devinit bt878_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
- int result;
+ int result = 0, has_dvb = 0, i;
unsigned char lat;
struct bt878 *bt;
#if defined(__powerpc__)
unsigned int cmd;
#endif
+ unsigned int cardid;
+ unsigned short id;
+ struct cards *dvb_cards;
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
bt878_num);
if (pci_enable_device(dev))
return -EIO;
+ pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id);
+ cardid = id << 16;
+ pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id);
+ cardid |= id;
+
+ for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) {
+ if (cardid == dvb_cards->pci_id) {
+ printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n",
+ __func__, cardid, dvb_cards->name);
+ has_dvb = 1;
+ }
+ }
+
+ if (!has_dvb) {
+ printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid);
+ result = -EINVAL;
+
+ goto fail0;
+ }
+
bt = &bt878[bt878_num];
bt->dev = dev;
bt->nr = bt878_num;
@@ -416,6 +456,8 @@ static int __devinit bt878_probe(struct pci_dev *dev,
pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+
+
printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ",
bt878_num, bt->id, bt->revision, dev->bus->number,
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
@@ -542,7 +584,7 @@ static struct pci_driver bt878_pci_driver = {
.remove = bt878_remove,
};
-static int bt878_pci_driver_registered = 0;
+static int bt878_pci_driver_registered;
/*******************************/
/* Module management functions */
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index a73baf00ca3..9faf93770d0 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -88,6 +88,23 @@
#define BT878_RISC_SYNC_MASK (1 << 15)
+
+#define BTTV_BOARD_UNKNOWN 0x00
+#define BTTV_BOARD_PINNACLESAT 0x5e
+#define BTTV_BOARD_NEBULA_DIGITV 0x68
+#define BTTV_BOARD_PC_HDTV 0x70
+#define BTTV_BOARD_TWINHAN_DST 0x71
+#define BTTV_BOARD_AVDVBT_771 0x7b
+#define BTTV_BOARD_AVDVBT_761 0x7c
+#define BTTV_BOARD_DVICO_DVBT_LITE 0x80
+#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
+
+struct cards {
+ __u32 pci_id;
+ __u16 card_id;
+ char *name;
+};
+
extern int bt878_num;
struct bt878 {
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 44fcbe77c8f..ea27b15007e 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -893,7 +893,7 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub)
return 0;
}
-static int dvb_bt8xx_remove(struct bttv_sub_device *sub)
+static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
{
struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev);
@@ -911,8 +911,6 @@ static int dvb_bt8xx_remove(struct bttv_sub_device *sub)
dvb_unregister_adapter(&card->dvb_adapter);
kfree(card);
-
- return 0;
}
static struct bttv_sub_driver driver = {
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 06b696e9acb..54f8b95717b 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -33,7 +33,7 @@
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/cdev.h>
-
+#include <linux/mutex.h>
#include "dvbdev.h"
static int dvbdev_debug;
@@ -44,7 +44,7 @@ MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
#define dprintk if (dvbdev_debug) printk
static LIST_HEAD(dvb_adapter_list);
-static DECLARE_MUTEX(dvbdev_register_lock);
+static DEFINE_MUTEX(dvbdev_register_lock);
static const char * const dnames[] = {
"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
@@ -202,11 +202,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
struct dvb_device *dvbdev;
int id;
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
if ((id = dvbdev_get_free_id (adap, type)) < 0) {
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL;
printk ("%s: could get find free device id...\n", __FUNCTION__);
return -ENFILE;
@@ -215,11 +215,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
if (!dvbdev) {
- up(&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
memcpy(dvbdev, template, sizeof(struct dvb_device));
dvbdev->type = type;
@@ -289,11 +289,11 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
{
int num;
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
if ((num = dvbdev_get_free_adapter_num ()) < 0) {
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return -ENFILE;
}
@@ -309,7 +309,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
list_add_tail (&adap->list_head, &dvb_adapter_list);
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return num;
}
@@ -320,10 +320,10 @@ int dvb_unregister_adapter(struct dvb_adapter *adap)
{
devfs_remove("dvb/adapter%d", adap->num);
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
list_del (&adap->list_head);
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return 0;
}
EXPORT_SYMBOL(dvb_unregister_adapter);
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 90a69d343b7..d3df12039b0 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -83,12 +83,18 @@ config DVB_USB_UMT_010
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
config DVB_USB_CXUSB
- tristate "Medion MD95700 hybrid USB2.0 (Conexant) support"
+ tristate "Conexant USB2.0 hybrid reference design support"
depends on DVB_USB
select DVB_CX22702
+ select DVB_LGDT330X
+ select DVB_MT352
help
- Say Y here to support the Medion MD95700 hybrid USB2.0 device. Currently
- only the DVB-T part is supported.
+ Say Y here to support the Conexant USB2.0 hybrid reference design.
+ Currently, only DVB and ATSC modes are supported, analog mode
+ shall be added in the future. Devices that require this module:
+
+ Medion MD95700 hybrid USB2.0 device.
+ DViCO FusionHDTV (Bluebird) USB2.0 devices
config DVB_USB_DIGITV
tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 18d169836c9..f327fac1688 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -184,7 +184,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
-struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x02, KEY_TV },
{ 0xfe, 0x0e, KEY_MP3 },
{ 0xfe, 0x1a, KEY_DVD },
@@ -234,7 +234,7 @@ struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
{
- static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
static u8 reset [] = { RESET, 0x80 };
static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
@@ -255,7 +255,7 @@ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
{ /* used in both lgz201 and th7579 */
- static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x29 };
static u8 reset [] = { RESET, 0x80 };
static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 };
@@ -273,7 +273,7 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
return 0;
}
-struct cx22702_config cxusb_cx22702_config = {
+static struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
.output_mode = CX22702_PARALLEL_OUTPUT,
@@ -282,13 +282,13 @@ struct cx22702_config cxusb_cx22702_config = {
.pll_set = dvb_usb_pll_set_i2c,
};
-struct lgdt330x_config cxusb_lgdt330x_config = {
+static struct lgdt330x_config cxusb_lgdt330x_config = {
.demod_address = 0x0e,
.demod_chip = LGDT3303,
.pll_set = dvb_usb_pll_set_i2c,
};
-struct mt352_config cxusb_dee1601_config = {
+static struct mt352_config cxusb_dee1601_config = {
.demod_address = 0x0f,
.demod_init = cxusb_dee1601_demod_init,
.pll_set = dvb_usb_pll_set,
@@ -691,6 +691,8 @@ module_init (cxusb_module_init);
module_exit (cxusb_module_exit);
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
MODULE_VERSION("1.0-alpha");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index e6c55c9c941..caa1346e306 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -175,11 +175,13 @@ static int digitv_probe(struct usb_interface *intf,
if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
u8 b[4] = { 0 };
- b[0] = 1;
- digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
+ if (d != NULL) { /* do that only when the firmware is loaded */
+ b[0] = 1;
+ digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
- b[0] = 0;
- digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+ b[0] = 0;
+ digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+ }
}
return ret;
}
@@ -194,7 +196,7 @@ static struct dvb_usb_properties digitv_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
- .firmware = "dvb-usb-digitv-01.fw",
+ .firmware = "dvb-usb-digitv-02.fw",
.size_of_priv = 0,
@@ -229,6 +231,7 @@ static struct dvb_usb_properties digitv_properties = {
{ &digitv_table[0], NULL },
{ NULL },
},
+ { NULL },
}
};
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 130ea7f21f5..12ebaf8bddc 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = {
.cold_ids = { &dtt200u_usb_table[0], NULL },
.warm_ids = { &dtt200u_usb_table[1], NULL },
},
- { 0 },
+ { NULL },
}
};
@@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = {
.cold_ids = { &dtt200u_usb_table[2], NULL },
.warm_ids = { &dtt200u_usb_table[3], NULL },
},
- { 0 },
+ { NULL },
}
};
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index 8535895819f..9222b0a81f7 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -24,6 +24,9 @@ static struct usb_cypress_controller cypress[] = {
{ .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
};
+static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
+ int *pos);
+
/*
* load a firmware packet to the device
*/
@@ -112,7 +115,8 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties
return ret;
}
-int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
+static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
+ int *pos)
{
u8 *b = (u8 *) &fw->data[*pos];
int data_offs = 4;
@@ -142,5 +146,3 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
return *pos;
}
-EXPORT_SYMBOL(dvb_usb_get_hexline);
-
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index dd568396e59..5e5d21ad93c 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -341,7 +341,6 @@ struct hexline {
u8 data[255];
u8 chk;
};
-extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *);
extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
#endif
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index afa00fdb5ec..4a95eca81c5 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -53,7 +53,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
return ret;
}
-int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+ u16 index, u8 *b, int blen)
{
deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
debug_dump(b,blen,deb_xfer);
@@ -88,7 +89,8 @@ unlock:
return ret;
}
-int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec)
+static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
+ int olen, u8 *i, int ilen, int msec)
{
u8 bout[olen+2];
u8 bin[ilen+1];
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
index a808d48e7bf..c2f97f96c21 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.h
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -101,8 +101,6 @@ extern int dvb_usb_vp702x_debug;
extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
-extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec);
extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
-extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
#endif
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
index 5242cca5db4..9999336aeeb 100644
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -23,10 +23,11 @@
struct vp7045_fe_state {
struct dvb_frontend fe;
+ struct dvb_frontend_ops ops;
+
struct dvb_usb_device *d;
};
-
static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
{
struct vp7045_fe_state *state = fe->demodulator_priv;
@@ -150,7 +151,8 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
goto error;
s->d = d;
- s->fe.ops = &vp7045_fe_ops;
+ memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
+ s->fe.ops = &s->ops;
s->fe.demodulator_priv = s;
goto success;
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 028204956bb..3835235b68d 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = {
.cold_ids = { &vp7045_usb_table[2], NULL },
.warm_ids = { &vp7045_usb_table[3], NULL },
},
- { 0 },
+ { NULL },
}
};
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index db3a8b40031..76b6a2aef32 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -28,12 +28,6 @@ config DVB_TDA8083
help
A DVB-S tuner module. Say Y when you want to support this frontend.
-config DVB_TDA80XX
- tristate "Philips TDA8044 or TDA8083 based"
- depends on DVB_CORE
- help
- A DVB-S tuner module. Say Y when you want to support this frontend.
-
config DVB_MT312
tristate "Zarlink MT312 based"
depends on DVB_CORE
@@ -139,12 +133,6 @@ config DVB_DIB3000MC
comment "DVB-C (cable) frontends"
depends on DVB_CORE
-config DVB_ATMEL_AT76C651
- tristate "Atmel AT76C651 based"
- depends on DVB_CORE
- help
- A DVB-C tuner module. Say Y when you want to support this frontend.
-
config DVB_VES1820
tristate "VLSI VES1820 based"
depends on DVB_CORE
@@ -166,18 +154,6 @@ config DVB_STV0297
comment "ATSC (North American/Korean Terresterial DTV) frontends"
depends on DVB_CORE
-config DVB_NXT2002
- tristate "Nxt2002 based"
- depends on DVB_CORE
- select FW_LOADER
- help
- An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
-
- This driver needs external firmware. Please use the command
- "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware
- or /lib/firmware (depending on configuration of firmware hotplug).
-
config DVB_NXT200X
tristate "Nextwave NXT2002/NXT2004 based"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 615ec830e1c..1af769cd90c 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_DVB_CORE) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
obj-$(CONFIG_DVB_SP8870) += sp8870.o
obj-$(CONFIG_DVB_CX22700) += cx22700.o
-obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o
obj-$(CONFIG_DVB_CX24110) += cx24110.o
obj-$(CONFIG_DVB_TDA8083) += tda8083.o
obj-$(CONFIG_DVB_L64781) += l64781.o
@@ -22,10 +21,8 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o
obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
obj-$(CONFIG_DVB_MT352) += mt352.o
obj-$(CONFIG_DVB_CX22702) += cx22702.o
-obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o
obj-$(CONFIG_DVB_TDA10021) += tda10021.o
obj-$(CONFIG_DVB_STV0297) += stv0297.o
-obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
obj-$(CONFIG_DVB_NXT200X) += nxt200x.o
obj-$(CONFIG_DVB_OR51211) += or51211.o
obj-$(CONFIG_DVB_OR51132) += or51132.o
diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c
deleted file mode 100644
index 8e0f4b3a141..00000000000
--- a/drivers/media/dvb/frontends/at76c651.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * at76c651.c
- *
- * Atmel DVB-C Frontend Driver (at76c651/tua6010xs)
- *
- * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
- * & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- * & 2003 Wolfram Joost <dbox2@frokaschwei.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * AT76C651
- * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
- * http://www.atmel.com/atmel/acrobat/doc1320.pdf
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include "dvb_frontend.h"
-#include "at76c651.h"
-
-
-struct at76c651_state {
-
- struct i2c_adapter* i2c;
-
- struct dvb_frontend_ops ops;
-
- const struct at76c651_config* config;
-
- struct dvb_frontend frontend;
-
- /* revision of the chip */
- u8 revision;
-
- /* last QAM value set */
- u8 qam;
-};
-
-static int debug;
-#define dprintk(args...) \
- do { \
- if (debug) printk(KERN_DEBUG "at76c651: " args); \
- } while (0)
-
-
-#if ! defined(__powerpc__)
-static __inline__ int __ilog2(unsigned long x)
-{
- int i;
-
- if (x == 0)
- return -1;
-
- for (i = 0; x != 0; i++)
- x >>= 1;
-
- return i - 1;
-}
-#endif
-
-static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data)
-{
- int ret;
- u8 buf[] = { reg, data };
- struct i2c_msg msg =
- { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-
- ret = i2c_transfer(state->i2c, &msg, 1);
-
- if (ret != 1)
- dprintk("%s: writereg error "
- "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- __FUNCTION__, reg, data, ret);
-
- msleep(10);
-
- return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static u8 at76c651_readreg(struct at76c651_state* state, u8 reg)
-{
- int ret;
- u8 val;
- struct i2c_msg msg[] = {
- { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 }
- };
-
- ret = i2c_transfer(state->i2c, msg, 2);
-
- if (ret != 2)
- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
-
- return val;
-}
-
-static int at76c651_reset(struct at76c651_state* state)
-{
- return at76c651_writereg(state, 0x07, 0x01);
-}
-
-static void at76c651_disable_interrupts(struct at76c651_state* state)
-{
- at76c651_writereg(state, 0x0b, 0x00);
-}
-
-static int at76c651_set_auto_config(struct at76c651_state *state)
-{
- /*
- * Autoconfig
- */
-
- at76c651_writereg(state, 0x06, 0x01);
-
- /*
- * Performance optimizations, should be done after autoconfig
- */
-
- at76c651_writereg(state, 0x10, 0x06);
- at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10);
- at76c651_writereg(state, 0x15, 0x28);
- at76c651_writereg(state, 0x20, 0x09);
- at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90);
- at76c651_writereg(state, 0x30, 0x90);
- if (state->qam == 5)
- at76c651_writereg(state, 0x35, 0x2A);
-
- /*
- * Initialize A/D-converter
- */
-
- if (state->revision == 0x11) {
- at76c651_writereg(state, 0x2E, 0x38);
- at76c651_writereg(state, 0x2F, 0x13);
- }
-
- at76c651_disable_interrupts(state);
-
- /*
- * Restart operation
- */
-
- at76c651_reset(state);
-
- return 0;
-}
-
-static void at76c651_set_bbfreq(struct at76c651_state* state)
-{
- at76c651_writereg(state, 0x04, 0x3f);
- at76c651_writereg(state, 0x05, 0xee);
-}
-
-static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate)
-{
- u8 exponent;
- u32 mantissa;
-
- if (symbol_rate > 9360000)
- return -EINVAL;
-
- /*
- * FREF = 57800 kHz
- * exponent = 10 + floor (log2(symbol_rate / FREF))
- * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent))
- */
-
- exponent = __ilog2((symbol_rate << 4) / 903125);
- mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289;
-
- at76c651_writereg(state, 0x00, mantissa >> 13);
- at76c651_writereg(state, 0x01, mantissa >> 5);
- at76c651_writereg(state, 0x02, (mantissa << 3) | exponent);
-
- return 0;
-}
-
-static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam)
-{
- switch (qam) {
- case QPSK:
- state->qam = 0x02;
- break;
- case QAM_16:
- state->qam = 0x04;
- break;
- case QAM_32:
- state->qam = 0x05;
- break;
- case QAM_64:
- state->qam = 0x06;
- break;
- case QAM_128:
- state->qam = 0x07;
- break;
- case QAM_256:
- state->qam = 0x08;
- break;
-#if 0
- case QAM_512:
- state->qam = 0x09;
- break;
- case QAM_1024:
- state->qam = 0x0A;
- break;
-#endif
- default:
- return -EINVAL;
-
- }
-
- return at76c651_writereg(state, 0x03, state->qam);
-}
-
-static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion)
-{
- u8 feciqinv = at76c651_readreg(state, 0x60);
-
- switch (inversion) {
- case INVERSION_OFF:
- feciqinv |= 0x02;
- feciqinv &= 0xFE;
- break;
-
- case INVERSION_ON:
- feciqinv |= 0x03;
- break;
-
- case INVERSION_AUTO:
- feciqinv &= 0xFC;
- break;
-
- default:
- return -EINVAL;
- }
-
- return at76c651_writereg(state, 0x60, feciqinv);
-}
-
-static int at76c651_set_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
-{
- int ret;
- struct at76c651_state* state = fe->demodulator_priv;
-
- at76c651_writereg(state, 0x0c, 0xc3);
- state->config->pll_set(fe, p);
- at76c651_writereg(state, 0x0c, 0xc2);
-
- if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate)))
- return ret;
-
- if ((ret = at76c651_set_inversion(state, p->inversion)))
- return ret;
-
- return at76c651_set_auto_config(state);
-}
-
-static int at76c651_set_defaults(struct dvb_frontend* fe)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- at76c651_set_symbol_rate(state, 6900000);
- at76c651_set_qam(state, QAM_64);
- at76c651_set_bbfreq(state);
- at76c651_set_auto_config(state);
-
- if (state->config->pll_init) {
- at76c651_writereg(state, 0x0c, 0xc3);
- state->config->pll_init(fe);
- at76c651_writereg(state, 0x0c, 0xc2);
- }
-
- return 0;
-}
-
-static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
- struct at76c651_state* state = fe->demodulator_priv;
- u8 sync;
-
- /*
- * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
- */
- sync = at76c651_readreg(state, 0x80);
- *status = 0;
-
- if (sync & (0x04 | 0x10)) /* AGC1 || TIM */
- *status |= FE_HAS_SIGNAL;
- if (sync & 0x10) /* TIM */
- *status |= FE_HAS_CARRIER;
- if (sync & 0x80) /* FEC */
- *status |= FE_HAS_VITERBI;
- if (sync & 0x40) /* CAR */
- *status |= FE_HAS_SYNC;
- if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */
- *status |= FE_HAS_LOCK;
-
- return 0;
-}
-
-static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16;
- *ber |= at76c651_readreg(state, 0x82) << 8;
- *ber |= at76c651_readreg(state, 0x83);
- *ber *= 10;
-
- return 0;
-}
-
-static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- u8 gain = ~at76c651_readreg(state, 0x91);
- *strength = (gain << 8) | gain;
-
- return 0;
-}
-
-static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- *snr = 0xFFFF -
- ((at76c651_readreg(state, 0x8F) << 8) |
- at76c651_readreg(state, 0x90));
-
- return 0;
-}
-
-static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
- struct at76c651_state* state = fe->demodulator_priv;
-
- *ucblocks = at76c651_readreg(state, 0x82);
-
- return 0;
-}
-
-static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings)
-{
- fesettings->min_delay_ms = 50;
- fesettings->step_size = 0;
- fesettings->max_drift = 0;
- return 0;
-}
-
-static void at76c651_release(struct dvb_frontend* fe)
-{
- struct at76c651_state* state = fe->demodulator_priv;
- kfree(state);
-}
-
-static struct dvb_frontend_ops at76c651_ops;
-
-struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
- struct i2c_adapter* i2c)
-{
- struct at76c651_state* state = NULL;
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->qam = 0;
-
- /* check if the demod is there */
- if (at76c651_readreg(state, 0x0e) != 0x65) goto error;
-
- /* finalise state setup */
- state->i2c = i2c;
- state->revision = at76c651_readreg(state, 0x0f) & 0xfe;
- memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops));
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
- return NULL;
-}
-
-static struct dvb_frontend_ops at76c651_ops = {
-
- .info = {
- .name = "Atmel AT76C651B DVB-C",
- .type = FE_QAM,
- .frequency_min = 48250000,
- .frequency_max = 863250000,
- .frequency_stepsize = 62500,
- /*.frequency_tolerance = */ /* FIXME: 12% of SR */
- .symbol_rate_min = 0, /* FIXME */
- .symbol_rate_max = 9360000, /* FIXME */
- .symbol_rate_tolerance = 4000,
- .caps = FE_CAN_INVERSION_AUTO |
- FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
- FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
- FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
- },
-
- .release = at76c651_release,
-
- .init = at76c651_set_defaults,
-
- .set_frontend = at76c651_set_parameters,
- .get_tune_settings = at76c651_get_tune_settings,
-
- .read_status = at76c651_read_status,
- .read_ber = at76c651_read_ber,
- .read_signal_strength = at76c651_read_signal_strength,
- .read_snr = at76c651_read_snr,
- .read_ucblocks = at76c651_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver");
-MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(at76c651_attach);
diff --git a/drivers/media/dvb/frontends/at76c651.h b/drivers/media/dvb/frontends/at76c651.h
deleted file mode 100644
index 34054df9360..00000000000
--- a/drivers/media/dvb/frontends/at76c651.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * at76c651.c
- *
- * Atmel DVB-C Frontend Driver (at76c651)
- *
- * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
- * & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
- * & 2003 Wolfram Joost <dbox2@frokaschwei.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * AT76C651
- * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
- * http://www.atmel.com/atmel/acrobat/doc1320.pdf
- */
-
-#ifndef AT76C651_H
-#define AT76C651_H
-
-#include <linux/dvb/frontend.h>
-
-struct at76c651_config
-{
- /* the demodulator's i2c address */
- u8 demod_address;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-};
-
-extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
- struct i2c_adapter* i2c);
-
-#endif // AT76C651_H
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 757075f007c..4dcb6050d4f 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -326,14 +326,14 @@ struct dvb_pll_desc dvb_pll_tuv1236d = {
};
EXPORT_SYMBOL(dvb_pll_tuv1236d);
-/* Samsung TBMV30111IN
+/* Samsung TBMV30111IN / TBMV30712IN1
* used in Air2PC ATSC - 2nd generation (nxt2002)
*/
-struct dvb_pll_desc dvb_pll_tbmv30111in = {
- .name = "Samsung TBMV30111IN",
+struct dvb_pll_desc dvb_pll_samsung_tbmv = {
+ .name = "Samsung TBMV30111IN / TBMV30712IN1",
.min = 54000000,
.max = 860000000,
- .count = 4,
+ .count = 6,
.entries = {
{ 172000000, 44000000, 166666, 0xb4, 0x01 },
{ 214000000, 44000000, 166666, 0xb4, 0x02 },
@@ -343,7 +343,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = {
{ 999999999, 44000000, 166666, 0xfc, 0x02 },
}
};
-EXPORT_SYMBOL(dvb_pll_tbmv30111in);
+EXPORT_SYMBOL(dvb_pll_samsung_tbmv);
/*
* Philips SD1878 Tuner.
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index f682c09189b..bb8d4b4eb18 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -38,7 +38,7 @@ extern struct dvb_pll_desc dvb_pll_tded4;
extern struct dvb_pll_desc dvb_pll_tuv1236d;
extern struct dvb_pll_desc dvb_pll_tdhu2;
-extern struct dvb_pll_desc dvb_pll_tbmv30111in;
+extern struct dvb_pll_desc dvb_pll_samsung_tbmv;
extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261;
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
deleted file mode 100644
index 4f263e65ba1..00000000000
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- Support for B2C2/BBTI Technisat Air2PC - ATSC
-
- Copyright (C) 2004 Taylor Jacob <rtjacob@earthlink.net>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/*
- * This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware
- * or /lib/firmware (depending on configuration of firmware hotplug).
- */
-#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
-#define CRC_CCIT_MASK 0x1021
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "nxt2002.h"
-
-struct nxt2002_state {
-
- struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
- const struct nxt2002_config* config;
- struct dvb_frontend frontend;
-
- /* demodulator private data */
- u8 initialised:1;
-};
-
-static int debug;
-#define dprintk(args...) \
- do { \
- if (debug) printk(KERN_DEBUG "nxt2002: " args); \
- } while (0)
-
-static int i2c_writebytes (struct nxt2002_state* state, u8 reg, u8 *buf, u8 len)
-{
- /* probbably a much better way or doing this */
- u8 buf2 [256],x;
- int err;
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
-
- buf2[0] = reg;
- for (x = 0 ; x < len ; x++)
- buf2[x+1] = buf[x];
-
- if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
- printk ("%s: i2c write error (addr %02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, err);
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static u8 i2c_readbytes (struct nxt2002_state* state, u8 reg, u8* buf, u8 len)
-{
- u8 reg2 [] = { reg };
-
- struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
-
- int err;
-
- if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
- printk ("%s: i2c read error (addr %02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, err);
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static u16 nxt2002_crc(u16 crc, u8 c)
-{
-
- u8 i;
- u16 input = (u16) c & 0xFF;
-
- input<<=8;
- for(i=0 ;i<8 ;i++) {
- if((crc ^ input) & 0x8000)
- crc=(crc<<1)^CRC_CCIT_MASK;
- else
- crc<<=1;
- input<<=1;
- }
- return crc;
-}
-
-static int nxt2002_writereg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len)
-{
- u8 buf;
- dprintk("%s\n", __FUNCTION__);
-
- /* set multi register length */
- i2c_writebytes(state,0x34,&len,1);
-
- /* set mutli register register */
- i2c_writebytes(state,0x35,&reg,1);
-
- /* send the actual data */
- i2c_writebytes(state,0x36,data,len);
-
- /* toggle the multireg write bit*/
- buf = 0x02;
- i2c_writebytes(state,0x21,&buf,1);
-
- i2c_readbytes(state,0x21,&buf,1);
-
- if ((buf & 0x02) == 0)
- return 0;
-
- dprintk("Error writing multireg register %02X\n",reg);
-
- return 0;
-}
-
-static int nxt2002_readreg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len)
-{
- u8 len2;
- dprintk("%s\n", __FUNCTION__);
-
- /* set multi register length */
- len2 = len & 0x80;
- i2c_writebytes(state,0x34,&len2,1);
-
- /* set mutli register register */
- i2c_writebytes(state,0x35,&reg,1);
-
- /* send the actual data */
- i2c_readbytes(state,reg,data,len);
-
- return 0;
-}
-
-static void nxt2002_microcontroller_stop (struct nxt2002_state* state)
-{
- u8 buf[2],counter = 0;
- dprintk("%s\n", __FUNCTION__);
-
- buf[0] = 0x80;
- i2c_writebytes(state,0x22,buf,1);
-
- while (counter < 20) {
- i2c_readbytes(state,0x31,buf,1);
- if (buf[0] & 0x40)
- return;
- msleep(10);
- counter++;
- }
-
- dprintk("Timeout waiting for micro to stop.. This is ok after firmware upload\n");
- return;
-}
-
-static void nxt2002_microcontroller_start (struct nxt2002_state* state)
-{
- u8 buf;
- dprintk("%s\n", __FUNCTION__);
-
- buf = 0x00;
- i2c_writebytes(state,0x22,&buf,1);
-}
-
-static int nxt2002_writetuner (struct nxt2002_state* state, u8* data)
-{
- u8 buf,count = 0;
-
- dprintk("Tuner Bytes: %02X %02X %02X %02X\n",data[0],data[1],data[2],data[3]);
-
- dprintk("%s\n", __FUNCTION__);
- /* stop the micro first */
- nxt2002_microcontroller_stop(state);
-
- /* set the i2c transfer speed to the tuner */
- buf = 0x03;
- i2c_writebytes(state,0x20,&buf,1);
-
- /* setup to transfer 4 bytes via i2c */
- buf = 0x04;
- i2c_writebytes(state,0x34,&buf,1);
-
- /* write actual tuner bytes */
- i2c_writebytes(state,0x36,data,4);
-
- /* set tuner i2c address */
- buf = 0xC2;
- i2c_writebytes(state,0x35,&buf,1);
-
- /* write UC Opmode to begin transfer */
- buf = 0x80;
- i2c_writebytes(state,0x21,&buf,1);
-
- while (count < 20) {
- i2c_readbytes(state,0x21,&buf,1);
- if ((buf & 0x80)== 0x00)
- return 0;
- msleep(100);
- count++;
- }
-
- printk("nxt2002: timeout error writing tuner\n");
- return 0;
-}
-
-static void nxt2002_agc_reset(struct nxt2002_state* state)
-{
- u8 buf;
- dprintk("%s\n", __FUNCTION__);
-
- buf = 0x08;
- i2c_writebytes(state,0x08,&buf,1);
-
- buf = 0x00;
- i2c_writebytes(state,0x08,&buf,1);
-
- return;
-}
-
-static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
-{
-
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 buf[256],written = 0,chunkpos = 0;
- u16 rambase,position,crc = 0;
-
- dprintk("%s\n", __FUNCTION__);
- dprintk("Firmware is %zu bytes\n",fw->size);
-
- /* Get the RAM base for this nxt2002 */
- i2c_readbytes(state,0x10,buf,1);
-
- if (buf[0] & 0x10)
- rambase = 0x1000;
- else
- rambase = 0x0000;
-
- dprintk("rambase on this nxt2002 is %04X\n",rambase);
-
- /* Hold the micro in reset while loading firmware */
- buf[0] = 0x80;
- i2c_writebytes(state,0x2B,buf,1);
-
- for (position = 0; position < fw->size ; position++) {
- if (written == 0) {
- crc = 0;
- chunkpos = 0x28;
- buf[0] = ((rambase + position) >> 8);
- buf[1] = (rambase + position) & 0xFF;
- buf[2] = 0x81;
- /* write starting address */
- i2c_writebytes(state,0x29,buf,3);
- }
- written++;
- chunkpos++;
-
- if ((written % 4) == 0)
- i2c_writebytes(state,chunkpos,&fw->data[position-3],4);
-
- crc = nxt2002_crc(crc,fw->data[position]);
-
- if ((written == 255) || (position+1 == fw->size)) {
- /* write remaining bytes of firmware */
- i2c_writebytes(state, chunkpos+4-(written %4),
- &fw->data[position-(written %4) + 1],
- written %4);
- buf[0] = crc << 8;
- buf[1] = crc & 0xFF;
-
- /* write crc */
- i2c_writebytes(state,0x2C,buf,2);
-
- /* do a read to stop things */
- i2c_readbytes(state,0x2A,buf,1);
-
- /* set transfer mode to complete */
- buf[0] = 0x80;
- i2c_writebytes(state,0x2B,buf,1);
-
- written = 0;
- }
- }
-
- printk ("done.\n");
- return 0;
-};
-
-static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u32 freq = 0;
- u16 tunerfreq = 0;
- u8 buf[4];
-
- freq = 44000 + ( p->frequency / 1000 );
-
- dprintk("freq = %d p->frequency = %d\n",freq,p->frequency);
-
- tunerfreq = freq * 24/4000;
-
- buf[0] = (tunerfreq >> 8) & 0x7F;
- buf[1] = (tunerfreq & 0xFF);
-
- if (p->frequency <= 214000000) {
- buf[2] = 0x84 + (0x06 << 3);
- buf[3] = (p->frequency <= 172000000) ? 0x01 : 0x02;
- } else if (p->frequency <= 721000000) {
- buf[2] = 0x84 + (0x07 << 3);
- buf[3] = (p->frequency <= 467000000) ? 0x02 : 0x08;
- } else if (p->frequency <= 841000000) {
- buf[2] = 0x84 + (0x0E << 3);
- buf[3] = 0x08;
- } else {
- buf[2] = 0x84 + (0x0F << 3);
- buf[3] = 0x02;
- }
-
- /* write frequency information */
- nxt2002_writetuner(state,buf);
-
- /* reset the agc now that tuning has been completed */
- nxt2002_agc_reset(state);
-
- /* set target power level */
- switch (p->u.vsb.modulation) {
- case QAM_64:
- case QAM_256:
- buf[0] = 0x74;
- break;
- case VSB_8:
- buf[0] = 0x70;
- break;
- default:
- return -EINVAL;
- break;
- }
- i2c_writebytes(state,0x42,buf,1);
-
- /* configure sdm */
- buf[0] = 0x87;
- i2c_writebytes(state,0x57,buf,1);
-
- /* write sdm1 input */
- buf[0] = 0x10;
- buf[1] = 0x00;
- nxt2002_writereg_multibyte(state,0x58,buf,2);
-
- /* write sdmx input */
- switch (p->u.vsb.modulation) {
- case QAM_64:
- buf[0] = 0x68;
- break;
- case QAM_256:
- buf[0] = 0x64;
- break;
- case VSB_8:
- buf[0] = 0x60;
- break;
- default:
- return -EINVAL;
- break;
- }
- buf[1] = 0x00;
- nxt2002_writereg_multibyte(state,0x5C,buf,2);
-
- /* write adc power lpf fc */
- buf[0] = 0x05;
- i2c_writebytes(state,0x43,buf,1);
-
- /* write adc power lpf fc */
- buf[0] = 0x05;
- i2c_writebytes(state,0x43,buf,1);
-
- /* write accumulator2 input */
- buf[0] = 0x80;
- buf[1] = 0x00;
- nxt2002_writereg_multibyte(state,0x4B,buf,2);
-
- /* write kg1 */
- buf[0] = 0x00;
- i2c_writebytes(state,0x4D,buf,1);
-
- /* write sdm12 lpf fc */
- buf[0] = 0x44;
- i2c_writebytes(state,0x55,buf,1);
-
- /* write agc control reg */
- buf[0] = 0x04;
- i2c_writebytes(state,0x41,buf,1);
-
- /* write agc ucgp0 */
- switch (p->u.vsb.modulation) {
- case QAM_64:
- buf[0] = 0x02;
- break;
- case QAM_256:
- buf[0] = 0x03;
- break;
- case VSB_8:
- buf[0] = 0x00;
- break;
- default:
- return -EINVAL;
- break;
- }
- i2c_writebytes(state,0x30,buf,1);
-
- /* write agc control reg */
- buf[0] = 0x00;
- i2c_writebytes(state,0x41,buf,1);
-
- /* write accumulator2 input */
- buf[0] = 0x80;
- buf[1] = 0x00;
- nxt2002_writereg_multibyte(state,0x49,buf,2);
- nxt2002_writereg_multibyte(state,0x4B,buf,2);
-
- /* write agc control reg */
- buf[0] = 0x04;
- i2c_writebytes(state,0x41,buf,1);
-
- nxt2002_microcontroller_start(state);
-
- /* adjacent channel detection should be done here, but I don't
- have any stations with this need so I cannot test it */
-
- return 0;
-}
-
-static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 lock;
- i2c_readbytes(state,0x31,&lock,1);
-
- *status = 0;
- if (lock & 0x20) {
- *status |= FE_HAS_SIGNAL;
- *status |= FE_HAS_CARRIER;
- *status |= FE_HAS_VITERBI;
- *status |= FE_HAS_SYNC;
- *status |= FE_HAS_LOCK;
- }
- return 0;
-}
-
-static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 b[3];
-
- nxt2002_readreg_multibyte(state,0xE6,b,3);
-
- *ber = ((b[0] << 8) + b[1]) * 8;
-
- return 0;
-}
-
-static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 b[2];
- u16 temp = 0;
-
- /* setup to read cluster variance */
- b[0] = 0x00;
- i2c_writebytes(state,0xA1,b,1);
-
- /* get multreg val */
- nxt2002_readreg_multibyte(state,0xA6,b,2);
-
- temp = (b[0] << 8) | b[1];
- *strength = ((0x7FFF - temp) & 0x0FFF) * 16;
-
- return 0;
-}
-
-static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 b[2];
- u16 temp = 0, temp2;
- u32 snrdb = 0;
-
- /* setup to read cluster variance */
- b[0] = 0x00;
- i2c_writebytes(state,0xA1,b,1);
-
- /* get multreg val from 0xA6 */
- nxt2002_readreg_multibyte(state,0xA6,b,2);
-
- temp = (b[0] << 8) | b[1];
- temp2 = 0x7FFF - temp;
-
- /* snr will be in db */
- if (temp2 > 0x7F00)
- snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
- else if (temp2 > 0x7EC0)
- snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
- else if (temp2 > 0x7C00)
- snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
- else
- snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
-
- /* the value reported back from the frontend will be FFFF=32db 0000=0db */
-
- *snr = snrdb * (0xFFFF/32000);
-
- return 0;
-}
-
-static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- u8 b[3];
-
- nxt2002_readreg_multibyte(state,0xE6,b,3);
- *ucblocks = b[2];
-
- return 0;
-}
-
-static int nxt2002_sleep(struct dvb_frontend* fe)
-{
- return 0;
-}
-
-static int nxt2002_init(struct dvb_frontend* fe)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- const struct firmware *fw;
- int ret;
- u8 buf[2];
-
- if (!state->initialised) {
- /* request the firmware, this will block until someone uploads it */
- printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
- ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE);
- printk("nxt2002: Waiting for firmware upload(2)...\n");
- if (ret) {
- printk("nxt2002: no firmware upload (timeout or file not found?)\n");
- return ret;
- }
-
- ret = nxt2002_load_firmware(fe, fw);
- if (ret) {
- printk("nxt2002: writing firmware to device failed\n");
- release_firmware(fw);
- return ret;
- }
- printk("nxt2002: firmware upload complete\n");
-
- /* Put the micro into reset */
- nxt2002_microcontroller_stop(state);
-
- /* ensure transfer is complete */
- buf[0]=0;
- i2c_writebytes(state,0x2B,buf,1);
-
- /* Put the micro into reset for real this time */
- nxt2002_microcontroller_stop(state);
-
- /* soft reset everything (agc,frontend,eq,fec)*/
- buf[0] = 0x0F;
- i2c_writebytes(state,0x08,buf,1);
- buf[0] = 0x00;
- i2c_writebytes(state,0x08,buf,1);
-
- /* write agc sdm configure */
- buf[0] = 0xF1;
- i2c_writebytes(state,0x57,buf,1);
-
- /* write mod output format */
- buf[0] = 0x20;
- i2c_writebytes(state,0x09,buf,1);
-
- /* write fec mpeg mode */
- buf[0] = 0x7E;
- buf[1] = 0x00;
- i2c_writebytes(state,0xE9,buf,2);
-
- /* write mux selection */
- buf[0] = 0x00;
- i2c_writebytes(state,0xCC,buf,1);
-
- state->initialised = 1;
- }
-
- return 0;
-}
-
-static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
- fesettings->min_delay_ms = 500;
- fesettings->step_size = 0;
- fesettings->max_drift = 0;
- return 0;
-}
-
-static void nxt2002_release(struct dvb_frontend* fe)
-{
- struct nxt2002_state* state = fe->demodulator_priv;
- kfree(state);
-}
-
-static struct dvb_frontend_ops nxt2002_ops;
-
-struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
- struct i2c_adapter* i2c)
-{
- struct nxt2002_state* state = NULL;
- u8 buf [] = {0,0,0,0,0};
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &nxt2002_ops, sizeof(struct dvb_frontend_ops));
- state->initialised = 0;
-
- /* Check the first 5 registers to ensure this a revision we can handle */
-
- i2c_readbytes(state, 0x00, buf, 5);
- if (buf[0] != 0x04) goto error; /* device id */
- if (buf[1] != 0x02) goto error; /* fab id */
- if (buf[2] != 0x11) goto error; /* month */
- if (buf[3] != 0x20) goto error; /* year msb */
- if (buf[4] != 0x00) goto error; /* year lsb */
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
- return NULL;
-}
-
-static struct dvb_frontend_ops nxt2002_ops = {
-
- .info = {
- .name = "Nextwave nxt2002 VSB/QAM frontend",
- .type = FE_ATSC,
- .frequency_min = 54000000,
- .frequency_max = 860000000,
- /* stepsize is just a guess */
- .frequency_stepsize = 166666,
- .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
- },
-
- .release = nxt2002_release,
-
- .init = nxt2002_init,
- .sleep = nxt2002_sleep,
-
- .set_frontend = nxt2002_setup_frontend_parameters,
- .get_tune_settings = nxt2002_get_tune_settings,
-
- .read_status = nxt2002_read_status,
- .read_ber = nxt2002_read_ber,
- .read_signal_strength = nxt2002_read_signal_strength,
- .read_snr = nxt2002_read_snr,
- .read_ucblocks = nxt2002_read_ucblocks,
-
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("NXT2002 ATSC (8VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
-MODULE_AUTHOR("Taylor Jacob");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(nxt2002_attach);
diff --git a/drivers/media/dvb/frontends/nxt2002.h b/drivers/media/dvb/frontends/nxt2002.h
deleted file mode 100644
index 462301f577e..00000000000
--- a/drivers/media/dvb/frontends/nxt2002.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- Driver for the Nxt2002 demodulator
-*/
-
-#ifndef NXT2002_H
-#define NXT2002_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-struct nxt2002_config
-{
- /* the demodulator's i2c address */
- u8 demod_address;
-
- /* request firmware for device */
- int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
-};
-
-extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
- struct i2c_adapter* i2c);
-
-#endif // NXT2002_H
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index 78d2b93d35b..9e353539450 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -1,9 +1,10 @@
/*
* Support for NXT2002 and NXT2004 - VSB/QAM
*
- * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com)
+ * Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
+ * Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net>
* based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
- * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com)
+ * and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com>
*
* 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
@@ -614,7 +615,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write sdm1 input */
buf[0] = 0x10;
buf[1] = 0x00;
- nxt200x_writebytes(state, 0x58, buf, 2);
+ switch (state->demod_chip) {
+ case NXT2002:
+ nxt200x_writereg_multibyte(state, 0x58, buf, 2);
+ break;
+ case NXT2004:
+ nxt200x_writebytes(state, 0x58, buf, 2);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
/* write sdmx input */
switch (p->u.vsb.modulation) {
@@ -632,7 +643,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
break;
}
buf[1] = 0x00;
- nxt200x_writebytes(state, 0x5C, buf, 2);
+ switch (state->demod_chip) {
+ case NXT2002:
+ nxt200x_writereg_multibyte(state, 0x5C, buf, 2);
+ break;
+ case NXT2004:
+ nxt200x_writebytes(state, 0x5C, buf, 2);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
/* write adc power lpf fc */
buf[0] = 0x05;
@@ -648,7 +669,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write accumulator2 input */
buf[0] = 0x80;
buf[1] = 0x00;
- nxt200x_writebytes(state, 0x4B, buf, 2);
+ switch (state->demod_chip) {
+ case NXT2002:
+ nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
+ break;
+ case NXT2004:
+ nxt200x_writebytes(state, 0x4B, buf, 2);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
/* write kg1 */
buf[0] = 0x00;
@@ -714,8 +745,19 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write accumulator2 input */
buf[0] = 0x80;
buf[1] = 0x00;
- nxt200x_writebytes(state, 0x49, buf,2);
- nxt200x_writebytes(state, 0x4B, buf,2);
+ switch (state->demod_chip) {
+ case NXT2002:
+ nxt200x_writereg_multibyte(state, 0x49, buf, 2);
+ nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
+ break;
+ case NXT2004:
+ nxt200x_writebytes(state, 0x49, buf, 2);
+ nxt200x_writebytes(state, 0x4B, buf, 2);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
/* write agc control reg */
buf[0] = 0x04;
@@ -1199,7 +1241,7 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
-MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob");
+MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(nxt200x_attach);
diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c
deleted file mode 100644
index d1cabb6a0a1..00000000000
--- a/drivers/media/dvb/frontends/tda80xx.c
+++ /dev/null
@@ -1,734 +0,0 @@
-/*
- * tda80xx.c
- *
- * Philips TDA8044 / TDA8083 QPSK demodulator driver
- *
- * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net>
- * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <asm/irq.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "tda80xx.h"
-
-enum {
- ID_TDA8044 = 0x04,
- ID_TDA8083 = 0x05,
-};
-
-
-struct tda80xx_state {
-
- struct i2c_adapter* i2c;
-
- struct dvb_frontend_ops ops;
-
- /* configuration settings */
- const struct tda80xx_config* config;
-
- struct dvb_frontend frontend;
-
- u32 clk;
- int afc_loop;
- struct work_struct worklet;
- fe_code_rate_t code_rate;
- fe_spectral_inversion_t spectral_inversion;
- fe_status_t status;
- u8 id;
-};
-
-static int debug = 1;
-#define dprintk if (debug) printk
-
-static u8 tda8044_inittab_pre[] = {
- 0x02, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea,
- 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x58,
- 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68,
- 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x00,
- 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00
-};
-
-static u8 tda8044_inittab_post[] = {
- 0x04, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea,
- 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x50,
- 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68,
- 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x6c,
- 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00
-};
-
-static u8 tda8083_inittab[] = {
- 0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
- 0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
- 0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
- 0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
- 0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-static __inline__ u32 tda80xx_div(u32 a, u32 b)
-{
- return (a + (b / 2)) / b;
-}
-
-static __inline__ u32 tda80xx_gcd(u32 a, u32 b)
-{
- u32 r;
-
- while ((r = a % b)) {
- a = b;
- b = r;
- }
-
- return b;
-}
-
-static int tda80xx_read(struct tda80xx_state* state, u8 reg, u8 *buf, u8 len)
-{
- int ret;
- struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
-
- ret = i2c_transfer(state->i2c, msg, 2);
-
- if (ret != 2)
- dprintk("%s: readreg error (reg %02x, ret == %i)\n",
- __FUNCTION__, reg, ret);
-
- mdelay(10);
-
- return (ret == 2) ? 0 : -EREMOTEIO;
-}
-
-static int tda80xx_write(struct tda80xx_state* state, u8 reg, const u8 *buf, u8 len)
-{
- int ret;
- u8 wbuf[len + 1];
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = wbuf, .len = len + 1 };
-
- wbuf[0] = reg;
- memcpy(&wbuf[1], buf, len);
-
- ret = i2c_transfer(state->i2c, &msg, 1);
-
- if (ret != 1)
- dprintk("%s: i2c xfer error (ret == %i)\n", __FUNCTION__, ret);
-
- mdelay(10);
-
- return (ret == 1) ? 0 : -EREMOTEIO;
-}
-
-static __inline__ u8 tda80xx_readreg(struct tda80xx_state* state, u8 reg)
-{
- u8 val;
-
- tda80xx_read(state, reg, &val, 1);
-
- return val;
-}
-
-static __inline__ int tda80xx_writereg(struct tda80xx_state* state, u8 reg, u8 data)
-{
- return tda80xx_write(state, reg, &data, 1);
-}
-
-static int tda80xx_set_parameters(struct tda80xx_state* state,
- fe_spectral_inversion_t inversion,
- u32 symbol_rate,
- fe_code_rate_t fec_inner)
-{
- u8 buf[15];
- u64 ratio;
- u32 clk;
- u32 k;
- u32 sr = symbol_rate;
- u32 gcd;
- u8 scd;
-
- if (symbol_rate > (state->clk * 3) / 16)
- scd = 0;
- else if (symbol_rate > (state->clk * 3) / 32)
- scd = 1;
- else if (symbol_rate > (state->clk * 3) / 64)
- scd = 2;
- else
- scd = 3;
-
- clk = scd ? (state->clk / (scd * 2)) : state->clk;
-
- /*
- * Viterbi decoder:
- * Differential decoding off
- * Spectral inversion unknown
- * QPSK modulation
- */
- if (inversion == INVERSION_ON)
- buf[0] = 0x60;
- else if (inversion == INVERSION_OFF)
- buf[0] = 0x20;
- else
- buf[0] = 0x00;
-
- /*
- * CLK ratio:
- * system clock frequency is up to 64 or 96 MHz
- *
- * formula:
- * r = k * clk / symbol_rate
- *
- * k: 2^21 for caa 0..3,
- * 2^20 for caa 4..5,
- * 2^19 for caa 6..7
- */
- if (symbol_rate <= (clk * 3) / 32)
- k = (1 << 19);
- else if (symbol_rate <= (clk * 3) / 16)
- k = (1 << 20);
- else
- k = (1 << 21);
-
- gcd = tda80xx_gcd(clk, sr);
- clk /= gcd;
- sr /= gcd;
-
- gcd = tda80xx_gcd(k, sr);
- k /= gcd;
- sr /= gcd;
-
- ratio = (u64)k * (u64)clk;
- do_div(ratio, sr);
-
- buf[1] = ratio >> 16;
- buf[2] = ratio >> 8;
- buf[3] = ratio;
-
- /* nyquist filter roll-off factor 35% */
- buf[4] = 0x20;
-
- clk = scd ? (state->clk / (scd * 2)) : state->clk;
-
- /* Anti Alias Filter */
- if (symbol_rate < (clk * 3) / 64)
- printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate);
- else if (symbol_rate <= clk / 16)
- buf[4] |= 0x07;
- else if (symbol_rate <= (clk * 3) / 32)
- buf[4] |= 0x06;
- else if (symbol_rate <= clk / 8)
- buf[4] |= 0x05;
- else if (symbol_rate <= (clk * 3) / 16)
- buf[4] |= 0x04;
- else if (symbol_rate <= clk / 4)
- buf[4] |= 0x03;
- else if (symbol_rate <= (clk * 3) / 8)
- buf[4] |= 0x02;
- else if (symbol_rate <= clk / 2)
- buf[4] |= 0x01;
- else
- buf[4] |= 0x00;
-
- /* Sigma Delta converter */
- buf[5] = 0x00;
-
- /* FEC: Possible puncturing rates */
- if (fec_inner == FEC_NONE)
- buf[6] = 0x00;
- else if ((fec_inner >= FEC_1_2) && (fec_inner <= FEC_8_9))
- buf[6] = (1 << (8 - fec_inner));
- else if (fec_inner == FEC_AUTO)
- buf[6] = 0xff;
- else
- return -EINVAL;
-
- /* carrier lock detector threshold value */
- buf[7] = 0x30;
- /* AFC1: proportional part settings */
- buf[8] = 0x42;
- /* AFC1: integral part settings */
- buf[9] = 0x98;
- /* PD: Leaky integrator SCPC mode */
- buf[10] = 0x28;
- /* AFC2, AFC1 controls */
- buf[11] = 0x30;
- /* PD: proportional part settings */
- buf[12] = 0x42;
- /* PD: integral part settings */
- buf[13] = 0x99;
- /* AGC */
- buf[14] = 0x50 | scd;
-
- printk("symbol_rate=%u clk=%u\n", symbol_rate, clk);
-
- return tda80xx_write(state, 0x01, buf, sizeof(buf));
-}
-
-static int tda80xx_set_clk(struct tda80xx_state* state)
-{
- u8 buf[2];
-
- /* CLK proportional part */
- buf[0] = (0x06 << 5) | 0x08; /* CMP[2:0], CSP[4:0] */
- /* CLK integral part */
- buf[1] = (0x04 << 5) | 0x1a; /* CMI[2:0], CSI[4:0] */
-
- return tda80xx_write(state, 0x17, buf, sizeof(buf));
-}
-
-#if 0
-static int tda80xx_set_scpc_freq_offset(struct tda80xx_state* state)
-{
- /* a constant value is nonsense here imho */
- return tda80xx_writereg(state, 0x22, 0xf9);
-}
-#endif
-
-static int tda80xx_close_loop(struct tda80xx_state* state)
-{
- u8 buf[2];
-
- /* PD: Loop closed, LD: lock detect enable, SCPC: Sweep mode - AFC1 loop closed */
- buf[0] = 0x68;
- /* AFC1: Loop closed, CAR Feedback: 8192 */
- buf[1] = 0x70;
-
- return tda80xx_write(state, 0x0b, buf, sizeof(buf));
-}
-
-static irqreturn_t tda80xx_irq(int irq, void *priv, struct pt_regs *pt)
-{
- schedule_work(priv);
-
- return IRQ_HANDLED;
-}
-
-static void tda80xx_read_status_int(struct tda80xx_state* state)
-{
- u8 val;
-
- static const fe_spectral_inversion_t inv_tab[] = {
- INVERSION_OFF, INVERSION_ON
- };
-
- static const fe_code_rate_t fec_tab[] = {
- FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
- FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8,
- };
-
- val = tda80xx_readreg(state, 0x02);
-
- state->status = 0;
-
- if (val & 0x01) /* demodulator lock */
- state->status |= FE_HAS_SIGNAL;
- if (val & 0x02) /* clock recovery lock */
- state->status |= FE_HAS_CARRIER;
- if (val & 0x04) /* viterbi lock */
- state->status |= FE_HAS_VITERBI;
- if (val & 0x08) /* deinterleaver lock (packet sync) */
- state->status |= FE_HAS_SYNC;
- if (val & 0x10) /* derandomizer lock (frame sync) */
- state->status |= FE_HAS_LOCK;
- if (val & 0x20) /* frontend can not lock */
- state->status |= FE_TIMEDOUT;
-
- if ((state->status & (FE_HAS_CARRIER)) && (state->afc_loop)) {
- printk("tda80xx: closing loop\n");
- tda80xx_close_loop(state);
- state->afc_loop = 0;
- }
-
- if (state->status & (FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK)) {
- val = tda80xx_readreg(state, 0x0e);
- state->code_rate = fec_tab[val & 0x07];
- if (state->status & (FE_HAS_SYNC | FE_HAS_LOCK))
- state->spectral_inversion = inv_tab[(val >> 7) & 0x01];
- else
- state->spectral_inversion = INVERSION_AUTO;
- }
- else {
- state->code_rate = FEC_AUTO;
- }
-}
-
-static void tda80xx_worklet(void *priv)
-{
- struct tda80xx_state *state = priv;
-
- tda80xx_writereg(state, 0x00, 0x04);
- enable_irq(state->config->irq);
-
- tda80xx_read_status_int(state);
-}
-
-static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state)
-{
- size_t i;
-
- for (i = 0; i < 100; i++) {
- if (tda80xx_readreg(state, 0x02) & 0x80)
- break;
- msleep(10);
- }
-}
-
-static int tda8044_init(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
- int ret;
-
- /*
- * this function is a mess...
- */
-
- if ((ret = tda80xx_write(state, 0x00, tda8044_inittab_pre, sizeof(tda8044_inittab_pre))))
- return ret;
-
- tda80xx_writereg(state, 0x0f, 0x50);
-#if 1
- tda80xx_writereg(state, 0x20, 0x8F); /* FIXME */
- tda80xx_writereg(state, 0x20, state->config->volt18setting); /* FIXME */
- //tda80xx_writereg(state, 0x00, 0x04);
- tda80xx_writereg(state, 0x00, 0x0C);
-#endif
- //tda80xx_writereg(state, 0x00, 0x08); /* Reset AFC1 loop filter */
-
- tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post));
-
- if (state->config->pll_init) {
- tda80xx_writereg(state, 0x1c, 0x80);
- state->config->pll_init(fe);
- tda80xx_writereg(state, 0x1c, 0x00);
- }
-
- return 0;
-}
-
-static int tda8083_init(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab));
-
- if (state->config->pll_init) {
- tda80xx_writereg(state, 0x1c, 0x80);
- state->config->pll_init(fe);
- tda80xx_writereg(state, 0x1c, 0x00);
- }
-
- return 0;
-}
-
-static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- switch (voltage) {
- case SEC_VOLTAGE_13:
- return tda80xx_writereg(state, 0x20, state->config->volt13setting);
- case SEC_VOLTAGE_18:
- return tda80xx_writereg(state, 0x20, state->config->volt18setting);
- case SEC_VOLTAGE_OFF:
- return tda80xx_writereg(state, 0x20, 0);
- default:
- return -EINVAL;
- }
-}
-
-static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- switch (tone) {
- case SEC_TONE_OFF:
- return tda80xx_writereg(state, 0x29, 0x00);
- case SEC_TONE_ON:
- return tda80xx_writereg(state, 0x29, 0x80);
- default:
- return -EINVAL;
- }
-}
-
-static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- if (cmd->msg_len > 6)
- return -EINVAL;
-
- tda80xx_writereg(state, 0x29, 0x08 | (cmd->msg_len - 3));
- tda80xx_write(state, 0x23, cmd->msg, cmd->msg_len);
- tda80xx_writereg(state, 0x29, 0x0c | (cmd->msg_len - 3));
- tda80xx_wait_diseqc_fifo(state);
-
- return 0;
-}
-
-static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- switch (cmd) {
- case SEC_MINI_A:
- tda80xx_writereg(state, 0x29, 0x14);
- break;
- case SEC_MINI_B:
- tda80xx_writereg(state, 0x29, 0x1c);
- break;
- default:
- return -EINVAL;
- }
-
- tda80xx_wait_diseqc_fifo(state);
-
- return 0;
-}
-
-static int tda80xx_sleep(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- tda80xx_writereg(state, 0x00, 0x02); /* enter standby */
-
- return 0;
-}
-
-static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- tda80xx_writereg(state, 0x1c, 0x80);
- state->config->pll_set(fe, p);
- tda80xx_writereg(state, 0x1c, 0x00);
-
- tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner);
- tda80xx_set_clk(state);
- //tda80xx_set_scpc_freq_offset(state);
- state->afc_loop = 1;
-
- return 0;
-}
-
-static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- if (!state->config->irq)
- tda80xx_read_status_int(state);
-
- p->inversion = state->spectral_inversion;
- p->u.qpsk.fec_inner = state->code_rate;
-
- return 0;
-}
-
-static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- if (!state->config->irq)
- tda80xx_read_status_int(state);
- *status = state->status;
-
- return 0;
-}
-
-static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
- int ret;
- u8 buf[3];
-
- if ((ret = tda80xx_read(state, 0x0b, buf, sizeof(buf))))
- return ret;
-
- *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
-
- return 0;
-}
-
-static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- u8 gain = ~tda80xx_readreg(state, 0x01);
- *strength = (gain << 8) | gain;
-
- return 0;
-}
-
-static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- u8 quality = tda80xx_readreg(state, 0x08);
- *snr = (quality << 8) | quality;
-
- return 0;
-}
-
-static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- *ucblocks = tda80xx_readreg(state, 0x0f);
- if (*ucblocks == 0xff)
- *ucblocks = 0xffffffff;
-
- return 0;
-}
-
-static int tda80xx_init(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- switch(state->id) {
- case ID_TDA8044:
- return tda8044_init(fe);
-
- case ID_TDA8083:
- return tda8083_init(fe);
- }
- return 0;
-}
-
-static void tda80xx_release(struct dvb_frontend* fe)
-{
- struct tda80xx_state* state = fe->demodulator_priv;
-
- if (state->config->irq)
- free_irq(state->config->irq, &state->worklet);
-
- kfree(state);
-}
-
-static struct dvb_frontend_ops tda80xx_ops;
-
-struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
- struct i2c_adapter* i2c)
-{
- struct tda80xx_state* state = NULL;
- int ret;
-
- /* allocate memory for the internal state */
- state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &tda80xx_ops, sizeof(struct dvb_frontend_ops));
- state->spectral_inversion = INVERSION_AUTO;
- state->code_rate = FEC_AUTO;
- state->status = 0;
- state->afc_loop = 0;
-
- /* check if the demod is there */
- if (tda80xx_writereg(state, 0x89, 0x00) < 0) goto error;
- state->id = tda80xx_readreg(state, 0x00);
-
- switch (state->id) {
- case ID_TDA8044:
- state->clk = 96000000;
- printk("tda80xx: Detected tda8044\n");
- break;
-
- case ID_TDA8083:
- state->clk = 64000000;
- printk("tda80xx: Detected tda8083\n");
- break;
-
- default:
- goto error;
- }
-
- /* setup IRQ */
- if (state->config->irq) {
- INIT_WORK(&state->worklet, tda80xx_worklet, state);
- if ((ret = request_irq(state->config->irq, tda80xx_irq, SA_ONESHOT, "tda80xx", &state->worklet)) < 0) {
- printk(KERN_ERR "tda80xx: request_irq failed (%d)\n", ret);
- goto error;
- }
- }
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- kfree(state);
- return NULL;
-}
-
-static struct dvb_frontend_ops tda80xx_ops = {
-
- .info = {
- .name = "Philips TDA80xx DVB-S",
- .type = FE_QPSK,
- .frequency_min = 500000,
- .frequency_max = 2700000,
- .frequency_stepsize = 125,
- .symbol_rate_min = 4500000,
- .symbol_rate_max = 45000000,
- .caps = FE_CAN_INVERSION_AUTO |
- FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
- FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
- FE_CAN_QPSK |
- FE_CAN_MUTE_TS
- },
-
- .release = tda80xx_release,
-
- .init = tda80xx_init,
- .sleep = tda80xx_sleep,
-
- .set_frontend = tda80xx_set_frontend,
- .get_frontend = tda80xx_get_frontend,
-
- .read_status = tda80xx_read_status,
- .read_ber = tda80xx_read_ber,
- .read_signal_strength = tda80xx_read_signal_strength,
- .read_snr = tda80xx_read_snr,
- .read_ucblocks = tda80xx_read_ucblocks,
-
- .diseqc_send_master_cmd = tda80xx_send_diseqc_msg,
- .diseqc_send_burst = tda80xx_send_diseqc_burst,
- .set_tone = tda80xx_set_tone,
- .set_voltage = tda80xx_set_voltage,
-};
-
-module_param(debug, int, 0644);
-
-MODULE_DESCRIPTION("Philips TDA8044 / TDA8083 DVB-S Demodulator driver");
-MODULE_AUTHOR("Felix Domke, Andreas Oberritter");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(tda80xx_attach);
diff --git a/drivers/media/dvb/frontends/tda80xx.h b/drivers/media/dvb/frontends/tda80xx.h
deleted file mode 100644
index cd639a0aad5..00000000000
--- a/drivers/media/dvb/frontends/tda80xx.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * tda80xx.c
- *
- * Philips TDA8044 / TDA8083 QPSK demodulator driver
- *
- * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net>
- * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef TDA80XX_H
-#define TDA80XX_H
-
-#include <linux/dvb/frontend.h>
-
-struct tda80xx_config
-{
- /* the demodulator's i2c address */
- u8 demod_address;
-
- /* IRQ to use (0=>no IRQ used) */
- u32 irq;
-
- /* Register setting to use for 13v */
- u8 volt13setting;
-
- /* Register setting to use for 18v */
- u8 volt18setting;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-};
-
-extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
- struct i2c_adapter* i2c);
-
-#endif // TDA80XX_H
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 327a8089193..d36369e9e88 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -81,7 +81,7 @@ static int adac = DVB_ADAC_TI;
static int hw_sections;
static int rgb_on;
static int volume = 255;
-static int budgetpatch = 0;
+static int budgetpatch;
module_param_named(debug, av7110_debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -103,7 +103,7 @@ MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0
static void restart_feeds(struct av7110 *av7110);
-static int av7110_num = 0;
+static int av7110_num;
#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
{\
@@ -2329,6 +2329,17 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
break;
+ case 0x0004: // Galaxis DVB-S rev1.3
+ /* ALPS BSRV2 */
+ av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
+ }
+ break;
+
case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
/* Grundig 29504-451 */
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
@@ -2930,6 +2941,7 @@ MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
+MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
@@ -2937,13 +2949,13 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
+ MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
-/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 6ea30df2e82..fafd25fab83 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -273,8 +273,6 @@ struct av7110 {
extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid);
-extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
-
extern int av7110_ir_init(struct av7110 *av7110);
extern void av7110_ir_exit(struct av7110 *av7110);
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index cb377452b57..b2e63e9fc05 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -146,52 +146,52 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
{
int i;
int blocks, rest;
- u32 base, bootblock = BOOT_BLOCK;
+ u32 base, bootblock = AV7110_BOOT_BLOCK;
dprintk(4, "%p\n", av7110);
- blocks = len / BOOT_MAX_SIZE;
- rest = len % BOOT_MAX_SIZE;
+ blocks = len / AV7110_BOOT_MAX_SIZE;
+ rest = len % AV7110_BOOT_MAX_SIZE;
base = DRAM_START_CODE;
for (i = 0; i < blocks; i++) {
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
return -ETIMEDOUT;
}
dprintk(4, "writing DRAM block %d\n", i);
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
bootblock ^= 0x1400;
- iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, BOOT_MAX_SIZE, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
- base += BOOT_MAX_SIZE;
+ iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ base += AV7110_BOOT_MAX_SIZE;
}
if (rest > 0) {
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
return -ETIMEDOUT;
}
if (rest > 4)
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE, rest);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
else
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE - 4, rest + 4);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
- iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
}
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
return -ETIMEDOUT;
}
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) {
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
return -ETIMEDOUT;
}
@@ -262,7 +262,7 @@ int av7110_bootarm(struct av7110 *av7110)
//saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index 84b83299b8b..4e173c67fbb 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -18,7 +18,7 @@ enum av7110_bootstate
{
BOOTSTATE_BUFFER_EMPTY = 0,
BOOTSTATE_BUFFER_FULL = 1,
- BOOTSTATE_BOOT_COMPLETE = 2
+ BOOTSTATE_AV7110_BOOT_COMPLETE = 2
};
enum av7110_type_rec_play_format
@@ -295,11 +295,11 @@ enum av7110_command_type {
#define DPRAM_BASE 0x4000
/* boot protocol area */
-#define BOOT_STATE (DPRAM_BASE + 0x3F8)
-#define BOOT_SIZE (DPRAM_BASE + 0x3FA)
-#define BOOT_BASE (DPRAM_BASE + 0x3FC)
-#define BOOT_BLOCK (DPRAM_BASE + 0x400)
-#define BOOT_MAX_SIZE 0xc00
+#define AV7110_BOOT_STATE (DPRAM_BASE + 0x3F8)
+#define AV7110_BOOT_SIZE (DPRAM_BASE + 0x3FA)
+#define AV7110_BOOT_BASE (DPRAM_BASE + 0x3FC)
+#define AV7110_BOOT_BLOCK (DPRAM_BASE + 0x400)
+#define AV7110_BOOT_MAX_SIZE 0xc00
/* firmware command protocol area */
#define IRQ_STATE (DPRAM_BASE + 0x0F4)
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 9138132ad25..617e4f6c0ed 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -155,6 +155,19 @@ static void input_repeat_key(unsigned long data)
}
+static int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
+{
+ int ret = 0;
+
+ dprintk(4, "%p\n", av7110);
+ if (av7110) {
+ ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
+ av7110->ir_config = ir_config;
+ }
+ return ret;
+}
+
+
static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
@@ -187,19 +200,6 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
}
-int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
-{
- int ret = 0;
-
- dprintk(4, "%p\n", av7110);
- if (av7110) {
- ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
- av7110->ir_config = ir_config;
- }
- return ret;
-}
-
-
static void ir_handler(struct av7110 *av7110, u32 ircom)
{
dprintk(4, "ircommand = %08x\n", ircom);
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index dd24896906f..faf728366c4 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -8,7 +8,8 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o
-tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
+tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \
+ mt20xx.o tda8290.o tea5767.o
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 7d5a068353f..994b75fe165 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -129,9 +129,9 @@ static unsigned char yuv[MAX_AR_FRAME_BYTES];
static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */
static int vga = 0; /* default mode(0:QVGA mode, other:VGA mode) */
static int vga_interlace = 0; /* 0 is normal mode for, else interlace mode */
-MODULE_PARM(freq, "i");
-MODULE_PARM(vga, "i");
-MODULE_PARM(vga_interlace, "i");
+module_param(freq, int, 0);
+module_param(vga, int, 0);
+module_param(vga_interlace, int, 0);
static int ar_initialize(struct video_device *dev);
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index 07c78f1f7a4..cc54b62f460 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -43,7 +43,7 @@ static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
-int debug = 0; /* debug output */
+int debug; /* debug output */
module_param(debug, int, 0644);
/* ---------------------------------------------------------------------- */
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index a48de3c0e3f..b4aca724927 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -37,7 +37,7 @@ MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
MODULE_AUTHOR("Gerd Knorr");
MODULE_LICENSE("GPL");
-static unsigned int debug = 0;
+static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 65323e78d5f..9749d6ed623 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -92,8 +92,8 @@ static void identify_by_eeprom(struct bttv *btv,
static int __devinit pvr_boot(struct bttv *btv);
/* config variables */
-static unsigned int triton1=0;
-static unsigned int vsfx=0;
+static unsigned int triton1;
+static unsigned int vsfx;
static unsigned int latency = UNSET;
int no_overlay=-1;
@@ -106,7 +106,7 @@ static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL };
#ifdef MODULE
static unsigned int autoload = 1;
#else
-static unsigned int autoload = 0;
+static unsigned int autoload;
#endif
static unsigned int gpiomask = UNSET;
static unsigned int audioall = UNSET;
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 0e697034678..578b2008508 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -48,47 +48,46 @@
unsigned int bttv_num; /* number of Bt848s in use */
struct bttv bttvs[BTTV_MAX];
-unsigned int bttv_debug = 0;
+unsigned int bttv_debug;
unsigned int bttv_verbose = 1;
-unsigned int bttv_gpio = 0;
+unsigned int bttv_gpio;
/* config variables */
#ifdef __BIG_ENDIAN
static unsigned int bigendian=1;
#else
-static unsigned int bigendian=0;
+static unsigned int bigendian;
#endif
static unsigned int radio[BTTV_MAX];
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
static unsigned int gbuffers = 8;
static unsigned int gbufsize = 0x208000;
static int video_nr = -1;
static int radio_nr = -1;
static int vbi_nr = -1;
-static int debug_latency = 0;
+static int debug_latency;
-static unsigned int fdsr = 0;
+static unsigned int fdsr;
/* options */
-static unsigned int combfilter = 0;
-static unsigned int lumafilter = 0;
+static unsigned int combfilter;
+static unsigned int lumafilter;
static unsigned int automute = 1;
-static unsigned int chroma_agc = 0;
+static unsigned int chroma_agc;
static unsigned int adc_crush = 1;
static unsigned int whitecrush_upper = 0xCF;
static unsigned int whitecrush_lower = 0x7F;
-static unsigned int vcr_hack = 0;
-static unsigned int irq_iswitch = 0;
+static unsigned int vcr_hack;
+static unsigned int irq_iswitch;
static unsigned int uv_ratio = 50;
-static unsigned int full_luma_range = 0;
-static unsigned int coring = 0;
+static unsigned int full_luma_range;
+static unsigned int coring;
extern int no_overlay;
/* API features (turn on/off stuff for testing) */
static unsigned int v4l2 = 1;
-
/* insmod args */
module_param(bttv_verbose, int, 0644);
module_param(bttv_gpio, int, 0644);
@@ -215,7 +214,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
we can capture, of the first and second field. */
.vbistart = { 7,320 },
},{
- .v4l2_id = V4L2_STD_NTSC_M,
+ .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
.name = "NTSC",
.Fsc = 28636363,
.swidth = 768,
@@ -685,16 +684,16 @@ int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit)
return 1;
/* is it free? */
- down(&btv->reslock);
+ mutex_lock(&btv->reslock);
if (btv->resources & bit) {
/* no, someone else uses it */
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
return 0;
}
/* it's free, grab it */
fh->resources |= bit;
btv->resources |= bit;
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
return 1;
}
@@ -717,10 +716,10 @@ void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
/* trying to free ressources not allocated by us ... */
printk("bttv: BUG! (btres)\n");
}
- down(&btv->reslock);
+ mutex_lock(&btv->reslock);
fh->resources &= ~bits;
btv->resources &= ~bits;
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
}
/* ----------------------------------------------------------------------- */
@@ -1537,12 +1536,12 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
case VIDIOCSFREQ:
{
unsigned long *freq = arg;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->freq=*freq;
bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,*freq);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1572,10 +1571,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (v->mode >= BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_tvnorm(btv,v->mode);
bttv_call_i2c_clients(btv,cmd,v);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1612,17 +1611,17 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (v->norm >= BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
if (channel == btv->input &&
v->norm == btv->tvnorm) {
/* nothing to do */
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
btv->tvnorm = v->norm;
set_input(btv,v->channel);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1635,14 +1634,14 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
v->flags |= VIDEO_AUDIO_MUTABLE;
v->mode = VIDEO_SOUND_MONO;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
bttv_call_i2c_clients(btv,cmd,v);
/* card specific hooks */
if (btv->audio_hook)
btv->audio_hook(btv,v,0);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOCSAUDIO:
@@ -1653,7 +1652,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (audio >= bttv_tvcards[btv->c.type].audio_inputs)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE);
bttv_call_i2c_clients(btv,cmd,v);
@@ -1661,7 +1660,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (btv->audio_hook)
btv->audio_hook(btv,v,1);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1695,10 +1694,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (i == BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_tvnorm(btv,i);
i2c_vidiocschan(btv);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_QUERYSTD:
@@ -1756,9 +1755,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (*i > bttv_tvcards[btv->c.type].video_inputs)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_input(btv,*i);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1770,7 +1769,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
memset(t,0,sizeof(*t));
strcpy(t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
@@ -1805,7 +1804,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
}
}
/* FIXME: fill capability+audmode */
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_S_TUNER:
@@ -1816,7 +1815,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
{
struct video_audio va;
memset(&va, 0, sizeof(struct video_audio));
@@ -1833,7 +1832,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (btv->audio_hook)
btv->audio_hook(btv,&va,1);
}
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1854,12 +1853,12 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (unlikely (f->type != V4L2_TUNER_ANALOG_TV))
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->freq = f->frequency;
bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,btv->freq);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_LOG_STATUS:
@@ -3157,7 +3156,7 @@ static int radio_open(struct inode *inode, struct file *file)
return -ENODEV;
dprintk("bttv%d: open called (radio)\n",btv->c.nr);
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->radio_user++;
@@ -3166,7 +3165,7 @@ static int radio_open(struct inode *inode, struct file *file)
bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
audio_mux(btv,AUDIO_RADIO);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -3921,8 +3920,8 @@ static int __devinit bttv_probe(struct pci_dev *dev,
sprintf(btv->c.name,"bttv%d",btv->c.nr);
/* initialize structs / fill in defaults */
- init_MUTEX(&btv->lock);
- init_MUTEX(&btv->reslock);
+ mutex_init(&btv->lock);
+ mutex_init(&btv->reslock);
spin_lock_init(&btv->s_lock);
spin_lock_init(&btv->gpio_lock);
init_waitqueue_head(&btv->gpioq);
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index 748d630c7fe..614c1201855 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -41,9 +41,9 @@ static struct i2c_client bttv_i2c_client_template;
static int attach_inform(struct i2c_client *client);
-static int i2c_debug = 0;
-static int i2c_hw = 0;
-static int i2c_scan = 0;
+static int i2c_debug;
+static int i2c_hw;
+static int i2c_scan;
module_param(i2c_debug, int, 0644);
module_param(i2c_hw, int, 0444);
module_param(i2c_scan, int, 0444);
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index dd00c20ab95..9cb72f176f7 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -35,6 +35,7 @@
#include <linux/videodev.h>
#include <linux/pci.h>
#include <linux/input.h>
+#include <linux/mutex.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
@@ -309,9 +310,9 @@ struct bttv {
/* locking */
spinlock_t s_lock;
- struct semaphore lock;
+ struct mutex lock;
int resources;
- struct semaphore reslock;
+ struct mutex reslock;
#ifdef VIDIOC_G_PRIORITY
struct v4l2_prio_state prio;
#endif
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index 297c32ab51e..840fe017712 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -167,29 +167,32 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user
if (kp->clipcount > 2048)
return -EINVAL;
if (kp->clipcount) {
- struct v4l2_clip32 *uclips = compat_ptr(up->clips);
- struct v4l2_clip *kclips;
+ struct v4l2_clip32 __user *uclips;
+ struct v4l2_clip __user *kclips;
int n = kp->clipcount;
+ compat_caddr_t p;
+ if (get_user(p, &up->clips))
+ return -EFAULT;
+ uclips = compat_ptr(p);
kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
kp->clips = kclips;
while (--n >= 0) {
- if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) ||
- copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+ if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+ return -EFAULT;
+ if (put_user(n ? kclips + 1 : NULL, &kclips->next))
return -EFAULT;
- kclips->next = n ? kclips + 1 : 0;
uclips += 1;
kclips += 1;
}
} else
- kp->clips = 0;
+ kp->clips = NULL;
return 0;
}
static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) ||
- copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
+ if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
put_user(kp->field, &up->field) ||
put_user(kp->chromakey, &up->chromakey) ||
put_user(kp->clipcount, &up->clipcount))
@@ -199,33 +202,29 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user
static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
return 0;
}
static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
+ return -EFAULT;
return 0;
}
@@ -279,18 +278,16 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_standard)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_standard)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_standard)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_standard)))
+ return -EFAULT;
return 0;
}
@@ -328,18 +325,16 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32
static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
+ return -EFAULT;
return 0;
}
@@ -380,11 +375,13 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
break;
case V4L2_MEMORY_USERPTR:
{
- unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr);
+ compat_long_t tmp;
- if(get_user(kp->length, &up->length) ||
- get_user(kp->m.userptr, &tmp))
- return -EFAULT;
+ if (get_user(kp->length, &up->length) ||
+ get_user(tmp, &up->m.userptr))
+ return -EFAULT;
+
+ kp->m.userptr = (unsigned long)compat_ptr(tmp);
}
break;
case V4L2_MEMORY_OVERLAY:
@@ -468,33 +465,29 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) ||
- copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) ||
- copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
+ return -EFAULT;
return 0;
}
static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) ||
- copy_from_user(kp, up, sizeof(struct v4l2_input)))
- return -EFAULT;
+ if (copy_from_user(kp, up, sizeof(struct v4l2_input)))
+ return -EFAULT;
return 0;
}
static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) ||
- copy_to_user(up, kp, sizeof(struct v4l2_input)))
- return -EFAULT;
+ if (copy_to_user(up, kp, sizeof(struct v4l2_input)))
+ return -EFAULT;
return 0;
}
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 1d75a42629d..08ffd1f325f 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL");
static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
-int cx25840_debug = 0;
+static int cx25840_debug;
module_param_named(debug,cx25840_debug, int, 0644);
@@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client)
cx25840_write(client, 0x808, 0xff);
cx25840_write(client, 0x80b, 0x10);
} else if (std & V4L2_STD_NTSC) {
- /* NTSC */
- if (state->pvr150_workaround) {
- /* Certain Hauppauge PVR150 models have a hardware bug
- that causes audio to drop out. For these models the
- audio standard must be set explicitly.
- To be precise: it affects cards with tuner models
- 85, 99 and 112 (model numbers from tveeprom). */
- if (std == V4L2_STD_NTSC_M_JP) {
- /* Japan uses EIAJ audio standard */
- cx25840_write(client, 0x808, 0x2f);
- } else {
- /* Others use the BTSC audio standard */
- cx25840_write(client, 0x808, 0x1f);
- }
- /* South Korea uses the A2-M (aka Zweiton M) audio
- standard, and should set 0x808 to 0x3f, but I don't
- know how to detect this. */
- } else if (std == V4L2_STD_NTSC_M_JP) {
+ /* Certain Hauppauge PVR150 models have a hardware bug
+ that causes audio to drop out. For these models the
+ audio standard must be set explicitly.
+ To be precise: it affects cards with tuner models
+ 85, 99 and 112 (model numbers from tveeprom). */
+ int hw_fix = state->pvr150_workaround;
+
+ if (std == V4L2_STD_NTSC_M_JP) {
/* Japan uses EIAJ audio standard */
- cx25840_write(client, 0x808, 0xf7);
+ cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7);
+ } else if (std == V4L2_STD_NTSC_M_KR) {
+ /* South Korea uses A2 audio standard */
+ cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8);
} else {
/* Others use the BTSC audio standard */
- cx25840_write(client, 0x808, 0xf6);
+ cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
}
- /* South Korea uses the A2-M (aka Zweiton M) audio standard,
- and should set 0x808 to 0xf8, but I don't know how to
- detect this. */
cx25840_write(client, 0x80b, 0x00);
}
@@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
u8 fmt=0; /* zero is autodetect */
/* First tests should be against specific std */
- if (std & V4L2_STD_NTSC_M_JP) {
+ if (std == V4L2_STD_NTSC_M_JP) {
fmt=0x2;
- } else if (std & V4L2_STD_NTSC_443) {
+ } else if (std == V4L2_STD_NTSC_443) {
fmt=0x3;
- } else if (std & V4L2_STD_PAL_M) {
+ } else if (std == V4L2_STD_PAL_M) {
fmt=0x5;
- } else if (std & V4L2_STD_PAL_N) {
+ } else if (std == V4L2_STD_PAL_N) {
fmt=0x6;
- } else if (std & V4L2_STD_PAL_Nc) {
+ } else if (std == V4L2_STD_PAL_Nc) {
fmt=0x7;
- } else if (std & V4L2_STD_PAL_60) {
+ } else if (std == V4L2_STD_PAL_60) {
fmt=0x8;
} else {
/* Then, test against generic ones */
@@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
}
switch (fmt) {
- case 0x1: return V4L2_STD_NTSC_M;
+ case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR;
case 0x2: return V4L2_STD_NTSC_M_JP;
case 0x3: return V4L2_STD_NTSC_443;
case 0x4: return V4L2_STD_PAL;
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 76fcb4e995c..e99dfbbf3e9 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -31,8 +31,8 @@ config VIDEO_CX88_DVB
config VIDEO_CX88_ALSA
tristate "ALSA DMA audio support"
- depends on VIDEO_CX88 && SND
- select SND_PCM_OSS
+ depends on VIDEO_CX88 && SND && EXPERIMENTAL
+ select SND_PCM
---help---
This is a video4linux driver for direct (DMA) audio on
Conexant 2388x based TV cards.
@@ -49,6 +49,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS
default y
depends on VIDEO_CX88_DVB
select DVB_MT352
+ select VIDEO_CX88_VP3054
select DVB_OR51132
select DVB_CX22702
select DVB_LGDT330X
@@ -70,6 +71,16 @@ config VIDEO_CX88_DVB_MT352
This adds DVB-T support for cards based on the
Connexant 2388x chip and the MT352 demodulator.
+config VIDEO_CX88_VP3054
+ tristate "VP-3054 Secondary I2C Bus Support"
+ default m
+ depends on DVB_MT352
+ ---help---
+ This adds DVB-T support for cards based on the
+ Connexant 2388x chip and the MT352 demodulator,
+ which also require support for the VP-3054
+ Secondary I2C bus, such at DNTV Live! DVB-T Pro.
+
config VIDEO_CX88_DVB_OR51132
bool "OR51132 ATSC Support"
default y
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index e4b2134fe56..2b902784fac 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -4,7 +4,9 @@ cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
+obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
+obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
@@ -17,6 +19,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1
extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1
extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1
-extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1
+extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1
EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 7695b521eb3..2acccd6d49b 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -116,7 +116,7 @@ MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
"{{Conexant,23882},"
"{{Conexant,23883}");
-static unsigned int debug = 0;
+static unsigned int debug;
module_param(debug,int,0644);
MODULE_PARM_DESC(debug,"enable debug messages");
@@ -128,7 +128,7 @@ MODULE_PARM_DESC(debug,"enable debug messages");
* BOARD Specific: Sets audio DMA
*/
-int _cx88_start_audio_dma(snd_cx88_card_t *chip)
+static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
{
struct cx88_buffer *buf = chip->buf;
struct cx88_core *core=chip->core;
@@ -173,7 +173,7 @@ int _cx88_start_audio_dma(snd_cx88_card_t *chip)
/*
* BOARD Specific: Resets audio DMA
*/
-int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
+static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
{
struct cx88_core *core=chip->core;
dprintk(1, "Stopping audio DMA\n");
@@ -333,10 +333,10 @@ static snd_pcm_hardware_t snd_cx88_digital_hw = {
.channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = (2*2048),
- .period_bytes_min = 256,
+ .period_bytes_min = 2048,
.period_bytes_max = 2048,
.periods_min = 2,
- .periods_max = 16,
+ .periods_max = 2,
};
/*
@@ -613,7 +613,7 @@ static snd_kcontrol_new_t snd_cx88_capture_volume = {
* Only boards with eeprom and byte 1 at eeprom=1 have it
*/
-struct pci_device_id cx88_audio_pci_tbl[] = {
+static struct pci_device_id cx88_audio_pci_tbl[] = {
{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0, }
@@ -653,7 +653,7 @@ static void snd_cx88_dev_free(snd_card_t * card)
* Alsa Constructor - Component probe
*/
-static int devno=0;
+static int devno;
static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci,
snd_cx88_card_t **rchip)
{
@@ -805,7 +805,6 @@ static struct pci_driver cx88_audio_pci_driver = {
.id_table = cx88_audio_pci_tbl,
.probe = cx88_audio_initdev,
.remove = cx88_audio_finidev,
- SND_PCI_PM_CALLBACKS
};
/****************************************************************************
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index ad2f565f522..1bc999247fd 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1246,6 +1246,11 @@ struct cx88_subid cx88_subids[] = {
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
},{
.subvendor = 0x18ac,
+ .subdevice = 0xdb54,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+ /* Re-branded DViCO: DigitalNow DVB-T Dual */
+ },{
+ .subvendor = 0x18ac,
.subdevice = 0xdb11,
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
/* Re-branded DViCO: UltraView DVB-T Plus */
@@ -1293,6 +1298,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
switch (tv.model)
{
case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
+ case 34519: /* WinTV-PCI-FM */
case 90002: /* Nova-T-PCI (9002) */
case 92001: /* Nova-S-Plus (Video and IR) */
case 92002: /* Nova-S-Plus (Video and IR) */
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 194446f28c5..3720f24a25c 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -32,6 +32,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
+#include <linux/mutex.h>
#include "cx88.h"
#include <media/v4l2-common.h>
@@ -75,7 +76,7 @@ MODULE_PARM_DESC(nocomb,"disable comb filter");
static unsigned int cx88_devcount;
static LIST_HEAD(cx88_devlist);
-static DECLARE_MUTEX(devlist);
+static DEFINE_MUTEX(devlist);
#define NO_SYNC_LINE (-1U)
@@ -786,12 +787,14 @@ static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
int cx88_start_audio_dma(struct cx88_core *core)
{
+ /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
+ int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
/* setup fifo + format */
- cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
- cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
- cx_write(MO_AUDD_LNGTH, 128); /* fifo bpl size */
- cx_write(MO_AUDR_LNGTH, 128); /* fifo bpl size */
+ cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
+ cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
/* start dma */
cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
@@ -1036,7 +1039,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
struct list_head *item;
int i;
- down(&devlist);
+ mutex_lock(&devlist);
list_for_each(item,&cx88_devlist) {
core = list_entry(item, struct cx88_core, devlist);
if (pci->bus->number != core->pci_bus)
@@ -1047,7 +1050,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
if (0 != get_ressources(core,pci))
goto fail_unlock;
atomic_inc(&core->refcount);
- up(&devlist);
+ mutex_unlock(&devlist);
return core;
}
core = kzalloc(sizeof(*core),GFP_KERNEL);
@@ -1122,13 +1125,13 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
cx88_card_setup(core);
cx88_ir_init(core,pci);
- up(&devlist);
+ mutex_unlock(&devlist);
return core;
fail_free:
kfree(core);
fail_unlock:
- up(&devlist);
+ mutex_unlock(&devlist);
return NULL;
}
@@ -1140,14 +1143,14 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
if (!atomic_dec_and_test(&core->refcount))
return;
- down(&devlist);
+ mutex_lock(&devlist);
cx88_ir_fini(core);
if (0 == core->i2c_rc)
i2c_bit_del_bus(&core->i2c_adap);
list_del(&core->devlist);
iounmap(core->lmmio);
cx88_devcount--;
- up(&devlist);
+ mutex_unlock(&devlist);
kfree(core);
}
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index da2ad5c4b55..165d948624a 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -482,6 +482,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
switch (core->board) {
case CX88_BOARD_DNTV_LIVE_DVB_T:
case CX88_BOARD_KWORLD_DVB_T:
+ case CX88_BOARD_KWORLD_DVB_T_CX22702:
ir_codes = ir_codes_dntv_live_dvb_t;
ir->gpio_addr = MO_GP1_IO;
ir->mask_keycode = 0x1f;
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 24118e43e73..da8d97ce0c4 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -60,6 +60,11 @@ static unsigned int audio_debug = 0;
module_param(audio_debug, int, 0644);
MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
+static unsigned int always_analog = 0;
+module_param(always_analog,int,0644);
+MODULE_PARM_DESC(always_analog,"force analog audio out");
+
+
#define dprintk(fmt, arg...) if (audio_debug) \
printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
@@ -155,7 +160,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
cx_write(AUD_I2SOUTPUTCNTL, 1);
cx_write(AUD_I2SCNTL, 0);
/* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
- } else {
+ }
+ if ((always_analog) || (!cx88_boards[core->board].blackbird)) {
ctl |= EN_DAC_ENABLE;
cx_write(AUD_CTL, ctl);
}
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
index 372cd29cedb..751a754a45e 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -32,6 +32,10 @@
#include "cx88-vp3054-i2c.h"
+MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
+MODULE_LICENSE("GPL");
+
/* ----------------------------------------------------------------------- */
static void vp3054_bit_setscl(void *data, int state)
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index dff3893f32f..e5ee8bceb21 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -139,6 +139,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
{
int ret, byte;
+ if (dev->state & DEV_DISCONNECTED)
+ return(-ENODEV);
+
em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
@@ -165,6 +168,9 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
u8 val;
int ret;
+ if (dev->state & DEV_DISCONNECTED)
+ return(-ENODEV);
+
em28xx_regdbg("req=%02x, reg=%02x:", req, reg);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
@@ -195,7 +201,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
int ret;
/*usb_control_msg seems to expect a kmalloced buffer */
- unsigned char *bufs = kmalloc(len, GFP_KERNEL);
+ unsigned char *bufs;
+
+ if (dev->state & DEV_DISCONNECTED)
+ return(-ENODEV);
+
+ bufs = kmalloc(len, GFP_KERNEL);
em28xx_regdbg("req=%02x reg=%02x:", req, reg);
@@ -212,7 +223,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, bufs, len, HZ);
- mdelay(5); /* FIXME: magic number */
+ msleep(5); /* FIXME: magic number */
kfree(bufs);
return ret;
}
@@ -253,7 +264,7 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val)
if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
return ret;
else if (((u8) ret) & 0x01) {
- em28xx_warn ("AC97 command still being exectuted: not handled properly!\n");
+ em28xx_warn ("AC97 command still being executed: not handled properly!\n");
}
return 0;
}
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 0591a705b7a..6ca8631bc36 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -78,7 +78,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
ret = dev->em28xx_read_reg(dev, 0x05);
if (ret == 0x80 + len - 1)
return len;
- mdelay(5);
+ msleep(5);
}
em28xx_warn("i2c write timed out\n");
return -EIO;
@@ -138,7 +138,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
return -ENODEV;
else if (msg == 0x84)
return 0;
- mdelay(5);
+ msleep(5);
}
return -ENODEV;
}
@@ -278,9 +278,9 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
msgs[i].buf,
msgs[i].len,
i == num - 1);
- if (rc < 0)
- goto err;
}
+ if (rc < 0)
+ goto err;
if (i2c_debug>=2)
printk("\n");
}
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 9b94f77d6fd..30dfa5370c7 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -76,6 +76,58 @@ static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = {
[ 0x40 ] = KEY_ZOOM,
};
+static IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
+ [ 0x3a ] = KEY_KP0,
+ [ 0x31 ] = KEY_KP1,
+ [ 0x32 ] = KEY_KP2,
+ [ 0x33 ] = KEY_KP3,
+ [ 0x34 ] = KEY_KP4,
+ [ 0x35 ] = KEY_KP5,
+ [ 0x36 ] = KEY_KP6,
+ [ 0x37 ] = KEY_KP7,
+ [ 0x38 ] = KEY_KP8,
+ [ 0x39 ] = KEY_KP9,
+
+ [ 0x2f ] = KEY_POWER,
+
+ [ 0x2e ] = KEY_P,
+ [ 0x1f ] = KEY_L,
+ [ 0x2b ] = KEY_I,
+
+ [ 0x2d ] = KEY_ZOOM,
+ [ 0x1e ] = KEY_ZOOM,
+ [ 0x1b ] = KEY_VOLUMEUP,
+ [ 0x0f ] = KEY_VOLUMEDOWN,
+ [ 0x17 ] = KEY_CHANNELUP,
+ [ 0x1c ] = KEY_CHANNELDOWN,
+ [ 0x25 ] = KEY_INFO,
+
+ [ 0x3c ] = KEY_MUTE,
+
+ [ 0x3d ] = KEY_LEFT,
+ [ 0x3b ] = KEY_RIGHT,
+
+ [ 0x3f ] = KEY_UP,
+ [ 0x3e ] = KEY_DOWN,
+ [ 0x1a ] = KEY_PAUSE,
+
+ [ 0x1d ] = KEY_MENU,
+ [ 0x19 ] = KEY_PLAY,
+ [ 0x16 ] = KEY_REWIND,
+ [ 0x13 ] = KEY_FORWARD,
+ [ 0x15 ] = KEY_PAUSE,
+ [ 0x0e ] = KEY_REWIND,
+ [ 0x0d ] = KEY_PLAY,
+ [ 0x0b ] = KEY_STOP,
+ [ 0x07 ] = KEY_FORWARD,
+ [ 0x27 ] = KEY_RECORD,
+ [ 0x26 ] = KEY_TUNER,
+ [ 0x29 ] = KEY_TEXT,
+ [ 0x2a ] = KEY_MEDIA,
+ [ 0x18 ] = KEY_EPG,
+ [ 0x27 ] = KEY_RECORD,
+};
+
/* ----------------------------------------------------------------------- */
static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
@@ -138,6 +190,28 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
+static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+ unsigned char buf[3];
+
+ /* poll IR chip */
+
+ if (3 != i2c_master_recv(&ir->c,buf,3)) {
+ dprintk("read error\n");
+ return -EIO;
+ }
+
+ dprintk("key %02x\n", buf[2]&0x3f);
+ if (buf[0]!=0x00){
+ return 0;
+ }
+
+ *ir_key = buf[2]&0x3f;
+ *ir_raw = buf[2]&0x3f;
+
+ return 1;
+}
+
/* ----------------------------------------------------------------------- */
void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
{
@@ -159,6 +233,9 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)");
break;
case (EM2820_BOARD_PINNACLE_USB_2):
+ ir->ir_codes = ir_codes_em_pinnacle_usb;
+ ir->get_key = get_key_pinnacle_usb;
+ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)");
break;
case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
ir->ir_codes = ir_codes_hauppauge_new;
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 3323dffe26a..94a14a2bb6d 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -6,6 +6,9 @@
Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Sascha Sommer <saschasommer@freenet.de>
+ Some parts based on SN9C10x PC Camera Controllers GPL driver made
+ by Luca Risolia <luca.risolia@studio.unibo.it>
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -29,6 +32,7 @@
#include <linux/i2c.h>
#include <linux/version.h>
#include <linux/video_decoder.h>
+#include <linux/mutex.h>
#include "em28xx.h"
#include <media/tuner.h>
@@ -191,7 +195,7 @@ static struct v4l2_queryctrl saa711x_qctrl[] = {
static struct usb_driver em28xx_usb_driver;
-static DECLARE_MUTEX(em28xx_sysfs_lock);
+static DEFINE_MUTEX(em28xx_sysfs_lock);
static DECLARE_RWSEM(em28xx_disconnect);
/********************* v4l2 interface ******************************************/
@@ -394,7 +398,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
*/
static void em28xx_release_resources(struct em28xx *dev)
{
- down(&em28xx_sysfs_lock);
+ mutex_lock(&em28xx_sysfs_lock);
em28xx_info("V4L2 device /dev/video%d deregistered\n",
dev->vdev->minor);
@@ -403,7 +407,7 @@ static void em28xx_release_resources(struct em28xx *dev)
/* video_unregister_device(dev->vbi_dev); */
em28xx_i2c_unregister(dev);
usb_put_dev(dev->udev);
- up(&em28xx_sysfs_lock);
+ mutex_unlock(&em28xx_sysfs_lock);
}
/*
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index 0b6c2096ec6..aad4a18aafd 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -484,7 +484,7 @@ static struct saa7146_ext_vv vv_data = {
};
static struct saa7146_extension extension = {
- .name = "hexium HV-PCI6/Orion",
+ .name = "hexium HV-PCI6 Orion",
.flags = 0, // SAA7146_USE_I2C_IRQ,
.pci_tbl = &pci_tbl[0],
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index 9b05a0ab776..69ed369c2f4 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -66,12 +66,12 @@ MODULE_LICENSE("GPL");
/* module parameters */
static int opmode = OPMODE_AUTO;
-int msp_debug = 0; /* msp_debug output */
-int msp_once = 0; /* no continous stereo monitoring */
-int msp_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france),
- the autoscan seems work well only with FM... */
+int msp_debug; /* msp_debug output */
+int msp_once; /* no continous stereo monitoring */
+int msp_amsound; /* hard-wire AM sound at 6.5 Hz (france),
+ the autoscan seems work well only with FM... */
int msp_standard = 1; /* Override auto detect of audio msp_standard, if needed. */
-int msp_dolby = 0;
+int msp_dolby;
int msp_stereo_thresh = 0x190; /* a2 threshold for stereo/bilingual
(msp34xxg only) 0x00a0-0x03c0 */
@@ -1031,8 +1031,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
default:
- /* nothing */
- break;
+ /* unknown */
+ return -EINVAL;
}
return 0;
}
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h
index 70a5ef8ba01..a9ac57d0700 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -6,14 +6,6 @@
/* ---------------------------------------------------------------------- */
-struct msp_matrix {
- int input;
- int output;
-};
-
-/* ioctl for MSP_SET_MATRIX will have to be registered */
-#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix)
-
/* This macro is allowed for *constants* only, gcc must calculate it
at compile time. Remember -- no floats in kernel mode */
#define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24)))
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
index 0bf1caac588..c7c9f3f8715 100644
--- a/drivers/media/video/mt20xx.c
+++ b/drivers/media/video/mt20xx.c
@@ -353,8 +353,8 @@ static int mt2032_init(struct i2c_client *c)
} while (xok != 1 );
t->xogc=xogc;
- t->tv_freq = mt2032_set_tv_freq;
- t->radio_freq = mt2032_set_radio_freq;
+ t->set_tv_freq = mt2032_set_tv_freq;
+ t->set_radio_freq = mt2032_set_radio_freq;
return(1);
}
@@ -481,8 +481,8 @@ static int mt2050_init(struct i2c_client *c)
i2c_master_recv(c,buf,1);
tuner_dbg("mt2050: sro is %x\n",buf[0]);
- t->tv_freq = mt2050_set_tv_freq;
- t->radio_freq = mt2050_set_radio_freq;
+ t->set_tv_freq = mt2050_set_tv_freq;
+ t->set_radio_freq = mt2050_set_radio_freq;
return 0;
}
@@ -494,8 +494,8 @@ int microtune_init(struct i2c_client *c)
int company_code;
memset(buf,0,sizeof(buf));
- t->tv_freq = NULL;
- t->radio_freq = NULL;
+ t->set_tv_freq = NULL;
+ t->set_radio_freq = NULL;
t->standby = NULL;
if (t->std & V4L2_STD_525_60) {
tuner_dbg("pinnacle ntsc\n");
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index b19c33434ea..f3fc361bec9 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -76,9 +76,9 @@ static volatile struct planb_registers *planb_regs;
static int def_norm = PLANB_DEF_NORM; /* default norm */
static int video_nr = -1;
-MODULE_PARM(def_norm, "i");
+module_param(def_norm, int, 0);
MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
-MODULE_PARM(video_nr,"i");
+module_param(video_nr, int, 0);
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index e70b17ef36e..d17395c4f55 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -50,15 +50,15 @@ static unsigned int rbds = 0;
static unsigned int plvl = 0;
static unsigned int bufblocks = 100;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
-MODULE_PARM(xtal, "i");
+module_param(xtal, int, 0);
MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
-MODULE_PARM(rbds, "i");
+module_param(rbds, int, 0);
MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0");
-MODULE_PARM(plvl, "i");
+module_param(plvl, int, 0);
MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
-MODULE_PARM(bufblocks, "i");
+module_param(bufblocks, int, 0);
MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100");
MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder");
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
index ae53063875f..6c161f2f5e2 100644
--- a/drivers/media/video/saa711x.c
+++ b/drivers/media/video/saa711x.c
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
#include <linux/video_decoder.h>
static int debug = 0;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)");
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 275d06af69d..5a35d3b6550 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -136,7 +136,7 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_FLYVIDEO2000] = {
/* "TC Wan" <tcwan@cs.usm.my> */
- .name = "LifeView FlyVIDEO2000",
+ .name = "LifeView/Typhoon FlyVIDEO2000",
.audio_clock = 0x00200000,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
.radio_type = UNSET,
@@ -1884,44 +1884,38 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x000,
},
},
- [SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS] = {
- .name = "Typhoon DVB-T Duo Digital/Analog Cardbus",
+ [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = {
+ .name = "LifeView/Typhoon FlyDVB-T Duo Cardbus",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_TDA8290,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.mpeg = SAA7134_MPEG_DVB,
- /* .gpiomask = 0xe000, */
+ .gpiomask = 0x00200000,
.inputs = {{
.name = name_tv,
.vmux = 1,
.amux = TV,
- /* .gpio = 0x0000, */
+ .gpio = 0x200000, /* GPIO21=High for TV input */
.tv = 1,
},{
+ .name = name_svideo, /* S-Video signal on S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+ },{
.name = name_comp1, /* Composite signal on S-Video input */
.vmux = 0,
.amux = LINE2,
- /* .gpio = 0x4000, */
},{
.name = name_comp2, /* Composite input */
.vmux = 3,
.amux = LINE2,
- /* .gpio = 0x4000, */
- },{
- .name = name_svideo, /* S-Video signal on S-Video input */
- .vmux = 8,
- .amux = LINE2,
- /* .gpio = 0x4000, */
}},
.radio = {
.name = name_radio,
- .amux = LINE2,
- },
- .mute = {
- .name = name_mute,
- .amux = LINE1,
+ .amux = TV,
+ .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */
},
},
[SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = {
@@ -2515,6 +2509,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 1 << 21,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -2529,6 +2524,11 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 8,
.amux = LINE1,
}},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
},
[SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = {
.name = "MSI TV@Anywhere plus",
@@ -2695,6 +2695,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_FLYVIDEO2000,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x4e42, /* Typhoon */
+ .subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */
+ .driver_data = SAA7134_BOARD_FLYVIDEO2000,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5168,
.subdevice = 0x0212, /* minipci, LR212 */
@@ -2929,7 +2935,7 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5168,
.subdevice = 0x0502, /* Cardbus version */
- .driver_data = SAA7134_BOARD_FLYDVBTDUO,
+ .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -2974,12 +2980,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x1370, /* cardbus version */
.driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
- },{ /* Typhoon DVB-T Duo Digital/Analog Cardbus */
+ },{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
- .subvendor = 0x4e42,
- .subdevice = 0x0502,
- .driver_data = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS,
+ .subvendor = 0x4e42, /* Typhoon */
+ .subdevice = 0x0502, /* LifeView LR502 OEM */
+ .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -3200,8 +3206,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004);
break;
- case SAA7134_BOARD_FLYDVBTDUO:
- case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS:
+ case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
/* turn the fan on */
saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 3983a6524ca..028904bd94a 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -31,6 +31,7 @@
#include <linux/sound.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include "saa7134-reg.h"
#include "saa7134.h"
@@ -84,7 +85,7 @@ MODULE_PARM_DESC(radio_nr, "radio device number");
MODULE_PARM_DESC(tuner, "tuner type");
MODULE_PARM_DESC(card, "card type");
-static DECLARE_MUTEX(devlist_lock);
+static DEFINE_MUTEX(devlist_lock);
LIST_HEAD(saa7134_devlist);
static LIST_HEAD(mops_list);
static unsigned int saa7134_devcount;
@@ -140,7 +141,7 @@ static int pending_call(struct notifier_block *self, unsigned long state,
return NOTIFY_DONE;
}
-static int pending_registered=0;
+static int pending_registered;
static struct notifier_block pending_notifier = {
.notifier_call = pending_call,
};
@@ -969,13 +970,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
pci_set_drvdata(pci_dev,dev);
saa7134_devcount++;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_for_each(item,&mops_list) {
mops = list_entry(item, struct saa7134_mpeg_ops, next);
mpeg_ops_attach(mops, dev);
}
list_add_tail(&dev->devlist,&saa7134_devlist);
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
/* check for signal */
saa7134_irq_video_intl(dev);
@@ -1031,13 +1032,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
saa7134_hwfini(dev);
/* unregister */
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_del(&dev->devlist);
list_for_each(item,&mops_list) {
mops = list_entry(item, struct saa7134_mpeg_ops, next);
mpeg_ops_detach(mops, dev);
}
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
saa7134_devcount--;
saa7134_i2c_unregister(dev);
@@ -1071,13 +1072,13 @@ int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
struct list_head *item;
struct saa7134_dev *dev;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_for_each(item,&saa7134_devlist) {
dev = list_entry(item, struct saa7134_dev, devlist);
mpeg_ops_attach(ops, dev);
}
list_add_tail(&ops->next,&mops_list);
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
return 0;
}
@@ -1086,13 +1087,13 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
struct list_head *item;
struct saa7134_dev *dev;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_del(&ops->next);
list_for_each(item,&saa7134_devlist) {
dev = list_entry(item, struct saa7134_dev, devlist);
mpeg_ops_detach(ops, dev);
}
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
}
EXPORT_SYMBOL(saa7134_ts_register);
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 399f9952596..1a536e86527 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -861,7 +861,7 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
&dev->i2c_adap);
break;
- case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS:
+ case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
&dev->i2c_adap);
break;
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 93268427750..afa4dcb3f96 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -180,8 +180,8 @@ static void tvaudio_init(struct saa7134_dev *dev)
saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff);
- // frame locked audio was reported not to be reliable
- saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x02);
+ /* frame locked audio is mandatory for NICAM */
+ saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01);
saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14);
saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50);
@@ -809,7 +809,12 @@ static int tvaudio_thread_ddep(void *data)
dprintk("ddep override: %s\n",stdres[audio_ddep]);
} else if (&card(dev).radio == dev->input) {
dprintk("FM Radio\n");
- norms = (0x0f << 2) | 0x01;
+ if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
+ norms = (0x11 << 2) | 0x01;
+ saa_dsp_writel(dev, 0x42c >> 2, 0x729555);
+ } else {
+ norms = (0x0f << 2) | 0x01;
+ }
} else {
/* (let chip) scan for sound carrier */
norms = 0;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index e70eae8d29b..3261d8bebdd 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -185,7 +185,7 @@ struct saa7134_format {
#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
#define SAA7134_BOARD_ADS_INSTANT_TV 58
#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
-#define SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS 60
+#define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60
#define SAA7134_BOARD_PHILIPS_TOUGH 61
#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
#define SAA7134_BOARD_KWORLD_XPERT 63
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 54fc33011ff..9d769264a32 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2012,7 +2012,6 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
{
struct saa7146 *saa = pci_get_drvdata(pdev);
- memset(saa, 0, sizeof(*saa));
saa->user = 0;
/* reset the saa7146 */
saawrite(0xffff0000, SAA7146_MC1);
@@ -2062,16 +2061,16 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
}
if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
- goto errvid;
+ goto errfree;
}
if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
- goto erraud;
+ goto errfree;
}
/* allocate 81920 byte buffer for clipping */
if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
- goto errosd;
+ goto errfree;
}
/* setup clipping registers */
saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
@@ -2085,15 +2084,11 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
I2CBusScan(saa);
return 0;
-errosd:
+errfree:
vfree(saa->osdbuf);
- saa->osdbuf = NULL;
-erraud:
vfree(saa->audbuf);
- saa->audbuf = NULL;
-errvid:
vfree(saa->vidbuf);
- saa->vidbuf = NULL;
+ saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;
err:
return -ENOMEM;
}
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index 2498b76df42..7b4fb282ac8 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -567,8 +567,8 @@ int tda8290_init(struct i2c_client *c)
}
tuner_info("tuner: type set to %s\n", c->name);
- t->tv_freq = set_tv_freq;
- t->radio_freq = set_radio_freq;
+ t->set_tv_freq = set_tv_freq;
+ t->set_radio_freq = set_radio_freq;
t->has_signal = has_signal;
t->standby = standby;
t->tda827x_lpsel = 0;
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 5815649bdc7..0d54f6c1982 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -231,7 +231,7 @@ static struct tvnorm tvnorms[] = {
cAudioIF_6_5 |
cVideoIF_38_90 ),
},{
- .std = V4L2_STD_NTSC_M,
+ .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
.name = "NTSC-M",
.b = ( cNegativeFmTV |
cQSS ),
@@ -619,6 +619,11 @@ static int tda9887_fixup_std(struct tda9887 *t)
tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
t->std = V4L2_STD_NTSC_M_JP;
break;
+ case 'k':
+ case 'K':
+ tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
+ t->std = V4L2_STD_NTSC_M_KR;
+ break;
case '-':
/* default parameter, do nothing */
break;
@@ -876,7 +881,7 @@ static int tda9887_resume(struct device * dev)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .id = -1, /* FIXME */
+ .id = I2C_DRIVERID_TDA9887,
.attach_adapter = tda9887_probe,
.detach_client = tda9887_detach,
.command = tda9887_command,
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index 921fe72f23d..c2b98f81c19 100644
--- a/drivers/media/video/tea5767.c
+++ b/drivers/media/video/tea5767.c
@@ -62,7 +62,7 @@ extern int tuner_debug;
#define TEA5767_PORT1_HIGH 0x01
-/* Forth register */
+/* Fourth register */
#define TEA5767_PORT2_HIGH 0x80
/* Chips stops working. Only I2C bus remains on */
#define TEA5767_STDBY 0x40
@@ -85,7 +85,7 @@ extern int tuner_debug;
/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
#define TEA5767_SRCH_IND 0x01
-/* Fiveth register */
+/* Fifth register */
/* By activating, it will use Xtal at 13 MHz as reference for divider */
#define TEA5767_PLLREF_ENABLE 0x80
@@ -109,13 +109,13 @@ extern int tuner_debug;
#define TEA5767_STEREO_MASK 0x80
#define TEA5767_IF_CNTR_MASK 0x7f
-/* Four register */
+/* Fourth register */
#define TEA5767_ADC_LEVEL_MASK 0xf0
/* should be 0 */
#define TEA5767_CHIP_ID_MASK 0x0f
-/* Fiveth register */
+/* Fifth register */
/* Reserved for future extensions */
#define TEA5767_RESERVED_MASK 0xff
@@ -220,19 +220,19 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
buffer[2] |= TEA5767_HIGH_LO_INJECT;
buffer[4] |= TEA5767_PLLREF_ENABLE;
- div = (frq * 4000 / 16 + 700000 + 225000 + 25000) / 50000;
+ div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_13MHz:
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
buffer[4] |= TEA5767_PLLREF_ENABLE;
- div = (frq * 4000 / 16 - 700000 - 225000 + 25000) / 50000;
+ div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_32768:
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
buffer[3] |= TEA5767_XTAL_32768;
/* const 700=4000*175 Khz - to adjust freq to right value */
- div = ((frq * 4000 / 16 - 700000 - 225000) + 16384) >> 15;
+ div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
break;
case TEA5767_HIGH_LO_32768:
default:
@@ -350,8 +350,8 @@ int tea5767_tuner_init(struct i2c_client *c)
tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio");
strlcpy(c->name, "tea5767", sizeof(c->name));
- t->tv_freq = set_tv_freq;
- t->radio_freq = set_radio_freq;
+ t->set_tv_freq = set_tv_freq;
+ t->set_radio_freq = set_radio_freq;
t->has_signal = tea5767_signal;
t->is_stereo = tea5767_stereo;
t->standby = tea5767_standby;
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index f30ef79d795..e7ee619d62c 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -82,7 +82,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->tv_freq) {
+ if (NULL == t->set_tv_freq) {
tuner_warn ("Tuner has no way to set tv freq\n");
return;
}
@@ -90,8 +90,14 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n",
freq / 16, freq % 16 * 100 / 16, tv_range[0],
tv_range[1]);
+ /* V4L2 spec: if the freq is not possible then the closest
+ possible value should be selected */
+ if (freq < tv_range[0] * 16)
+ freq = tv_range[0] * 16;
+ else
+ freq = tv_range[1] * 16;
}
- t->tv_freq(c, freq);
+ t->set_tv_freq(c, freq);
}
static void set_radio_freq(struct i2c_client *c, unsigned int freq)
@@ -102,18 +108,23 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->radio_freq) {
+ if (NULL == t->set_radio_freq) {
tuner_warn ("tuner has no way to set radio frequency\n");
return;
}
- if (freq <= radio_range[0] * 16000 || freq >= radio_range[1] * 16000) {
+ if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n",
freq / 16000, freq % 16000 * 100 / 16000,
radio_range[0], radio_range[1]);
+ /* V4L2 spec: if the freq is not possible then the closest
+ possible value should be selected */
+ if (freq < radio_range[0] * 16000)
+ freq = radio_range[0] * 16000;
+ else
+ freq = radio_range[1] * 16000;
}
- t->radio_freq(c, freq);
- return;
+ t->set_radio_freq(c, freq);
}
static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -125,15 +136,16 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
tuner_dbg("radio freq set to %lu.%02lu\n",
freq / 16000, freq % 16000 * 100 / 16000);
set_radio_freq(c, freq);
+ t->radio_freq = freq;
break;
case V4L2_TUNER_ANALOG_TV:
case V4L2_TUNER_DIGITAL_TV:
tuner_dbg("tv freq set to %lu.%02lu\n",
freq / 16, freq % 16 * 100 / 16);
set_tv_freq(c, freq);
+ t->tv_freq = freq;
break;
}
- t->freq = freq;
}
static void set_type(struct i2c_client *c, unsigned int type,
@@ -204,6 +216,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
buffer[3] = 0xa4;
i2c_master_send(c,buffer,4);
default_tuner_init(c);
+ break;
default:
default_tuner_init(c);
break;
@@ -212,7 +225,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
if (t->mode_mask == T_UNINITIALIZED)
t->mode_mask = new_mode_mask;
- set_freq(c, t->freq);
+ set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
c->adapter->name, c->driver->driver.name, c->addr << 1, type,
t->mode_mask);
@@ -353,6 +366,11 @@ static int tuner_fixup_std(struct tuner *t)
tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
t->std = V4L2_STD_NTSC_M_JP;
break;
+ case 'k':
+ case 'K':
+ tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
+ t->std = V4L2_STD_NTSC_M_KR;
+ break;
case '-':
/* default parameter, do nothing */
break;
@@ -377,11 +395,11 @@ static void tuner_status(struct i2c_client *client)
default: p = "undefined"; break;
}
if (t->mode == V4L2_TUNER_RADIO) {
- freq = t->freq / 16000;
- freq_fraction = (t->freq % 16000) * 100 / 16000;
+ freq = t->radio_freq / 16000;
+ freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
} else {
- freq = t->freq / 16;
- freq_fraction = (t->freq % 16) * 100 / 16;
+ freq = t->tv_freq / 16;
+ freq_fraction = (t->tv_freq % 16) * 100 / 16;
}
tuner_info("Tuner mode: %s\n", p);
tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
@@ -436,7 +454,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
printk("%02x ",buffer[i]);
printk("\n");
}
- /* TEA5767 autodetection code - only for addr = 0xc0 */
+ /* autodetection code based on the i2c addr */
if (!no_autodetect) {
switch (addr) {
case 0x42:
@@ -456,7 +474,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
t->type = TUNER_TEA5767;
t->mode_mask = T_RADIO;
t->mode = T_STANDBY;
- t->freq = 87.5 * 16; /* Sets freq to FM range */
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
default_mode_mask &= ~T_RADIO;
goto register_client;
@@ -469,7 +487,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
if (default_mode_mask != T_UNINITIALIZED) {
tuner_dbg ("Setting mode_mask to 0x%02x\n", default_mode_mask);
t->mode_mask = default_mode_mask;
- t->freq = 400 * 16; /* Sets freq to VHF High */
+ t->tv_freq = 400 * 16; /* Sets freq to VHF High */
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
default_mode_mask = T_UNINITIALIZED;
}
@@ -565,16 +584,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
set_addr(client, (struct tuner_setup *)arg);
break;
case AUDC_SET_RADIO:
- set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO");
+ if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
+ == EINVAL)
+ return 0;
+ if (t->radio_freq)
+ set_freq(client, t->radio_freq);
break;
case TUNER_SET_STANDBY:
- {
- if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
- return 0;
- if (t->standby)
- t->standby (client);
- break;
- }
+ if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+ return 0;
+ if (t->standby)
+ t->standby (client);
+ break;
case VIDIOCSAUDIO:
if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
return 0;
@@ -583,7 +604,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* Should be implemented, since bttv calls it */
tuner_dbg("VIDIOCSAUDIO not implemented.\n");
-
break;
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
@@ -609,8 +629,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (vc->norm < ARRAY_SIZE(map))
t->std = map[vc->norm];
tuner_fixup_std(t);
- if (t->freq)
- set_tv_freq(client, t->freq);
+ if (t->tv_freq)
+ set_tv_freq(client, t->tv_freq);
return 0;
}
case VIDIOCSFREQ:
@@ -684,15 +704,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
t->std = *id;
tuner_fixup_std(t);
- if (t->freq)
- set_freq(client, t->freq);
+ if (t->tv_freq)
+ set_freq(client, t->tv_freq);
break;
}
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *f = arg;
- t->freq = f->frequency;
switch_v4l2();
if (V4L2_TUNER_RADIO == f->type &&
V4L2_TUNER_RADIO != t->mode) {
@@ -700,7 +719,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
== EINVAL)
return 0;
}
- set_freq(client,t->freq);
+ set_freq(client,f->frequency);
break;
}
@@ -712,7 +731,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
switch_v4l2();
f->type = t->mode;
- f->frequency = t->freq;
+ f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
+ t->radio_freq : t->tv_freq;
break;
}
case VIDIOC_G_TUNER:
@@ -763,7 +783,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (V4L2_TUNER_RADIO == t->mode) {
t->audmode = tuner->audmode;
- set_radio_freq(client, t->freq);
+ set_radio_freq(client, t->radio_freq);
}
break;
}
@@ -791,8 +811,13 @@ static int tuner_resume(struct device *dev)
struct tuner *t = i2c_get_clientdata (c);
tuner_dbg ("resume\n");
- if (t->freq)
- set_freq(c, t->freq);
+ if (V4L2_TUNER_RADIO == t->mode) {
+ if (t->radio_freq)
+ set_freq(c, t->radio_freq);
+ } else {
+ if (t->tv_freq)
+ set_freq(c, t->tv_freq);
+ }
return 0;
}
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index e5fb7436583..37977ff4978 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -79,722 +79,16 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
#define TUNER_PLL_LOCKED 0x40
#define TUNER_STEREO_MK3 0x04
-#define TUNER_MAX_RANGES 3
-
-/* ---------------------------------------------------------------------- */
-
-struct tunertype
-{
- char *name;
-
- int count;
- struct {
- unsigned short thresh;
- unsigned char cb;
- } ranges[TUNER_MAX_RANGES];
- unsigned char config;
-};
-
-/*
- * The floats in the tuner struct are computed at compile time
- * by gcc and cast back to integers. Thus we don't violate the
- * "no float in kernel" rule.
+#define TUNER_PARAM_ANALOG 0 /* to be removed */
+/* FIXME:
+ * Right now, all tuners are using the first tuner_params[] array element
+ * for analog mode. In the future, we will be merging similar tuner
+ * definitions together, such that each tuner definition will have a
+ * tuner_params struct for each available video standard. At that point,
+ * TUNER_PARAM_ANALOG will be removed, and the tuner_params[] array
+ * element will be chosen based on the video standard in use.
+ *
*/
-static struct tunertype tuners[] = {
- /* 0-9 */
- [TUNER_TEMIC_PAL] = { /* TEMIC PAL */
- .name = "Temic PAL (4002 FH5)",
- .count = 3,
- .ranges = {
- { 16 * 140.25 /*MHz*/, 0x02, },
- { 16 * 463.25 /*MHz*/, 0x04, },
- { 16 * 999.99 , 0x01, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
- .name = "Philips PAL_I (FI1246 and compatibles)",
- .count = 3,
- .ranges = {
- { 16 * 140.25 /*MHz*/, 0xa0, },
- { 16 * 463.25 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
- .name = "Philips NTSC (FI1236,FM1236 and compatibles)",
- .count = 3,
- .ranges = {
- { 16 * 157.25 /*MHz*/, 0xa0, },
- { 16 * 451.25 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
- .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
- .count = 3,
- .ranges = {
- { 16 * 168.25 /*MHz*/, 0xa7, },
- { 16 * 447.25 /*MHz*/, 0x97, },
- { 16 * 999.99 , 0x37, },
- },
- .config = 0x8e,
- },
- [TUNER_ABSENT] = { /* Tuner Absent */
- .name = "NoTuner",
- .count = 1,
- .ranges = {
- { 0, 0x00, },
- },
- .config = 0x00,
- },
- [TUNER_PHILIPS_PAL] = { /* Philips PAL */
- .name = "Philips PAL_BG (FI1216 and compatibles)",
- .count = 3,
- .ranges = {
- { 16 * 168.25 /*MHz*/, 0xa0, },
- { 16 * 447.25 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
- .name = "Temic NTSC (4032 FY5)",
- .count = 3,
- .ranges = {
- { 16 * 157.25 /*MHz*/, 0x02, },
- { 16 * 463.25 /*MHz*/, 0x04, },
- { 16 * 999.99 , 0x01, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
- .name = "Temic PAL_I (4062 FY5)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0x02, },
- { 16 * 450.00 /*MHz*/, 0x04, },
- { 16 * 999.99 , 0x01, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
- .name = "Temic NTSC (4036 FY5)",
- .count = 3,
- .ranges = {
- { 16 * 157.25 /*MHz*/, 0xa0, },
- { 16 * 463.25 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
- .name = "Alps HSBH1",
- .count = 3,
- .ranges = {
- { 16 * 137.25 /*MHz*/, 0x01, },
- { 16 * 385.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
-
- /* 10-19 */
- [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
- .name = "Alps TSBE1",
- .count = 3,
- .ranges = {
- { 16 * 137.25 /*MHz*/, 0x01, },
- { 16 * 385.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
- .name = "Alps TSBB5",
- .count = 3,
- .ranges = {
- { 16 * 133.25 /*MHz*/, 0x01, },
- { 16 * 351.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
- .name = "Alps TSBE5",
- .count = 3,
- .ranges = {
- { 16 * 133.25 /*MHz*/, 0x01, },
- { 16 * 351.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
- .name = "Alps TSBC5",
- .count = 3,
- .ranges = {
- { 16 * 133.25 /*MHz*/, 0x01, },
- { 16 * 351.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
- .name = "Temic PAL_BG (4006FH5)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0xa0, },
- { 16 * 450.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
- .name = "Alps TSCH6",
- .count = 3,
- .ranges = {
- { 16 * 137.25 /*MHz*/, 0x14, },
- { 16 * 385.25 /*MHz*/, 0x12, },
- { 16 * 999.99 , 0x11, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
- .name = "Temic PAL_DK (4016 FY5)",
- .count = 3,
- .ranges = {
- { 16 * 168.25 /*MHz*/, 0xa0, },
- { 16 * 456.25 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
- .name = "Philips NTSC_M (MK2)",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
- .name = "Temic PAL_I (4066 FY5)",
- .count = 3,
- .ranges = {
- { 16 * 169.00 /*MHz*/, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
- .name = "Temic PAL* auto (4006 FN5)",
- .count = 3,
- .ranges = {
- { 16 * 169.00 /*MHz*/, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
-
- /* 20-29 */
- [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
- .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
- .count = 3,
- .ranges = {
- { 16 * 141.00 /*MHz*/, 0xa0, },
- { 16 * 464.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
- .name = "Temic NTSC (4039 FR5)",
- .count = 3,
- .ranges = {
- { 16 * 158.00 /*MHz*/, 0xa0, },
- { 16 * 453.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
- .name = "Temic PAL/SECAM multi (4046 FM5)",
- .count = 3,
- .ranges = {
- { 16 * 169.00 /*MHz*/, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
- .name = "Philips PAL_DK (FI1256 and compatibles)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0xa0, },
- { 16 * 450.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
- .name = "Philips PAL/SECAM multi (FQ1216ME)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0xa0, },
- { 16 * 450.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
- .name = "LG PAL_I+FM (TAPC-I001D)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0xa0, },
- { 16 * 450.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
- .name = "LG PAL_I (TAPC-I701D)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0xa0, },
- { 16 * 450.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
- .name = "LG NTSC+FM (TPI8NSR01F)",
- .count = 3,
- .ranges = {
- { 16 * 210.00 /*MHz*/, 0xa0, },
- { 16 * 497.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
- .name = "LG PAL_BG+FM (TPI8PSB01D)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0xa0, },
- { 16 * 450.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_LG_PAL] = { /* LGINNOTEK PAL */
- .name = "LG PAL_BG (TPI8PSB11D)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0xa0, },
- { 16 * 450.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
-
- /* 30-39 */
- [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
- .name = "Temic PAL* auto + FM (4009 FN5)",
- .count = 3,
- .ranges = {
- { 16 * 141.00 /*MHz*/, 0xa0, },
- { 16 * 464.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
- .name = "SHARP NTSC_JP (2U5JF5540)",
- .count = 3,
- .ranges = {
- { 16 * 137.25 /*MHz*/, 0x01, },
- { 16 * 317.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
- .name = "Samsung PAL TCPM9091PD27",
- .count = 3,
- .ranges = {
- { 16 * 169 /*MHz*/, 0xa0, },
- { 16 * 464 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_MT2032] = { /* Microtune PAL|NTSC */
- .name = "MT20xx universal",
- /* see mt20xx.c for details */ },
- [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
- .name = "Temic PAL_BG (4106 FH5)",
- .count = 3,
- .ranges = {
- { 16 * 141.00 /*MHz*/, 0xa0, },
- { 16 * 464.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
- .name = "Temic PAL_DK/SECAM_L (4012 FY5)",
- .count = 3,
- .ranges = {
- { 16 * 140.25 /*MHz*/, 0x02, },
- { 16 * 463.25 /*MHz*/, 0x04, },
- { 16 * 999.99 , 0x01, },
- },
- .config = 0x8e,
- },
- [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
- .name = "Temic NTSC (4136 FY5)",
- .count = 3,
- .ranges = {
- { 16 * 158.00 /*MHz*/, 0xa0, },
- { 16 * 453.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
- .name = "LG PAL (newer TAPC series)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0x01, },
- { 16 * 450.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
- .name = "Philips PAL/SECAM multi (FM1216ME MK3)",
- .count = 3,
- .ranges = {
- { 16 * 158.00 /*MHz*/, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
- [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
- .name = "LG NTSC (newer TAPC series)",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0x01, },
- { 16 * 450.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
-
- /* 40-49 */
- [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
- .name = "HITACHI V7-J180AT",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0x01, },
- { 16 * 450.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
- .name = "Philips PAL_MK (FI1216 MK)",
- .count = 3,
- .ranges = {
- { 16 * 140.25 /*MHz*/, 0x01, },
- { 16 * 463.25 /*MHz*/, 0xc2, },
- { 16 * 999.99 , 0xcf, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
- .name = "Philips 1236D ATSC/NTSC dual in",
- .count = 3,
- .ranges = {
- { 16 * 157.25 /*MHz*/, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
- .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
- .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
- [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
- .name = "Microtune 4049 FM5",
- .count = 3,
- .ranges = {
- { 16 * 141.00 /*MHz*/, 0xa0, },
- { 16 * 464.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
- .name = "Panasonic VP27s/ENGE4324D",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01, },
- { 16 * 454.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0xce,
- },
- [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
- .name = "LG NTSC (TAPE series)",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
- [TUNER_TNF_8831BGFF] = { /* Philips PAL */
- .name = "Tenna TNF 8831 BGFF)",
- .count = 3,
- .ranges = {
- { 16 * 161.25 /*MHz*/, 0xa0, },
- { 16 * 463.25 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
- .name = "Microtune 4042 FI5 ATSC/NTSC dual in",
- .count = 3,
- .ranges = {
- { 16 * 162.00 /*MHz*/, 0xa2, },
- { 16 * 457.00 /*MHz*/, 0x94, },
- { 16 * 999.99 , 0x31, },
- },
- .config = 0x8e,
- },
-
- /* 50-59 */
- [TUNER_TCL_2002N] = { /* TCL NTSC */
- .name = "TCL 2002N",
- .count = 3,
- .ranges = {
- { 16 * 172.00 /*MHz*/, 0x01, },
- { 16 * 448.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
- .name = "Philips PAL/SECAM_D (FM 1256 I-H3)",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
- [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
- .name = "Thomson DTT 7610 (ATSC/NTSC)",
- .count = 3,
- .ranges = {
- { 16 * 157.25 /*MHz*/, 0x39, },
- { 16 * 454.00 /*MHz*/, 0x3a, },
- { 16 * 999.99 , 0x3c, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
- .name = "Philips FQ1286",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x41, },
- { 16 * 454.00 /*MHz*/, 0x42, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
- .name = "tda8290+75",
- /* see tda8290.c for details */ },
- [TUNER_TCL_2002MB] = { /* TCL PAL */
- .name = "TCL 2002MB",
- .count = 3,
- .ranges = {
- { 16 * 170.00 /*MHz*/, 0x01, },
- { 16 * 450.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0xce,
- },
- [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
- .name = "Philips PAL/SECAM multi (FQ1216AME MK4)",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0xce,
- },
- [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
- .name = "Philips FQ1236A MK4",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
- [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
- .name = "Ymec TVision TVF-8531MF/8831MF/8731MF",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x90, },
- { 16 * 999.99 , 0x30, },
- },
- .config = 0x8e,
- },
- [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
- .name = "Ymec TVision TVF-5533MF",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01, },
- { 16 * 454.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
-
- /* 60-69 */
- [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
- /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
- .name = "Thomson DTT 761X (ATSC/NTSC)",
- .count = 3,
- .ranges = {
- { 16 * 145.25 /*MHz*/, 0x39, },
- { 16 * 415.25 /*MHz*/, 0x3a, },
- { 16 * 999.99 , 0x3c, },
- },
- .config = 0x8e,
- },
- [TUNER_TENA_9533_DI] = { /* Philips PAL */
- .name = "Tena TNF9533-D/IF/TNF9533-B/DF",
- .count = 3,
- .ranges = {
- { 16 * 160.25 /*MHz*/, 0x01, },
- { 16 * 464.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
- [TUNER_TEA5767] = { /* Philips RADIO */
- .name = "Philips TEA5767HN FM Radio",
- /* see tea5767.c for details */},
- [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
- .name = "Philips FMD1216ME MK3 Hybrid Tuner",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x51, },
- { 16 * 442.00 /*MHz*/, 0x52, },
- { 16 * 999.99 , 0x54, },
- },
- .config = 0x86,
- },
- [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */
- .name = "LG TDVS-H062F/TUA6034",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0x01 },
- { 16 * 455.00 /*MHz*/, 0x02 },
- { 16 * 999.99 , 0x04 },
- },
- .config = 0x8e,
- },
- [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
- .name = "Ymec TVF66T5-B/DFF",
- .count = 3,
- .ranges = {
- { 16 * 160.25 /*MHz*/, 0x01, },
- { 16 * 464.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */
- .name = "LG NTSC (TALN mini series)",
- .count = 3,
- .ranges = {
- { 16 * 137.25 /*MHz*/, 0x01, },
- { 16 * 373.25 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x08, },
- },
- .config = 0x8e,
- },
- [TUNER_PHILIPS_TD1316] = { /* Philips PAL */
- .name = "Philips TD1316 Hybrid Tuner",
- .count = 3,
- .ranges = {
- { 16 * 160.00 /*MHz*/, 0xa1, },
- { 16 * 442.00 /*MHz*/, 0xa2, },
- { 16 * 999.99 , 0xa4, },
- },
- .config = 0xc8,
- },
- [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
- .name = "Philips TUV1236D ATSC/NTSC dual in",
- .count = 3,
- .ranges = {
- { 16 * 157.25 /*MHz*/, 0x01, },
- { 16 * 454.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0xce,
- },
- [TUNER_TNF_5335MF] = { /* Philips NTSC */
- .name = "Tena TNF 5335 MF",
- .count = 3,
- .ranges = {
- { 16 * 157.25 /*MHz*/, 0x01, },
- { 16 * 454.00 /*MHz*/, 0x02, },
- { 16 * 999.99 , 0x04, },
- },
- .config = 0x8e,
- },
-};
-
-unsigned const int tuner_count = ARRAY_SIZE(tuners);
/* ---------------------------------------------------------------------- */
@@ -842,16 +136,23 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
u8 config, tuneraddr;
u16 div;
struct tunertype *tun;
- unsigned char buffer[4];
- int rc, IFPCoff, i;
+ u8 buffer[4];
+ int rc, IFPCoff, i, j;
tun = &tuners[t->type];
- for (i = 0; i < tun->count; i++) {
- if (freq > tun->ranges[i].thresh)
+ j = TUNER_PARAM_ANALOG;
+
+ for (i = 0; i < tun->params[j].count; i++) {
+ if (freq > tun->params[j].ranges[i].limit)
continue;
break;
}
- config = tun->ranges[i].cb;
+ if (i == tun->params[j].count) {
+ tuner_dbg("TV frequency out of range (%d > %d)",
+ freq, tun->params[j].ranges[i - 1].limit);
+ freq = tun->params[j].ranges[--i].limit;
+ }
+ config = tun->params[j].ranges[i].cb;
/* i == 0 -> VHF_LO */
/* i == 1 -> VHF_HI */
/* i == 2 -> UHF */
@@ -914,7 +215,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
case TUNER_MICROTUNE_4042FI5:
/* Set the charge pump for fast tuning */
- tun->config |= TUNER_CHARGE_PUMP;
+ tun->params[j].config |= TUNER_CHARGE_PUMP;
break;
case TUNER_PHILIPS_TUV1236D:
@@ -943,20 +244,6 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
break;
}
- /*
- * Philips FI1216MK2 remark from specification :
- * for channel selection involving band switching, and to ensure
- * smooth tuning to the desired channel without causing
- * unnecessary charge pump action, it is recommended to consider
- * the difference between wanted channel frequency and the
- * current channel frequency. Unnecessary charge pump action
- * will result in very low tuning voltage which may drive the
- * oscillator to extreme conditions.
- *
- * Progfou: specification says to send config data before
- * frequency in case (wanted frequency < current frequency).
- */
-
/* IFPCoff = Video Intermediate Frequency - Vif:
940 =16*58.75 NTSC/J (Japan)
732 =16*45.75 M/N STD
@@ -988,17 +275,18 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
offset / 16, offset % 16 * 100 / 16,
div);
- if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
- buffer[0] = tun->config;
+ if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
+ buffer[0] = tun->params[j].config;
buffer[1] = config;
buffer[2] = (div>>8) & 0x7f;
buffer[3] = div & 0xff;
} else {
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
- buffer[2] = tun->config;
+ buffer[2] = tun->params[j].config;
buffer[3] = config;
}
+ t->last_div = div;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
@@ -1024,10 +312,10 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
}
/* Set the charge pump for optimized phase noise figure */
- tun->config &= ~TUNER_CHARGE_PUMP;
+ tun->params[j].config &= ~TUNER_CHARGE_PUMP;
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
- buffer[2] = tun->config;
+ buffer[2] = tun->params[j].config;
buffer[3] = config;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
@@ -1041,13 +329,15 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
{
struct tunertype *tun;
struct tuner *t = i2c_get_clientdata(c);
- unsigned char buffer[4];
- unsigned div;
- int rc;
+ u8 buffer[4];
+ u16 div;
+ int rc, j;
tun = &tuners[t->type];
+ j = TUNER_PARAM_ANALOG;
+
div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */
- buffer[2] = (tun->config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
+ buffer[2] = (tun->params[j].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
switch (t->type) {
case TUNER_TENA_9533_DI:
@@ -1076,9 +366,19 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
}
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
+ if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
+ buffer[0] = buffer[2];
+ buffer[1] = buffer[3];
+ buffer[2] = (div>>8) & 0x7f;
+ buffer[3] = div & 0xff;
+ } else {
+ buffer[0] = (div>>8) & 0x7f;
+ buffer[1] = div & 0xff;
+ }
tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
+ t->last_div = div;
if (4 != (rc = i2c_master_send(c,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
@@ -1092,10 +392,10 @@ int default_tuner_init(struct i2c_client *c)
t->type, tuners[t->type].name);
strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
- t->tv_freq = default_set_tv_freq;
- t->radio_freq = default_set_radio_freq;
+ t->set_tv_freq = default_set_tv_freq;
+ t->set_radio_freq = default_set_radio_freq;
t->has_signal = tuner_signal;
- t->is_stereo = tuner_stereo;
+ t->is_stereo = tuner_stereo;
t->standby = NULL;
return 0;
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
new file mode 100644
index 00000000000..6fe781798d8
--- /dev/null
+++ b/drivers/media/video/tuner-types.c
@@ -0,0 +1,1406 @@
+/*
+ *
+ * i2c tv tuner chip device type database.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <media/tuner.h>
+#include <media/tuner-types.h>
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * The floats in the tuner struct are computed at compile time
+ * by gcc and cast back to integers. Thus we don't violate the
+ * "no float in kernel" rule.
+ *
+ * A tuner_range may be referenced by multiple tuner_params structs.
+ * There are many duplicates in here. Reusing tuner_range structs,
+ * rather than defining new ones for each tuner, will cut down on
+ * memory usage, and is preferred when possible.
+ *
+ * Each tuner_params array may contain one or more elements, one
+ * for each video standard.
+ *
+ * FIXME: Some tuner_range definitions are duplicated, and
+ * should be eliminated.
+ *
+ * FIXME: tunertype struct contains an element, has_tda988x.
+ * We must set this for all tunertypes that contain a tda988x
+ * chip, and then we can remove this setting from the various
+ * card structs.
+ */
+
+/* 0-9 */
+/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */
+
+static struct tuner_range tuner_philips_pal_i_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_i_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_i_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 451.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */
+
+static struct tuner_range tuner_philips_secam_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa7, },
+ { 16 * 447.25 /*MHz*/, 0x97, },
+ { 16 * 999.99 , 0x37, },
+};
+
+static struct tuner_params tuner_philips_secam_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_SECAM,
+ .ranges = tuner_philips_secam_ranges,
+ .count = ARRAY_SIZE(tuner_philips_secam_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_pal_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa0, },
+ { 16 * 447.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */
+
+static struct tuner_range tuner_temic_pal_i_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x02, },
+ { 16 * 450.00 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_i_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_i_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4036fy5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_alps_tsb_1_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 385.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_alps_tsb_1_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 10-19 */
+/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_alps_tsb_1_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_1_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */
+
+static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = {
+ { 16 * 133.25 /*MHz*/, 0x01, },
+ { 16 * 351.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_alps_tsbb5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */
+
+static struct tuner_params tuner_alps_tsbe5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */
+
+static struct tuner_params tuner_alps_tsbc5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4006fh5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4006fh5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4006fh5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */
+
+static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x14, },
+ { 16 * 385.25 /*MHz*/, 0x12, },
+ { 16 * 999.99 , 0x11, },
+};
+
+static struct tuner_params tuner_alps_tshc6_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_alps_tshc6_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_pal_dk_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa0, },
+ { 16 * 456.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_pal_dk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_dk_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_ntsc_m_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_ntsc_m_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_ntsc_m_ranges,
+ .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */
+
+static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_40x6f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4006fn5_multi_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_40x6f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 20-29 */
+/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = {
+ { 16 * 141.00 /*MHz*/, 0xa0, },
+ { 16 * 464.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4009f_5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0xa0, },
+ { 16 * 453.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4039fr5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4039fr5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4039fr5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4046fm5_pal_ranges[] = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4046fm5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4046fm5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4046fm5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */
+
+static struct tuner_range tuner_lg_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_dk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */
+
+static struct tuner_params tuner_philips_fq1216me_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */
+
+static struct tuner_params tuner_lg_pal_i_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */
+
+static struct tuner_params tuner_lg_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_ntsc_fm_ranges[] = {
+ { 16 * 210.00 /*MHz*/, 0xa0, },
+ { 16 * 497.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_lg_ntsc_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_ntsc_fm_ranges,
+ .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */
+
+static struct tuner_params tuner_lg_pal_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */
+
+static struct tuner_params tuner_lg_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 30-39 */
+/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */
+
+static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 317.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_sharp_2u5jf5540_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_sharp_2u5jf5540_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */
+
+static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = {
+ { 16 * 169 /*MHz*/, 0xa0, },
+ { 16 * 464 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_samsung_pal_tcpm9091pd27_ranges,
+ .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4106fh5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4012fy5_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_4012fy5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4012fy5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4012fy5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4136_fy5_ntsc_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0xa0, },
+ { 16 * 453.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4136_fy5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4136_fy5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4136_fy5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */
+
+static struct tuner_range tuner_lg_new_tapc_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_lg_pal_new_tapc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_fm1216me_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_fm1216me_mk3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
+
+static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 40-49 */
+/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */
+
+static struct tuner_params tuner_hitachi_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x01, },
+ { 16 * 463.25 /*MHz*/, 0xc2, },
+ { 16 * 999.99 , 0xcf, },
+};
+
+static struct tuner_params tuner_philips_pal_mk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_mk_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */
+
+static struct tuner_range tuner_philips_atsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_atsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_atsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_atsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_fm1236_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_fm1236_mk3_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_4in1_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_4in1_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_4in1_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_4in1_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */
+
+static struct tuner_params tuner_microtune_4049_fm5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */
+
+static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_panasonic_vp27_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_panasonic_vp27_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_ntsc_tape_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_lg_ntsc_tape_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_ntsc_tape_ranges,
+ .count = ARRAY_SIZE(tuner_lg_ntsc_tape_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
+
+static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
+ { 16 * 161.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_tnf_8831bgff_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tnf_8831bgff_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */
+
+static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
+ { 16 * 162.00 /*MHz*/, 0xa2, },
+ { 16 * 457.00 /*MHz*/, 0x94, },
+ { 16 * 999.99 , 0x31, },
+};
+
+static struct tuner_params tuner_microtune_4042fi5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_microtune_4042fi5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 50-59 */
+/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */
+
+static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = {
+ { 16 * 172.00 /*MHz*/, 0x01, },
+ { 16 * 448.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_tcl_2002n_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tcl_2002n_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fm1256_ih3_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fm1256_ih3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
+
+static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x39, },
+ { 16 * 454.00 /*MHz*/, 0x3a, },
+ { 16 * 999.99 , 0x3c, },
+};
+
+static struct tuner_params tuner_thomson_dtt7610_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_thomson_dtt7610_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x41, },
+ { 16 * 454.00 /*MHz*/, 0x42, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fq1286_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_fq1286_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */
+
+static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_tcl_2002mb_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tcl_2002mb_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fq12_6a___mk4_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fq12_6a___mk4_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */
+
+static struct tuner_params tuner_philips_fq1236a_mk4_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_fq12_6a___mk4_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_ymec_tvf_8531mf_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_ymec_tvf_8531mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_ymec_tvf_8531mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_ymec_tvf_5533mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 60-69 */
+/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */
+/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+
+static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
+ { 16 * 145.25 /*MHz*/, 0x39, },
+ { 16 * 415.25 /*MHz*/, 0x3a, },
+ { 16 * 999.99 , 0x3c, },
+};
+
+
+static struct tuner_params tuner_thomson_dtt761x_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_thomson_dtt761x_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
+
+static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = {
+ { 16 * 160.25 /*MHz*/, 0x01, },
+ { 16 * 464.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_tena_9533_di_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tuner_tena_9533_di_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tuner_tena_9533_di_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x51, },
+ { 16 * 442.00 /*MHz*/, 0x52, },
+ { 16 * 999.99 , 0x54, },
+};
+
+
+static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
+ .config = 0x86,
+ },
+};
+
+
+/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */
+
+static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01 },
+ { 16 * 455.00 /*MHz*/, 0x02 },
+ { 16 * 999.99 , 0x04 },
+};
+
+
+static struct tuner_params tuner_tua6034_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tua6034_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
+
+static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = {
+ { 16 * 160.25 /*MHz*/, 0x01, },
+ { 16 * 464.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 373.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_lg_taln_mini_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_taln_mini_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa1, },
+ { 16 * 442.00 /*MHz*/, 0xa2, },
+ { 16 * 999.99 , 0xa4, },
+};
+
+static struct tuner_params tuner_philips_td1316_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_td1316_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
+ .config = 0xc8,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
+
+static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+
+static struct tuner_params tuner_tuner_tuv1236d_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tuv1236d_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_tnf_5335mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tnf_5335mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 70-79 */
+/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
+
+static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
+ { 16 * 175.75 /*MHz*/, 0x01, },
+ { 16 * 410.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* --------------------------------------------------------------------- */
+
+struct tunertype tuners[] = {
+ /* 0-9 */
+ [TUNER_TEMIC_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL (4002 FH5)",
+ .params = tuner_temic_pal_params,
+ },
+ [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
+ .name = "Philips PAL_I (FI1246 and compatibles)",
+ .params = tuner_philips_pal_i_params,
+ },
+ [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
+ .name = "Philips NTSC (FI1236,FM1236 and compatibles)",
+ .params = tuner_philips_ntsc_params,
+ },
+ [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
+ .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
+ .params = tuner_philips_secam_params,
+ },
+ [TUNER_ABSENT] = { /* Tuner Absent */
+ .name = "NoTuner",
+ },
+ [TUNER_PHILIPS_PAL] = { /* Philips PAL */
+ .name = "Philips PAL_BG (FI1216 and compatibles)",
+ .params = tuner_philips_pal_params,
+ },
+ [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4032 FY5)",
+ .params = tuner_temic_ntsc_params,
+ },
+ [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
+ .name = "Temic PAL_I (4062 FY5)",
+ .params = tuner_temic_pal_i_params,
+ },
+ [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4036 FY5)",
+ .params = tuner_temic_4036fy5_ntsc_params,
+ },
+ [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
+ .name = "Alps HSBH1",
+ .params = tuner_alps_tsbh1_ntsc_params,
+ },
+
+ /* 10-19 */
+ [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
+ .name = "Alps TSBE1",
+ .params = tuner_alps_tsb_1_params,
+ },
+ [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
+ .name = "Alps TSBB5",
+ .params = tuner_alps_tsbb5_params,
+ },
+ [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
+ .name = "Alps TSBE5",
+ .params = tuner_alps_tsbe5_params,
+ },
+ [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
+ .name = "Alps TSBC5",
+ .params = tuner_alps_tsbc5_params,
+ },
+ [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4006FH5)",
+ .params = tuner_temic_4006fh5_params,
+ },
+ [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
+ .name = "Alps TSCH6",
+ .params = tuner_alps_tshc6_params,
+ },
+ [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
+ .name = "Temic PAL_DK (4016 FY5)",
+ .params = tuner_temic_pal_dk_params,
+ },
+ [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
+ .name = "Philips NTSC_M (MK2)",
+ .params = tuner_philips_ntsc_m_params,
+ },
+ [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
+ .name = "Temic PAL_I (4066 FY5)",
+ .params = tuner_temic_4066fy5_pal_i_params,
+ },
+ [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL* auto (4006 FN5)",
+ .params = tuner_temic_4006fn5_multi_params,
+ },
+
+ /* 20-29 */
+ [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
+ .params = tuner_temic_4009f_5_params,
+ },
+ [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4039 FR5)",
+ .params = tuner_temic_4039fr5_params,
+ },
+ [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
+ .name = "Temic PAL/SECAM multi (4046 FM5)",
+ .params = tuner_temic_4046fm5_params,
+ },
+ [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
+ .name = "Philips PAL_DK (FI1256 and compatibles)",
+ .params = tuner_philips_pal_dk_params,
+ },
+ [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FQ1216ME)",
+ .params = tuner_philips_fq1216me_params,
+ },
+ [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
+ .name = "LG PAL_I+FM (TAPC-I001D)",
+ .params = tuner_lg_pal_i_fm_params,
+ },
+ [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
+ .name = "LG PAL_I (TAPC-I701D)",
+ .params = tuner_lg_pal_i_params,
+ },
+ [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC+FM (TPI8NSR01F)",
+ .params = tuner_lg_ntsc_fm_params,
+ },
+ [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
+ .name = "LG PAL_BG+FM (TPI8PSB01D)",
+ .params = tuner_lg_pal_fm_params,
+ },
+ [TUNER_LG_PAL] = { /* LGINNOTEK PAL */
+ .name = "LG PAL_BG (TPI8PSB11D)",
+ .params = tuner_lg_pal_params,
+ },
+
+ /* 30-39 */
+ [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
+ .name = "Temic PAL* auto + FM (4009 FN5)",
+ .params = tuner_temic_4009_fn5_multi_pal_fm_params,
+ },
+ [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
+ .name = "SHARP NTSC_JP (2U5JF5540)",
+ .params = tuner_sharp_2u5jf5540_params,
+ },
+ [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
+ .name = "Samsung PAL TCPM9091PD27",
+ .params = tuner_samsung_pal_tcpm9091pd27_params,
+ },
+ [TUNER_MT2032] = { /* Microtune PAL|NTSC */
+ .name = "MT20xx universal",
+ /* see mt20xx.c for details */ },
+ [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4106 FH5)",
+ .params = tuner_temic_4106fh5_params,
+ },
+ [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
+ .name = "Temic PAL_DK/SECAM_L (4012 FY5)",
+ .params = tuner_temic_4012fy5_params,
+ },
+ [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4136 FY5)",
+ .params = tuner_temic_4136_fy5_params,
+ },
+ [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
+ .name = "LG PAL (newer TAPC series)",
+ .params = tuner_lg_pal_new_tapc_params,
+ },
+ [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FM1216ME MK3)",
+ .params = tuner_fm1216me_mk3_params,
+ },
+ [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (newer TAPC series)",
+ .params = tuner_lg_ntsc_new_tapc_params,
+ },
+
+ /* 40-49 */
+ [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
+ .name = "HITACHI V7-J180AT",
+ .params = tuner_hitachi_ntsc_params,
+ },
+ [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
+ .name = "Philips PAL_MK (FI1216 MK)",
+ .params = tuner_philips_pal_mk_params,
+ },
+ [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
+ .name = "Philips 1236D ATSC/NTSC dual in",
+ .params = tuner_philips_atsc_params,
+ },
+ [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
+ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
+ .params = tuner_fm1236_mk3_params,
+ },
+ [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
+ .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
+ .params = tuner_philips_4in1_params,
+ },
+ [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
+ .name = "Microtune 4049 FM5",
+ .params = tuner_microtune_4049_fm5_params,
+ },
+ [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
+ .name = "Panasonic VP27s/ENGE4324D",
+ .params = tuner_panasonic_vp27_params,
+ },
+ [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (TAPE series)",
+ .params = tuner_lg_ntsc_tape_params,
+ },
+ [TUNER_TNF_8831BGFF] = { /* Philips PAL */
+ .name = "Tenna TNF 8831 BGFF)",
+ .params = tuner_tnf_8831bgff_params,
+ },
+ [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
+ .name = "Microtune 4042 FI5 ATSC/NTSC dual in",
+ .params = tuner_microtune_4042fi5_params,
+ },
+
+ /* 50-59 */
+ [TUNER_TCL_2002N] = { /* TCL NTSC */
+ .name = "TCL 2002N",
+ .params = tuner_tcl_2002n_params,
+ },
+ [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM_D (FM 1256 I-H3)",
+ .params = tuner_philips_fm1256_ih3_params,
+ },
+ [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
+ .name = "Thomson DTT 7610 (ATSC/NTSC)",
+ .params = tuner_thomson_dtt7610_params,
+ },
+ [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
+ .name = "Philips FQ1286",
+ .params = tuner_philips_fq1286_params,
+ },
+ [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
+ .name = "tda8290+75",
+ /* see tda8290.c for details */ },
+ [TUNER_TCL_2002MB] = { /* TCL PAL */
+ .name = "TCL 2002MB",
+ .params = tuner_tcl_2002mb_params,
+ },
+ [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FQ1216AME MK4)",
+ .params = tuner_philips_fq1216ame_mk4_params,
+ },
+ [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
+ .name = "Philips FQ1236A MK4",
+ .params = tuner_philips_fq1236a_mk4_params,
+ },
+ [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
+ .name = "Ymec TVision TVF-8531MF/8831MF/8731MF",
+ .params = tuner_ymec_tvf_8531mf_params,
+ },
+ [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
+ .name = "Ymec TVision TVF-5533MF",
+ .params = tuner_ymec_tvf_5533mf_params,
+ },
+
+ /* 60-69 */
+ [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
+ /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+ .name = "Thomson DTT 761X (ATSC/NTSC)",
+ .params = tuner_thomson_dtt761x_params,
+ },
+ [TUNER_TENA_9533_DI] = { /* Philips PAL */
+ .name = "Tena TNF9533-D/IF/TNF9533-B/DF",
+ .params = tuner_tena_9533_di_params,
+ },
+ [TUNER_TEA5767] = { /* Philips RADIO */
+ .name = "Philips TEA5767HN FM Radio",
+ /* see tea5767.c for details */
+ },
+ [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
+ .name = "Philips FMD1216ME MK3 Hybrid Tuner",
+ .params = tuner_tuner_philips_fmd1216me_mk3_params,
+ },
+ [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */
+ .name = "LG TDVS-H062F/TUA6034",
+ .params = tuner_tua6034_params,
+ },
+ [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
+ .name = "Ymec TVF66T5-B/DFF",
+ .params = tuner_ymec_tvf66t5_b_dff_params,
+ },
+ [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (TALN mini series)",
+ .params = tuner_lg_taln_mini_params,
+ },
+ [TUNER_PHILIPS_TD1316] = { /* Philips PAL */
+ .name = "Philips TD1316 Hybrid Tuner",
+ .params = tuner_philips_td1316_params,
+ },
+ [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
+ .name = "Philips TUV1236D ATSC/NTSC dual in",
+ .params = tuner_tuner_tuv1236d_params,
+ },
+ [TUNER_TNF_5335MF] = { /* Philips NTSC */
+ .name = "Tena TNF 5335 MF",
+ .params = tuner_tnf_5335mf_params,
+ },
+
+ /* 70-79 */
+ [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */
+ .name = "Samsung TCPN 2121P30A",
+ .params = tuner_samsung_tcpn_2121p30a_params,
+ },
+};
+
+unsigned const int tuner_count = ARRAY_SIZE(tuners);
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 6d03b9b05c6..c8e5ad0e818 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -390,6 +390,14 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9840_SW, t);
}
+static int tda9840_checkit(struct CHIPSTATE *chip)
+{
+ int rc;
+ rc = chip_read(chip);
+ /* lower 5 bits should be 0 */
+ return ((rc & 0x1f) == 0) ? 1 : 0;
+}
+
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for tda985x */
@@ -1264,6 +1272,7 @@ static struct CHIPDESC chiplist[] = {
.addr_hi = I2C_TDA9840 >> 1,
.registers = 5,
+ .checkit = tda9840_checkit,
.getmode = tda9840_getmode,
.setmode = tda9840_setmode,
.checkmode = generic_checkmode,
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 5e71a354e87..582551b0969 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -190,7 +190,7 @@ hauppauge_tuner[] =
{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
{ TUNER_TCL_2002N, "TCL 2002N 6A"},
{ TUNER_PHILIPS_FM1236_MK3, "Philips FQ1236 MK3"},
- { TUNER_ABSENT, "Samsung TCPN 2121P30A"},
+ { TUNER_SAMSUNG_TCPN_2121P30A, "Samsung TCPN 2121P30A"},
{ TUNER_ABSENT, "Samsung TCPE 4121P30A"},
{ TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"},
/* 90-99 */
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 9094fa9f2ec..1864423b304 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -634,7 +634,7 @@ struct i2c_vbi_ram_value {
unsigned char values[26];
};
-struct i2c_vbi_ram_value vbi_ram_default[] =
+static struct i2c_vbi_ram_value vbi_ram_default[] =
{
{0x010, /* WST SECAM 6 */
{ 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x0, 0x0, 0x0, 0x10, 0x0 }
@@ -746,24 +746,27 @@ static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std)
static inline void tvp5150_reset(struct i2c_client *c)
{
- u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom;
+ u8 msb_id, lsb_id, msb_rom, lsb_rom;
struct tvp5150 *decoder = i2c_get_clientdata(c);
- type=tvp5150_read(c,TVP5150_AUTOSW_MSK);
msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID);
lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID);
msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER);
lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER);
- if (type==0xdc) {
- ver_656=tvp5150_read(c,TVP5150_REV_SELECT);
- tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656);
- } else if (type==0xfc) {
- tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
+ if ((msb_rom==4)&&(lsb_rom==0)) { /* Is TVP5150AM1 */
+ tvp5150_info("tvp%02x%02xam1 detected.\n",msb_id, lsb_id);
+
+ /* ITU-T BT.656.4 timing */
+ tvp5150_write(c,TVP5150_REV_SELECT,0);
} else {
- tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type);
+ if ((msb_rom==3)||(lsb_rom==0x21)) { /* Is TVP5150A */
+ tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
+ } else {
+ tvp5150_info("*** unknown tvp%02x%02x chip detected.\n",msb_id,lsb_id);
+ tvp5150_info("*** Rom ver is %d.%d\n",msb_rom,lsb_rom);
+ }
}
- tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom);
/* Initializes TVP5150 to its default values */
tvp5150_write_inittab(c, tvp5150_init_default);
@@ -893,6 +896,17 @@ static int tvp5150_command(struct i2c_client *c,
}
case DECODER_GET_STATUS:
{
+ int *iarg = arg;
+ int status;
+ int res=0;
+ status = tvp5150_read(c, 0x88);
+ if(status&0x08){
+ res |= DECODER_STATUS_COLOR;
+ }
+ if(status&0x04 && status&0x02){
+ res |= DECODER_STATUS_GOOD;
+ }
+ *iarg=res;
break;
}
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 5dbd7c1b362..cd2c4475525 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -306,6 +306,7 @@ static const char *v4l2_int_ioctls[] = {
#endif
[_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
[_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT",
+ [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX",
[_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index d5be2598714..078880e4c8c 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -29,7 +29,6 @@
#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/semaphore.h>
#include <linux/videodev.h>
@@ -83,7 +82,7 @@ static struct class video_class = {
*/
static struct video_device *video_device[VIDEO_NUM_DEVICES];
-static DECLARE_MUTEX(videodev_lock);
+static DEFINE_MUTEX(videodev_lock);
struct video_device* video_devdata(struct file *file)
{
@@ -102,15 +101,15 @@ static int video_open(struct inode *inode, struct file *file)
if(minor>=VIDEO_NUM_DEVICES)
return -ENODEV;
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
vfl=video_device[minor];
if(vfl==NULL) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
request_module("char-major-%d-%d", VIDEO_MAJOR, minor);
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
vfl=video_device[minor];
if (vfl==NULL) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENODEV;
}
}
@@ -123,7 +122,7 @@ static int video_open(struct inode *inode, struct file *file)
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return err;
}
@@ -304,12 +303,12 @@ int video_register_device(struct video_device *vfd, int type, int nr)
}
/* pick a minor number */
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
if (nr >= 0 && nr < end-base) {
/* use the one the driver asked for */
i = base+nr;
if (NULL != video_device[i]) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENFILE;
}
} else {
@@ -318,13 +317,13 @@ int video_register_device(struct video_device *vfd, int type, int nr)
if (NULL == video_device[i])
break;
if (i == end) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENFILE;
}
}
video_device[i]=vfd;
vfd->minor=i;
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base);
devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor),
@@ -362,14 +361,14 @@ int video_register_device(struct video_device *vfd, int type, int nr)
void video_unregister_device(struct video_device *vfd)
{
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
if(video_device[vfd->minor]!=vfd)
panic("videodev: bad unregister");
devfs_remove(vfd->devfs_name);
video_device[vfd->minor]=NULL;
class_device_unregister(&vfd->class_dev);
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
}
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 8a2e2657f4c..33ace373241 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -29,6 +29,8 @@
# For mptctl:
#CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
#
+# For mptfc:
+#CFLAGS_mptfc.o += -DMPT_DEBUG_FC
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index d890b2b8a93..642a61b6d0a 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -81,6 +81,10 @@ MODULE_LICENSE("GPL");
/*
* cmd line parameters
*/
+static int mpt_msi_enable;
+module_param(mpt_msi_enable, int, 0);
+MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+
#ifdef MFCNT
static int mfcounter = 0;
#define PRINT_MF_COUNT 20000
@@ -174,7 +178,7 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
-static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
/* module entry point */
@@ -313,7 +317,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
if (ioc->bus_type == FC)
mpt_fc_log_info(ioc, log_info);
else if (ioc->bus_type == SPI)
- mpt_sp_log_info(ioc, log_info);
+ mpt_spi_log_info(ioc, log_info);
else if (ioc->bus_type == SAS)
mpt_sas_log_info(ioc, log_info);
}
@@ -448,8 +452,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
} else if (func == MPI_FUNCTION_EVENT_ACK) {
dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
ioc->name));
- } else if (func == MPI_FUNCTION_CONFIG ||
- func == MPI_FUNCTION_TOOLBOX) {
+ } else if (func == MPI_FUNCTION_CONFIG) {
CONFIGPARMS *pCfg;
unsigned long flags;
@@ -1444,6 +1447,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->pci_irq = -1;
if (pdev->irq) {
+ if (mpt_msi_enable && !pci_enable_msi(pdev))
+ printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
+
r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
if (r < 0) {
@@ -1483,6 +1489,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
list_del(&ioc->list);
free_irq(ioc->pci_irq, ioc);
+ if (mpt_msi_enable)
+ pci_disable_msi(pdev);
+ if (ioc->alt_ioc)
+ ioc->alt_ioc->alt_ioc = NULL;
iounmap(mem);
kfree(ioc);
pci_set_drvdata(pdev, NULL);
@@ -2136,6 +2146,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
if (ioc->pci_irq != -1) {
free_irq(ioc->pci_irq, ioc);
+ if (mpt_msi_enable)
+ pci_disable_msi(ioc->pcidev);
ioc->pci_irq = -1;
}
@@ -2157,6 +2169,10 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
sz_last = ioc->alloc_total;
dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+
+ if (ioc->alt_ioc)
+ ioc->alt_ioc->alt_ioc = NULL;
+
kfree(ioc);
}
@@ -2770,13 +2786,16 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
/* RAID FW may take a long time to enable
*/
- if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
- > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) {
- rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
- reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
+ if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+ > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
+ (ioc->bus_type == SAS)) {
+ rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+ (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+ 300 /*seconds*/, sleepFlag);
} else {
- rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
- reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag);
+ rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+ (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+ 30 /*seconds*/, sleepFlag);
}
return rc;
}
@@ -4387,6 +4406,138 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+static void
+mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
+ MpiEventDataRaid_t * pRaidEventData)
+{
+ int volume;
+ int reason;
+ int disk;
+ int status;
+ int flags;
+ int state;
+
+ volume = pRaidEventData->VolumeID;
+ reason = pRaidEventData->ReasonCode;
+ disk = pRaidEventData->PhysDiskNum;
+ status = le32_to_cpu(pRaidEventData->SettingsStatus);
+ flags = (status >> 0) & 0xff;
+ state = (status >> 8) & 0xff;
+
+ if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
+ return;
+ }
+
+ if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
+ reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
+ (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
+ printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
+ ioc->name, disk);
+ } else {
+ printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
+ ioc->name, volume);
+ }
+
+ switch(reason) {
+ case MPI_EVENT_RAID_RC_VOLUME_CREATED:
+ printk(MYIOC_s_INFO_FMT " volume has been created\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_VOLUME_DELETED:
+
+ printk(MYIOC_s_INFO_FMT " volume has been deleted\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
+ printk(MYIOC_s_INFO_FMT " volume settings have been changed\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+ printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n",
+ ioc->name,
+ state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
+ ? "optimal"
+ : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
+ ? "degraded"
+ : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
+ ? "failed"
+ : "state unknown",
+ flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
+ ? ", enabled" : "",
+ flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
+ ? ", quiesced" : "",
+ flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
+ ? ", resync in progress" : "" );
+ break;
+
+ case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
+ printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n",
+ ioc->name, disk);
+ break;
+
+ case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+ printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+ printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
+ printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n",
+ ioc->name);
+ break;
+
+ case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+ printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n",
+ ioc->name,
+ state == MPI_PHYSDISK0_STATUS_ONLINE
+ ? "online"
+ : state == MPI_PHYSDISK0_STATUS_MISSING
+ ? "missing"
+ : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
+ ? "not compatible"
+ : state == MPI_PHYSDISK0_STATUS_FAILED
+ ? "failed"
+ : state == MPI_PHYSDISK0_STATUS_INITIALIZING
+ ? "initializing"
+ : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
+ ? "offline requested"
+ : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
+ ? "failed requested"
+ : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
+ ? "offline"
+ : "state unknown",
+ flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
+ ? ", out of sync" : "",
+ flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
+ ? ", quiesced" : "" );
+ break;
+
+ case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
+ printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n",
+ ioc->name, disk);
+ break;
+
+ case MPI_EVENT_RAID_RC_SMART_DATA:
+ printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n",
+ ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
+ break;
+
+ case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
+ printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n",
+ ioc->name, disk);
+ break;
+ }
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* GetIoUnitPage2 - Retrieve BIOS version and boot order information.
* @ioc: Pointer to MPT_ADAPTER structure
@@ -4598,6 +4749,14 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
MpiDeviceInfo_t *pdevice = NULL;
+ /*
+ * Save "Set to Avoid SCSI Bus Resets" flag
+ */
+ ioc->spi_data.bus_reset =
+ (le32_to_cpu(pPP2->PortFlags) &
+ MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
+ 0 : 1 ;
+
/* Save the Port Page 2 data
* (reformat into a 32bit quantity)
*/
@@ -5167,115 +5326,6 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mpt_toolbox - Generic function to issue toolbox message
- * @ioc - Pointer to an adapter structure
- * @cfg - Pointer to a toolbox structure. Struct contains
- * action, page address, direction, physical address
- * and pointer to a configuration page header
- * Page header is updated.
- *
- * Returns 0 for success
- * -EPERM if not allowed due to ISR context
- * -EAGAIN if no msg frames currently available
- * -EFAULT for non-successful reply or no reply (timeout)
- */
-int
-mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
-{
- ToolboxIstwiReadWriteRequest_t *pReq;
- MPT_FRAME_HDR *mf;
- struct pci_dev *pdev;
- unsigned long flags;
- int rc;
- u32 flagsLength;
- int in_isr;
-
- /* Prevent calling wait_event() (below), if caller happens
- * to be in ISR context, because that is fatal!
- */
- in_isr = in_interrupt();
- if (in_isr) {
- dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
- ioc->name));
- return -EPERM;
- }
-
- /* Get and Populate a free Frame
- */
- if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
- dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
- ioc->name));
- return -EAGAIN;
- }
- pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
- pReq->Tool = pCfg->action;
- pReq->Reserved = 0;
- pReq->ChainOffset = 0;
- pReq->Function = MPI_FUNCTION_TOOLBOX;
- pReq->Reserved1 = 0;
- pReq->Reserved2 = 0;
- pReq->MsgFlags = 0;
- pReq->Flags = pCfg->dir;
- pReq->BusNum = 0;
- pReq->Reserved3 = 0;
- pReq->NumAddressBytes = 0x01;
- pReq->Reserved4 = 0;
- pReq->DataLength = cpu_to_le16(0x04);
- pdev = ioc->pcidev;
- if (pdev->devfn & 1)
- pReq->DeviceAddr = 0xB2;
- else
- pReq->DeviceAddr = 0xB0;
- pReq->Addr1 = 0;
- pReq->Addr2 = 0;
- pReq->Addr3 = 0;
- pReq->Reserved5 = 0;
-
- /* Add a SGE to the config request.
- */
-
- flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
-
- mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
-
- dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
- ioc->name, pReq->Tool));
-
- /* Append pCfg pointer to end of mf
- */
- *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
-
- /* Initalize the timer
- */
- init_timer(&pCfg->timer);
- pCfg->timer.data = (unsigned long) ioc;
- pCfg->timer.function = mpt_timer_expired;
- pCfg->wait_done = 0;
-
- /* Set the timer; ensure 10 second minimum */
- if (pCfg->timeout < 10)
- pCfg->timer.expires = jiffies + HZ*10;
- else
- pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
-
- /* Add to end of Q, set timer and then issue this command */
- spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_add_tail(&pCfg->linkage, &ioc->configQ);
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
- add_timer(&pCfg->timer);
- mpt_put_msg_frame(mpt_base_index, ioc, mf);
- wait_event(mpt_waitq, pCfg->wait_done);
-
- /* mf has been freed - do not access */
-
- rc = pCfg->status;
-
- return rc;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_timer_expired - Call back for timer process.
* Used only internal config functionality.
@@ -5967,6 +6017,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
}
}
break;
+ case MPI_EVENT_INTEGRATED_RAID:
+ mptbase_raid_process_event_data(ioc,
+ (MpiEventDataRaid_t *)pEventReply->Data);
+ break;
default:
break;
}
@@ -5978,7 +6032,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
int idx;
- idx = ioc->eventContext % ioc->eventLogSize;
+ idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
ioc->events[idx].event = event;
ioc->events[idx].eventContext = ioc->eventContext;
@@ -6046,7 +6100,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
+ * mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
* @ioc: Pointer to MPT_ADAPTER structure
* @mr: Pointer to MPT reply frame
* @log_info: U32 LogInfo word from the IOC
@@ -6054,7 +6108,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
* Refer to lsi/sp_log.h.
*/
static void
-mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
+mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
{
u32 info = log_info & 0x00FF0000;
char *desc = "unknown";
@@ -6376,7 +6430,6 @@ EXPORT_SYMBOL(mpt_lan_index);
EXPORT_SYMBOL(mpt_stm_index);
EXPORT_SYMBOL(mpt_HardResetHandler);
EXPORT_SYMBOL(mpt_config);
-EXPORT_SYMBOL(mpt_toolbox);
EXPORT_SYMBOL(mpt_findImVolumes);
EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 47053ac6506..723d5430095 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.03.06"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06"
+#define MPT_LINUX_VERSION_COMMON "3.03.07"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.07"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -123,7 +123,7 @@
#define MPT_MAX_FRAME_SIZE 128
#define MPT_DEFAULT_FRAME_SIZE 128
-#define MPT_REPLY_FRAME_SIZE 0x40 /* Must be a multiple of 8 */
+#define MPT_REPLY_FRAME_SIZE 0x50 /* Must be a multiple of 8 */
#define MPT_SG_REQ_128_SCALE 1
#define MPT_SG_REQ_96_SCALE 2
@@ -510,9 +510,10 @@ struct mptfc_rport_info
{
struct list_head list;
struct fc_rport *rport;
- VirtDevice *vdev;
+ struct scsi_target *starget;
FCDevicePage0_t pg0;
u8 flags;
+ u8 remap_needed;
};
/*
@@ -615,6 +616,7 @@ typedef struct _MPT_ADAPTER
* increments by 32 bytes
*/
int errata_flag_1064;
+ int aen_event_read_flag; /* flag to indicate event log was read*/
u8 FirstWhoInit;
u8 upload_fw; /* If set, do a fw upload */
u8 reload_fw; /* Force a FW Reload on next reset */
@@ -631,6 +633,7 @@ typedef struct _MPT_ADAPTER
struct mutex sas_topology_mutex;
MPT_SAS_MGMT sas_mgmt;
int num_ports;
+ struct work_struct mptscsih_persistTask;
struct list_head fc_rports;
spinlock_t fc_rport_lock; /* list and ri flags */
@@ -803,6 +806,12 @@ typedef struct _mpt_sge {
#define dreplyprintk(x)
#endif
+#ifdef DMPT_DEBUG_FC
+#define dfcprintk(x) printk x
+#else
+#define dfcprintk(x)
+#endif
+
#ifdef MPT_DEBUG_TM
#define dtmprintk(x) printk x
#define DBG_DUMP_TM_REQUEST_FRAME(mfp) \
@@ -1018,7 +1027,6 @@ extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
-extern int mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index bdf70998798..9b64e07400d 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -136,6 +136,12 @@ static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
*/
static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
+/*
+ * Event Handler function
+ */
+static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+struct fasync_struct *async_queue=NULL;
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Scatter gather list (SGL) sizes and limits...
@@ -385,18 +391,18 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
}
/* Now wait for the command to complete */
- ii = wait_event_interruptible_timeout(mptctl_wait,
+ ii = wait_event_timeout(mptctl_wait,
ioctl->wait_done == 1,
HZ*5 /* 5 second timeout */);
if(ii <=0 && (ioctl->wait_done != 1 )) {
+ mpt_free_msg_frame(hd->ioc, mf);
ioctl->wait_done = 0;
retval = -1; /* return failure */
}
mptctl_bus_reset_done:
- mpt_free_msg_frame(hd->ioc, mf);
mptctl_free_tm_flags(ioctl->ioc);
return retval;
}
@@ -472,6 +478,69 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* ASYNC Event Notification Support */
+static int
+mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+{
+ u8 event;
+
+ event = le32_to_cpu(pEvReply->Event) & 0xFF;
+
+ dctlprintk(("%s() called\n", __FUNCTION__));
+ if(async_queue == NULL)
+ return 1;
+
+ /* Raise SIGIO for persistent events.
+ * TODO - this define is not in MPI spec yet,
+ * but they plan to set it to 0x21
+ */
+ if (event == 0x21 ) {
+ ioc->aen_event_read_flag=1;
+ dctlprintk(("Raised SIGIO to application\n"));
+ devtprintk(("Raised SIGIO to application\n"));
+ kill_fasync(&async_queue, SIGIO, POLL_IN);
+ return 1;
+ }
+
+ /* This flag is set after SIGIO was raised, and
+ * remains set until the application has read
+ * the event log via ioctl=MPTEVENTREPORT
+ */
+ if(ioc->aen_event_read_flag)
+ return 1;
+
+ /* Signal only for the events that are
+ * requested for by the application
+ */
+ if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
+ ioc->aen_event_read_flag=1;
+ dctlprintk(("Raised SIGIO to application\n"));
+ devtprintk(("Raised SIGIO to application\n"));
+ kill_fasync(&async_queue, SIGIO, POLL_IN);
+ }
+ return 1;
+}
+
+static int
+mptctl_fasync(int fd, struct file *filep, int mode)
+{
+ MPT_ADAPTER *ioc;
+
+ list_for_each_entry(ioc, &ioc_list, list)
+ ioc->aen_event_read_flag=0;
+
+ dctlprintk(("%s() called\n", __FUNCTION__));
+ return fasync_helper(fd, filep, mode, &async_queue);
+}
+
+static int
+mptctl_release(struct inode *inode, struct file *filep)
+{
+ dctlprintk(("%s() called\n", __FUNCTION__));
+ return fasync_helper(-1, filep, 0, &async_queue);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* MPT ioctl handler
* cmd - specify the particular IOCTL command to be issued
@@ -674,22 +743,23 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
u16 iocstat;
pFWDownloadReply_t ReplyMsg = NULL;
- dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
+ dctlprintk(("mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
- dctlprintk((KERN_INFO "DbG: kfwdl.bufp = %p\n", ufwbuf));
- dctlprintk((KERN_INFO "DbG: kfwdl.fwlen = %d\n", (int)fwlen));
- dctlprintk((KERN_INFO "DbG: kfwdl.ioc = %04xh\n", ioc));
+ dctlprintk(("DbG: kfwdl.bufp = %p\n", ufwbuf));
+ dctlprintk(("DbG: kfwdl.fwlen = %d\n", (int)fwlen));
+ dctlprintk(("DbG: kfwdl.ioc = %04xh\n", ioc));
- if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) {
- dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n",
- __FILE__, __LINE__, ioc));
+ if (mpt_verify_adapter(ioc, &iocp) < 0) {
+ dctlprintk(("ioctl_fwdl - ioc%d not found!\n",
+ ioc));
return -ENODEV; /* (-6) No such device or address */
- }
+ } else {
- /* Valid device. Get a message frame and construct the FW download message.
- */
- if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
- return -EAGAIN;
+ /* Valid device. Get a message frame and construct the FW download message.
+ */
+ if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+ return -EAGAIN;
+ }
dlmsg = (FWDownload_t*) mf;
ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
sgOut = (char *) (ptsge + 1);
@@ -702,7 +772,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
dlmsg->ChainOffset = 0;
dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD;
dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0;
- dlmsg->MsgFlags = 0;
+ if (iocp->facts.MsgVersion >= MPI_VERSION_01_05)
+ dlmsg->MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT;
+ else
+ dlmsg->MsgFlags = 0;
+
/* Set up the Transaction SGE.
*/
@@ -754,7 +828,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
goto fwdl_out;
}
- dctlprintk((KERN_INFO "DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags));
+ dctlprintk(("DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags));
/*
* Parse SG list, copying sgl itself,
@@ -803,11 +877,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
/*
* Finally, perform firmware download.
*/
- iocp->ioctl->wait_done = 0;
+ ReplyMsg = NULL;
mpt_put_msg_frame(mptctl_id, iocp, mf);
/* Now wait for the command to complete */
- ret = wait_event_interruptible_timeout(mptctl_wait,
+ ret = wait_event_timeout(mptctl_wait,
iocp->ioctl->wait_done == 1,
HZ*60);
@@ -1145,7 +1219,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
/* Fill in the data and return the structure to the calling
* program
*/
- if (ioc->bus_type == FC)
+ if (ioc->bus_type == SAS)
+ karg->adapterType = MPT_IOCTL_INTERFACE_SAS;
+ else if (ioc->bus_type == FC)
karg->adapterType = MPT_IOCTL_INTERFACE_FC;
else
karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
@@ -1170,12 +1246,11 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
} else if (cim_rev == 2) {
- /* Get the PCI bus, device, function and segment ID numbers
+ /* Get the PCI bus, device, function and segment ID numbers
for the IOC */
karg->pciInfo.u.bits.busNumber = pdev->bus->number;
karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
- karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
karg->pciInfo.segmentID = pci_domain_nr(pdev->bus);
}
@@ -1500,7 +1575,7 @@ mptctl_eventquery (unsigned long arg)
return -ENODEV;
}
- karg.eventEntries = ioc->eventLogSize;
+ karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
karg.eventTypes = ioc->eventTypes;
/* Copy the data from kernel memory to user memory
@@ -1550,7 +1625,6 @@ mptctl_eventenable (unsigned long arg)
memset(ioc->events, 0, sz);
ioc->alloc_total += sz;
- ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE;
ioc->eventContext = 0;
}
@@ -1590,7 +1664,7 @@ mptctl_eventreport (unsigned long arg)
maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS);
- max = ioc->eventLogSize < maxEvents ? ioc->eventLogSize : maxEvents;
+ max = MPTCTL_EVENT_LOG_SIZE < maxEvents ? MPTCTL_EVENT_LOG_SIZE : maxEvents;
/* If fewer than 1 event is requested, there must have
* been some type of error.
@@ -1598,6 +1672,9 @@ mptctl_eventreport (unsigned long arg)
if ((max < 1) || !ioc->events)
return -ENODATA;
+ /* reset this flag so SIGIO can restart */
+ ioc->aen_event_read_flag=0;
+
/* Copy the data from kernel memory to user memory
*/
numBytes = max * sizeof(MPT_IOCTL_EVENTS);
@@ -1817,6 +1894,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
case MPI_FUNCTION_FW_DOWNLOAD:
case MPI_FUNCTION_FC_PRIMITIVE_SEND:
+ case MPI_FUNCTION_TOOLBOX:
+ case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
break;
case MPI_FUNCTION_SCSI_IO_REQUEST:
@@ -1837,7 +1916,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
goto done_free_mem;
}
- pScsiReq->MsgFlags = mpt_msg_flags();
+ pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
+ pScsiReq->MsgFlags |= mpt_msg_flags();
+
/* verify that app has not requested
* more sense data than driver
@@ -1888,6 +1969,25 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
}
break;
+ case MPI_FUNCTION_SMP_PASSTHROUGH:
+ /* Check mf->PassthruFlags to determine if
+ * transfer is ImmediateMode or not.
+ * Immediate mode returns data in the ReplyFrame.
+ * Else, we are sending request and response data
+ * in two SGLs at the end of the mf.
+ */
+ break;
+
+ case MPI_FUNCTION_SATA_PASSTHROUGH:
+ if (!ioc->sh) {
+ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ "SCSI driver is not loaded. \n",
+ __FILE__, __LINE__);
+ rc = -EFAULT;
+ goto done_free_mem;
+ }
+ break;
+
case MPI_FUNCTION_RAID_ACTION:
/* Just add a SGE
*/
@@ -1900,7 +2000,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
int scsidir = MPI_SCSIIO_CONTROL_READ;
int dataSize;
- pScsiReq->MsgFlags = mpt_msg_flags();
+ pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
+ pScsiReq->MsgFlags |= mpt_msg_flags();
+
/* verify that app has not requested
* more sense data than driver
@@ -2130,7 +2232,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
/* Now wait for the command to complete */
timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
- timeout = wait_event_interruptible_timeout(mptctl_wait,
+ timeout = wait_event_timeout(mptctl_wait,
ioc->ioctl->wait_done == 1,
HZ*timeout);
@@ -2246,13 +2348,16 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
hp_host_info_t __user *uarg = (void __user *) arg;
MPT_ADAPTER *ioc;
struct pci_dev *pdev;
- char *pbuf;
+ char *pbuf=NULL;
dma_addr_t buf_dma;
hp_host_info_t karg;
CONFIGPARMS cfg;
ConfigPageHeader_t hdr;
int iocnum;
int rc, cim_rev;
+ ToolboxIstwiReadWriteRequest_t *IstwiRWRequest;
+ MPT_FRAME_HDR *mf = NULL;
+ MPIHeader_t *mpi_hdr;
dctlprintk((": mptctl_hp_hostinfo called.\n"));
/* Reset long to int. Should affect IA64 and SPARC only
@@ -2370,7 +2475,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
karg.base_io_addr = pci_resource_start(pdev, 0);
- if (ioc->bus_type == FC)
+ if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
karg.bus_phys_width = HP_BUS_WIDTH_UNK;
else
karg.bus_phys_width = HP_BUS_WIDTH_16;
@@ -2388,20 +2493,67 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
}
}
- cfg.pageAddr = 0;
- cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
- cfg.dir = MPI_TB_ISTWI_FLAGS_READ;
- cfg.timeout = 10;
+ /*
+ * Gather ISTWI(Industry Standard Two Wire Interface) Data
+ */
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+ dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+ ioc->name,__FUNCTION__));
+ goto out;
+ }
+
+ IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf;
+ mpi_hdr = (MPIHeader_t *) mf;
+ memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t));
+ IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX;
+ IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
+ IstwiRWRequest->MsgContext = mpi_hdr->MsgContext;
+ IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ;
+ IstwiRWRequest->NumAddressBytes = 0x01;
+ IstwiRWRequest->DataLength = cpu_to_le16(0x04);
+ if (pdev->devfn & 1)
+ IstwiRWRequest->DeviceAddr = 0xB2;
+ else
+ IstwiRWRequest->DeviceAddr = 0xB0;
+
pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
- if (pbuf) {
- cfg.physAddr = buf_dma;
- if ((mpt_toolbox(ioc, &cfg)) == 0) {
- karg.rsvd = *(u32 *)pbuf;
- }
- pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
- pbuf = NULL;
+ if (!pbuf)
+ goto out;
+ mpt_add_sge((char *)&IstwiRWRequest->SGL,
+ (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
+
+ ioc->ioctl->wait_done = 0;
+ mpt_put_msg_frame(mptctl_id, ioc, mf);
+
+ rc = wait_event_timeout(mptctl_wait,
+ ioc->ioctl->wait_done == 1,
+ HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
+
+ if(rc <=0 && (ioc->ioctl->wait_done != 1 )) {
+ /*
+ * Now we need to reset the board
+ */
+ mpt_free_msg_frame(ioc, mf);
+ mptctl_timeout_expired(ioc->ioctl);
+ goto out;
}
+ /*
+ *ISTWI Data Definition
+ * pbuf[0] = FW_VERSION = 0x4
+ * pbuf[1] = Bay Count = 6 or 4 or 2, depending on
+ * the config, you should be seeing one out of these three values
+ * pbuf[2] = Drive Installed Map = bit pattern depend on which
+ * bays have drives in them
+ * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3)
+ */
+ if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID)
+ karg.rsvd = *(u32 *)pbuf;
+
+ out:
+ if (pbuf)
+ pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
+
/* Copy the data from kernel memory to user memory
*/
if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
@@ -2459,7 +2611,7 @@ mptctl_hp_targetinfo(unsigned long arg)
/* There is nothing to do for FCP parts.
*/
- if (ioc->bus_type == FC)
+ if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
return 0;
if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL))
@@ -2569,6 +2721,8 @@ mptctl_hp_targetinfo(unsigned long arg)
static struct file_operations mptctl_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
+ .release = mptctl_release,
+ .fasync = mptctl_fasync,
.unlocked_ioctl = mptctl_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_mpctl_ioctl,
@@ -2813,6 +2967,11 @@ static int __init mptctl_init(void)
/* FIXME! */
}
+ if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
+ devtprintk((KERN_INFO MYNAM
+ ": Registered for IOC event notifications\n"));
+ }
+
return 0;
out_fail:
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index 518996e0348..a2f8a97992e 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -169,8 +169,10 @@ struct mpt_ioctl_pci_info2 {
* Read only.
* Data starts at offset 0xC
*/
-#define MPT_IOCTL_INTERFACE_FC (0x01)
#define MPT_IOCTL_INTERFACE_SCSI (0x00)
+#define MPT_IOCTL_INTERFACE_FC (0x01)
+#define MPT_IOCTL_INTERFACE_FC_IP (0x02)
+#define MPT_IOCTL_INTERFACE_SAS (0x03)
#define MPT_IOCTL_VERSION_LENGTH (32)
struct mpt_ioctl_iocinfo {
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index b102c7666d0..c3a3499bce2 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -93,10 +93,11 @@ static int mptfcDoneCtx = -1;
static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */
-int mptfc_slave_alloc(struct scsi_device *device);
+static int mptfc_target_alloc(struct scsi_target *starget);
+static int mptfc_slave_alloc(struct scsi_device *sdev);
static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
- void (*done)(struct scsi_cmnd *));
-
+ void (*done)(struct scsi_cmnd *));
+static void mptfc_target_destroy(struct scsi_target *starget);
static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
static void __devexit mptfc_remove(struct pci_dev *pdev);
@@ -107,10 +108,10 @@ static struct scsi_host_template mptfc_driver_template = {
.name = "MPT FC Host",
.info = mptscsih_info,
.queuecommand = mptfc_qcmd,
- .target_alloc = mptscsih_target_alloc,
+ .target_alloc = mptfc_target_alloc,
.slave_alloc = mptfc_slave_alloc,
.slave_configure = mptscsih_slave_configure,
- .target_destroy = mptscsih_target_destroy,
+ .target_destroy = mptfc_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
@@ -348,14 +349,33 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
}
static void
+mptfc_remap_sdev(struct scsi_device *sdev, void *arg)
+{
+ VirtDevice *vdev;
+ VirtTarget *vtarget;
+ struct scsi_target *starget;
+
+ starget = scsi_target(sdev);
+ if (starget->hostdata == arg) {
+ vtarget = arg;
+ vdev = sdev->hostdata;
+ if (vdev) {
+ vdev->bus_id = vtarget->bus_id;
+ vdev->target_id = vtarget->target_id;
+ }
+ }
+}
+
+static void
mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
{
struct fc_rport_identifiers rport_ids;
struct fc_rport *rport;
struct mptfc_rport_info *ri;
- int match = 0;
- u64 port_name;
+ int new_ri = 1;
+ u64 pn;
unsigned long flags;
+ VirtTarget *vtarget;
if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
return;
@@ -363,14 +383,14 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
/* scan list looking for a match */
spin_lock_irqsave(&ioc->fc_rport_lock, flags);
list_for_each_entry(ri, &ioc->fc_rports, list) {
- port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
- if (port_name == rport_ids.port_name) { /* match */
+ pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+ if (pn == rport_ids.port_name) { /* match */
list_move_tail(&ri->list, &ioc->fc_rports);
- match = 1;
+ new_ri = 0;
break;
}
}
- if (!match) { /* allocate one */
+ if (new_ri) { /* allocate one */
spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
if (!ri)
@@ -382,40 +402,43 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
ri->pg0 = *pg0; /* add/update pg0 data */
ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
+ /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
- rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
+ rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
spin_lock_irqsave(&ioc->fc_rport_lock, flags);
if (rport) {
- if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
- ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
- ri->vdev = NULL;
- ri->rport = rport;
- *((struct mptfc_rport_info **)rport->dd_data) = ri;
- }
- rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+ ri->rport = rport;
+ if (new_ri) /* may have been reset by user */
+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+ *((struct mptfc_rport_info **)rport->dd_data) = ri;
/*
* if already mapped, remap here. If not mapped,
- * slave_alloc will allocate vdev and map
+ * target_alloc will allocate vtarget and map,
+ * slave_alloc will fill in vdev from vtarget.
*/
- if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
- ri->vdev->target_id = ri->pg0.CurrentTargetID;
- ri->vdev->bus_id = ri->pg0.CurrentBus;
- ri->vdev->vtarget->target_id = ri->vdev->target_id;
- ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
+ if (ri->starget) {
+ vtarget = ri->starget->hostdata;
+ if (vtarget) {
+ vtarget->target_id = pg0->CurrentTargetID;
+ vtarget->bus_id = pg0->CurrentBus;
+ starget_for_each_device(ri->starget,
+ vtarget,mptfc_remap_sdev);
+ }
+ ri->remap_needed = 0;
}
- #ifdef MPT_DEBUG
- printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
+ dfcprintk ((MYIOC_s_INFO_FMT
+ "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
"rport tid %d, tmo %d\n",
- ioc->sh->host_no,
+ ioc->name,
+ oc->sh->host_no,
pg0->PortIdentifier,
pg0->WWNN,
pg0->WWPN,
pg0->CurrentTargetID,
ri->rport->scsi_target_id,
- ri->rport->dev_loss_tmo);
- #endif
+ ri->rport->dev_loss_tmo));
} else {
list_del(&ri->list);
kfree(ri);
@@ -427,6 +450,65 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
}
/*
+ * OS entry point to allow for host driver to free allocated memory
+ * Called if no device present or device being unloaded
+ */
+static void
+mptfc_target_destroy(struct scsi_target *starget)
+{
+ struct fc_rport *rport;
+ struct mptfc_rport_info *ri;
+
+ rport = starget_to_rport(starget);
+ if (rport) {
+ ri = *((struct mptfc_rport_info **)rport->dd_data);
+ if (ri) /* better be! */
+ ri->starget = NULL;
+ }
+ if (starget->hostdata)
+ kfree(starget->hostdata);
+ starget->hostdata = NULL;
+}
+
+/*
+ * OS entry point to allow host driver to alloc memory
+ * for each scsi target. Called once per device the bus scan.
+ * Return non-zero if allocation fails.
+ */
+static int
+mptfc_target_alloc(struct scsi_target *starget)
+{
+ VirtTarget *vtarget;
+ struct fc_rport *rport;
+ struct mptfc_rport_info *ri;
+ int rc;
+
+ vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+ if (!vtarget)
+ return -ENOMEM;
+ starget->hostdata = vtarget;
+
+ rc = -ENODEV;
+ rport = starget_to_rport(starget);
+ if (rport) {
+ ri = *((struct mptfc_rport_info **)rport->dd_data);
+ if (ri) { /* better be! */
+ vtarget->target_id = ri->pg0.CurrentTargetID;
+ vtarget->bus_id = ri->pg0.CurrentBus;
+ ri->starget = starget;
+ ri->remap_needed = 0;
+ rc = 0;
+ }
+ }
+ if (rc != 0) {
+ kfree(vtarget);
+ starget->hostdata = NULL;
+ }
+
+ return rc;
+}
+
+/*
* OS entry point to allow host driver to alloc memory
* for each scsi device. Called once per device the bus scan.
* Return non-zero if allocation fails.
@@ -440,7 +522,6 @@ mptfc_slave_alloc(struct scsi_device *sdev)
VirtDevice *vdev;
struct scsi_target *starget;
struct fc_rport *rport;
- struct mptfc_rport_info *ri;
unsigned long flags;
@@ -451,55 +532,44 @@ mptfc_slave_alloc(struct scsi_device *sdev)
hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
if (!vdev) {
printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
hd->ioc->name, sizeof(VirtDevice));
return -ENOMEM;
}
- memset(vdev, 0, sizeof(VirtDevice));
spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
- if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
- spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
- kfree(vdev);
- return -ENODEV;
- }
-
sdev->hostdata = vdev;
starget = scsi_target(sdev);
vtarget = starget->hostdata;
+
if (vtarget->num_luns == 0) {
+ vtarget->ioc_id = hd->ioc->id;
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
MPT_TARGET_FLAGS_VALID_INQUIRY;
hd->Targets[sdev->id] = vtarget;
}
- vtarget->target_id = vdev->target_id;
- vtarget->bus_id = vdev->bus_id;
-
vdev->vtarget = vtarget;
vdev->ioc_id = hd->ioc->id;
vdev->lun = sdev->lun;
- vdev->target_id = ri->pg0.CurrentTargetID;
- vdev->bus_id = ri->pg0.CurrentBus;
-
- ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
- ri->vdev = vdev;
+ vdev->target_id = vtarget->target_id;
+ vdev->bus_id = vtarget->bus_id;
spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
vtarget->num_luns++;
-#ifdef MPT_DEBUG
- printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
+ dfcprintk ((MYIOC_s_INFO_FMT
+ "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
"CurrentTargetID %d, %x %llx %llx\n",
- sdev->host->host_no,
- vtarget->num_luns,
- sdev->id, ri->pg0.CurrentTargetID,
- ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
-#endif
+ ioc->name,
+ sdev->host->host_no,
+ vtarget->num_luns,
+ sdev->id, ri->pg0.CurrentTargetID,
+ ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
return 0;
}
@@ -507,6 +577,7 @@ mptfc_slave_alloc(struct scsi_device *sdev)
static int
mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
{
+ struct mptfc_rport_info *ri;
struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
int err;
@@ -516,6 +587,10 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
done(SCpnt);
return 0;
}
+ ri = *((struct mptfc_rport_info **)rport->dd_data);
+ if (unlikely(ri->remap_needed))
+ return SCSI_MLQUEUE_HOST_BUSY;
+
return mptscsih_qcmd(SCpnt,done);
}
@@ -591,16 +666,20 @@ mptfc_rescan_devices(void *arg)
ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
MPT_RPORT_INFO_FLAGS_MISSING);
+ ri->remap_needed = 1;
fc_remote_port_delete(ri->rport);
/*
* remote port not really deleted 'cause
* binding is by WWPN and driver only
- * registers FCP_TARGETs
+ * registers FCP_TARGETs but cannot trust
+ * data structures.
*/
- #ifdef MPT_DEBUG
- printk ("mptfc_rescan.%d: %llx deleted\n",
- ioc->sh->host_no, ri->pg0.WWPN);
- #endif
+ ri->rport = NULL;
+ dfcprintk ((MYIOC_s_INFO_FMT
+ "mptfc_rescan.%d: %llx deleted\n",
+ ioc->name,
+ ioc->sh->host_no,
+ ri->pg0.WWPN));
}
}
spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
@@ -872,9 +951,8 @@ mptfc_init(void)
}
error = pci_register_driver(&mptfc_driver);
- if (error) {
+ if (error)
fc_release_transport(mptfc_transport_template);
- }
return error;
}
@@ -885,7 +963,8 @@ mptfc_init(void)
* @pdev: Pointer to pci_dev structure
*
*/
-static void __devexit mptfc_remove(struct pci_dev *pdev)
+static void __devexit
+mptfc_remove(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct mptfc_rport_info *p, *n;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 5a06d8d8694..2512d0e6155 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -89,6 +89,8 @@ static int mptsasMgmtCtx = -1;
enum mptsas_hotplug_action {
MPTSAS_ADD_DEVICE,
MPTSAS_DEL_DEVICE,
+ MPTSAS_ADD_RAID,
+ MPTSAS_DEL_RAID,
};
struct mptsas_hotplug_event {
@@ -114,6 +116,7 @@ struct mptsas_hotplug_event {
struct mptsas_devinfo {
u16 handle; /* unique id to address this device */
+ u16 handle_parent; /* unique id to address parent device */
u8 phy_id; /* phy number of parent device */
u8 port_id; /* sas physical port this device
is assoc'd with */
@@ -301,9 +304,8 @@ mptsas_slave_alloc(struct scsi_device *sdev)
}
mutex_unlock(&hd->ioc->sas_topology_mutex);
- printk("No matching SAS device found!!\n");
kfree(vdev);
- return -ENODEV;
+ return -ENXIO;
out:
vtarget->ioc_id = vdev->ioc_id;
@@ -321,6 +323,7 @@ mptsas_slave_destroy(struct scsi_device *sdev)
struct sas_rphy *rphy;
struct mptsas_portinfo *p;
int i;
+ VirtDevice *vdev;
/*
* Handle hotplug removal case.
@@ -344,8 +347,29 @@ mptsas_slave_destroy(struct scsi_device *sdev)
out:
mutex_unlock(&hd->ioc->sas_topology_mutex);
/*
- * TODO: Issue target reset to flush firmware outstanding commands.
+ * Issue target reset to flush firmware outstanding commands.
*/
+ vdev = sdev->hostdata;
+ if (vdev->configured_lun){
+ if (mptscsih_TMHandler(hd,
+ MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+ vdev->bus_id,
+ vdev->target_id,
+ 0, 0, 5 /* 5 second timeout */)
+ < 0){
+
+ /* The TM request failed!
+ * Fatal error case.
+ */
+ printk(MYIOC_s_WARN_FMT
+ "Error processing TaskMgmt id=%d TARGET_RESET\n",
+ hd->ioc->name,
+ vdev->target_id);
+
+ hd->tmPending = 0;
+ hd->tmState = TM_STATE_NONE;
+ }
+ }
mptscsih_slave_destroy(sdev);
}
@@ -714,6 +738,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
mptsas_print_device_pg0(buffer);
device_info->handle = le16_to_cpu(buffer->DevHandle);
+ device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
device_info->phy_id = buffer->PhyNum;
device_info->port_id = buffer->PhysicalPort;
device_info->id = buffer->TargetID;
@@ -863,6 +888,26 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
return error;
}
+/*
+ * Returns true if there is a scsi end device
+ */
+static inline int
+mptsas_is_end_device(struct mptsas_devinfo * attached)
+{
+ if ((attached->handle) &&
+ (attached->device_info &
+ MPI_SAS_DEVICE_INFO_END_DEVICE) &&
+ ((attached->device_info &
+ MPI_SAS_DEVICE_INFO_SSP_TARGET) |
+ (attached->device_info &
+ MPI_SAS_DEVICE_INFO_STP_TARGET) |
+ (attached->device_info &
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
+ return 1;
+ else
+ return 0;
+}
+
static void
mptsas_parse_device_info(struct sas_identify *identify,
struct mptsas_devinfo *device_info)
@@ -1227,7 +1272,7 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
}
static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
{
struct mptsas_portinfo *port_info;
struct mptsas_phyinfo *phy_info = NULL;
@@ -1239,12 +1284,12 @@ mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
*/
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry(port_info, &ioc->sas_topology, list) {
- for (i = 0; i < port_info->num_phys; i++) {
- if (port_info->phy_info[i].attached.handle == handle) {
- phy_info = &port_info->phy_info[i];
- break;
- }
- }
+ for (i = 0; i < port_info->num_phys; i++)
+ if (mptsas_is_end_device(&port_info->phy_info[i].attached))
+ if (port_info->phy_info[i].attached.id == id) {
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
}
mutex_unlock(&ioc->sas_topology_mutex);
@@ -1258,36 +1303,58 @@ mptsas_hotplug_work(void *arg)
MPT_ADAPTER *ioc = ev->ioc;
struct mptsas_phyinfo *phy_info;
struct sas_rphy *rphy;
+ struct scsi_device *sdev;
char *ds = NULL;
-
- if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
- ds = "ssp";
- if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
- ds = "stp";
- if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
- ds = "sata";
+ struct mptsas_devinfo sas_device;
switch (ev->event_type) {
case MPTSAS_DEL_DEVICE:
- printk(MYIOC_s_INFO_FMT
- "removing %s device, channel %d, id %d, phy %d\n",
- ioc->name, ds, ev->channel, ev->id, ev->phy_id);
- phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
+ phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
if (!phy_info) {
printk("mptsas: remove event for non-existant PHY.\n");
break;
}
+ if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+ ds = "ssp";
+ if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+ ds = "stp";
+ if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "sata";
+
+ printk(MYIOC_s_INFO_FMT
+ "removing %s device, channel %d, id %d, phy %d\n",
+ ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
+
if (phy_info->rphy) {
sas_rphy_delete(phy_info->rphy);
phy_info->rphy = NULL;
}
break;
case MPTSAS_ADD_DEVICE:
- printk(MYIOC_s_INFO_FMT
- "attaching %s device, channel %d, id %d, phy %d\n",
- ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+ /*
+ * When there is no sas address,
+ * RAID volumes are being deleted,
+ * and hidden phy disk are being added.
+ * We don't know the SAS data yet,
+ * so lookup sas device page to get
+ * pertaining info
+ */
+ if (!ev->sas_address) {
+ if (mptsas_sas_device_pg0(ioc,
+ &sas_device, ev->id,
+ (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
+ break;
+ ev->handle = sas_device.handle;
+ ev->parent_handle = sas_device.handle_parent;
+ ev->channel = sas_device.channel;
+ ev->phy_id = sas_device.phy_id;
+ ev->sas_address = sas_device.sas_address;
+ ev->device_info = sas_device.device_info;
+ }
phy_info = mptsas_find_phyinfo_by_parent(ioc,
ev->parent_handle, ev->phy_id);
@@ -1310,10 +1377,23 @@ mptsas_hotplug_work(void *arg)
phy_info->attached.sas_address = ev->sas_address;
phy_info->attached.device_info = ev->device_info;
+ if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+ ds = "ssp";
+ if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+ ds = "stp";
+ if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "sata";
+
+ printk(MYIOC_s_INFO_FMT
+ "attaching %s device, channel %d, id %d, phy %d\n",
+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+
rphy = sas_rphy_alloc(phy_info->phy);
if (!rphy)
break; /* non-fatal: an rphy can be added later */
+ rphy->scsi_target_id = phy_info->attached.id;
mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
if (sas_rphy_add(rphy)) {
sas_rphy_free(rphy);
@@ -1322,6 +1402,40 @@ mptsas_hotplug_work(void *arg)
phy_info->rphy = rphy;
break;
+ case MPTSAS_ADD_RAID:
+ sdev = scsi_device_lookup(
+ ioc->sh,
+ ioc->num_ports,
+ ev->id,
+ 0);
+ if (sdev) {
+ scsi_device_put(sdev);
+ break;
+ }
+ printk(MYIOC_s_INFO_FMT
+ "attaching device, channel %d, id %d\n",
+ ioc->name, ioc->num_ports, ev->id);
+ scsi_add_device(ioc->sh,
+ ioc->num_ports,
+ ev->id,
+ 0);
+ mpt_findImVolumes(ioc);
+ break;
+ case MPTSAS_DEL_RAID:
+ sdev = scsi_device_lookup(
+ ioc->sh,
+ ioc->num_ports,
+ ev->id,
+ 0);
+ if (!sdev)
+ break;
+ printk(MYIOC_s_INFO_FMT
+ "removing device, channel %d, id %d\n",
+ ioc->name, ioc->num_ports, ev->id);
+ scsi_remove_device(sdev);
+ scsi_device_put(sdev);
+ mpt_findImVolumes(ioc);
+ break;
}
kfree(ev);
@@ -1372,23 +1486,94 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc,
schedule_work(&ev->work);
}
+static void
+mptscsih_send_raid_event(MPT_ADAPTER *ioc,
+ EVENT_DATA_RAID *raid_event_data)
+{
+ struct mptsas_hotplug_event *ev;
+ RAID_VOL0_STATUS * volumeStatus;
+
+ if (ioc->bus_type != SAS)
+ return;
+
+ ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev) {
+ printk(KERN_WARNING "mptsas: lost hotplug event\n");
+ return;
+ }
+
+ memset(ev,0,sizeof(struct mptsas_hotplug_event));
+ INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+ ev->ioc = ioc;
+ ev->id = raid_event_data->VolumeID;
+
+ switch (raid_event_data->ReasonCode) {
+ case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+ ev->event_type = MPTSAS_ADD_DEVICE;
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+ ev->event_type = MPTSAS_DEL_DEVICE;
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_DELETED:
+ ev->event_type = MPTSAS_DEL_RAID;
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_CREATED:
+ ev->event_type = MPTSAS_ADD_RAID;
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+ volumeStatus = (RAID_VOL0_STATUS *) &
+ raid_event_data->SettingsStatus;
+ ev->event_type = (volumeStatus->State ==
+ MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
+ MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
+ break;
+ default:
+ break;
+ }
+ schedule_work(&ev->work);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* work queue thread to clear the persitency table */
+static void
+mptscsih_sas_persist_clear_table(void * arg)
+{
+ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+
+ mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
+}
+
static int
mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
{
+ int rc=1;
u8 event = le32_to_cpu(reply->Event) & 0xFF;
if (!ioc->sh)
- return 1;
+ goto out;
switch (event) {
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
mptscsih_send_sas_event(ioc,
(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
- return 1; /* currently means nothing really */
-
+ break;
+ case MPI_EVENT_INTEGRATED_RAID:
+ mptscsih_send_raid_event(ioc,
+ (EVENT_DATA_RAID *)reply->Data);
+ break;
+ case MPI_EVENT_PERSISTENT_TABLE_FULL:
+ INIT_WORK(&ioc->mptscsih_persistTask,
+ mptscsih_sas_persist_clear_table,
+ (void *)ioc);
+ schedule_work(&ioc->mptscsih_persistTask);
+ break;
default:
- return mptscsih_event_process(ioc, reply);
+ rc = mptscsih_event_process(ioc, reply);
+ break;
}
+ out:
+
+ return rc;
}
static int
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index cdac5578fdf..4fee6befc93 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -144,7 +144,6 @@ static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
-static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
@@ -159,11 +158,9 @@ static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
-static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget);
+static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
-static struct work_struct mptscsih_persistTask;
-
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
static void mptscsih_domainValidation(void *hd);
@@ -563,11 +560,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
MPT_SCSI_HOST *hd;
SCSIIORequest_t *pScsiReq;
SCSIIOReply_t *pScsiReply;
- u16 req_idx;
+ u16 req_idx, req_idx_MR;
hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+ req_idx_MR = (mr != NULL) ?
+ le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
+ if ((req_idx != req_idx_MR) ||
+ (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
+ printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
+ ioc->name);
+ printk (MYIOC_s_ERR_FMT
+ "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
+ ioc->name, req_idx, req_idx_MR, mf, mr,
+ hd->ScsiLookup[req_idx_MR]);
+ return 0;
+ }
+
sc = hd->ScsiLookup[req_idx];
if (sc == NULL) {
MPIHeader_t *hdr = (MPIHeader_t *)mf;
@@ -730,6 +740,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
break;
+ case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
+ sc->resid=0;
case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
if (scsi_status == MPI_SCSI_STATUS_BUSY)
@@ -789,7 +801,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
- case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
default:
@@ -1530,7 +1541,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
*
* Returns 0 for SUCCESS or -1 if FAILED.
*/
-static int
+int
mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
{
MPT_ADAPTER *ioc;
@@ -1721,6 +1732,20 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
return retval;
}
+static int
+mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
+{
+ switch (ioc->bus_type) {
+ case FC:
+ return 40;
+ case SAS:
+ return 10;
+ case SPI:
+ default:
+ return 2;
+ }
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
@@ -1792,7 +1817,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
vdev->bus_id, vdev->target_id, vdev->lun,
- ctx2abort, 2 /* 2 second timeout */);
+ ctx2abort, mptscsih_get_tm_timeout(ioc));
printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
hd->ioc->name,
@@ -1843,7 +1868,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
vdev->bus_id, vdev->target_id,
- 0, 0, 5 /* 5 second timeout */);
+ 0, 0, mptscsih_get_tm_timeout(hd->ioc));
printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
hd->ioc->name,
@@ -1893,7 +1918,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
- vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */);
+ vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
hd->ioc->name,
@@ -2016,6 +2041,42 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static void
+mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
+{
+ char *desc;
+
+ switch (response_code) {
+ case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
+ desc = "The task completed.";
+ break;
+ case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
+ desc = "The IOC received an invalid frame status.";
+ break;
+ case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
+ desc = "The task type is not supported.";
+ break;
+ case MPI_SCSITASKMGMT_RSP_TM_FAILED:
+ desc = "The requested task failed.";
+ break;
+ case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
+ desc = "The task completed successfully.";
+ break;
+ case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
+ desc = "The LUN request is invalid.";
+ break;
+ case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
+ desc = "The task is in the IOC queue and has not been sent to target.";
+ break;
+ default:
+ desc = "unknown";
+ break;
+ }
+ printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
+ ioc->name, response_code, desc);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
* @ioc: Pointer to MPT_ADAPTER structure
@@ -2064,6 +2125,11 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
tmType = pScsiTmReq->TaskType;
+ if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
+ pScsiTmReply->ResponseCode)
+ mptscsih_taskmgmt_response_code(ioc,
+ pScsiTmReply->ResponseCode);
+
dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
@@ -2255,7 +2321,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
vtarget->luns[0] &= ~(1 << vdevice->lun);
vtarget->num_luns--;
if (vtarget->num_luns == 0) {
- mptscsih_negotiate_to_asyn_narrow(hd, vtarget);
+ mptscsih_negotiate_to_asyn_narrow(hd, vdevice);
if (hd->ioc->bus_type == SPI) {
if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
@@ -2423,7 +2489,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
int idx;
MPT_ADAPTER *ioc = hd->ioc;
- idx = ioc->eventContext % ioc->eventLogSize;
+ idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
ioc->events[idx].eventContext = ioc->eventContext;
@@ -2585,16 +2651,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* work queue thread to clear the persitency table */
-static void
-mptscsih_sas_persist_clear_table(void * arg)
-{
- MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
-
- mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
int
mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
{
@@ -2656,13 +2712,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
break;
}
- /* Persistent table is full. */
- case MPI_EVENT_PERSISTENT_TABLE_FULL:
- INIT_WORK(&mptscsih_persistTask,
- mptscsih_sas_persist_clear_table,(void *)ioc);
- schedule_work(&mptscsih_persistTask);
- break;
-
case MPI_EVENT_NONE: /* 00 */
case MPI_EVENT_LOG_DATA: /* 01 */
case MPI_EVENT_STATE_CHANGE: /* 02 */
@@ -3863,8 +3912,9 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
*
*/
static void
-mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
+mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
{
+ VirtTarget *vtarget = vdevice->vtarget;
MPT_ADAPTER *ioc= hd->ioc;
SCSIDevicePage1_t *pcfg1Data;
CONFIGPARMS cfg;
@@ -3874,7 +3924,8 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
int requested, configuration, data,i;
u8 flags, factor;
- if (ioc->bus_type != SPI)
+ if ((ioc->bus_type != SPI) ||
+ (!vdevice->configured_lun))
return;
if (!ioc->spi_data.sdp1length)
@@ -3910,7 +3961,7 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
}
mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
&configuration, flags);
- dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+ dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC "
"offset=0 negoFlags=%x request=%x config=%x\n",
id, flags, requested, configuration));
pcfg1Data->RequestedParameters = cpu_to_le32(requested);
@@ -3923,7 +3974,7 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
flags = vtarget->negoFlags;
mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
&configuration, flags);
- dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+ dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC "
"offset=0 negoFlags=%x request=%x config=%x\n",
vtarget->target_id, flags, requested, configuration));
pcfg1Data->RequestedParameters = cpu_to_le32(requested);
@@ -5620,5 +5671,6 @@ EXPORT_SYMBOL(mptscsih_event_process);
EXPORT_SYMBOL(mptscsih_ioc_reset);
EXPORT_SYMBOL(mptscsih_change_queue_depth);
EXPORT_SYMBOL(mptscsih_timer_expired);
+EXPORT_SYMBOL(mptscsih_TMHandler);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index d3cba12f4bd..44b248d51ea 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -108,3 +108,4 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE
extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
extern void mptscsih_timer_expired(unsigned long data);
+extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 7dce29277cb..f148dfa3911 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -384,6 +384,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_mptspi_probe;
}
+ /*
+ * issue internal bus reset
+ */
+ if (ioc->spi_data.bus_reset)
+ mptscsih_TMHandler(hd,
+ MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+ 0, 0, 0, 0, 5);
+
scsi_scan_host(sh);
return 0;
@@ -445,7 +453,7 @@ static void __exit
mptspi_exit(void)
{
pci_unregister_driver(&mptspi_driver);
-
+
mpt_reset_deregister(mptspiDoneCtx);
dprintk((KERN_INFO MYNAM
": Deregistered for IOC reset notifications\n"));
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index 90628562851..184974cc734 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -60,4 +60,7 @@ extern void i2o_iop_remove(struct i2o_controller *);
#define I2O_IN_PORT 0x40
#define I2O_OUT_PORT 0x44
+/* Motorola/Freescale specific register offset */
+#define I2O_MOTOROLA_PORT_OFFSET 0x10400
+
#define I2O_IRQ_OUTBOUND_POST 0x00000008
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index f9e5a23697a..c08ddac3717 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -732,7 +732,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid);
msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt));
- if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
+ if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
status = SUCCESS;
return status;
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index d698d7709c3..4f1515cae5d 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -88,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
struct device *dev = &pdev->dev;
int i;
+ if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+ printk(KERN_ERR "%s: device already claimed\n", c->name);
+ return -ENODEV;
+ }
+
for (i = 0; i < 6; i++) {
/* Skip I/O spaces */
if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -163,6 +168,24 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
c->in_port = c->base.virt + I2O_IN_PORT;
c->out_port = c->base.virt + I2O_OUT_PORT;
+ /* Motorola/Freescale chip does not follow spec */
+ if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) {
+ /* Check if CPU is enabled */
+ if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) {
+ printk(KERN_INFO "%s: MPC82XX needs CPU running to "
+ "service I2O.\n", c->name);
+ i2o_pci_free(c);
+ return -ENODEV;
+ } else {
+ c->irq_status += I2O_MOTOROLA_PORT_OFFSET;
+ c->irq_mask += I2O_MOTOROLA_PORT_OFFSET;
+ c->in_port += I2O_MOTOROLA_PORT_OFFSET;
+ c->out_port += I2O_MOTOROLA_PORT_OFFSET;
+ printk(KERN_INFO "%s: MPC82XX workarounds activated.\n",
+ c->name);
+ }
+ }
+
if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
i2o_pci_free(c);
return -ENOMEM;
@@ -298,7 +321,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
struct i2o_controller *c;
int rc;
struct pci_dev *i960 = NULL;
- int pci_dev_busy = 0;
+ int enabled = pdev->is_enabled;
printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
@@ -308,16 +331,12 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
return -ENODEV;
}
- if ((rc = pci_enable_device(pdev))) {
- printk(KERN_WARNING "i2o: couldn't enable device %s\n",
- pci_name(pdev));
- return rc;
- }
-
- if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
- printk(KERN_ERR "i2o: device already claimed\n");
- return -ENODEV;
- }
+ if (!enabled)
+ if ((rc = pci_enable_device(pdev))) {
+ printk(KERN_WARNING "i2o: couldn't enable device %s\n",
+ pci_name(pdev));
+ return rc;
+ }
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
@@ -395,9 +414,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
if ((rc = i2o_pci_alloc(c))) {
printk(KERN_ERR "%s: DMA / IO allocation for I2O controller "
- " failed\n", c->name);
- if (rc == -ENODEV)
- pci_dev_busy = 1;
+ "failed\n", c->name);
goto free_controller;
}
@@ -425,7 +442,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
i2o_iop_free(c);
disable:
- if (!pci_dev_busy)
+ if (!enabled)
pci_disable_device(pdev);
return rc;
diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c
index 7e98434cfa3..9783caf4969 100644
--- a/drivers/misc/ibmasm/uart.c
+++ b/drivers/misc/ibmasm/uart.c
@@ -50,7 +50,7 @@ void ibmasm_register_uart(struct service_processor *sp)
memset(&uport, 0, sizeof(struct uart_port));
uport.irq = sp->irq;
uport.uartclk = 3686400;
- uport.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ;
+ uport.flags = UPF_SHARE_IRQ;
uport.iotype = UPIO_MEM;
uport.membase = iomem_base;
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c483a863b11..5d397b7a549 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -65,7 +65,7 @@ config MMC_AU1X
depends on SOC_AU1X00 && MMC
help
This selects the AMD Alchemy(R) Multimedia card interface.
- iIf you have a Alchemy platform with a MMC slot, say Y or M here.
+ If you have a Alchemy platform with a MMC slot, say Y or M here.
If unsure, say N.
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index aaf04638054..227c39a7c1b 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -194,7 +194,7 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
- switch(cmd->flags) {
+ switch (mmc_rsp_type(cmd->flags)) {
case MMC_RSP_R1:
mmccmd |= SD_CMD_RT_1;
break;
@@ -483,34 +483,35 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
cmd = mrq->cmd;
cmd->error = MMC_ERR_NONE;
- if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) {
-
- /* Techincally, we should be getting all 48 bits of the response
- * (SD_RESP1 + SD_RESP2), but because our response omits the CRC,
- * our data ends up being shifted 8 bits to the right. In this case,
- * that means that the OSR data starts at bit 31, so we can just
- * read RESP0 and return that
- */
-
- cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
- }
- else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
- u32 r[4];
- int i;
-
- r[0] = au_readl(host->iobase + SD_RESP3);
- r[1] = au_readl(host->iobase + SD_RESP2);
- r[2] = au_readl(host->iobase + SD_RESP1);
- r[3] = au_readl(host->iobase + SD_RESP0);
-
- /* The CRC is omitted from the response, so really we only got
- * 120 bytes, but the engine expects 128 bits, so we have to shift
- * things up
- */
-
- for(i = 0; i < 4; i++) {
- cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
- if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136) {
+ u32 r[4];
+ int i;
+
+ r[0] = au_readl(host->iobase + SD_RESP3);
+ r[1] = au_readl(host->iobase + SD_RESP2);
+ r[2] = au_readl(host->iobase + SD_RESP1);
+ r[3] = au_readl(host->iobase + SD_RESP0);
+
+ /* The CRC is omitted from the response, so really
+ * we only got 120 bytes, but the engine expects
+ * 128 bits, so we have to shift things up
+ */
+
+ for(i = 0; i < 4; i++) {
+ cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
+ if (i != 3)
+ cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+ }
+ } else {
+ /* Techincally, we should be getting all 48 bits of
+ * the response (SD_RESP1 + SD_RESP2), but because
+ * our response omits the CRC, our data ends up
+ * being shifted 8 bits to the right. In this case,
+ * that means that the OSR data starts at bit 31,
+ * so we can just read RESP0 and return that
+ */
+ cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
}
}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index bfca5c176e8..1888060c5e0 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -211,7 +211,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
appcmd.opcode = MMC_APP_CMD;
appcmd.arg = rca << 16;
- appcmd.flags = MMC_RSP_R1;
+ appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
appcmd.retries = 0;
memset(appcmd.resp, 0, sizeof(appcmd.resp));
appcmd.data = NULL;
@@ -331,7 +331,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
cmd.opcode = MMC_SELECT_CARD;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE)
@@ -358,7 +358,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
struct mmc_command cmd;
cmd.opcode = SD_APP_SET_BUS_WIDTH;
cmd.arg = SD_BUS_WIDTH_4;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
CMD_RETRIES);
@@ -386,7 +386,7 @@ static void mmc_deselect_cards(struct mmc_host *host)
cmd.opcode = MMC_SELECT_CARD;
cmd.arg = 0;
- cmd.flags = MMC_RSP_NONE;
+ cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
mmc_wait_for_cmd(host, &cmd, 0);
}
@@ -677,7 +677,7 @@ static void mmc_idle_cards(struct mmc_host *host)
cmd.opcode = MMC_GO_IDLE_STATE;
cmd.arg = 0;
- cmd.flags = MMC_RSP_NONE;
+ cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
mmc_wait_for_cmd(host, &cmd, 0);
@@ -738,7 +738,7 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
cmd.opcode = MMC_SEND_OP_COND;
cmd.arg = ocr;
- cmd.flags = MMC_RSP_R3;
+ cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
for (i = 100; i; i--) {
err = mmc_wait_for_cmd(host, &cmd, 0);
@@ -766,7 +766,7 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
cmd.opcode = SD_APP_OP_COND;
cmd.arg = ocr;
- cmd.flags = MMC_RSP_R3;
+ cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
for (i = 100; i; i--) {
err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
@@ -805,7 +805,7 @@ static void mmc_discover_cards(struct mmc_host *host)
cmd.opcode = MMC_ALL_SEND_CID;
cmd.arg = 0;
- cmd.flags = MMC_RSP_R2;
+ cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err == MMC_ERR_TIMEOUT) {
@@ -835,7 +835,7 @@ static void mmc_discover_cards(struct mmc_host *host)
cmd.opcode = SD_SEND_RELATIVE_ADDR;
cmd.arg = 0;
- cmd.flags = MMC_RSP_R6;
+ cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE)
@@ -856,7 +856,7 @@ static void mmc_discover_cards(struct mmc_host *host)
} else {
cmd.opcode = MMC_SET_RELATIVE_ADDR;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE)
@@ -878,7 +878,7 @@ static void mmc_read_csds(struct mmc_host *host)
cmd.opcode = MMC_SEND_CSD;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R2;
+ cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE) {
@@ -920,7 +920,7 @@ static void mmc_read_scrs(struct mmc_host *host)
cmd.opcode = MMC_APP_CMD;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, 0);
if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
@@ -932,7 +932,7 @@ static void mmc_read_scrs(struct mmc_host *host)
cmd.opcode = SD_APP_SEND_SCR;
cmd.arg = 0;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
memset(&data, 0, sizeof(struct mmc_data));
@@ -1003,7 +1003,7 @@ static void mmc_check_cards(struct mmc_host *host)
cmd.opcode = MMC_SEND_STATUS;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err == MMC_ERR_NONE)
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 5b014c370e8..8eb2a2ede64 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -171,14 +171,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.mrq.data = &brq.data;
brq.cmd.arg = req->sector << 9;
- brq.cmd.flags = MMC_RSP_R1;
+ brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
brq.data.timeout_ns = card->csd.tacc_ns * 10;
brq.data.timeout_clks = card->csd.tacc_clks * 10;
brq.data.blksz_bits = md->block_bits;
brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
brq.stop.opcode = MMC_STOP_TRANSMISSION;
brq.stop.arg = 0;
- brq.stop.flags = MMC_RSP_R1B;
+ brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
if (rq_data_dir(req) == READ) {
brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
@@ -223,7 +223,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
cmd.opcode = MMC_SEND_STATUS;
cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 5);
if (err) {
printk(KERN_ERR "%s: error %d requesting status\n",
@@ -430,7 +430,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
mmc_card_claim_host(card);
cmd.opcode = MMC_SET_BLOCKLEN;
cmd.arg = 1 << md->block_bits;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 5);
mmc_card_release_host(card);
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 634ef53e85a..9fef29d978b 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -97,6 +97,13 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
if (data->flags & MMC_DATA_READ) {
datactrl |= MCI_DPSM_DIRECTION;
irqmask = MCI_RXFIFOHALFFULLMASK;
+
+ /*
+ * If we have less than a FIFOSIZE of bytes to transfer,
+ * trigger a PIO interrupt as soon as any data is available.
+ */
+ if (host->size < MCI_FIFOSIZE)
+ irqmask |= MCI_RXDATAAVLBLMASK;
} else {
/*
* We don't actually need to include "FIFO empty" here
@@ -124,15 +131,10 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
}
c |= cmd->opcode | MCI_CPSM_ENABLE;
- switch (cmd->flags & MMC_RSP_MASK) {
- case MMC_RSP_NONE:
- default:
- break;
- case MMC_RSP_LONG:
- c |= MCI_CPSM_LONGRSP;
- case MMC_RSP_SHORT:
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136)
+ c |= MCI_CPSM_LONGRSP;
c |= MCI_CPSM_RESPONSE;
- break;
}
if (/*interrupt*/0)
c |= MCI_CPSM_INTERRUPT;
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index ee8f8a0420d..285d7d06809 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -178,14 +178,15 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd,
if (cmd->flags & MMC_RSP_BUSY)
cmdat |= CMDAT_BUSY;
- switch (cmd->flags & (MMC_RSP_MASK | MMC_RSP_CRC)) {
- case MMC_RSP_SHORT | MMC_RSP_CRC:
+#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
+ switch (RSP_TYPE(mmc_resp_type(cmd))) {
+ case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6 */
cmdat |= CMDAT_RESP_SHORT;
break;
- case MMC_RSP_SHORT:
+ case RSP_TYPE(MMC_RSP_R3):
cmdat |= CMDAT_RESP_R3;
break;
- case MMC_RSP_LONG | MMC_RSP_CRC:
+ case RSP_TYPE(MMC_RSP_R2):
cmdat |= CMDAT_RESP_R2;
break;
default:
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index f2575762536..3be397d436f 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -459,7 +459,7 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
/*
* Do we expect a reply?
*/
- if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) {
+ if (cmd->flags & MMC_RSP_PRESENT) {
/*
* Read back status.
*/
@@ -476,10 +476,10 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
cmd->error = MMC_ERR_BADCRC;
/* All ok */
else {
- if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT)
- wbsd_get_short_reply(host, cmd);
- else
+ if (cmd->flags & MMC_RSP_136)
wbsd_get_long_reply(host, cmd);
+ else
+ wbsd_get_short_reply(host, cmd);
}
}
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index eafa23f5cbd..205bb708333 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -31,6 +31,7 @@ config MTD_JEDECPROBE
config MTD_GEN_PROBE
tristate
+ select OBSOLETE_INTERMODULE
config MTD_CFI_ADV_OPTIONS
bool "Flash chip driver advanced configuration options"
@@ -259,7 +260,7 @@ config MTD_ABSENT
with this driver will return -ENODEV upon access.
config MTD_OBSOLETE_CHIPS
- depends on MTD && BROKEN
+ depends on MTD
bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
help
This option does not enable any code directly, but will allow you to
@@ -272,7 +273,7 @@ config MTD_OBSOLETE_CHIPS
config MTD_AMDSTD
tristate "AMD compatible flash chip support (non-CFI)"
- depends on MTD && MTD_OBSOLETE_CHIPS
+ depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN
help
This option enables support for flash chips using AMD-compatible
commands, including some which are not CFI-compatible and hence
@@ -290,7 +291,7 @@ config MTD_SHARP
config MTD_JEDEC
tristate "JEDEC device support"
- depends on MTD && MTD_OBSOLETE_CHIPS
+ depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN
help
Enable older older JEDEC flash interface devices for self
programming flash. It is commonly used in older AMD chips. It is
@@ -300,7 +301,7 @@ config MTD_JEDEC
config MTD_XIP
bool "XIP aware MTD support"
- depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARM
+ depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP
default y if XIP_KERNEL
help
This allows MTD support to work with flash memory which is also
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 69c04945591..ded2c33f5b8 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -1019,8 +1019,8 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
#define XIP_INVAL_CACHED_RANGE(map, from, size) \
INVALIDATE_CACHED_RANGE(map, from, size)
-#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
- UDELAY(map, chip, adr, usec)
+#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec) \
+ UDELAY(map, chip, cmd_adr, usec)
/*
* Extra notes:
@@ -1052,7 +1052,7 @@ do { \
spin_lock(chip->mutex); \
} while (0)
-#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \
+#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec) \
do { \
spin_unlock(chip->mutex); \
INVALIDATE_CACHED_RANGE(map, adr, len); \
@@ -1284,7 +1284,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
map_write(map, datum, adr);
chip->state = mode;
- INVALIDATE_CACHE_UDELAY(map, chip,
+ INVALIDATE_CACHE_UDELAY(map, chip, adr,
adr, map_bankwidth(map),
chip->word_write_time);
@@ -1572,8 +1572,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
map_write(map, CMD(0xd0), cmd_adr);
chip->state = FL_WRITING;
- INVALIDATE_CACHE_UDELAY(map, chip,
- cmd_adr, len,
+ INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr,
+ adr, len,
chip->buffer_write_time);
timeo = jiffies + (HZ/2);
@@ -1744,7 +1744,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
chip->state = FL_ERASING;
chip->erase_suspended = 0;
- INVALIDATE_CACHE_UDELAY(map, chip,
+ INVALIDATE_CACHE_UDELAY(map, chip, adr,
adr, len,
chip->erase_time*1000/2);
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 5038e90ceb1..dd628cb51e3 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -218,6 +218,7 @@ config MTD_DOC2001PLUS
config MTD_DOCPROBE
tristate
select MTD_DOCECC
+ select OBSOLETE_INTERMODULE
config MTD_DOCECC
tristate
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
index 701620b6bae..8b3784e2de8 100644
--- a/drivers/mtd/maps/dc21285.c
+++ b/drivers/mtd/maps/dc21285.c
@@ -110,8 +110,9 @@ static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const voi
{
while (len > 0) {
map_word d;
- d.x[0] = *((uint32_t*)from)++;
+ d.x[0] = *((uint32_t*)from);
dc21285_write32(map, d, to);
+ from += 4;
to += 4;
len -= 4;
}
@@ -121,8 +122,9 @@ static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const voi
{
while (len > 0) {
map_word d;
- d.x[0] = *((uint16_t*)from)++;
+ d.x[0] = *((uint16_t*)from);
dc21285_write16(map, d, to);
+ from += 2;
to += 2;
len -= 2;
}
@@ -131,8 +133,9 @@ static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const voi
static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
map_word d;
- d.x[0] = *((uint8_t*)from)++;
+ d.x[0] = *((uint8_t*)from);
dc21285_write8(map, d, to);
+ from++;
to++;
len--;
}
diff --git a/drivers/mtd/maps/tsunami_flash.c b/drivers/mtd/maps/tsunami_flash.c
index 9e21e6c02f8..0f915ac3102 100644
--- a/drivers/mtd/maps/tsunami_flash.c
+++ b/drivers/mtd/maps/tsunami_flash.c
@@ -62,7 +62,7 @@ static void tsunami_flash_copy_to(
static struct map_info tsunami_flash_map = {
.name = "flash chip on the Tsunami TIG bus",
.size = MAX_TIG_FLASH_SIZE,
- .phys = NO_XIP;
+ .phys = NO_XIP,
.bankwidth = 1,
.read = tsunami_flash_read8,
.copy_from = tsunami_flash_copy_from,
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 7488ee7f7ca..7f47124f118 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -753,9 +753,11 @@ enum tx_desc_status {
enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };
struct vortex_extra_stats {
- unsigned long tx_deferred;
- unsigned long tx_multiple_collisions;
- unsigned long rx_bad_ssd;
+ unsigned long tx_deferred;
+ unsigned long tx_max_collisions;
+ unsigned long tx_multiple_collisions;
+ unsigned long tx_single_collisions;
+ unsigned long rx_bad_ssd;
};
struct vortex_private {
@@ -863,12 +865,14 @@ static struct {
const char str[ETH_GSTRING_LEN];
} ethtool_stats_keys[] = {
{ "tx_deferred" },
+ { "tx_max_collisions" },
{ "tx_multiple_collisions" },
+ { "tx_single_collisions" },
{ "rx_bad_ssd" },
};
/* number of ETHTOOL_GSTATS u64's */
-#define VORTEX_NUM_STATS 3
+#define VORTEX_NUM_STATS 5
static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
int chip_idx, int card_idx);
@@ -2108,9 +2112,12 @@ vortex_error(struct net_device *dev, int status)
iowrite8(0, ioaddr + TxStatus);
if (tx_status & 0x30) { /* txJabber or txUnderrun */
do_tx_reset = 1;
- } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */
- do_tx_reset = 1;
- reset_mask = 0x0108; /* Reset interface logic, but not download logic */
+ } else if (tx_status & 0x08) { /* maxCollisions */
+ vp->xstats.tx_max_collisions++;
+ if (vp->drv_flags & MAX_COLLISION_RESET) {
+ do_tx_reset = 1;
+ reset_mask = 0x0108; /* Reset interface logic, but not download logic */
+ }
} else { /* Merely re-enable the transmitter. */
iowrite16(TxEnable, ioaddr + EL3_CMD);
}
@@ -2926,7 +2933,6 @@ static void update_stats(void __iomem *ioaddr, struct net_device *dev)
EL3WINDOW(6);
vp->stats.tx_carrier_errors += ioread8(ioaddr + 0);
vp->stats.tx_heartbeat_errors += ioread8(ioaddr + 1);
- vp->stats.collisions += ioread8(ioaddr + 3);
vp->stats.tx_window_errors += ioread8(ioaddr + 4);
vp->stats.rx_fifo_errors += ioread8(ioaddr + 5);
vp->stats.tx_packets += ioread8(ioaddr + 6);
@@ -2939,10 +2945,15 @@ static void update_stats(void __iomem *ioaddr, struct net_device *dev)
vp->stats.tx_bytes += ioread16(ioaddr + 12);
/* Extra stats for get_ethtool_stats() */
vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2);
+ vp->xstats.tx_single_collisions += ioread8(ioaddr + 3);
vp->xstats.tx_deferred += ioread8(ioaddr + 8);
EL3WINDOW(4);
vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12);
+ vp->stats.collisions = vp->xstats.tx_multiple_collisions
+ + vp->xstats.tx_single_collisions
+ + vp->xstats.tx_max_collisions;
+
{
u8 up = ioread8(ioaddr + 13);
vp->stats.rx_bytes += (up & 0x0f) << 16;
@@ -3036,8 +3047,10 @@ static void vortex_get_ethtool_stats(struct net_device *dev,
spin_unlock_irqrestore(&vp->lock, flags);
data[0] = vp->xstats.tx_deferred;
- data[1] = vp->xstats.tx_multiple_collisions;
- data[2] = vp->xstats.rx_bad_ssd;
+ data[1] = vp->xstats.tx_max_collisions;
+ data[2] = vp->xstats.tx_multiple_collisions;
+ data[3] = vp->xstats.tx_single_collisions;
+ data[4] = vp->xstats.rx_bad_ssd;
}
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index adfba44dac5..2beac55b57d 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -586,6 +586,7 @@ struct rtl8139_private {
dma_addr_t tx_bufs_dma;
signed char phys[4]; /* MII device addresses. */
char twistie, twist_row, twist_col; /* Twister tune state. */
+ unsigned int watchdog_fired : 1;
unsigned int default_port : 4; /* Last dev->if_port value. */
unsigned int have_thread : 1;
spinlock_t lock;
@@ -638,6 +639,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev);
static void __set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
static void rtl8139_thread (void *_data);
+static void rtl8139_tx_timeout_task(void *_data);
static struct ethtool_ops rtl8139_ethtool_ops;
/* write MMIO register, with flush */
@@ -1598,13 +1600,14 @@ static void rtl8139_thread (void *_data)
{
struct net_device *dev = _data;
struct rtl8139_private *tp = netdev_priv(dev);
- unsigned long thr_delay;
+ unsigned long thr_delay = next_tick;
- if (rtnl_shlock_nowait() == 0) {
+ if (tp->watchdog_fired) {
+ tp->watchdog_fired = 0;
+ rtl8139_tx_timeout_task(_data);
+ } else if (rtnl_shlock_nowait() == 0) {
rtl8139_thread_iter (dev, tp, tp->mmio_addr);
rtnl_unlock ();
-
- thr_delay = next_tick;
} else {
/* unlikely race. mitigate with fast poll. */
thr_delay = HZ / 2;
@@ -1631,7 +1634,8 @@ static void rtl8139_stop_thread(struct rtl8139_private *tp)
if (tp->have_thread) {
cancel_rearming_delayed_work(&tp->thread);
tp->have_thread = 0;
- }
+ } else
+ flush_scheduled_work();
}
static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
@@ -1642,14 +1646,13 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
/* XXX account for unsent Tx packets in tp->stats.tx_dropped */
}
-
-static void rtl8139_tx_timeout (struct net_device *dev)
+static void rtl8139_tx_timeout_task (void *_data)
{
+ struct net_device *dev = _data;
struct rtl8139_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
int i;
u8 tmp8;
- unsigned long flags;
printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x "
"media %2.2x.\n", dev->name, RTL_R8 (ChipCmd),
@@ -1670,23 +1673,34 @@ static void rtl8139_tx_timeout (struct net_device *dev)
if (tmp8 & CmdTxEnb)
RTL_W8 (ChipCmd, CmdRxEnb);
- spin_lock(&tp->rx_lock);
+ spin_lock_bh(&tp->rx_lock);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000);
/* Stop a shared interrupt from scavenging while we are. */
- spin_lock_irqsave (&tp->lock, flags);
+ spin_lock_irq(&tp->lock);
rtl8139_tx_clear (tp);
- spin_unlock_irqrestore (&tp->lock, flags);
+ spin_unlock_irq(&tp->lock);
/* ...and finally, reset everything */
if (netif_running(dev)) {
rtl8139_hw_start (dev);
netif_wake_queue (dev);
}
- spin_unlock(&tp->rx_lock);
+ spin_unlock_bh(&tp->rx_lock);
}
+static void rtl8139_tx_timeout (struct net_device *dev)
+{
+ struct rtl8139_private *tp = netdev_priv(dev);
+
+ if (!tp->have_thread) {
+ INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev);
+ schedule_delayed_work(&tp->thread, next_tick);
+ } else
+ tp->watchdog_fired = 1;
+
+}
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 1421941487c..e45a8f95971 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -4,9 +4,10 @@
#
menu "Network device support"
+ depends on NET
config NETDEVICES
- depends on NET
+ default y if UML
bool "Network device support"
---help---
You can say N here if you don't intend to connect your Linux box to
@@ -23,9 +24,6 @@ config NETDEVICES
If unsure, say Y.
-# All the following symbols are dependent on NETDEVICES - do not repeat
-# that for each of the symbols.
-if NETDEVICES
config IFB
tristate "Intermediate Functional Block support"
@@ -1914,6 +1912,15 @@ config E1000_NAPI
If in doubt, say N.
+config E1000_DISABLE_PACKET_SPLIT
+ bool "Disable Packet Split for PCI express adapters"
+ depends on E1000
+ help
+ Say Y here if you want to use the legacy receive path for PCI express
+ hadware.
+
+ If in doubt, say N.
+
source "drivers/net/ixp2000/Kconfig"
config MYRI_SBUS
@@ -2013,8 +2020,8 @@ config SIS190
will be called sis190. This is recommended.
config SKGE
- tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
+ tristate "New SysKonnect GigaEthernet support"
+ depends on PCI
select CRC32
---help---
This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
@@ -2024,13 +2031,28 @@ config SKGE
It does not support the link failover and network management
features that "portable" vendor supplied sk98lin driver does.
+ This driver supports adapters based on the original Yukon chipset:
+ Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
+ Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872.
+
+ It does not support the newer Yukon2 chipset: a separate driver,
+ sky2, is provided for Yukon2-based adapters.
+
+ To compile this driver as a module, choose M here: the module
+ will be called skge. This is recommended.
config SKY2
tristate "SysKonnect Yukon2 support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
select CRC32
---help---
- This driver support the Marvell Yukon 2 Gigabit Ethernet adapter.
+ This driver supports Gigabit Ethernet adapters based on the the
+ Marvell Yukon 2 chipset:
+ Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/
+ 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
+
+ This driver does not support the original Yukon chipset: a seperate
+ driver, skge, is provided for Yukon-based adapters.
To compile this driver as a module, choose M here: the module
will be called sky2. This is recommended.
@@ -2040,8 +2062,15 @@ config SK98LIN
depends on PCI
---help---
Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
- compliant Gigabit Ethernet Adapter. The following adapters are supported
- by this driver:
+ compliant Gigabit Ethernet Adapter.
+
+ This driver supports the original Yukon chipset. A cleaner driver is
+ also available (skge) which seems to work better than this one.
+
+ This driver does not support the newer Yukon2 chipset. A seperate
+ driver, sky2, is provided to support Yukon2-based adapters.
+
+ The following adapters are supported by this driver:
- 3Com 3C940 Gigabit LOM Ethernet Adapter
- 3Com 3C941 Gigabit LOM Ethernet Adapter
- Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
@@ -2053,7 +2082,6 @@ config SK98LIN
- Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
- Allied Telesyn AT-2971T Gigabit Ethernet Adapter
- Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
- - DGE-530T Gigabit Ethernet Adapter
- EG1032 v2 Instant Gigabit Network Adapter
- EG1064 v2 Instant Gigabit Network Adapter
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
@@ -2686,8 +2714,6 @@ config NETCONSOLE
If you want to log kernel messages over the network, enable this.
See <file:Documentation/networking/netconsole.txt> for details.
-endif #NETDEVICES
-
config NETPOLL
def_bool NETCONSOLE
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index b8953de5664..b508812e97a 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -1002,6 +1002,8 @@ static int __devinit ace_init(struct net_device *dev)
mac1 = 0;
for(i = 0; i < 4; i++) {
+ int tmp;
+
mac1 = mac1 << 8;
tmp = read_eeprom_byte(dev, 0x8c+i);
if (tmp < 0) {
@@ -1012,6 +1014,8 @@ static int __devinit ace_init(struct net_device *dev)
}
mac2 = 0;
for(i = 4; i < 8; i++) {
+ int tmp;
+
mac2 = mac2 << 8;
tmp = read_eeprom_byte(dev, 0x8c+i);
if (tmp < 0) {
diff --git a/drivers/net/appletalk/cops.h b/drivers/net/appletalk/cops.h
index c68ba9c2ef4..fd2750b269c 100644
--- a/drivers/net/appletalk/cops.h
+++ b/drivers/net/appletalk/cops.h
@@ -51,7 +51,7 @@
struct ltfirmware
{
unsigned int length;
- unsigned char * data;
+ const unsigned char *data;
};
#define DAYNA 1
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 7aa49b974dc..c3267e4e1bb 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1399,7 +1399,6 @@ static int b44_open(struct net_device *dev)
b44_init_rings(bp);
b44_init_hw(bp);
- netif_carrier_off(dev);
b44_check_phy(bp);
err = request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev);
@@ -1464,7 +1463,7 @@ static int b44_close(struct net_device *dev)
#endif
b44_halt(bp);
b44_free_rings(bp);
- netif_carrier_off(bp->dev);
+ netif_carrier_off(dev);
spin_unlock_irq(&bp->lock);
@@ -2000,6 +1999,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
dev->irq = pdev->irq;
SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
+ netif_carrier_off(dev);
+
err = b44_get_invariants(bp);
if (err) {
printk(KERN_ERR PFX "Problem fetching invariants of chip, "
@@ -2136,7 +2137,7 @@ static int __init b44_init(void)
/* 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));
+ dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
return pci_module_init(&b44_driver);
}
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 49fa1e4413f..a24200d0a61 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -1,6 +1,6 @@
/* bnx2.c: Broadcom NX2 network driver.
*
- * Copyright (c) 2004, 2005 Broadcom Corporation
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
*
* 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
@@ -14,8 +14,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.4.30"
-#define DRV_MODULE_RELDATE "October 11, 2005"
+#define DRV_MODULE_VERSION "1.4.31"
+#define DRV_MODULE_RELDATE "January 19, 2006"
#define RUN_AT(x) (jiffies + (x))
@@ -316,6 +316,10 @@ bnx2_enable_int(struct bnx2 *bp)
u32 val;
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx);
+
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx);
val = REG_RD(bp, BNX2_HC_COMMAND);
@@ -1171,7 +1175,8 @@ bnx2_init_5708s_phy(struct bnx2 *bp)
}
if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B0)) {
+ (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
+ (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
/* increase tx signal amplitude */
bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
BCM5708S_BLK_ADDR_TX_MISC);
@@ -1326,44 +1331,78 @@ bnx2_set_mac_loopback(struct bnx2 *bp)
return 0;
}
+static int bnx2_test_link(struct bnx2 *);
+
+static int
+bnx2_set_phy_loopback(struct bnx2 *bp)
+{
+ u32 mac_mode;
+ int rc, i;
+
+ spin_lock_bh(&bp->phy_lock);
+ rc = bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+ BMCR_SPEED1000);
+ spin_unlock_bh(&bp->phy_lock);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < 10; i++) {
+ if (bnx2_test_link(bp) == 0)
+ break;
+ udelay(10);
+ }
+
+ mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
+ mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
+ BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
+ BNX2_EMAC_MODE_25G);
+
+ mac_mode |= BNX2_EMAC_MODE_PORT_GMII;
+ REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
+ bp->link_up = 1;
+ return 0;
+}
+
static int
-bnx2_fw_sync(struct bnx2 *bp, u32 msg_data)
+bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
{
int i;
u32 val;
- if (bp->fw_timed_out)
- return -EBUSY;
-
bp->fw_wr_seq++;
msg_data |= bp->fw_wr_seq;
REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
/* wait for an acknowledgement. */
- for (i = 0; i < (FW_ACK_TIME_OUT_MS * 1000)/5; i++) {
- udelay(5);
+ for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) {
+ msleep(10);
val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB);
if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
break;
}
+ if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0)
+ return 0;
/* If we timed out, inform the firmware that this is the case. */
- if (((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) &&
- ((msg_data & BNX2_DRV_MSG_DATA) != BNX2_DRV_MSG_DATA_WAIT0)) {
+ if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
+ if (!silent)
+ printk(KERN_ERR PFX "fw sync timeout, reset code = "
+ "%x\n", msg_data);
msg_data &= ~BNX2_DRV_MSG_CODE;
msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
- bp->fw_timed_out = 1;
-
return -EBUSY;
}
+ if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK)
+ return -EIO;
+
return 0;
}
@@ -1657,7 +1696,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
rmb();
while (sw_cons != hw_cons) {
unsigned int len;
- u16 status;
+ u32 status;
struct sw_bd *rx_buf;
struct sk_buff *skb;
@@ -1673,7 +1712,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
rx_hdr = (struct l2_fhdr *) skb->data;
len = rx_hdr->l2_fhdr_pkt_len - 4;
- if (rx_hdr->l2_fhdr_errors &
+ if ((status = rx_hdr->l2_fhdr_status) &
(L2_FHDR_ERRORS_BAD_CRC |
L2_FHDR_ERRORS_PHY_DECODE |
L2_FHDR_ERRORS_ALIGNMENT |
@@ -1732,15 +1771,13 @@ reuse_rx:
}
- status = rx_hdr->l2_fhdr_status;
skb->ip_summed = CHECKSUM_NONE;
if (bp->rx_csum &&
(status & (L2_FHDR_STATUS_TCP_SEGMENT |
L2_FHDR_STATUS_UDP_DATAGRAM))) {
- u16 cksum = rx_hdr->l2_fhdr_tcp_udp_xsum;
-
- if (cksum == 0xffff)
+ if (likely((status & (L2_FHDR_ERRORS_TCP_XSUM |
+ L2_FHDR_ERRORS_UDP_XSUM)) == 0))
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
@@ -1794,7 +1831,7 @@ static irqreturn_t
bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs)
{
struct net_device *dev = dev_instance;
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
prefetch(bp->status_blk);
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
@@ -1814,7 +1851,7 @@ static irqreturn_t
bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
struct net_device *dev = dev_instance;
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
/* When using INTx, it is possible for the interrupt to arrive
* at the CPU before the status block posted prior to the
@@ -1859,7 +1896,7 @@ bnx2_has_work(struct bnx2 *bp)
static int
bnx2_poll(struct net_device *dev, int *budget)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
if ((bp->status_blk->status_attn_bits &
STATUS_ATTN_BITS_LINK_STATE) !=
@@ -1891,9 +1928,20 @@ bnx2_poll(struct net_device *dev, int *budget)
if (!bnx2_has_work(bp)) {
netif_rx_complete(dev);
+ if (likely(bp->flags & USING_MSI_FLAG)) {
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bp->last_status_idx);
+ return 0;
+ }
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+ bp->last_status_idx);
+
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- bp->last_status_idx);
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bp->last_status_idx);
return 0;
}
@@ -1906,7 +1954,7 @@ bnx2_poll(struct net_device *dev, int *budget)
static void
bnx2_set_rx_mode(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
u32 rx_mode, sort_mode;
int i;
@@ -1916,11 +1964,11 @@ bnx2_set_rx_mode(struct net_device *dev)
BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
#ifdef BCM_VLAN
- if (!bp->vlgrp) {
+ if (!bp->vlgrp && !(bp->flags & ASF_ENABLE_FLAG))
rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
- }
#else
- rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
+ if (!(bp->flags & ASF_ENABLE_FLAG))
+ rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
#endif
if (dev->flags & IFF_PROMISC) {
/* Promiscuous mode. */
@@ -2338,7 +2386,6 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
val |= BNX2_EMAC_MODE_PORT_MII |
BNX2_EMAC_MODE_MPKT_RCVD |
BNX2_EMAC_MODE_ACPI_RCVD |
- BNX2_EMAC_MODE_FORCE_LINK |
BNX2_EMAC_MODE_MPKT;
REG_WR(bp, BNX2_EMAC_MODE, val);
@@ -2374,7 +2421,8 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
}
- bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg);
+ if (!(bp->flags & NO_WOL_FLAG))
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 0);
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
@@ -2708,9 +2756,16 @@ bnx2_init_nvram(struct bnx2 *bp)
if (j == entry_count) {
bp->flash_info = NULL;
printk(KERN_ALERT PFX "Unknown flash/EEPROM type.\n");
- rc = -ENODEV;
+ return -ENODEV;
}
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2);
+ val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK;
+ if (val)
+ bp->flash_size = val;
+ else
+ bp->flash_size = bp->flash_info->total_size;
+
return rc;
}
@@ -3014,16 +3069,14 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
udelay(5);
+ /* Wait for the firmware to tell us it is ok to issue a reset. */
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1);
+
/* Deposit a driver reset signature so the firmware knows that
* this is a soft reset. */
REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE,
BNX2_DRV_RESET_SIGNATURE_MAGIC);
- bp->fw_timed_out = 0;
-
- /* Wait for the firmware to tell us it is ok to issue a reset. */
- bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code);
-
/* Do a dummy read to force the chip to complete all current transaction
* before we issue a reset. */
val = REG_RD(bp, BNX2_MISC_ID);
@@ -3062,10 +3115,10 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
return -ENODEV;
}
- bp->fw_timed_out = 0;
-
/* Wait for the firmware to finish its initialization. */
- bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code);
+ rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 0);
+ if (rc)
+ return rc;
if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
/* Adjust the voltage regular to two steps lower. The default
@@ -3083,6 +3136,7 @@ static int
bnx2_init_chip(struct bnx2 *bp)
{
u32 val;
+ int rc;
/* Make sure the interrupt is not active. */
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
@@ -3098,7 +3152,7 @@ bnx2_init_chip(struct bnx2 *bp)
val |= (0x2 << 20) | (1 << 11);
- if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz = 133))
+ if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz == 133))
val |= (1 << 23);
if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
@@ -3218,17 +3272,22 @@ bnx2_init_chip(struct bnx2 *bp)
REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
+ if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
+ BNX2_PORT_FEATURE_ASF_ENABLED)
+ bp->flags |= ASF_ENABLE_FLAG;
+
/* Initialize the receive filter. */
bnx2_set_rx_mode(bp->dev);
- bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET);
+ rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
+ 0);
REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
udelay(20);
- return 0;
+ return rc;
}
@@ -3880,26 +3939,33 @@ bnx2_test_memory(struct bnx2 *bp)
return ret;
}
+#define BNX2_MAC_LOOPBACK 0
+#define BNX2_PHY_LOOPBACK 1
+
static int
-bnx2_test_loopback(struct bnx2 *bp)
+bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
{
unsigned int pkt_size, num_pkts, i;
struct sk_buff *skb, *rx_skb;
unsigned char *packet;
- u16 rx_start_idx, rx_idx, send_idx;
- u32 send_bseq, val;
+ u16 rx_start_idx, rx_idx;
+ u32 val;
dma_addr_t map;
struct tx_bd *txbd;
struct sw_bd *rx_buf;
struct l2_fhdr *rx_hdr;
int ret = -ENODEV;
- if (!netif_running(bp->dev))
- return -ENODEV;
-
- bp->loopback = MAC_LOOPBACK;
- bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_DIAG);
- bnx2_set_mac_loopback(bp);
+ if (loopback_mode == BNX2_MAC_LOOPBACK) {
+ bp->loopback = MAC_LOOPBACK;
+ bnx2_set_mac_loopback(bp);
+ }
+ else if (loopback_mode == BNX2_PHY_LOOPBACK) {
+ bp->loopback = 0;
+ bnx2_set_phy_loopback(bp);
+ }
+ else
+ return -EINVAL;
pkt_size = 1514;
skb = dev_alloc_skb(pkt_size);
@@ -3921,11 +3987,9 @@ bnx2_test_loopback(struct bnx2 *bp)
udelay(5);
rx_start_idx = bp->status_blk->status_rx_quick_consumer_index0;
- send_idx = 0;
- send_bseq = 0;
num_pkts = 0;
- txbd = &bp->tx_desc_ring[send_idx];
+ txbd = &bp->tx_desc_ring[TX_RING_IDX(bp->tx_prod)];
txbd->tx_bd_haddr_hi = (u64) map >> 32;
txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff;
@@ -3933,13 +3997,11 @@ bnx2_test_loopback(struct bnx2 *bp)
txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
num_pkts++;
- send_idx = NEXT_TX_BD(send_idx);
-
- send_bseq += pkt_size;
-
- REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, send_idx);
- REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, send_bseq);
+ bp->tx_prod = NEXT_TX_BD(bp->tx_prod);
+ bp->tx_prod_bseq += pkt_size;
+ REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, bp->tx_prod);
+ REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
udelay(100);
@@ -3952,7 +4014,7 @@ bnx2_test_loopback(struct bnx2 *bp)
pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE);
dev_kfree_skb_irq(skb);
- if (bp->status_blk->status_tx_quick_consumer_index0 != send_idx) {
+ if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_prod) {
goto loopback_test_done;
}
@@ -3971,7 +4033,7 @@ bnx2_test_loopback(struct bnx2 *bp)
pci_unmap_addr(rx_buf, mapping),
bp->rx_buf_size, PCI_DMA_FROMDEVICE);
- if (rx_hdr->l2_fhdr_errors &
+ if (rx_hdr->l2_fhdr_status &
(L2_FHDR_ERRORS_BAD_CRC |
L2_FHDR_ERRORS_PHY_DECODE |
L2_FHDR_ERRORS_ALIGNMENT |
@@ -3998,6 +4060,30 @@ loopback_test_done:
return ret;
}
+#define BNX2_MAC_LOOPBACK_FAILED 1
+#define BNX2_PHY_LOOPBACK_FAILED 2
+#define BNX2_LOOPBACK_FAILED (BNX2_MAC_LOOPBACK_FAILED | \
+ BNX2_PHY_LOOPBACK_FAILED)
+
+static int
+bnx2_test_loopback(struct bnx2 *bp)
+{
+ int rc = 0;
+
+ if (!netif_running(bp->dev))
+ return BNX2_LOOPBACK_FAILED;
+
+ bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
+ spin_lock_bh(&bp->phy_lock);
+ bnx2_init_phy(bp);
+ spin_unlock_bh(&bp->phy_lock);
+ if (bnx2_run_loopback(bp, BNX2_MAC_LOOPBACK))
+ rc |= BNX2_MAC_LOOPBACK_FAILED;
+ if (bnx2_run_loopback(bp, BNX2_PHY_LOOPBACK))
+ rc |= BNX2_PHY_LOOPBACK_FAILED;
+ return rc;
+}
+
#define NVRAM_SIZE 0x200
#define CRC32_RESIDUAL 0xdebb20e3
@@ -4167,7 +4253,7 @@ bnx2_restart_timer:
static int
bnx2_open(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
int rc;
bnx2_set_power_state(bp, PCI_D0);
@@ -4280,7 +4366,7 @@ bnx2_reset_task(void *data)
static void
bnx2_tx_timeout(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
/* This allows the netif to be shutdown gracefully before resetting */
schedule_work(&bp->reset_task);
@@ -4291,7 +4377,7 @@ bnx2_tx_timeout(struct net_device *dev)
static void
bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
bnx2_netif_stop(bp);
@@ -4305,7 +4391,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
static void
bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
bnx2_netif_stop(bp);
@@ -4326,7 +4412,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
static int
bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
dma_addr_t mapping;
struct tx_bd *txbd;
struct sw_bd *tx_buf;
@@ -4455,7 +4541,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
static int
bnx2_close(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
u32 reset_code;
/* Calling flush_scheduled_work() may deadlock because
@@ -4467,7 +4553,9 @@ bnx2_close(struct net_device *dev)
bnx2_netif_stop(bp);
del_timer_sync(&bp->timer);
- if (bp->wol)
+ if (bp->flags & NO_WOL_FLAG)
+ reset_code = BNX2_DRV_MSG_CODE_UNLOAD;
+ else if (bp->wol)
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
else
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
@@ -4501,7 +4589,7 @@ bnx2_close(struct net_device *dev)
static struct net_device_stats *
bnx2_get_stats(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
struct statistics_block *stats_blk = bp->stats_blk;
struct net_device_stats *net_stats = &bp->net_stats;
@@ -4575,7 +4663,7 @@ bnx2_get_stats(struct net_device *dev)
static int
bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
cmd->supported = SUPPORTED_Autoneg;
if (bp->phy_flags & PHY_SERDES_FLAG) {
@@ -4622,7 +4710,7 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int
bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
u8 autoneg = bp->autoneg;
u8 req_duplex = bp->req_duplex;
u16 req_line_speed = bp->req_line_speed;
@@ -4694,7 +4782,7 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static void
bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
strcpy(info->driver, DRV_MODULE_NAME);
strcpy(info->version, DRV_MODULE_VERSION);
@@ -4702,15 +4790,14 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0';
info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0';
info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0';
- info->fw_version[6] = (bp->fw_ver & 0xff) + '0';
- info->fw_version[1] = info->fw_version[3] = info->fw_version[5] = '.';
- info->fw_version[7] = 0;
+ info->fw_version[1] = info->fw_version[3] = '.';
+ info->fw_version[5] = 0;
}
static void
bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
if (bp->flags & NO_WOL_FLAG) {
wol->supported = 0;
@@ -4729,7 +4816,7 @@ bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static int
bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
if (wol->wolopts & ~WAKE_MAGIC)
return -EINVAL;
@@ -4749,7 +4836,7 @@ bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static int
bnx2_nway_reset(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
u32 bmcr;
if (!(bp->autoneg & AUTONEG_SPEED)) {
@@ -4785,19 +4872,19 @@ bnx2_nway_reset(struct net_device *dev)
static int
bnx2_get_eeprom_len(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
- if (bp->flash_info == 0)
+ if (bp->flash_info == NULL)
return 0;
- return (int) bp->flash_info->total_size;
+ return (int) bp->flash_size;
}
static int
bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 *eebuf)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
int rc;
/* parameters already validated in ethtool_get_eeprom */
@@ -4811,7 +4898,7 @@ static int
bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 *eebuf)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
int rc;
/* parameters already validated in ethtool_set_eeprom */
@@ -4824,7 +4911,7 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
static int
bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
memset(coal, 0, sizeof(struct ethtool_coalesce));
@@ -4846,7 +4933,7 @@ bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
static int
bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff;
@@ -4890,7 +4977,7 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
static void
bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
ering->rx_max_pending = MAX_RX_DESC_CNT;
ering->rx_mini_max_pending = 0;
@@ -4907,7 +4994,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
static int
bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
if ((ering->rx_pending > MAX_RX_DESC_CNT) ||
(ering->tx_pending > MAX_TX_DESC_CNT) ||
@@ -4930,7 +5017,7 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
static void
bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
epause->autoneg = ((bp->autoneg & AUTONEG_FLOW_CTRL) != 0);
epause->rx_pause = ((bp->flow_ctrl & FLOW_CTRL_RX) != 0);
@@ -4940,7 +5027,7 @@ bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
static int
bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
bp->req_flow_ctrl = 0;
if (epause->rx_pause)
@@ -4967,7 +5054,7 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
static u32
bnx2_get_rx_csum(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
return bp->rx_csum;
}
@@ -4975,7 +5062,7 @@ bnx2_get_rx_csum(struct net_device *dev)
static int
bnx2_set_rx_csum(struct net_device *dev, u32 data)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
bp->rx_csum = data;
return 0;
@@ -5124,7 +5211,7 @@ bnx2_self_test_count(struct net_device *dev)
static void
bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS);
if (etest->flags & ETH_TEST_FL_OFFLINE) {
@@ -5140,10 +5227,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
buf[1] = 1;
etest->flags |= ETH_TEST_FL_FAILED;
}
- if (bnx2_test_loopback(bp) != 0) {
- buf[2] = 1;
+ if ((buf[2] = bnx2_test_loopback(bp)) != 0)
etest->flags |= ETH_TEST_FL_FAILED;
- }
if (!netif_running(bp->dev)) {
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
@@ -5200,7 +5285,7 @@ static void
bnx2_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *buf)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
int i;
u32 *hw_stats = (u32 *) bp->stats_blk;
u8 *stats_len_arr = NULL;
@@ -5240,7 +5325,7 @@ bnx2_get_ethtool_stats(struct net_device *dev,
static int
bnx2_phys_id(struct net_device *dev, u32 data)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
int i;
u32 save;
@@ -5312,7 +5397,7 @@ static int
bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct mii_ioctl_data *data = if_mii(ifr);
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
int err;
switch(cmd) {
@@ -5354,7 +5439,7 @@ static int
bnx2_change_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
@@ -5370,7 +5455,7 @@ bnx2_change_mac_addr(struct net_device *dev, void *p)
static int
bnx2_change_mtu(struct net_device *dev, int new_mtu)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE))
@@ -5391,7 +5476,7 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
static void
poll_bnx2(struct net_device *dev)
{
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
disable_irq(bp->pdev->irq);
bnx2_interrupt(bp->pdev->irq, dev, NULL);
@@ -5409,7 +5494,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
- bp = dev->priv;
+ bp = netdev_priv(dev);
bp->flags = 0;
bp->phy_flags = 0;
@@ -5629,6 +5714,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
}
}
+ if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ bp->flags |= NO_WOL_FLAG;
+
if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
bp->tx_quick_cons_trip_int =
bp->tx_quick_cons_trip;
@@ -5725,7 +5813,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->ethtool_ops = &bnx2_ethtool_ops;
dev->weight = 64;
- bp = dev->priv;
+ bp = netdev_priv(dev);
#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
dev->poll_controller = poll_bnx2;
@@ -5784,7 +5872,7 @@ static void __devexit
bnx2_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
flush_scheduled_work();
@@ -5803,7 +5891,7 @@ static int
bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
u32 reset_code;
if (!netif_running(dev))
@@ -5812,7 +5900,9 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
bnx2_netif_stop(bp);
netif_device_detach(dev);
del_timer_sync(&bp->timer);
- if (bp->wol)
+ if (bp->flags & NO_WOL_FLAG)
+ reset_code = BNX2_DRV_MSG_CODE_UNLOAD;
+ else if (bp->wol)
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
else
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
@@ -5826,7 +5916,7 @@ static int
bnx2_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct bnx2 *bp = dev->priv;
+ struct bnx2 *bp = netdev_priv(dev);
if (!netif_running(dev))
return 0;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 76bb5f1a250..9f691cbd666 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -1,6 +1,6 @@
/* bnx2.h: Broadcom NX2 network driver.
*
- * Copyright (c) 2004, 2005 Broadcom Corporation
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
*
* 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
@@ -277,19 +277,7 @@ struct statistics_block {
* l2_fhdr definition
*/
struct l2_fhdr {
-#if defined(__BIG_ENDIAN)
- u16 l2_fhdr_errors;
- u16 l2_fhdr_status;
-#elif defined(__LITTLE_ENDIAN)
- u16 l2_fhdr_status;
- u16 l2_fhdr_errors;
-#endif
- #define L2_FHDR_ERRORS_BAD_CRC (1<<1)
- #define L2_FHDR_ERRORS_PHY_DECODE (1<<2)
- #define L2_FHDR_ERRORS_ALIGNMENT (1<<3)
- #define L2_FHDR_ERRORS_TOO_SHORT (1<<4)
- #define L2_FHDR_ERRORS_GIANT_FRAME (1<<5)
-
+ u32 l2_fhdr_status;
#define L2_FHDR_STATUS_RULE_CLASS (0x7<<0)
#define L2_FHDR_STATUS_RULE_P2 (1<<3)
#define L2_FHDR_STATUS_RULE_P3 (1<<4)
@@ -301,6 +289,14 @@ struct l2_fhdr {
#define L2_FHDR_STATUS_TCP_SEGMENT (1<<14)
#define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15)
+ #define L2_FHDR_ERRORS_BAD_CRC (1<<17)
+ #define L2_FHDR_ERRORS_PHY_DECODE (1<<18)
+ #define L2_FHDR_ERRORS_ALIGNMENT (1<<19)
+ #define L2_FHDR_ERRORS_TOO_SHORT (1<<20)
+ #define L2_FHDR_ERRORS_GIANT_FRAME (1<<21)
+ #define L2_FHDR_ERRORS_TCP_XSUM (1<<28)
+ #define L2_FHDR_ERRORS_UDP_XSUM (1<<31)
+
u32 l2_fhdr_hash;
#if defined(__BIG_ENDIAN)
u16 l2_fhdr_pkt_len;
@@ -3956,6 +3952,7 @@ struct bnx2 {
#define NO_WOL_FLAG 8
#define USING_DAC_FLAG 0x10
#define USING_MSI_FLAG 0x20
+#define ASF_ENABLE_FLAG 0x40
u32 phy_flags;
#define PHY_SERDES_FLAG 1
@@ -3986,6 +3983,7 @@ struct bnx2 {
#define CHIP_ID_5706_A2 0x57060020
#define CHIP_ID_5708_A0 0x57080000
#define CHIP_ID_5708_B0 0x57081000
+#define CHIP_ID_5708_B1 0x57081010
#define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf)
@@ -3998,7 +3996,7 @@ struct bnx2 {
u16 bus_speed_mhz;
u8 wol;
- u8 fw_timed_out;
+ u8 pad;
u16 fw_wr_seq;
u16 fw_drv_pulse_wr_seq;
@@ -4074,6 +4072,7 @@ struct bnx2 {
struct net_device_stats net_stats;
struct flash_spec *flash_info;
+ u32 flash_size;
};
static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
@@ -4172,7 +4171,7 @@ struct fw_info {
* the firmware has timed out, the driver will assume there is no firmware
* running and there won't be any firmware-driver synchronization during a
* driver reset. */
-#define FW_ACK_TIME_OUT_MS 50
+#define FW_ACK_TIME_OUT_MS 100
#define BNX2_DRV_RESET_SIGNATURE 0x00000000
@@ -4275,6 +4274,9 @@ struct fw_info {
#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1 0x100
#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2 0x200
+#define BNX2_SHARED_HW_CFG_CONFIG2 0x00000040
+#define BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK 0x00fff000
+
#define BNX2_DEV_INFO_BC_REV 0x0000004c
#define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050
diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h
index ab07a4900e9..0c21bd84981 100644
--- a/drivers/net/bnx2_fw.h
+++ b/drivers/net/bnx2_fw.h
@@ -1,6 +1,6 @@
/* bnx2_fw.h: Broadcom NX2 network driver.
*
- * Copyright (c) 2004, 2005 Broadcom Corporation
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
*
* 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
@@ -978,20 +978,20 @@ static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
static int bnx2_RXP_b06FwReleaseMajor = 0x1;
static int bnx2_RXP_b06FwReleaseMinor = 0x0;
static int bnx2_RXP_b06FwReleaseFix = 0x0;
-static u32 bnx2_RXP_b06FwStartAddr = 0x08003104;
+static u32 bnx2_RXP_b06FwStartAddr = 0x08003184;
static u32 bnx2_RXP_b06FwTextAddr = 0x08000000;
-static int bnx2_RXP_b06FwTextLen = 0x562c;
-static u32 bnx2_RXP_b06FwDataAddr = 0x08005660;
+static int bnx2_RXP_b06FwTextLen = 0x588c;
+static u32 bnx2_RXP_b06FwDataAddr = 0x080058e0;
static int bnx2_RXP_b06FwDataLen = 0x0;
-static u32 bnx2_RXP_b06FwRodataAddr = 0x00000000;
-static int bnx2_RXP_b06FwRodataLen = 0x0;
-static u32 bnx2_RXP_b06FwBssAddr = 0x08005680;
-static int bnx2_RXP_b06FwBssLen = 0x1394;
-static u32 bnx2_RXP_b06FwSbssAddr = 0x08005660;
-static int bnx2_RXP_b06FwSbssLen = 0x18;
-static u32 bnx2_RXP_b06FwText[(0x562c/4) + 1] = {
- 0x0a000c41, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e352e,
- 0x38000000, 0x02050803, 0x00000000, 0x0000000d, 0x00000000, 0x00000000,
+static u32 bnx2_RXP_b06FwRodataAddr = 0x08005890;
+static int bnx2_RXP_b06FwRodataLen = 0x28;
+static u32 bnx2_RXP_b06FwBssAddr = 0x08005900;
+static int bnx2_RXP_b06FwBssLen = 0x13a4;
+static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0;
+static int bnx2_RXP_b06FwSbssLen = 0x1c;
+static u32 bnx2_RXP_b06FwText[(0x588c/4) + 1] = {
+ 0x0a000c61, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e362e,
+ 0x31000000, 0x02060103, 0x00000000, 0x0000000d, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -1513,408 +1513,435 @@ static u32 bnx2_RXP_b06FwText[(0x562c/4) + 1] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425660,
- 0x3c030800, 0x24636a14, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004,
- 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x26103104, 0x3c1c0800,
- 0x279c5660, 0x0e001035, 0x00000000, 0x0000000d, 0x3c080800, 0x8d023100,
- 0x2c420080, 0x50400001, 0xad003100, 0x8d073100, 0x3c040800, 0x24840100,
- 0x8f460100, 0x00071840, 0x00671821, 0x00031940, 0x00641021, 0xac460000,
- 0x8f450104, 0x00831021, 0xac450004, 0x8f460108, 0xac460008, 0x8f45010c,
- 0xac45000c, 0x8f460114, 0xac460010, 0x8f450118, 0xac450014, 0x8f460124,
- 0xac460018, 0x8f450128, 0xac45001c, 0x8f464010, 0xac460020, 0x8f454014,
- 0xac450024, 0x8f464018, 0xac460028, 0x8f45401c, 0xac45002c, 0x8f464020,
- 0xac460030, 0x8f454024, 0xac450034, 0x8f464028, 0xac460038, 0x8f45402c,
- 0xac45003c, 0x8f464030, 0xac460040, 0x8f454034, 0xac450044, 0x8f464038,
- 0xac460048, 0x8f45403c, 0xac45004c, 0x8f464040, 0xac460050, 0x8f454044,
- 0xac450054, 0x8f464048, 0xac460058, 0x8f45404c, 0x24e70001, 0x00402021,
- 0xad073100, 0x03e00008, 0xac85005c, 0x8f820004, 0x9743010c, 0x00804821,
- 0x00403021, 0x30421000, 0x10400010, 0x306affff, 0x30c20020, 0x1440000e,
- 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff, 0x3463ffff,
- 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001, 0x0a000cb1,
- 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d, 0x00405821,
- 0x8f820010, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01, 0x00c24024,
- 0x3c031000, 0x15030015, 0x3c020001, 0x31420200, 0x54400012, 0x3c020001,
- 0x9744010e, 0x24020003, 0xa342018b, 0x97850012, 0x24020002, 0x34e30002,
- 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff, 0xa744018e,
- 0xa74501a6, 0xaf4801b8, 0x03e00008, 0x00001021, 0x3c020001, 0x00c21024,
- 0x10400039, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff, 0x8f4201b8,
- 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c,
- 0x24020080, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005,
- 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000cec, 0x00021400, 0x9743011e,
- 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x24020003,
- 0x30838000, 0x1060000d, 0xa7420188, 0x93420116, 0x304200fc, 0x005a1021,
- 0x24424004, 0x8c430000, 0x3063ffff, 0x14600005, 0x00000000, 0x3c02ffff,
- 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104,
- 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
- 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f820010, 0x30434000,
- 0x10600016, 0x00404021, 0x3c020f00, 0x00c21024, 0x14400012, 0x00000000,
- 0x93420116, 0x34424000, 0x03421821, 0x94650002, 0x2ca21389, 0x1040000b,
- 0x3c020800, 0x24425680, 0x00051942, 0x00031880, 0x00621821, 0x30a5001f,
- 0x8c640000, 0x24020001, 0x00a21004, 0x00822024, 0x01244825, 0x11200039,
- 0x3c021000, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3046ffff,
- 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006,
- 0x8f85000c, 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e,
- 0x10a00005, 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000d41, 0x00021400,
- 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010,
- 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d,
+ 0x3c020800, 0x244258e0, 0x3c030800, 0x24636ca4, 0xac400000, 0x0043202b,
+ 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800,
+ 0x26103184, 0x3c1c0800, 0x279c58e0, 0x0e00104a, 0x00000000, 0x0000000d,
+ 0x27bdffe8, 0xafb00010, 0xafbf0014, 0x0e000f1d, 0x00808021, 0x1440000d,
+ 0x00000000, 0x8f820010, 0x10400005, 0x00000000, 0x9743011c, 0x9742011e,
+ 0x0a000c89, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825,
+ 0xaf830004, 0x8f840008, 0x3c020020, 0x34424000, 0x00821824, 0x54620004,
+ 0x3c020020, 0x8f820014, 0x0a000c9a, 0x34421000, 0x34428000, 0x00821824,
+ 0x14620004, 0x00000000, 0x8f820014, 0x34428000, 0xaf820014, 0x8f820008,
+ 0x9743010c, 0x00403021, 0x30421000, 0x10400010, 0x3069ffff, 0x30c20020,
+ 0x1440000e, 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff,
+ 0x3463ffff, 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001,
+ 0x0a000cb2, 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d,
+ 0x00405821, 0x8f820014, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01,
+ 0x00c24024, 0x3c031000, 0x15030015, 0x3c020001, 0x31220200, 0x14400012,
+ 0x3c020001, 0x9744010e, 0x24020003, 0xa342018b, 0x97850016, 0x24020002,
+ 0x34e30002, 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff,
+ 0xa744018e, 0xa74501a6, 0xaf4801b8, 0x0a000f19, 0x00001021, 0x3c020001,
+ 0x00c21024, 0x1040002f, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9784000a,
+ 0x8f850004, 0x8f870014, 0x24020080, 0x24030002, 0xaf420180, 0x24020003,
+ 0xa743018c, 0xa746018e, 0xa7420188, 0x30e28000, 0xa7440190, 0x1040000c,
+ 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000,
+ 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014,
+ 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff,
+ 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19,
+ 0x00001021, 0x8f820014, 0x30434000, 0x10600016, 0x00404021, 0x3c020f00,
+ 0x00c21024, 0x14400012, 0x00000000, 0x93420116, 0x34424000, 0x03421821,
+ 0x94650002, 0x2ca21389, 0x1040000b, 0x3c020800, 0x24425900, 0x00051942,
+ 0x00031880, 0x00621821, 0x30a5001f, 0x8c640000, 0x24020001, 0x00a21004,
+ 0x00822024, 0x02048025, 0x12000030, 0x3c021000, 0x9742010e, 0x34e80002,
+ 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180,
+ 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
+ 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
- 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
- 0xaf4201b8, 0x03e00008, 0x00001021, 0x00c21024, 0x104000e3, 0x3c020800,
- 0x8c430030, 0x10600040, 0x31024000, 0x1040003e, 0x3c030f00, 0x00c31824,
- 0x3c020100, 0x0043102b, 0x1440003a, 0x3c030800, 0x9742010e, 0x34e70002,
+ 0xaf4201b8, 0x0a000f19, 0x00001021, 0x00c21024, 0x104000c0, 0x3c020800,
+ 0x8c430030, 0x10600037, 0x31024000, 0x10400035, 0x3c030f00, 0x00c31824,
+ 0x3c020100, 0x0043102b, 0x14400031, 0x3c030800, 0x9742010e, 0x34e80002,
0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
- 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, 0x24020080, 0x24030002,
- 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, 0xa7440190, 0x9743011c,
- 0x9742011e, 0x0a000d86, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400,
- 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188,
+ 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020080,
+ 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
+ 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008,
+ 0x10400035, 0x34ea0002, 0x3c020f00, 0x00c21024, 0x14400032, 0x8d620034,
+ 0x31220200, 0x1040002f, 0x8d620034, 0x9742010e, 0x30e8fffb, 0x3c038000,
+ 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
+ 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, 0x24030002,
+ 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, 0xa7440190,
+ 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+ 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024,
+ 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+ 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
+ 0x8d620034, 0x8f860008, 0x10400012, 0x30c20100, 0x10400010, 0x3c020f00,
+ 0x00c21024, 0x3c030200, 0x1043000c, 0x3c020800, 0x8c430038, 0x8f840004,
+ 0x3c020800, 0x2442003c, 0x2463ffff, 0x00832024, 0x00822021, 0x90830000,
+ 0x24630004, 0x0a000de1, 0x000329c0, 0x00000000, 0x00061602, 0x3042000f,
+ 0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, 0x0062182b, 0x50600001,
+ 0x24050800, 0x9742010e, 0x3148ffff, 0x3c038000, 0x24420004, 0x3046ffff,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+ 0x8f840004, 0x8f870014, 0x24020002, 0xaf450180, 0xa742018c, 0xa746018e,
+ 0xa7480188, 0x30e28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
+ 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
+ 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c,
+ 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
+ 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x8f424000,
+ 0x30420100, 0x104000d5, 0x3c020800, 0x8c440024, 0x24030001, 0x1483002f,
+ 0x00405021, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3045ffff,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+ 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e,
+ 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
+ 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
+ 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, 0x9743010c,
+ 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
+ 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x30820001,
+ 0x1040002e, 0x30eb0004, 0x9742010e, 0x30e9fffb, 0x3c038000, 0x24420004,
+ 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b,
+ 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c,
+ 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8,
0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff,
- 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, 0x97820012,
+ 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016,
0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825,
- 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021,
- 0x3c030800, 0x8c620024, 0x30420008, 0x1040003e, 0x34e80002, 0x3c020f00,
- 0x00c21024, 0x1440003b, 0x8d620034, 0x31420200, 0x10400038, 0x8d620034,
- 0x9742010e, 0x30e7fffb, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8,
- 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c,
- 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005,
- 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000dca, 0x00021400, 0x9743011e,
- 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000,
- 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
- 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024,
- 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
- 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
- 0x8d620034, 0x8f860004, 0x1040001a, 0x30c20100, 0x10400018, 0x3c020f00,
- 0x00c21024, 0x3c030200, 0x10430014, 0x00000000, 0x8f82000c, 0x10400004,
- 0x00000000, 0x9742011c, 0x0a000df8, 0x3044ffff, 0x9742011e, 0x3044ffff,
- 0x3c030800, 0x8c620038, 0x3c030800, 0x2463003c, 0x2442ffff, 0x00822024,
- 0x00831821, 0x90620000, 0x24420004, 0x0a000e0d, 0x000229c0, 0x00000000,
- 0x00061602, 0x3042000f, 0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300,
- 0x0062182b, 0x50600001, 0x24050800, 0x9742010e, 0x3107ffff, 0x3c038000,
+ 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3127ffff, 0x8d420024,
+ 0x30420004, 0x10400030, 0x8d420024, 0x9742010e, 0x30e9fffb, 0x3c038000,
0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
- 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf450180, 0xa742018c,
- 0xa746018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a000e26,
- 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8,
- 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc,
- 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
- 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104,
- 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
- 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f424000, 0x30420100,
- 0x104000f9, 0x3c020800, 0x8c440024, 0x24030001, 0x14830038, 0x00404821,
- 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8,
- 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97830006, 0x8f84000c,
- 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e, 0x10800005, 0xa7430190,
- 0x9743011c, 0x9742011e, 0x0a000e65, 0x00021400, 0x9743011e, 0x9742011c,
- 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c,
- 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000,
- 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010,
- 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff,
- 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008,
- 0x00001021, 0x30820001, 0x10400037, 0x30ea0004, 0x9742010e, 0x30e8fffb,
+ 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020100, 0x24030002,
+ 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, 0xa7440190,
+ 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+ 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x01021024,
+ 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+ 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
+ 0x3127ffff, 0x8d420024, 0x30420008, 0x1040002d, 0x00000000, 0x9742010e,
+ 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020180,
+ 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000,
+ 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x15600041, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b,
+ 0xa4800010, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800,
+ 0x8c620024, 0x30420001, 0x1040002e, 0x00001021, 0x9742010e, 0x34e70002,
0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
- 0x24020003, 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf400180,
- 0xa742018c, 0xa745018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e,
- 0x0a000e9f, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825,
- 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116,
- 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
- 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c,
- 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
- 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3107ffff, 0x8d220024, 0x30420004,
- 0x10400039, 0x8d220024, 0x9742010e, 0x30e8fffb, 0x3c038000, 0x24420004,
- 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b,
- 0x97840006, 0x8f85000c, 0x24020100, 0x24030002, 0xaf420180, 0xa743018c,
- 0xa746018e, 0x10a00005, 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000eda,
- 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8,
- 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc,
- 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
- 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104,
- 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
- 0x3c021000, 0xaf4201b8, 0x3107ffff, 0x8d220024, 0x30420008, 0x10400036,
- 0x00000000, 0x9742010e, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8,
- 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c,
- 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005,
- 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000f14, 0x00021400, 0x9743011e,
- 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000,
- 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
- 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024,
- 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+ 0x24020003, 0xa342018b, 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002,
+ 0xaf400180, 0xa742018c, 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190,
+ 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+ 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024,
+ 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
- 0x1540004a, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024,
- 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b, 0xa4800010,
- 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x3c030800, 0x8c620024,
- 0x30420001, 0x10400037, 0x00001021, 0x9742010e, 0x34e60002, 0x3c038000,
- 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
- 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf400180, 0xa742018c,
- 0xa745018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a000f5e,
- 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8,
- 0x8f840010, 0x30828000, 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc,
+ 0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x8f4b0070,
+ 0x93420112, 0x8f840008, 0x00022882, 0x30820100, 0x14400003, 0x24a30003,
+ 0x03e00008, 0x00001021, 0x30824000, 0x10400010, 0x27424000, 0x00031880,
+ 0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
+ 0x8c490000, 0x93430116, 0x27424000, 0x306300fc, 0x00431021, 0x8c4a0000,
+ 0x0a000f45, 0x3c030800, 0x30822000, 0x1040ffea, 0x00031880, 0x27424000,
+ 0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
+ 0x8c490000, 0x00005021, 0x3c030800, 0x24680100, 0x00071602, 0x00021080,
+ 0x00481021, 0x8c460000, 0x00071b82, 0x306303fc, 0x01031821, 0x8c640400,
+ 0x00071182, 0x304203fc, 0x01021021, 0x8c450800, 0x30e300ff, 0x00031880,
+ 0x01031821, 0x00091602, 0x00021080, 0x01021021, 0x00c43026, 0x8c640c00,
+ 0x8c431000, 0x00c53026, 0x00091382, 0x304203fc, 0x01021021, 0x8c451400,
+ 0x312200ff, 0x00021080, 0x01021021, 0x00c43026, 0x00c33026, 0x00091982,
+ 0x306303fc, 0x01031821, 0x8c641800, 0x8c431c00, 0x00c53026, 0x00c43026,
+ 0x11400015, 0x00c33026, 0x000a1602, 0x00021080, 0x01021021, 0x8c432000,
+ 0x000a1382, 0x304203fc, 0x01021021, 0x8c452400, 0x314200ff, 0x00021080,
+ 0x01021021, 0x00c33026, 0x000a1982, 0x306303fc, 0x01031821, 0x8c642800,
+ 0x8c432c00, 0x00c53026, 0x00c43026, 0x00c33026, 0x8f430070, 0x3c050800,
+ 0x8ca43100, 0x2c820020, 0x10400008, 0x006b5823, 0x3c020800, 0x24423104,
+ 0x00041880, 0x00621821, 0x24820001, 0xac6b0000, 0xaca23100, 0xaf860004,
+ 0x03e00008, 0x24020001, 0x27bdffe8, 0xafbf0010, 0x8f460128, 0x8f840010,
+ 0xaf460020, 0x8f450104, 0x8f420100, 0x24030800, 0xaf850008, 0xaf820014,
+ 0xaf4301b8, 0x1080000a, 0x3c020800, 0x8c430034, 0x10600007, 0x30a22000,
+ 0x10400005, 0x34a30100, 0x8f82000c, 0xaf830008, 0x24420001, 0xaf82000c,
+ 0x3c020800, 0x8c4300c0, 0x10600006, 0x3c030800, 0x8c6200c4, 0x24040001,
+ 0x24420001, 0x0a000fd5, 0xac6200c4, 0x8f820008, 0x3c030010, 0x00431024,
+ 0x14400009, 0x3c02001f, 0x3c030800, 0x8c620020, 0x00002021, 0x24420001,
+ 0x0e000c78, 0xac620020, 0x0a000fd5, 0x00402021, 0x3442ff00, 0x14c20009,
+ 0x2403bfff, 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e000c78,
+ 0xac620020, 0x0a000fd5, 0x00402021, 0x8f820014, 0x00431024, 0x14400006,
+ 0x00000000, 0xaf400048, 0x0e0011a9, 0xaf400040, 0x0a000fd5, 0x00402021,
+ 0x0e001563, 0x00000000, 0x00402021, 0x10800005, 0x3c024000, 0x8f430124,
+ 0x3c026020, 0xac430014, 0x3c024000, 0xaf420138, 0x00000000, 0x8fbf0010,
+ 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
+ 0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, 0x00621824, 0x3c023000,
+ 0x10620021, 0x0043102b, 0x14400006, 0x3c024000, 0x3c022000, 0x10620009,
+ 0x3c024000, 0x0a001040, 0x00000000, 0x10620045, 0x3c025000, 0x10620047,
+ 0x3c024000, 0x0a001040, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, 0x24030002, 0xa083000b,
+ 0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, 0x8f420144, 0x3c031000,
+ 0xac820024, 0xaf4301b8, 0x0a001040, 0x3c024000, 0x8f420148, 0x24030002,
+ 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
+ 0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001027, 0x3c038000,
+ 0x12020007, 0x00000000, 0x0a001034, 0x00000000, 0x0e00112c, 0x00000000,
+ 0x0a001025, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
+ 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
+ 0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
+ 0x0a001040, 0x3c024000, 0x0000000d, 0x00000000, 0x240002bf, 0x0a001040,
+ 0x3c024000, 0x0e001441, 0x00000000, 0x0a001040, 0x3c024000, 0x0e0015ea,
+ 0x00000000, 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014,
+ 0x8fb00010, 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8,
+ 0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
+ 0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
+ 0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
+ 0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
+ 0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
+ 0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
+ 0x8e021980, 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd,
+ 0x32020001, 0x10400004, 0x32020002, 0x0e000f92, 0x00000000, 0x32020002,
+ 0x1040fff6, 0x00000000, 0x0e000fe0, 0x00000000, 0x0a001071, 0x00000000,
+ 0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
+ 0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
+ 0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
+ 0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
+ 0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
+ 0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
+ 0x8e021980, 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008,
+ 0x27bd0018, 0x00804821, 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
+ 0x8f840004, 0x8f880014, 0xaf490180, 0xa745018c, 0xa746018e, 0xa7470188,
+ 0x31028000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc,
0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
- 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104,
+ 0x34427fff, 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104,
0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
- 0x3c021000, 0xaf4201b8, 0x00001021, 0x03e00008, 0x00000000, 0x27bdffe8,
- 0xafbf0010, 0x8f460128, 0x8f84000c, 0xaf460020, 0x8f450104, 0x8f420100,
- 0x24030800, 0xaf850004, 0xaf820010, 0xaf4301b8, 0x1080000a, 0x3c020800,
- 0x8c430034, 0x10600007, 0x30a22000, 0x10400005, 0x34a30100, 0x8f820008,
- 0xaf830004, 0x24420001, 0xaf820008, 0x3c020800, 0x8c4300c0, 0x10600006,
- 0x3c030800, 0x8c6200c4, 0x24040001, 0x24420001, 0x0a000fc0, 0xac6200c4,
- 0x8f820004, 0x3c030010, 0x00431024, 0x14400009, 0x3c02001f, 0x3c030800,
- 0x8c620020, 0x00002021, 0x24420001, 0x0e000c99, 0xac620020, 0x0a000fc0,
- 0x00402021, 0x3442ff00, 0x14c20009, 0x2403bfff, 0x3c030800, 0x8c620020,
- 0x24040001, 0x24420001, 0x0e000c99, 0xac620020, 0x0a000fc0, 0x00402021,
- 0x8f820010, 0x00431024, 0x14400006, 0x00000000, 0xaf400048, 0x0e001144,
- 0xaf400040, 0x0a000fc0, 0x00402021, 0x0e0014c9, 0x00000000, 0x00402021,
- 0x10800005, 0x3c024000, 0x8f430124, 0x3c026020, 0xac430014, 0x3c024000,
- 0xaf420138, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0,
- 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420140, 0xaf420020, 0x8f430148,
- 0x3c027000, 0x00621824, 0x3c023000, 0x10620021, 0x0043102b, 0x14400006,
- 0x3c024000, 0x3c022000, 0x10620009, 0x3c024000, 0x0a00102b, 0x00000000,
- 0x10620045, 0x3c025000, 0x10620047, 0x3c024000, 0x0a00102b, 0x00000000,
+ 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008,
+ 0xa083000b, 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000,
0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
0x8f420148, 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148,
- 0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0xaf4301b8, 0x0a00102b,
- 0x3c024000, 0x8f420148, 0x24030002, 0x3044ffff, 0x00021402, 0x305000ff,
- 0x1203000c, 0x27510180, 0x2a020003, 0x10400005, 0x24020003, 0x0600001d,
- 0x36053000, 0x0a001012, 0x3c038000, 0x12020007, 0x00000000, 0x0a00101f,
- 0x00000000, 0x0e00111f, 0x00000000, 0x0a001010, 0x00402021, 0x0e001131,
- 0x00000000, 0x00402021, 0x36053000, 0x3c038000, 0x8f4201b8, 0x00431024,
- 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, 0xa6240010, 0x8f420144,
- 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00102b, 0x3c024000, 0x0000000d,
- 0x00000000, 0x24000295, 0x0a00102b, 0x3c024000, 0x0e0013a7, 0x00000000,
- 0x0a00102b, 0x3c024000, 0x0e001552, 0x00000000, 0x3c024000, 0xaf420178,
- 0x00000000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
- 0x24020800, 0x03e00008, 0xaf4201b8, 0x27bdffe8, 0x3c04600c, 0xafbf0014,
- 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x3c106000, 0x00431024,
- 0x3442380c, 0x24030003, 0xac825000, 0x3c020008, 0xaf430008, 0x8e040808,
- 0x0342d825, 0x8e020808, 0x3c030800, 0xac600020, 0x3084fff0, 0x2c840001,
- 0x3042fff0, 0x38420010, 0x2c420001, 0xaf84000c, 0xaf820000, 0x0e001574,
- 0x00000000, 0x0e0014c7, 0x00000000, 0x3c020400, 0x3442000c, 0x3c03ffff,
- 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, 0x34420200, 0xae021980,
- 0x8f500000, 0x32020003, 0x1040fffd, 0x32020001, 0x10400004, 0x32020002,
- 0x0e000f7d, 0x00000000, 0x32020002, 0x1040fff6, 0x00000000, 0x0e000fcb,
- 0x00000000, 0x0a00105c, 0x00000000, 0x27bdffe8, 0x3c04600c, 0xafbf0014,
- 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x3c106000, 0x00431024,
- 0x3442380c, 0x24030003, 0xac825000, 0x3c020008, 0xaf430008, 0x8e040808,
- 0x0342d825, 0x8e020808, 0x3c030800, 0xac600020, 0x3084fff0, 0x2c840001,
- 0x3042fff0, 0x38420010, 0x2c420001, 0xaf84000c, 0xaf820000, 0x0e001574,
- 0x00000000, 0x0e0014c7, 0x00000000, 0x3c020400, 0x3442000c, 0x3c03ffff,
- 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, 0x8fbf0014, 0x34420200,
- 0xae021980, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x30a5ffff, 0x30c6ffff,
- 0x30e7ffff, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
- 0xa342018b, 0x97830006, 0x8f82000c, 0xaf440180, 0xa745018c, 0xa746018e,
- 0x10400005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a0010ad, 0x00021400,
- 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010,
- 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021,
- 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
- 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff,
- 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
- 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8,
- 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b,
- 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180,
- 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148,
- 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148, 0xa4830010,
- 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8, 0x27bdffe0,
- 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002, 0x3044ffff,
- 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, 0x10400005,
- 0x24020003, 0x0600001d, 0x36053000, 0x0a00110a, 0x3c038000, 0x12020007,
- 0x00000000, 0x0a001117, 0x00000000, 0x0e00111f, 0x00000000, 0x0a001108,
- 0x00402021, 0x0e001131, 0x00000000, 0x00402021, 0x36053000, 0x3c038000,
- 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b,
- 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00111b,
- 0x8fbf0018, 0x0000000d, 0x00000000, 0x24000295, 0x8fbf0018, 0x8fb10014,
- 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389, 0x1040000d,
- 0x00001021, 0x3c030800, 0x24635680, 0x00042942, 0x00052880, 0x00a32821,
- 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025, 0x03e00008,
- 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389, 0x1040000e,
- 0x00001021, 0x3c030800, 0x24635680, 0x00042942, 0x00052880, 0x00a32821,
- 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827, 0x00832024,
- 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x27bdffb0, 0xafbf0048,
- 0x93620023, 0x30420010, 0x1440025b, 0x24020001, 0x93420116, 0x93630005,
- 0x34424000, 0x30630001, 0x14600005, 0x03425821, 0x0e001548, 0x00000000,
- 0x0a0013a5, 0x8fbf0048, 0x93420112, 0x8f430104, 0x3c040020, 0x34424000,
- 0x00641824, 0x10600012, 0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8,
+ 0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8,
+ 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002,
+ 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
+ 0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001117, 0x3c038000,
+ 0x12020007, 0x00000000, 0x0a001124, 0x00000000, 0x0e00112c, 0x00000000,
+ 0x0a001115, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
+ 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
+ 0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
+ 0x0a001128, 0x8fbf0018, 0x0000000d, 0x00000000, 0x240002bf, 0x8fbf0018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389,
+ 0x1040000d, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
+ 0x00a32821, 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025,
+ 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389,
+ 0x1040000e, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
+ 0x00a32821, 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827,
+ 0x00832024, 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x9482000c,
+ 0x24870014, 0x00021302, 0x00021080, 0x00824021, 0x00e8182b, 0x1060004f,
+ 0x00000000, 0x90e30000, 0x2c620009, 0x10400047, 0x3c020800, 0x24425890,
+ 0x00031880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, 0x0a0011a4,
+ 0x24e70001, 0x90e30001, 0x2402000a, 0x54620024, 0x01003821, 0x01071023,
+ 0x2c42000a, 0x54400020, 0x01003821, 0x3c050800, 0x8ca26c98, 0x24e70002,
+ 0x34420100, 0xaca26c98, 0x90e30000, 0x90e20001, 0x90e40002, 0x90e60003,
+ 0x24e70004, 0x24a56c98, 0x00031e00, 0x00021400, 0x00621825, 0x00042200,
+ 0x00641825, 0x00661825, 0xaca30004, 0x90e20000, 0x90e30001, 0x90e40002,
+ 0x90e60003, 0x24e70004, 0x00021600, 0x00031c00, 0x00431025, 0x00042200,
+ 0x00441025, 0x00461025, 0x0a0011a4, 0xaca20008, 0x90e30001, 0x24020004,
+ 0x1062000e, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020003,
+ 0x10620008, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020002,
+ 0x14620003, 0x01001021, 0x00601021, 0x00e21021, 0x0a0011a4, 0x00403821,
+ 0x90e20001, 0x0a0011a4, 0x00e23821, 0x01003821, 0x00e8102b, 0x5440ffb4,
+ 0x90e30000, 0x03e00008, 0x24020001, 0x27bdff90, 0x3c030800, 0xafbf006c,
+ 0xafbe0068, 0xafb70064, 0xafb60060, 0xafb5005c, 0xafb40058, 0xafb30054,
+ 0xafb20050, 0xafb1004c, 0xafb00048, 0xac606c98, 0x93620023, 0x30420010,
+ 0x1440027c, 0x24020001, 0x93420116, 0x93630005, 0x34424000, 0x30630001,
+ 0x14600005, 0x0342b021, 0x0e0015e0, 0x00000000, 0x0a001436, 0x8fbf006c,
+ 0x93420112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x10600012,
+ 0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1,
+ 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, 0x0a0011f1, 0xa0a3000a,
+ 0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, 0x3c038000, 0x27450180,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
+ 0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a3000a,
+ 0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, 0xa0a00012, 0xa0a00013,
+ 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x0e0015e0,
+ 0xaf4201b8, 0x0a001436, 0x8fbf006c, 0x8f820000, 0x10400016, 0x00000000,
+ 0x8f420104, 0x3c030001, 0x00431024, 0x10400011, 0x00000000, 0x8ca3000c,
+ 0x8f620030, 0x1462022d, 0x24020001, 0x8ca30010, 0x8f62002c, 0x14620229,
+ 0x24020001, 0x9763003a, 0x96c20000, 0x14430225, 0x24020001, 0x97630038,
+ 0x96c20002, 0x14430221, 0x24020001, 0xaf400048, 0xaf400054, 0xaf400040,
+ 0x8f740040, 0x8f650048, 0x00b43023, 0x04c10004, 0x00000000, 0x0000000d,
+ 0x00000000, 0x240001af, 0x9742011a, 0x3052ffff, 0x12400004, 0x8ed30004,
+ 0x02721021, 0x0a001228, 0x2451ffff, 0x02608821, 0x92d7000d, 0xa7a00020,
+ 0xa3a0001a, 0xafa00028, 0x9362003f, 0x32e30004, 0x1060003a, 0x305000ff,
+ 0x24040012, 0x16040006, 0x24020001, 0x3c040800, 0x8c830028, 0x24630001,
+ 0x0a001328, 0xac830028, 0x8f620044, 0x16620010, 0x27a60010, 0x27450180,
+ 0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, 0xafb40028, 0xa3b00022,
+ 0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
+ 0x0a00130d, 0x00000000, 0x8f620044, 0x02621023, 0x0440001a, 0x02651023,
+ 0x044100d9, 0x24020001, 0x3c020800, 0x8c4300d8, 0x10600004, 0x24020001,
+ 0xa7a20020, 0x0a00125e, 0xafb40028, 0x2402001a, 0xa7a20020, 0x24020020,
+ 0xafb40028, 0xa3b00022, 0xa3a40023, 0xa3a2001a, 0x27a60010, 0x27450180,
+ 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d,
+ 0x00000000, 0x0a001328, 0x24020001, 0x0293f023, 0x1bc00016, 0x025e102a,
+ 0x54400007, 0x32f700fe, 0x57d2000f, 0x027e9821, 0x32e20001, 0x5440000c,
+ 0x027e9821, 0x32f700fe, 0x0240f021, 0x3c040800, 0x8c8300c8, 0x00009021,
+ 0x24020001, 0xa7a20020, 0xafb40028, 0x24630001, 0x0a001282, 0xac8300c8,
+ 0x025e1023, 0x0a001282, 0x3052ffff, 0x0000f021, 0x24a2ffff, 0x02221823,
+ 0x1860001f, 0x0072102a, 0x54400019, 0x00a08821, 0x97a20020, 0x3c040800,
+ 0x8c8300cc, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, 0x02741026,
+ 0x2c420001, 0xac8300cc, 0x2cc30001, 0x00431024, 0x1440000a, 0x02401821,
+ 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x0a00130d, 0x00000000, 0x00a08821, 0x02431023, 0x3052ffff,
+ 0x0a0012ae, 0x32f700f6, 0x02741023, 0x18400008, 0x97a20020, 0x3c040800,
+ 0x8c8300d4, 0xafb30028, 0x34420400, 0x24630001, 0xa7a20020, 0xac8300d4,
+ 0x32e20002, 0x1040001c, 0x32e20010, 0x8f620044, 0x1662000d, 0x27a60010,
+ 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
+ 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
+ 0x54400003, 0x8ed50008, 0x0a001328, 0x24020001, 0x8f630054, 0x26a2ffff,
+ 0x00431023, 0x18400011, 0x27a60010, 0x97a20020, 0x3c040800, 0x8c8300d0,
+ 0x27450180, 0x3c078000, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020,
+ 0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, 0x0a00130d,
+ 0x00000000, 0x32e20020, 0x10400011, 0x00000000, 0x96c20012, 0x0052102b,
+ 0x10400008, 0x97a20020, 0x96d20012, 0x12400003, 0x02721021, 0x0a0012f2,
+ 0x2451ffff, 0x02608821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004,
+ 0xa7a20020, 0xa3a3001a, 0x8f420104, 0x3c030080, 0x00431024, 0x10400037,
+ 0x3a03000a, 0x0e001151, 0x02c02021, 0x24030002, 0x1443002b, 0x3c030800,
+ 0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001,
+ 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128,
+ 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a,
+ 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012,
+ 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024,
+ 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000,
+ 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a001436, 0x8fbf006c,
+ 0x8c626c98, 0x30420100, 0x10400003, 0x24636c98, 0x8c620004, 0xaf62017c,
+ 0x3a03000a, 0x2c630001, 0x3a02000c, 0x2c420001, 0x00621825, 0x14600003,
+ 0x2402000e, 0x56020030, 0x00009021, 0x52400008, 0x96c4000e, 0x12400004,
+ 0xa7b20040, 0x02721021, 0x0a001343, 0x2451ffff, 0x02608821, 0x96c4000e,
+ 0x93630035, 0x8f62004c, 0x00642004, 0x00952021, 0x00821023, 0x18400015,
+ 0x00000000, 0x8f620018, 0x02621023, 0x1c400015, 0x97a20020, 0x8f620018,
+ 0x1662001c, 0x00000000, 0x8f62001c, 0x02a21023, 0x1c40000e, 0x97a20020,
+ 0x8f62001c, 0x16a20015, 0x00000000, 0x8f620058, 0x00821023, 0x18400011,
+ 0x97a20020, 0x0a001364, 0xafb10028, 0x8f620058, 0x00821023, 0x0441000b,
+ 0x97a20020, 0xafb10028, 0xafb30034, 0xafb50038, 0xafa4003c, 0x34420020,
+ 0x0a00136d, 0xa7a20020, 0x02809821, 0x02608821, 0x8f640058, 0x8f62004c,
+ 0x02a21023, 0x18400009, 0x00000000, 0x8f620054, 0x02a21023, 0x1c400005,
+ 0x97a20020, 0xafb10028, 0xafb50024, 0x0a001385, 0x34420040, 0x9742011a,
+ 0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c,
+ 0x8f620054, 0x10620004, 0x97a20020, 0xafb10028, 0x34420080, 0xa7a20020,
+ 0x24020014, 0x1202000a, 0x2a020015, 0x10400005, 0x2402000c, 0x12020006,
+ 0x32e20001, 0x0a0013c6, 0x00000000, 0x24020016, 0x16020035, 0x32e20001,
+ 0x8f620084, 0x24420001, 0x16a20031, 0x32e20001, 0x24020014, 0x12020021,
+ 0x2a020015, 0x10400005, 0x2402000c, 0x12020008, 0x32e20001, 0x0a0013c6,
+ 0x00000000, 0x24020016, 0x1202000c, 0x32e20001, 0x0a0013c6, 0x00000000,
+ 0x97a30020, 0x2402000e, 0xafb10028, 0xa3b00022, 0xa3a20023, 0xafb50024,
+ 0x34630054, 0x0a0013c5, 0xa7a30020, 0x97a20020, 0x93a4001a, 0x24030010,
+ 0xafb10028, 0xa3b00022, 0xa3a30023, 0xafb50024, 0x3442005d, 0x34840002,
+ 0xa7a20020, 0x0a0013c5, 0xa3a4001a, 0x97a20020, 0x24030012, 0xa3a30023,
+ 0x93a3001a, 0xafb10028, 0xa3b00022, 0xafb50024, 0x3042fffe, 0x3442005c,
+ 0x34630002, 0xa7a20020, 0xa3a3001a, 0x32e20001, 0x10400030, 0x2402000c,
+ 0x12020013, 0x2a02000d, 0x10400005, 0x2402000a, 0x12020008, 0x97a20020,
+ 0x0a0013f8, 0x32e20009, 0x2402000e, 0x1202001b, 0x32e20009, 0x0a0013f9,
+ 0x0002102b, 0x93a4001a, 0x24030008, 0xafb10028, 0xa3b00022, 0xa3a30023,
+ 0x0a0013f4, 0x34420013, 0x97a30020, 0x30620004, 0x14400005, 0x93a2001a,
+ 0x3463001b, 0xa7a30020, 0x0a0013e7, 0x24030016, 0x3463001b, 0xa7a30020,
+ 0x24030010, 0xafb10028, 0xa3b00022, 0xa3a30023, 0x34420002, 0x0a0013f7,
+ 0xa3a2001a, 0x97a20020, 0x93a4001a, 0x24030010, 0xafb10028, 0xa3b00022,
+ 0xa3a30023, 0x3442001b, 0x34840002, 0xa7a20020, 0xa3a4001a, 0x32e20009,
+ 0x0002102b, 0x00021023, 0x30420007, 0x12400015, 0x34450003, 0x8f820018,
+ 0x24030800, 0x27440180, 0x24420001, 0xaf820018, 0x24020004, 0xaf4301b8,
+ 0xa4850008, 0xa082000b, 0x93430120, 0x00003021, 0x3c021000, 0xa492000e,
+ 0xac950024, 0xac930028, 0x007e1821, 0xa483000c, 0xaf4201b8, 0x0a001413,
+ 0x97a20020, 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
+ 0x8fa30028, 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002,
+ 0xa0a2000b, 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012,
+ 0x93a20023, 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024,
+ 0x8fa30038, 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8,
+ 0x00c01021, 0x8fbf006c, 0x8fbe0068, 0x8fb70064, 0x8fb60060, 0x8fb5005c,
+ 0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x03e00008,
+ 0x27bd0070, 0x8f470140, 0x8f460148, 0x3c028000, 0x00c24024, 0x00062c02,
+ 0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, 0x2862001a, 0x1040001f,
+ 0x24020008, 0x106200be, 0x28620009, 0x1040000d, 0x24020001, 0x10620046,
+ 0x28620002, 0x50400005, 0x24020006, 0x1060002e, 0x00a01821, 0x0a00155e,
+ 0x00000000, 0x1062005b, 0x00a01821, 0x0a00155e, 0x00000000, 0x2402000b,
+ 0x10620084, 0x2862000c, 0x10400005, 0x24020009, 0x106200bc, 0x00061c02,
+ 0x0a00155e, 0x00000000, 0x2402000e, 0x106200b7, 0x00061c02, 0x0a00155e,
+ 0x00000000, 0x28620021, 0x10400009, 0x2862001f, 0x104000c1, 0x2402001b,
+ 0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, 0x0a00155e, 0x00000000,
+ 0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, 0x24020080, 0x1062005a,
+ 0x00a01821, 0x0a00155e, 0x00000000, 0x240200c9, 0x106200cd, 0x30c5ffff,
+ 0x0a00155e, 0x00000000, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
+ 0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a,
+ 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024,
+ 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, 0x11000009, 0x00a01821,
+ 0x3c020800, 0x24030002, 0xa0436c88, 0x24426c88, 0xac470008, 0x8f430144,
+ 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
+ 0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b,
+ 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x3c026000,
+ 0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, 0x3c058000, 0x8f4201b8,
+ 0x00451024, 0x1440fffd, 0x00000000, 0xac870000, 0x91026c88, 0x00002821,
+ 0x10400002, 0x25076c88, 0x8ce50008, 0xac850004, 0xa4830008, 0x91036c88,
+ 0x24020002, 0xa082000b, 0xa4860010, 0x34630001, 0xa083000a, 0x8f420144,
+ 0xac820024, 0x91036c88, 0x10600002, 0x00001021, 0x8ce20004, 0xac820028,
+ 0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006c88, 0x03e00008, 0xac400808,
+ 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b,
+ 0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008,
+ 0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, 0x93620005, 0x30420004,
+ 0x14400020, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, 0x3c038000,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
+ 0x34630001, 0x00e31825, 0x34420004, 0xa3620005, 0xaf430020, 0x93620005,
+ 0x30420004, 0x14400003, 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, 0xac870000, 0xa082000b,
+ 0xaf4301b8, 0x0a00150d, 0x00061c02, 0x0000000d, 0x03e00008, 0x00000000,
+ 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
+ 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, 0xa083000b,
+ 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, 0x03e00008,
+ 0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
+ 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4860010,
+ 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8,
+ 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
+ 0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, 0xac870000, 0xac800004,
+ 0xa083000b, 0xa4860010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8,
+ 0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
+ 0xac870000, 0xac800004, 0xa4830008, 0xa080000a, 0x0a001518, 0xa082000b,
+ 0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
+ 0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4401a4,
+ 0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, 0x0000000d, 0x03e00008,
+ 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011,
+ 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000,
+ 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040,
+ 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008,
+ 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
+ 0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4501a4,
+ 0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, 0x3c029000, 0x34420001,
+ 0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x03e00008, 0x00000000, 0x3c028000, 0x34420001, 0x00822025,
+ 0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, 0x3c038000, 0x8f4201b8,
0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040,
0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000,
- 0x0a001181, 0xa0a3000a, 0x8f420104, 0x3c030040, 0x00431024, 0x1040001d,
- 0x3c038000, 0x27450180, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
- 0x8f420128, 0xaca20000, 0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008,
- 0x24020002, 0xa0a3000a, 0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010,
- 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c,
- 0xaca40018, 0x0e001548, 0xaf4201b8, 0x0a0013a5, 0x8fbf0048, 0x8f820000,
- 0x10400016, 0x00000000, 0x8f420104, 0x3c030001, 0x00431024, 0x10400011,
- 0x00000000, 0x8ca3000c, 0x8f620030, 0x1462020c, 0x24020001, 0x8ca30010,
- 0x8f62002c, 0x14620208, 0x24020001, 0x9763003a, 0x95620000, 0x14430204,
- 0x24020001, 0x97630038, 0x95620002, 0x14430200, 0x24020001, 0xaf400048,
- 0xaf400054, 0xaf400040, 0x8f690040, 0x8f6a0048, 0x01497023, 0x05c10004,
- 0x00000000, 0x0000000d, 0x00000000, 0x24000169, 0x9742011a, 0x3046ffff,
- 0x10c00004, 0x8d680004, 0x01061021, 0x0a0011b8, 0x2445ffff, 0x01002821,
- 0x916c000d, 0xa7a00020, 0xa3a0001a, 0xafa00028, 0x9362003f, 0x31830004,
- 0x1060003a, 0x304700ff, 0x24040012, 0x14e40006, 0x24020001, 0x3c040800,
- 0x8c830028, 0x24630001, 0x0a00128d, 0xac830028, 0x8f620044, 0x15020010,
- 0x27a60010, 0x27450180, 0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020,
- 0xafa90028, 0xa3a70022, 0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024,
- 0x1440fffd, 0x00000000, 0x0a001272, 0x00000000, 0x8f620044, 0x01021023,
- 0x0440001a, 0x010a1023, 0x044100ae, 0x24020001, 0x3c020800, 0x8c4300d8,
- 0x10600004, 0x24020001, 0xa7a20020, 0x0a0011ee, 0xafa90028, 0x2402001a,
- 0xa7a20020, 0x24020020, 0xafa90028, 0xa3a70022, 0xa3a40023, 0xa3a2001a,
- 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
- 0x00000000, 0x0a001272, 0x00000000, 0x0a00128d, 0x24020001, 0x01286823,
- 0x19a00016, 0x00cd102a, 0x54400007, 0x318c00fe, 0x55a6000f, 0x010d4021,
- 0x31820001, 0x5440000c, 0x010d4021, 0x318c00fe, 0x00c06821, 0x3c040800,
- 0x8c8300c8, 0x00003021, 0x24020001, 0xa7a20020, 0xafa90028, 0x24630001,
- 0x0a001212, 0xac8300c8, 0x00cd1023, 0x0a001212, 0x3046ffff, 0x00006821,
- 0x2542ffff, 0x00a21823, 0x1860001e, 0x0066102a, 0x14400018, 0x01402821,
- 0x97a20020, 0x3c040800, 0x8c8300cc, 0xafa90028, 0x34420001, 0x24630001,
- 0xa7a20020, 0x01091026, 0x2c420001, 0xac8300cc, 0x2dc30001, 0x00431024,
- 0x1440000a, 0x00c01821, 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8,
- 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272, 0x00000000, 0x00c31023,
- 0x3046ffff, 0x0a00123d, 0x318c00f6, 0x01091023, 0x18400008, 0x97a20020,
- 0x3c040800, 0x8c8300d4, 0xafa80028, 0x34420400, 0x24630001, 0xa7a20020,
- 0xac8300d4, 0x31820002, 0x1040001c, 0x31820010, 0x8f620044, 0x1502000d,
- 0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafa90028, 0x34420001,
- 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272,
- 0x00000000, 0x97a20020, 0x27450180, 0x3c038000, 0xafa90028, 0x34420001,
- 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272,
- 0x00000000, 0x54400003, 0x8d6a0008, 0x0a00128d, 0x24020001, 0x8f630054,
- 0x2542ffff, 0x00431023, 0x1840002e, 0x97a20020, 0x27a60010, 0x3c040800,
- 0x8c8300d0, 0x27450180, 0x3c078000, 0xafa90028, 0x34420001, 0x24630001,
- 0xa7a20020, 0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000,
- 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018,
- 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010,
- 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014,
- 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001,
- 0x3c031000, 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a0013a5,
- 0x8fbf0048, 0x31820020, 0x10400011, 0x00000000, 0x95620012, 0x0046102b,
- 0x10400008, 0x97a20020, 0x95660012, 0x10c00003, 0x01061021, 0x0a00129e,
- 0x2445ffff, 0x01002821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004,
- 0xa7a20020, 0xa3a3001a, 0x8f420104, 0x38e3000a, 0x2c630001, 0x38e2000c,
- 0x2c420001, 0x00621825, 0x14600003, 0x2402000e, 0x54e2002a, 0x00003021,
- 0x50c00008, 0x9564000e, 0x10c00004, 0xa7a60040, 0x01061021, 0x0a0012b6,
- 0x2445ffff, 0x01002821, 0x9564000e, 0x93630035, 0x8f62004c, 0x00642004,
- 0x008a2021, 0x00821023, 0x1840001d, 0x00000000, 0x8f620018, 0x01021023,
- 0x1c40000f, 0x97a20020, 0x8f620018, 0x15020016, 0x00000000, 0x8f62001c,
- 0x01421023, 0x1c400008, 0x97a20020, 0x8f62001c, 0x1542000f, 0x00000000,
- 0x8f620058, 0x00821023, 0x1840000b, 0x97a20020, 0xafa50028, 0xafa80034,
- 0xafaa0038, 0xafa4003c, 0x34420020, 0x0a0012da, 0xa7a20020, 0x01204021,
- 0x01002821, 0x8f640058, 0x8f62004c, 0x01421023, 0x18400009, 0x00000000,
- 0x8f620054, 0x01421023, 0x1c400005, 0x97a20020, 0xafa50028, 0xafaa0024,
- 0x0a0012f2, 0x34420040, 0x9742011a, 0x1440000c, 0x24020014, 0x8f620058,
- 0x14820009, 0x24020014, 0x8f63004c, 0x8f620054, 0x10620004, 0x97a20020,
- 0xafa50028, 0x34420080, 0xa7a20020, 0x24020014, 0x10e2000a, 0x28e20015,
- 0x10400005, 0x2402000c, 0x10e20006, 0x31820001, 0x0a001333, 0x00000000,
- 0x24020016, 0x14e20035, 0x31820001, 0x8f620084, 0x24420001, 0x15420031,
- 0x31820001, 0x24020014, 0x10e20021, 0x28e20015, 0x10400005, 0x2402000c,
- 0x10e20008, 0x31820001, 0x0a001333, 0x00000000, 0x24020016, 0x10e2000c,
- 0x31820001, 0x0a001333, 0x00000000, 0x97a30020, 0x2402000e, 0xafa50028,
- 0xa3a70022, 0xa3a20023, 0xafaa0024, 0x34630054, 0x0a001332, 0xa7a30020,
- 0x97a20020, 0x93a4001a, 0x24030010, 0xafa50028, 0xa3a70022, 0xa3a30023,
- 0xafaa0024, 0x3442005d, 0x34840002, 0xa7a20020, 0x0a001332, 0xa3a4001a,
- 0x97a20020, 0x24030012, 0xa3a30023, 0x93a3001a, 0xafa50028, 0xa3a70022,
- 0xafaa0024, 0x3042fffe, 0x3442005c, 0x34630002, 0xa7a20020, 0xa3a3001a,
- 0x31820001, 0x10400030, 0x2402000c, 0x10e20013, 0x28e2000d, 0x10400005,
- 0x2402000a, 0x10e20008, 0x97a20020, 0x0a001365, 0x31820009, 0x2402000e,
- 0x10e2001b, 0x31820009, 0x0a001366, 0x0002102b, 0x93a4001a, 0x24030008,
- 0xafa50028, 0xa3a70022, 0xa3a30023, 0x0a001361, 0x34420013, 0x97a30020,
- 0x30620004, 0x14400005, 0x93a2001a, 0x3463001b, 0xa7a30020, 0x0a001354,
- 0x24030016, 0x3463001b, 0xa7a30020, 0x24030010, 0xafa50028, 0xa3a70022,
- 0xa3a30023, 0x34420002, 0x0a001364, 0xa3a2001a, 0x97a20020, 0x93a4001a,
- 0x24030010, 0xafa50028, 0xa3a70022, 0xa3a30023, 0x3442001b, 0x34840002,
- 0xa7a20020, 0xa3a4001a, 0x31820009, 0x0002102b, 0x00021023, 0x30420007,
- 0x10c00017, 0x34440003, 0x8f820014, 0x24030800, 0x27450180, 0x24420001,
- 0xaf820014, 0x24020004, 0xaf4301b8, 0xa4a40008, 0xa0a2000b, 0x93440120,
- 0x3c031000, 0xa4a6000e, 0xacaa0024, 0xaca80028, 0x008d2021, 0xa4a4000c,
- 0xaf4301b8, 0x97a20020, 0x00003021, 0x3042ffbf, 0x0a001381, 0xa7a20020,
- 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000, 0x8f4201b8,
- 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8fa30028,
- 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002, 0xa0a2000b,
- 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012, 0x93a20023,
- 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024, 0x8fa30038,
- 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8, 0x00c01021,
- 0x8fbf0048, 0x03e00008, 0x27bd0050, 0x8f470140, 0x8f460148, 0x3c028000,
- 0x00c24024, 0x00062c02, 0x30a300ff, 0x24020019, 0x106200e7, 0x27440180,
- 0x2862001a, 0x1040001f, 0x24020008, 0x106200be, 0x28620009, 0x1040000d,
- 0x24020001, 0x10620046, 0x28620002, 0x50400005, 0x24020006, 0x1060002e,
- 0x00a01821, 0x0a0014c4, 0x00000000, 0x1062005b, 0x00a01821, 0x0a0014c4,
- 0x00000000, 0x2402000b, 0x10620084, 0x2862000c, 0x10400005, 0x24020009,
- 0x106200bc, 0x00061c02, 0x0a0014c4, 0x00000000, 0x2402000e, 0x106200b7,
- 0x00061c02, 0x0a0014c4, 0x00000000, 0x28620021, 0x10400009, 0x2862001f,
- 0x104000c1, 0x2402001b, 0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02,
- 0x0a0014c4, 0x00000000, 0x240200c2, 0x106200ca, 0x286200c3, 0x10400005,
- 0x24020080, 0x1062005a, 0x00a01821, 0x0a0014c4, 0x00000000, 0x240200c9,
- 0x106200cd, 0x30c5ffff, 0x0a0014c4, 0x00000000, 0x3c058000, 0x8f4201b8,
- 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac870000,
- 0xac800004, 0xa082000a, 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000,
- 0xac800028, 0xac830024, 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808,
- 0x11000009, 0x00a01821, 0x3c020800, 0x24030002, 0xa0436a08, 0x24426a08,
- 0xac470008, 0x8f430144, 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8,
- 0x00451024, 0x1440fffd, 0x24020002, 0xac800000, 0xac870004, 0xa4830008,
- 0xa082000a, 0xa082000b, 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000,
- 0xac820028, 0x3c026000, 0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800,
- 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x00000000, 0xac870000,
- 0x91026a08, 0x00002821, 0x10400002, 0x25076a08, 0x8ce50008, 0xac850004,
- 0xa4830008, 0x91036a08, 0x24020002, 0xa082000b, 0xa4860010, 0x34630001,
- 0xa083000a, 0x8f420144, 0xac820024, 0x91036a08, 0x10600002, 0x00001021,
- 0x8ce20004, 0xac820028, 0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006a08,
- 0x03e00008, 0xac400808, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
- 0x24020002, 0xa082000b, 0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000,
- 0xa4820012, 0x03e00008, 0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02,
- 0x93620005, 0x30420004, 0x14400020, 0x3c029000, 0x34420001, 0x00e21025,
- 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
- 0x93620005, 0x3c038000, 0x34630001, 0x00e31825, 0x34420004, 0xa3620005,
- 0xaf430020, 0x93620005, 0x30420004, 0x14400003, 0x3c038000, 0x0000000d,
- 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020005, 0x3c031000,
- 0xac870000, 0xa082000b, 0xaf4301b8, 0x0a001473, 0x00061c02, 0x0000000d,
- 0x03e00008, 0x00000000, 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024,
- 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004,
- 0xa082000a, 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028,
- 0xac830024, 0x03e00008, 0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024,
- 0x1440fffd, 0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a,
- 0xa082000b, 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028,
- 0x03e00008, 0xaf4301b8, 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024,
- 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xa082000a, 0x3c021000,
- 0xac870000, 0xac800004, 0xa083000b, 0xa4860010, 0xac800024, 0xac800028,
- 0x03e00008, 0xaf4201b8, 0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024,
- 0x1440fffd, 0x24020002, 0xac870000, 0xac800004, 0xa4830008, 0xa080000a,
- 0x0a00147e, 0xa082000b, 0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024,
- 0x1440fffd, 0x24020002, 0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000,
- 0xa7430188, 0xaf4401a4, 0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8,
- 0x0000000d, 0x03e00008, 0x00000000, 0x03e00008, 0x00000000, 0x8f420100,
- 0x3042003e, 0x14400011, 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0,
- 0x10400005, 0x00000000, 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001,
- 0xaf400054, 0xaf400040, 0x8f420100, 0x30423800, 0x54400001, 0xaf400044,
- 0x24020001, 0x03e00008, 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024,
- 0x1440fffd, 0x24020002, 0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000,
- 0xa7430188, 0xaf4501a4, 0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8,
- 0x3c029000, 0x34420001, 0x00822025, 0xaf440020, 0x3c038000, 0x8f420020,
- 0x00431024, 0x1440fffd, 0x00000000, 0x03e00008, 0x00000000, 0x3c028000,
- 0x34420001, 0x00822025, 0x03e00008, 0xaf440020, 0x308600ff, 0x27450180,
- 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128,
- 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1, 0xa4a20008, 0x24020002,
- 0xa0a2000b, 0x3c021000, 0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013,
- 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008,
- 0xaf4201b8, 0x24020001, 0xacc40000, 0x03e00008, 0xa4e50000, 0x03e00008,
- 0x24020001, 0x24020001, 0xaf400044, 0x03e00008, 0xaf400050, 0x00803021,
- 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
- 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018,
- 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010,
- 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014,
- 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc2002c, 0x3c031000,
- 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, 0x03e00008, 0xaf400050,
- 0x27bdffe8, 0xafbf0010, 0x0e001032, 0x00000000, 0x00002021, 0x0e000c99,
- 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f460148, 0x27450180,
- 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, 0x00431024, 0x1440fffd,
- 0x00000000, 0x8f440140, 0x00061202, 0x304200ff, 0x00061c02, 0xaca20004,
- 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, 0xaca30024, 0x10e0000a,
- 0xaca40000, 0x28e20004, 0x14400005, 0x24020001, 0x24020005, 0x54e20005,
- 0xa0a0000a, 0x24020001, 0x0a001571, 0xa0a2000a, 0xa0a0000a, 0x3c021000,
- 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, 0x10c00007, 0x00000000,
- 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004,
- 0x03e00008, 0x00000000, 0x0a001587, 0x00a01021, 0xac860000, 0x00000000,
- 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008,
- 0x00000000, 0x00000000 };
+ 0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024,
+ 0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, 0xaf4201b8, 0x24020001,
+ 0xacc40000, 0x03e00008, 0xa4e50000, 0x24020001, 0xaf400044, 0x03e00008,
+ 0xaf400050, 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1,
+ 0xa4a20008, 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a,
+ 0x94c20010, 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013,
+ 0x8cc30014, 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028,
+ 0x8cc2002c, 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044,
+ 0x03e00008, 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e001047, 0x00000000,
+ 0x00002021, 0x0e000c78, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018,
+ 0x8f460148, 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff,
+ 0x00061c02, 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b,
+ 0xaca30024, 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001,
+ 0x24020005, 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a001609, 0xa0a2000a,
+ 0xa0a0000a, 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021,
+ 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
+ 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00161f, 0x00a01021,
+ 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa,
+ 0x24a5ffff, 0x03e00008, 0x00000000, 0x00000000 };
static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b06FwBss[(0x1394/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b06FwSbss[(0x18/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = {
+ 0x0800468c, 0x0800458c, 0x08004630, 0x08004648, 0x08004660, 0x08004680,
+ 0x0800468c, 0x0800468c, 0x08004594, 0x00000000, 0x00000000 };
+static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 };
+static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
static u32 bnx2_rv2p_proc1[] = {
0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004,
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2582d98ef5c..bcf9f17daf0 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -576,7 +576,7 @@ static int bond_update_speed_duplex(struct slave *slave)
slave->duplex = DUPLEX_FULL;
if (slave_dev->ethtool_ops) {
- u32 res;
+ int res;
if (!slave_dev->ethtool_ops->get_settings) {
return -1;
@@ -1145,7 +1145,8 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
}
#define BOND_INTERSECT_FEATURES \
- (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
+ (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
+ NETIF_F_TSO|NETIF_F_UFO)
/*
* Compute the common dev->feature set available to all slaves. Some
@@ -1168,6 +1169,16 @@ static int bond_compute_features(struct bonding *bond)
NETIF_F_HW_CSUM)))
features &= ~NETIF_F_SG;
+ /*
+ * features will include NETIF_F_TSO (NETIF_F_UFO) iff all
+ * slave devices support NETIF_F_TSO (NETIF_F_UFO), which
+ * implies that all slaves also support scatter-gather
+ * (NETIF_F_SG), which implies that features also includes
+ * NETIF_F_SG. So no need to check whether we have an
+ * illegal combination of NETIF_F_{TSO,UFO} and
+ * !NETIF_F_SG
+ */
+
features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
bond_dev->features = features;
@@ -1570,6 +1581,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
printk(KERN_INFO DRV_NAME
": %s: %s not enslaved\n",
bond_dev->name, slave_dev->name);
+ write_unlock_bh(&bond->lock);
return -EINVAL;
}
@@ -4080,6 +4092,8 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
static struct ethtool_ops bond_ethtool_ops = {
.get_tx_csum = ethtool_op_get_tx_csum,
+ .get_tso = ethtool_op_get_tso,
+ .get_ufo = ethtool_op_get_ufo,
.get_sg = ethtool_op_get_sg,
.get_drvinfo = bond_ethtool_get_drvinfo,
};
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 32d13da43a0..041bcc58355 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -260,7 +260,7 @@ static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer,
char *ifname;
int i, res, found, ret = count;
struct slave *slave;
- struct net_device *dev = 0;
+ struct net_device *dev = NULL;
struct bonding *bond = to_bond(cd);
/* Quick sanity check -- is the bond interface up? */
@@ -995,7 +995,7 @@ static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, s
printk(KERN_INFO DRV_NAME
": %s: Setting primary slave to None.\n",
bond->dev->name);
- bond->primary_slave = 0;
+ bond->primary_slave = NULL;
bond_select_active_slave(bond);
} else {
printk(KERN_INFO DRV_NAME
@@ -1123,7 +1123,7 @@ static ssize_t bonding_store_active_slave(struct class_device *cd, const char *b
printk(KERN_INFO DRV_NAME
": %s: Setting active slave to None.\n",
bond->dev->name);
- bond->primary_slave = 0;
+ bond->primary_slave = NULL;
bond_select_active_slave(bond);
} else {
printk(KERN_INFO DRV_NAME
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 1f7ca453bb4..6e295fce5c6 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -335,6 +335,30 @@ static inline void cas_mask_intr(struct cas *cp)
cas_disable_irq(cp, i);
}
+static inline void cas_buffer_init(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_set((atomic_t *)&page->lru.next, 1);
+}
+
+static inline int cas_buffer_count(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ return atomic_read((atomic_t *)&page->lru.next);
+}
+
+static inline void cas_buffer_inc(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_inc((atomic_t *)&page->lru.next);
+}
+
+static inline void cas_buffer_dec(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_dec((atomic_t *)&page->lru.next);
+}
+
static void cas_enable_irq(struct cas *cp, const int ring)
{
if (ring == 0) { /* all but TX_DONE */
@@ -472,6 +496,7 @@ static int cas_page_free(struct cas *cp, cas_page_t *page)
{
pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size,
PCI_DMA_FROMDEVICE);
+ cas_buffer_dec(page);
__free_pages(page->buffer, cp->page_order);
kfree(page);
return 0;
@@ -501,6 +526,7 @@ static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
page->buffer = alloc_pages(flags, cp->page_order);
if (!page->buffer)
goto page_err;
+ cas_buffer_init(page);
page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0,
cp->page_size, PCI_DMA_FROMDEVICE);
return page;
@@ -579,7 +605,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags)
list_for_each_safe(elem, tmp, &list) {
cas_page_t *page = list_entry(elem, cas_page_t, list);
- if (page_count(page->buffer) > 1)
+ if (cas_buffer_count(page) > 1)
continue;
list_del(elem);
@@ -1347,7 +1373,7 @@ static inline cas_page_t *cas_page_spare(struct cas *cp, const int index)
cas_page_t *page = cp->rx_pages[1][index];
cas_page_t *new;
- if (page_count(page->buffer) == 1)
+ if (cas_buffer_count(page) == 1)
return page;
new = cas_page_dequeue(cp);
@@ -1367,7 +1393,7 @@ static cas_page_t *cas_page_swap(struct cas *cp, const int ring,
cas_page_t **page1 = cp->rx_pages[1];
/* swap if buffer is in use */
- if (page_count(page0[index]->buffer) > 1) {
+ if (cas_buffer_count(page0[index]) > 1) {
cas_page_t *new = cas_page_spare(cp, index);
if (new) {
page1[index] = page0[index];
@@ -1925,8 +1951,8 @@ static void cas_tx(struct net_device *dev, struct cas *cp,
u64 compwb = le64_to_cpu(cp->init_block->tx_compwb);
#endif
if (netif_msg_intr(cp))
- printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %lx\n",
- cp->dev->name, status, compwb);
+ printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %llx\n",
+ cp->dev->name, status, (unsigned long long)compwb);
/* process all the rings */
for (ring = 0; ring < N_TX_RINGS; ring++) {
#ifdef USE_TX_COMPWB
@@ -2039,6 +2065,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->len += hlen - swivel;
get_page(page->buffer);
+ cas_buffer_inc(page);
frag->page = page->buffer;
frag->page_offset = off;
frag->size = hlen - swivel;
@@ -2063,6 +2090,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
frag++;
get_page(page->buffer);
+ cas_buffer_inc(page);
frag->page = page->buffer;
frag->page_offset = 0;
frag->size = hlen;
@@ -2225,7 +2253,7 @@ static int cas_post_rxds_ringN(struct cas *cp, int ring, int num)
released = 0;
while (entry != last) {
/* make a new buffer if it's still in use */
- if (page_count(page[entry]->buffer) > 1) {
+ if (cas_buffer_count(page[entry]) > 1) {
cas_page_t *new = cas_page_dequeue(cp);
if (!new) {
/* let the timer know that we need to
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index fab6586d87e..ef54ebeb29b 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -93,6 +93,9 @@
Deepak Saxena : dsaxena@plexity.net
: Intel IXDP2351 platform support
+ Dmitry Pervushin : dpervushin@ru.mvista.com
+ : PNX010X platform support
+
*/
/* Always include 'config.h' first in case the user wants to turn on
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 4726722a063..24253c807e5 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1,25 +1,25 @@
/*******************************************************************************
-
+
Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
-
- 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)
+
+ 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
+
+ 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
+ this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
+
The full GNU General Public License is included in this distribution in the
file called LICENSE.
-
+
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -160,7 +160,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.4.14-k4"DRV_EXT
+#define DRV_VERSION "3.5.10-k2"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation"
#define PFX DRV_NAME ": "
@@ -320,7 +320,7 @@ enum cuc_dump {
cuc_dump_complete = 0x0000A005,
cuc_dump_reset_complete = 0x0000A007,
};
-
+
enum port {
software_reset = 0x0000,
selftest = 0x0001,
@@ -715,10 +715,10 @@ static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
writeb(ctrl, &nic->csr->eeprom_ctrl_lo);
e100_write_flush(nic); udelay(4);
-
+
writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
e100_write_flush(nic); udelay(4);
-
+
/* Eeprom drives a dummy zero to EEDO after receiving
* complete address. Use this to adjust addr_len. */
ctrl = readb(&nic->csr->eeprom_ctrl_lo);
@@ -726,7 +726,7 @@ static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
*addr_len -= (i - 16);
i = 17;
}
-
+
data = (data << 1) | (ctrl & eedo ? 1 : 0);
}
@@ -1170,7 +1170,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
}
-static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
/* *INDENT-OFF* */
static struct {
@@ -1213,13 +1213,13 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* driver can change the algorithm.
*
* INTDELAY - This loads the dead-man timer with its inital value.
-* When this timer expires the interrupt is asserted, and the
+* When this timer expires the interrupt is asserted, and the
* timer is reset each time a new packet is received. (see
* BUNDLEMAX below to set the limit on number of chained packets)
* The current default is 0x600 or 1536. Experiments show that
* the value should probably stay within the 0x200 - 0x1000.
*
-* BUNDLEMAX -
+* BUNDLEMAX -
* This sets the maximum number of frames that will be bundled. In
* some situations, such as the TCP windowing algorithm, it may be
* better to limit the growth of the bundle size than let it go as
@@ -1229,7 +1229,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* an interrupt for every frame received. If you do not want to put
* a limit on the bundle size, set this value to xFFFF.
*
-* BUNDLESMALL -
+* BUNDLESMALL -
* This contains a bit-mask describing the minimum size frame that
* will be bundled. The default masks the lower 7 bits, which means
* that any frame less than 128 bytes in length will not be bundled,
@@ -1244,7 +1244,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
*
* The current default is 0xFF80, which masks out the lower 7 bits.
* This means that any frame which is x7F (127) bytes or smaller
-* will cause an immediate interrupt. Because this value must be a
+* will cause an immediate interrupt. Because this value must be a
* bit mask, there are only a few valid values that can be used. To
* turn this feature off, the driver can write the value xFFFF to the
* lower word of this instruction (in the same way that the other
@@ -1253,7 +1253,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* standard Ethernet frames are <= 2047 bytes in length.
*************************************************************************/
-/* if you wish to disable the ucode functionality, while maintaining the
+/* if you wish to disable the ucode functionality, while maintaining the
* workarounds it provides, set the following defines to:
* BUNDLESMALL 0
* BUNDLEMAX 1
@@ -1284,12 +1284,46 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
for (i = 0; i < UCODE_SIZE; i++)
cb->u.ucode[i] = cpu_to_le32(ucode[i]);
- cb->command = cpu_to_le16(cb_ucode);
+ cb->command = cpu_to_le16(cb_ucode | cb_el);
return;
}
noloaducode:
- cb->command = cpu_to_le16(cb_nop);
+ cb->command = cpu_to_le16(cb_nop | cb_el);
+}
+
+static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb,
+ void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
+{
+ int err = 0, counter = 50;
+ struct cb *cb = nic->cb_to_clean;
+
+ if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode)))
+ DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err);
+
+ /* must restart cuc */
+ nic->cuc_cmd = cuc_start;
+
+ /* wait for completion */
+ e100_write_flush(nic);
+ udelay(10);
+
+ /* wait for possibly (ouch) 500ms */
+ while (!(cb->status & cpu_to_le16(cb_complete))) {
+ msleep(10);
+ if (!--counter) break;
+ }
+
+ /* ack any interupts, something could have been set */
+ writeb(~0, &nic->csr->scb.stat_ack);
+
+ /* if the command failed, or is not OK, notify and return */
+ if (!counter || !(cb->status & cpu_to_le16(cb_ok))) {
+ DPRINTK(PROBE,ERR, "ucode load failed\n");
+ err = -EPERM;
+ }
+
+ return err;
}
static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
@@ -1357,13 +1391,13 @@ static int e100_phy_init(struct nic *nic)
mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
}
- if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
+ if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
(mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) {
/* enable/disable MDI/MDI-X auto-switching.
MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */
if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) ||
- (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
- !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
+ (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
+ !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0);
else
mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH);
@@ -1388,7 +1422,7 @@ static int e100_hw_init(struct nic *nic)
return err;
if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
return err;
- if((err = e100_exec_cb(nic, NULL, e100_load_ucode)))
+ if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode)))
return err;
if((err = e100_exec_cb(nic, NULL, e100_configure)))
return err;
@@ -1493,7 +1527,7 @@ static void e100_update_stats(struct nic *nic)
}
}
-
+
if(e100_exec_cmd(nic, cuc_dump_reset, 0))
DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
}
@@ -1542,10 +1576,10 @@ static void e100_watchdog(unsigned long data)
mii_check_link(&nic->mii);
/* Software generated interrupt to recover from (rare) Rx
- * allocation failure.
- * Unfortunately have to use a spinlock to not re-enable interrupts
- * accidentally, due to hardware that shares a register between the
- * interrupt mask bit and the SW Interrupt generation bit */
+ * allocation failure.
+ * Unfortunately have to use a spinlock to not re-enable interrupts
+ * accidentally, due to hardware that shares a register between the
+ * interrupt mask bit and the SW Interrupt generation bit */
spin_lock_irq(&nic->cmd_lock);
writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
spin_unlock_irq(&nic->cmd_lock);
@@ -1830,7 +1864,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
struct rx *rx_to_start = NULL;
/* are we already rnr? then pay attention!!! this ensures that
- * the state machine progression never allows a start with a
+ * the state machine progression never allows a start with a
* partially cleaned list, avoiding a race between hardware
* and rx_to_clean when in NAPI mode */
if(RU_SUSPENDED == nic->ru_running)
@@ -2066,7 +2100,7 @@ static void e100_tx_timeout(struct net_device *netdev)
{
struct nic *nic = netdev_priv(netdev);
- /* Reset outside of interrupt context, to avoid request_irq
+ /* Reset outside of interrupt context, to avoid request_irq
* in interrupt context */
schedule_work(&nic->tx_timeout_task);
}
@@ -2313,7 +2347,7 @@ static int e100_set_ringparam(struct net_device *netdev,
struct param_range *rfds = &nic->params.rfds;
struct param_range *cbs = &nic->params.cbs;
- if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
if(netif_running(netdev))
@@ -2631,7 +2665,9 @@ static int __devinit e100_probe(struct pci_dev *pdev,
nic->flags |= wol_magic;
/* ack any pending wake events, disable PME */
- pci_enable_wake(pdev, 0, 0);
+ err = pci_enable_wake(pdev, 0, 0);
+ if (err)
+ DPRINTK(PROBE, ERR, "Error clearing wake event\n");
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev))) {
@@ -2682,6 +2718,7 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
if(netif_running(netdev))
e100_down(nic);
@@ -2689,9 +2726,14 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
netif_device_detach(netdev);
pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), nic->flags & (wol_magic | e100_asf(nic)));
+ retval = pci_enable_wake(pdev, pci_choose_state(pdev, state),
+ nic->flags & (wol_magic | e100_asf(nic)));
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error enabling wake\n");
pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error %d setting power state\n", retval);
return 0;
}
@@ -2700,13 +2742,16 @@ static int e100_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
- pci_set_power_state(pdev, PCI_D0);
+ retval = pci_set_power_state(pdev, PCI_D0);
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error waking adapter\n");
pci_restore_state(pdev);
/* ack any pending wake events, disable PME */
- pci_enable_wake(pdev, 0, 0);
- if(e100_hw_init(nic))
- DPRINTK(HW, ERR, "e100_hw_init failed\n");
+ retval = pci_enable_wake(pdev, 0, 0);
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error clearing wake events\n");
netif_device_attach(netdev);
if(netif_running(netdev))
@@ -2721,12 +2766,15 @@ static void e100_shutdown(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
#ifdef CONFIG_PM
- pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+ retval = pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
#else
- pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
+ retval = pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
#endif
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error enabling wake\n");
}
@@ -2739,7 +2787,7 @@ static struct pci_driver e100_driver = {
.suspend = e100_suspend,
.resume = e100_resume,
#endif
- .shutdown = e100_shutdown,
+ .shutdown = e100_shutdown,
};
static int __init e100_init_module(void)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index e02e9ba2e18..27c77306193 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -72,10 +72,6 @@
#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
@@ -87,6 +83,10 @@
struct e1000_adapter;
#include "e1000_hw.h"
+#ifdef CONFIG_E1000_MQ
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#endif
#ifdef DBG
#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
@@ -169,6 +169,13 @@ struct e1000_buffer {
uint16_t next_to_watch;
};
+#ifdef CONFIG_E1000_MQ
+struct e1000_queue_stats {
+ uint64_t packets;
+ uint64_t bytes;
+};
+#endif
+
struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
@@ -191,10 +198,12 @@ struct e1000_tx_ring {
spinlock_t tx_lock;
uint16_t tdh;
uint16_t tdt;
- uint64_t pkt;
boolean_t last_tx_tso;
+#ifdef CONFIG_E1000_MQ
+ struct e1000_queue_stats tx_stats;
+#endif
};
struct e1000_rx_ring {
@@ -216,9 +225,17 @@ struct e1000_rx_ring {
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
+ struct sk_buff *rx_skb_top;
+ struct sk_buff *rx_skb_prev;
+
+ /* cpu for rx queue */
+ int cpu;
+
uint16_t rdh;
uint16_t rdt;
- uint64_t pkt;
+#ifdef CONFIG_E1000_MQ
+ struct e1000_queue_stats rx_stats;
+#endif
};
#define E1000_DESC_UNUSED(R) \
@@ -251,6 +268,9 @@ struct e1000_adapter {
uint16_t link_speed;
uint16_t link_duplex;
spinlock_t stats_lock;
+#ifdef CONFIG_E1000_NAPI
+ spinlock_t tx_queue_lock;
+#endif
atomic_t irq_sem;
struct work_struct tx_timeout_task;
struct work_struct watchdog_task;
@@ -264,6 +284,7 @@ struct e1000_adapter {
#ifdef CONFIG_E1000_MQ
struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
#endif
+ unsigned long tx_queue_len;
uint32_t txd_cmd;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
@@ -271,9 +292,11 @@ struct e1000_adapter {
uint64_t gotcl_old;
uint64_t tpt_old;
uint64_t colc_old;
+ uint32_t tx_timeout_count;
uint32_t tx_fifo_head;
uint32_t tx_head_addr;
uint32_t tx_fifo_size;
+ uint8_t tx_timeout_factor;
atomic_t tx_fifo_stall;
boolean_t pcix_82544;
boolean_t detect_tx_hung;
@@ -281,14 +304,15 @@ struct e1000_adapter {
/* RX */
#ifdef CONFIG_E1000_NAPI
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do);
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
#else
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring);
#endif
void (*alloc_rx_buf) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
struct e1000_rx_ring *rx_ring; /* One per active queue */
#ifdef CONFIG_E1000_NAPI
struct net_device *polling_netdev; /* One per active queue */
@@ -296,13 +320,15 @@ struct e1000_adapter {
#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];
+ cpumask_t cpumask;
#endif
- int num_queues;
+ int num_tx_queues;
+ int num_rx_queues;
uint64_t hw_csum_err;
uint64_t hw_csum_good;
uint64_t rx_hdr_split;
+ uint32_t alloc_rx_buff_failed;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
@@ -330,6 +356,7 @@ struct e1000_adapter {
struct e1000_rx_ring test_rx_ring;
+ u32 *config_space;
int msg_enable;
#ifdef CONFIG_PCI_MSI
boolean_t have_msi;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index c88f1a3c1b1..5cedc81786e 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -80,6 +80,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "tx_deferred_ok", E1000_STAT(stats.dc) },
{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
+ { "tx_timeout_count", E1000_STAT(tx_timeout_count) },
{ "rx_long_length_errors", E1000_STAT(stats.roc) },
{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
@@ -93,9 +94,20 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
{ "rx_header_split", E1000_STAT(rx_hdr_split) },
+ { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
};
-#define E1000_STATS_LEN \
+
+#ifdef CONFIG_E1000_MQ
+#define E1000_QUEUE_STATS_LEN \
+ (((struct e1000_adapter *)netdev->priv)->num_tx_queues + \
+ ((struct e1000_adapter *)netdev->priv)->num_rx_queues) \
+ * (sizeof(struct e1000_queue_stats) / sizeof(uint64_t))
+#else
+#define E1000_QUEUE_STATS_LEN 0
+#endif
+#define E1000_GLOBAL_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
+#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)
static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
"Register test (offline)", "Eeprom test (offline)",
"Interrupt test (offline)", "Loopback test (offline)",
@@ -109,7 +121,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- if(hw->media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
@@ -121,7 +133,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->advertising = ADVERTISED_TP;
- if(hw->autoneg == 1) {
+ if (hw->autoneg == 1) {
ecmd->advertising |= ADVERTISED_Autoneg;
/* the e1000 autoneg seems to match ethtool nicely */
@@ -132,7 +144,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy_addr;
- if(hw->mac_type == e1000_82543)
+ if (hw->mac_type == e1000_82543)
ecmd->transceiver = XCVR_EXTERNAL;
else
ecmd->transceiver = XCVR_INTERNAL;
@@ -148,13 +160,13 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_FIBRE;
- if(hw->mac_type >= e1000_82545)
+ if (hw->mac_type >= e1000_82545)
ecmd->transceiver = XCVR_INTERNAL;
else
ecmd->transceiver = XCVR_EXTERNAL;
}
- if(netif_carrier_ok(adapter->netdev)) {
+ if (netif_carrier_ok(adapter->netdev)) {
e1000_get_speed_and_duplex(hw, &adapter->link_speed,
&adapter->link_duplex);
@@ -163,7 +175,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
/* unfortunatly FULL_DUPLEX != DUPLEX_FULL
* and HALF_DUPLEX != DUPLEX_HALF */
- if(adapter->link_duplex == FULL_DUPLEX)
+ if (adapter->link_duplex == FULL_DUPLEX)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
@@ -183,13 +195,21 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- if(ecmd->autoneg == AUTONEG_ENABLE) {
+ /* When SoL/IDER sessions are active, autoneg/speed/duplex
+ * cannot be changed */
+ if (e1000_check_phy_reset_block(hw)) {
+ DPRINTK(DRV, ERR, "Cannot change link characteristics "
+ "when SoL/IDER is active.\n");
+ return -EINVAL;
+ }
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
hw->autoneg = 1;
- if(hw->media_type == e1000_media_type_fiber)
+ if (hw->media_type == e1000_media_type_fiber)
hw->autoneg_advertised = ADVERTISED_1000baseT_Full |
ADVERTISED_FIBRE |
ADVERTISED_Autoneg;
- else
+ else
hw->autoneg_advertised = ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
@@ -199,12 +219,12 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ADVERTISED_TP;
ecmd->advertising = hw->autoneg_advertised;
} else
- if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
+ if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
return -EINVAL;
/* reset the link */
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_reset(adapter);
e1000_up(adapter);
@@ -221,14 +241,14 @@ e1000_get_pauseparam(struct net_device *netdev,
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- pause->autoneg =
+ pause->autoneg =
(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
-
- if(hw->fc == e1000_fc_rx_pause)
+
+ if (hw->fc == e1000_fc_rx_pause)
pause->rx_pause = 1;
- else if(hw->fc == e1000_fc_tx_pause)
+ else if (hw->fc == e1000_fc_tx_pause)
pause->tx_pause = 1;
- else if(hw->fc == e1000_fc_full) {
+ else if (hw->fc == e1000_fc_full) {
pause->rx_pause = 1;
pause->tx_pause = 1;
}
@@ -240,31 +260,30 @@ e1000_set_pauseparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
-
+
adapter->fc_autoneg = pause->autoneg;
- if(pause->rx_pause && pause->tx_pause)
+ if (pause->rx_pause && pause->tx_pause)
hw->fc = e1000_fc_full;
- else if(pause->rx_pause && !pause->tx_pause)
+ else if (pause->rx_pause && !pause->tx_pause)
hw->fc = e1000_fc_rx_pause;
- else if(!pause->rx_pause && pause->tx_pause)
+ else if (!pause->rx_pause && pause->tx_pause)
hw->fc = e1000_fc_tx_pause;
- else if(!pause->rx_pause && !pause->tx_pause)
+ else if (!pause->rx_pause && !pause->tx_pause)
hw->fc = e1000_fc_none;
hw->original_fc = hw->fc;
- if(adapter->fc_autoneg == AUTONEG_ENABLE) {
- if(netif_running(adapter->netdev)) {
+ if (adapter->fc_autoneg == AUTONEG_ENABLE) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
e1000_reset(adapter);
- }
- else
+ } else
return ((hw->media_type == e1000_media_type_fiber) ?
e1000_setup_link(hw) : e1000_force_mac_fc(hw));
-
+
return 0;
}
@@ -281,14 +300,14 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
struct e1000_adapter *adapter = netdev_priv(netdev);
adapter->rx_csum = data;
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
e1000_reset(adapter);
return 0;
}
-
+
static uint32_t
e1000_get_tx_csum(struct net_device *netdev)
{
@@ -300,7 +319,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(adapter->hw.mac_type < e1000_82543) {
+ if (adapter->hw.mac_type < e1000_82543) {
if (!data)
return -EINVAL;
return 0;
@@ -319,8 +338,8 @@ static int
e1000_set_tso(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if((adapter->hw.mac_type < e1000_82544) ||
- (adapter->hw.mac_type == e1000_82547))
+ if ((adapter->hw.mac_type < e1000_82544) ||
+ (adapter->hw.mac_type == e1000_82547))
return data ? -EINVAL : 0;
if (data)
@@ -328,7 +347,7 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
else
netdev->features &= ~NETIF_F_TSO;
return 0;
-}
+}
#endif /* NETIF_F_TSO */
static uint32_t
@@ -345,7 +364,7 @@ e1000_set_msglevel(struct net_device *netdev, uint32_t data)
adapter->msg_enable = data;
}
-static int
+static int
e1000_get_regs_len(struct net_device *netdev)
{
#define E1000_REGS_LEN 32
@@ -381,7 +400,7 @@ e1000_get_regs(struct net_device *netdev,
regs_buff[11] = E1000_READ_REG(hw, TIDV);
regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */
- if(hw->phy_type == e1000_phy_igp) {
+ if (hw->phy_type == e1000_phy_igp) {
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_A);
e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
@@ -435,7 +454,7 @@ e1000_get_regs(struct net_device *netdev,
e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */
regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
- if(hw->mac_type >= e1000_82540 &&
+ if (hw->mac_type >= e1000_82540 &&
hw->media_type == e1000_media_type_copper) {
regs_buff[26] = E1000_READ_REG(hw, MANC);
}
@@ -459,7 +478,7 @@ e1000_get_eeprom(struct net_device *netdev,
int ret_val = 0;
uint16_t i;
- if(eeprom->len == 0)
+ if (eeprom->len == 0)
return -EINVAL;
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
@@ -469,16 +488,16 @@ e1000_get_eeprom(struct net_device *netdev,
eeprom_buff = kmalloc(sizeof(uint16_t) *
(last_word - first_word + 1), GFP_KERNEL);
- if(!eeprom_buff)
+ if (!eeprom_buff)
return -ENOMEM;
- if(hw->eeprom.type == e1000_eeprom_spi)
+ if (hw->eeprom.type == e1000_eeprom_spi)
ret_val = e1000_read_eeprom(hw, first_word,
last_word - first_word + 1,
eeprom_buff);
else {
for (i = 0; i < last_word - first_word + 1; i++)
- if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
+ if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
&eeprom_buff[i])))
break;
}
@@ -505,10 +524,10 @@ e1000_set_eeprom(struct net_device *netdev,
int max_len, first_word, last_word, ret_val = 0;
uint16_t i;
- if(eeprom->len == 0)
+ if (eeprom->len == 0)
return -EOPNOTSUPP;
- if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT;
max_len = hw->eeprom.word_size * 2;
@@ -516,19 +535,19 @@ e1000_set_eeprom(struct net_device *netdev,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
eeprom_buff = kmalloc(max_len, GFP_KERNEL);
- if(!eeprom_buff)
+ if (!eeprom_buff)
return -ENOMEM;
ptr = (void *)eeprom_buff;
- if(eeprom->offset & 1) {
+ if (eeprom->offset & 1) {
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
ret_val = e1000_read_eeprom(hw, first_word, 1,
&eeprom_buff[0]);
ptr++;
}
- if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
+ if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
/* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */
ret_val = e1000_read_eeprom(hw, last_word, 1,
@@ -547,9 +566,9 @@ 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
+ /* 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) ||
+ if ((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
(hw->mac_type == e1000_82573)))
e1000_update_eeprom_checksum(hw);
@@ -567,21 +586,21 @@ e1000_get_drvinfo(struct net_device *netdev,
strncpy(drvinfo->driver, e1000_driver_name, 32);
strncpy(drvinfo->version, e1000_driver_version, 32);
-
- /* EEPROM image version # is reported as firware version # for
+
+ /* EEPROM image version # is reported as firmware version # for
* 8257{1|2|3} controllers */
e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
switch (adapter->hw.mac_type) {
case e1000_82571:
case e1000_82572:
case e1000_82573:
- sprintf(firmware_version, "%d.%d-%d",
+ sprintf(firmware_version, "%d.%d-%d",
(eeprom_data & 0xF000) >> 12,
(eeprom_data & 0x0FF0) >> 4,
eeprom_data & 0x000F);
break;
default:
- sprintf(firmware_version, "n/a");
+ sprintf(firmware_version, "N/A");
}
strncpy(drvinfo->fw_version, firmware_version, 32);
@@ -613,7 +632,7 @@ e1000_get_ringparam(struct net_device *netdev,
ring->rx_jumbo_pending = 0;
}
-static int
+static int
e1000_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
@@ -623,8 +642,8 @@ e1000_set_ringparam(struct net_device *netdev,
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;
+ tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
+ rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
if (netif_running(adapter->netdev))
e1000_down(adapter);
@@ -650,25 +669,25 @@ e1000_set_ringparam(struct net_device *netdev,
txdr = adapter->tx_ring;
rxdr = adapter->rx_ring;
- if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
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));
- E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+ E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);
txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?
E1000_MAX_TXD : E1000_MAX_82544_TXD));
- E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+ E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
txdr[i].count = txdr->count;
+ for (i = 0; i < adapter->num_rx_queues; i++)
rxdr[i].count = rxdr->count;
- }
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
@@ -688,7 +707,7 @@ e1000_set_ringparam(struct net_device *netdev,
kfree(rx_old);
adapter->rx_ring = rx_new;
adapter->tx_ring = tx_new;
- if((err = e1000_up(adapter)))
+ if ((err = e1000_up(adapter)))
return err;
}
@@ -707,10 +726,10 @@ err_setup_rx:
uint32_t pat, value; \
uint32_t test[] = \
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
- for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \
+ for (pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \
E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
value = E1000_READ_REG(&adapter->hw, R); \
- if(value != (test[pat] & W & M)) { \
+ if (value != (test[pat] & W & M)) { \
DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
"0x%08X expected 0x%08X\n", \
E1000_##R, value, (test[pat] & W & M)); \
@@ -726,7 +745,7 @@ err_setup_rx:
uint32_t value; \
E1000_WRITE_REG(&adapter->hw, R, W & M); \
value = E1000_READ_REG(&adapter->hw, R); \
- if((W & M) != (value & M)) { \
+ if ((W & M) != (value & M)) { \
DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
"expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \
*data = (adapter->hw.mac_type < e1000_82543) ? \
@@ -762,7 +781,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);
E1000_WRITE_REG(&adapter->hw, STATUS, toggle);
after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;
- if(value != after) {
+ if (value != after) {
DPRINTK(DRV, ERR, "failed STATUS register test got: "
"0x%08X expected: 0x%08X\n", after, value);
*data = 1;
@@ -790,7 +809,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
- if(adapter->hw.mac_type >= e1000_82543) {
+ if (adapter->hw.mac_type >= e1000_82543) {
REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
@@ -798,7 +817,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
- for(i = 0; i < E1000_RAR_ENTRIES; i++) {
+ for (i = 0; i < E1000_RAR_ENTRIES; i++) {
REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
0xFFFFFFFF);
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
@@ -814,7 +833,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
}
- for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+ for (i = 0; i < E1000_MC_TBL_SIZE; i++)
REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
*data = 0;
@@ -830,8 +849,8 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 0;
/* Read and add up the contents of the EEPROM */
- for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+ for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+ if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
*data = 1;
break;
}
@@ -839,7 +858,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
}
/* If Checksum is not Correct return error else test passed */
- if((checksum != (uint16_t) EEPROM_SUM) && !(*data))
+ if ((checksum != (uint16_t) EEPROM_SUM) && !(*data))
*data = 2;
return *data;
@@ -868,9 +887,9 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 0;
/* Hook up test interrupt handler just for this test */
- if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+ if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
shared_int = FALSE;
- } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ,
+ } else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
netdev->name, netdev)){
*data = 1;
return -1;
@@ -881,12 +900,12 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
msec_delay(10);
/* Test each interrupt */
- for(; i < 10; i++) {
+ for (; i < 10; i++) {
/* Interrupt to test */
mask = 1 << i;
- if(!shared_int) {
+ if (!shared_int) {
/* Disable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
@@ -897,8 +916,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, IMC, mask);
E1000_WRITE_REG(&adapter->hw, ICS, mask);
msec_delay(10);
-
- if(adapter->test_icr & mask) {
+
+ if (adapter->test_icr & mask) {
*data = 3;
break;
}
@@ -915,12 +934,12 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, ICS, mask);
msec_delay(10);
- if(!(adapter->test_icr & mask)) {
+ if (!(adapter->test_icr & mask)) {
*data = 4;
break;
}
- if(!shared_int) {
+ if (!shared_int) {
/* Disable the other interrupts to be reported in
* the cause register and then force the other
* interrupts and see if any get posted. If
@@ -932,7 +951,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);
msec_delay(10);
- if(adapter->test_icr) {
+ if (adapter->test_icr) {
*data = 5;
break;
}
@@ -957,40 +976,39 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
int i;
- if(txdr->desc && txdr->buffer_info) {
- for(i = 0; i < txdr->count; i++) {
- if(txdr->buffer_info[i].dma)
+ if (txdr->desc && txdr->buffer_info) {
+ for (i = 0; i < txdr->count; i++) {
+ if (txdr->buffer_info[i].dma)
pci_unmap_single(pdev, txdr->buffer_info[i].dma,
txdr->buffer_info[i].length,
PCI_DMA_TODEVICE);
- if(txdr->buffer_info[i].skb)
+ if (txdr->buffer_info[i].skb)
dev_kfree_skb(txdr->buffer_info[i].skb);
}
}
- if(rxdr->desc && rxdr->buffer_info) {
- for(i = 0; i < rxdr->count; i++) {
- if(rxdr->buffer_info[i].dma)
+ if (rxdr->desc && rxdr->buffer_info) {
+ for (i = 0; i < rxdr->count; i++) {
+ if (rxdr->buffer_info[i].dma)
pci_unmap_single(pdev, rxdr->buffer_info[i].dma,
rxdr->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
- if(rxdr->buffer_info[i].skb)
+ if (rxdr->buffer_info[i].skb)
dev_kfree_skb(rxdr->buffer_info[i].skb);
}
}
- if(txdr->desc) {
+ if (txdr->desc) {
pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
txdr->desc = NULL;
}
- if(rxdr->desc) {
+ if (rxdr->desc) {
pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
rxdr->desc = NULL;
}
kfree(txdr->buffer_info);
txdr->buffer_info = NULL;
-
kfree(rxdr->buffer_info);
rxdr->buffer_info = NULL;
@@ -1008,11 +1026,11 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
/* Setup Tx descriptor ring and Tx buffers */
- if(!txdr->count)
- txdr->count = E1000_DEFAULT_TXD;
+ if (!txdr->count)
+ txdr->count = E1000_DEFAULT_TXD;
size = txdr->count * sizeof(struct e1000_buffer);
- if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+ if (!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
ret_val = 1;
goto err_nomem;
}
@@ -1020,7 +1038,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
E1000_ROUNDUP(txdr->size, 4096);
- if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
+ if (!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
ret_val = 2;
goto err_nomem;
}
@@ -1039,12 +1057,12 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
- for(i = 0; i < txdr->count; i++) {
+ for (i = 0; i < txdr->count; i++) {
struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
struct sk_buff *skb;
unsigned int size = 1024;
- if(!(skb = alloc_skb(size, GFP_KERNEL))) {
+ if (!(skb = alloc_skb(size, GFP_KERNEL))) {
ret_val = 3;
goto err_nomem;
}
@@ -1064,18 +1082,18 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
/* Setup Rx descriptor ring and Rx buffers */
- if(!rxdr->count)
- rxdr->count = E1000_DEFAULT_RXD;
+ if (!rxdr->count)
+ rxdr->count = E1000_DEFAULT_RXD;
size = rxdr->count * sizeof(struct e1000_buffer);
- if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+ if (!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
ret_val = 4;
goto err_nomem;
}
memset(rxdr->buffer_info, 0, size);
rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
- if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+ if (!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
ret_val = 5;
goto err_nomem;
}
@@ -1095,11 +1113,11 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- for(i = 0; i < rxdr->count; i++) {
+ for (i = 0; i < rxdr->count; i++) {
struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
struct sk_buff *skb;
- if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
+ if (!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
GFP_KERNEL))) {
ret_val = 6;
goto err_nomem;
@@ -1208,15 +1226,15 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
/* Check Phy Configuration */
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
- if(phy_reg != 0x4100)
+ if (phy_reg != 0x4100)
return 9;
e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
- if(phy_reg != 0x0070)
+ if (phy_reg != 0x0070)
return 10;
e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
- if(phy_reg != 0x001A)
+ if (phy_reg != 0x001A)
return 11;
return 0;
@@ -1230,7 +1248,7 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
adapter->hw.autoneg = FALSE;
- if(adapter->hw.phy_type == e1000_phy_m88) {
+ if (adapter->hw.phy_type == e1000_phy_m88) {
/* Auto-MDI/MDIX Off */
e1000_write_phy_reg(&adapter->hw,
M88E1000_PHY_SPEC_CTRL, 0x0808);
@@ -1250,14 +1268,14 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
E1000_CTRL_FD); /* Force Duplex to FULL */
- if(adapter->hw.media_type == e1000_media_type_copper &&
+ if (adapter->hw.media_type == e1000_media_type_copper &&
adapter->hw.phy_type == e1000_phy_m88) {
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
} else {
/* Set the ILOS bit on the fiber Nic is half
* duplex link is detected. */
stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
- if((stat_reg & E1000_STATUS_FD) == 0)
+ if ((stat_reg & E1000_STATUS_FD) == 0)
ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
}
@@ -1266,7 +1284,7 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
- if(adapter->hw.phy_type == e1000_phy_m88)
+ if (adapter->hw.phy_type == e1000_phy_m88)
e1000_phy_disable_receiver(adapter);
udelay(500);
@@ -1282,14 +1300,14 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
switch (adapter->hw.mac_type) {
case e1000_82543:
- if(adapter->hw.media_type == e1000_media_type_copper) {
+ if (adapter->hw.media_type == e1000_media_type_copper) {
/* Attempt to setup Loopback mode on Non-integrated PHY.
* Some PHY registers get corrupted at random, so
* attempt this 10 times.
*/
- while(e1000_nonintegrated_phy_loopback(adapter) &&
+ while (e1000_nonintegrated_phy_loopback(adapter) &&
count++ < 10);
- if(count < 11)
+ if (count < 11)
return 0;
}
break;
@@ -1327,11 +1345,11 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
static int
e1000_setup_loopback_test(struct e1000_adapter *adapter)
{
- uint32_t rctl;
struct e1000_hw *hw = &adapter->hw;
+ uint32_t rctl;
if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes) {
+ hw->media_type == e1000_media_type_internal_serdes) {
switch (hw->mac_type) {
case e1000_82545:
case e1000_82546:
@@ -1362,25 +1380,25 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
static void
e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
uint32_t rctl;
uint16_t phy_reg;
- struct e1000_hw *hw = &adapter->hw;
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = E1000_READ_REG(hw, RCTL);
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ E1000_WRITE_REG(hw, RCTL, rctl);
switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes){
+ hw->media_type == e1000_media_type_internal_serdes) {
#define E1000_SERDES_LB_OFF 0x400
E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
msec_delay(10);
break;
}
- /* fall thru for Cu adapters */
+ /* Fall Through */
case e1000_82545:
case e1000_82546:
case e1000_82545_rev_3:
@@ -1401,7 +1419,7 @@ static void
e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
{
memset(skb->data, 0xFF, frame_size);
- frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
+ frame_size &= ~1;
memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
@@ -1410,9 +1428,9 @@ e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
static int
e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
{
- frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
- if(*(skb->data + 3) == 0xFF) {
- if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+ frame_size &= ~1;
+ if (*(skb->data + 3) == 0xFF) {
+ if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
(*(skb->data + frame_size / 2 + 12) == 0xAF)) {
return 0;
}
@@ -1431,53 +1449,53 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
- /* Calculate the loop count based on the largest descriptor ring
+ /* Calculate the loop count based on the largest descriptor ring
* The idea is to wrap the largest ring a number of times using 64
* send/receive pairs during each loop
*/
- if(rxdr->count <= txdr->count)
+ if (rxdr->count <= txdr->count)
lc = ((txdr->count / 64) * 2) + 1;
else
lc = ((rxdr->count / 64) * 2) + 1;
k = l = 0;
- for(j = 0; j <= lc; j++) { /* loop count loop */
- for(i = 0; i < 64; i++) { /* send the packets */
- e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
+ for (j = 0; j <= lc; j++) { /* loop count loop */
+ for (i = 0; i < 64; i++) { /* send the packets */
+ e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
1024);
- pci_dma_sync_single_for_device(pdev,
+ pci_dma_sync_single_for_device(pdev,
txdr->buffer_info[k].dma,
txdr->buffer_info[k].length,
PCI_DMA_TODEVICE);
- if(unlikely(++k == txdr->count)) k = 0;
+ if (unlikely(++k == txdr->count)) k = 0;
}
E1000_WRITE_REG(&adapter->hw, TDT, k);
msec_delay(200);
time = jiffies; /* set the start time for the receive */
good_cnt = 0;
do { /* receive the sent packets */
- pci_dma_sync_single_for_cpu(pdev,
+ pci_dma_sync_single_for_cpu(pdev,
rxdr->buffer_info[l].dma,
rxdr->buffer_info[l].length,
PCI_DMA_FROMDEVICE);
-
+
ret_val = e1000_check_lbtest_frame(
rxdr->buffer_info[l].skb,
1024);
- if(!ret_val)
+ if (!ret_val)
good_cnt++;
- if(unlikely(++l == rxdr->count)) l = 0;
- /* time + 20 msecs (200 msecs on 2.4) is more than
- * enough time to complete the receives, if it's
+ if (unlikely(++l == rxdr->count)) l = 0;
+ /* time + 20 msecs (200 msecs on 2.4) is more than
+ * enough time to complete the receives, if it's
* exceeded, break and error off
*/
} while (good_cnt < 64 && jiffies < (time + 20));
- if(good_cnt != 64) {
+ if (good_cnt != 64) {
ret_val = 13; /* ret_val is the same as mis-compare */
- break;
+ break;
}
- if(jiffies >= (time + 2)) {
+ if (jiffies >= (time + 2)) {
ret_val = 14; /* error code for time out error */
break;
}
@@ -1488,14 +1506,25 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
static int
e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
{
- if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
- if((*data = e1000_setup_loopback_test(adapter)))
- goto err_loopback_setup;
+ /* PHY loopback cannot be performed if SoL/IDER
+ * sessions are active */
+ if (e1000_check_phy_reset_block(&adapter->hw)) {
+ DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
+ "when SoL/IDER is active.\n");
+ *data = 0;
+ goto out;
+ }
+
+ if ((*data = e1000_setup_desc_rings(adapter)))
+ goto out;
+ if ((*data = e1000_setup_loopback_test(adapter)))
+ goto err_loopback;
*data = e1000_run_loopback_test(adapter);
e1000_loopback_cleanup(adapter);
-err_loopback_setup:
- e1000_free_desc_rings(adapter);
+
err_loopback:
+ e1000_free_desc_rings(adapter);
+out:
return *data;
}
@@ -1519,17 +1548,17 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 1;
} else {
e1000_check_for_link(&adapter->hw);
- if(adapter->hw.autoneg) /* if auto_neg is set wait for it */
+ if (adapter->hw.autoneg) /* if auto_neg is set wait for it */
msec_delay(4000);
- if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+ if (!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
*data = 1;
}
}
return *data;
}
-static int
+static int
e1000_diag_test_count(struct net_device *netdev)
{
return E1000_TEST_LEN;
@@ -1542,7 +1571,7 @@ e1000_diag_test(struct net_device *netdev,
struct e1000_adapter *adapter = netdev_priv(netdev);
boolean_t if_running = netif_running(netdev);
- if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
/* Offline tests */
/* save speed, duplex, autoneg settings */
@@ -1552,27 +1581,27 @@ e1000_diag_test(struct net_device *netdev,
/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result */
- if(e1000_link_test(adapter, &data[4]))
+ if (e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
- if(if_running)
+ if (if_running)
e1000_down(adapter);
else
e1000_reset(adapter);
- if(e1000_reg_test(adapter, &data[0]))
+ if (e1000_reg_test(adapter, &data[0]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_eeprom_test(adapter, &data[1]))
+ if (e1000_eeprom_test(adapter, &data[1]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_intr_test(adapter, &data[2]))
+ if (e1000_intr_test(adapter, &data[2]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_loopback_test(adapter, &data[3]))
+ if (e1000_loopback_test(adapter, &data[3]))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* restore speed, duplex, autoneg settings */
@@ -1581,11 +1610,11 @@ e1000_diag_test(struct net_device *netdev,
adapter->hw.autoneg = autoneg;
e1000_reset(adapter);
- if(if_running)
+ if (if_running)
e1000_up(adapter);
} else {
/* Online tests */
- if(e1000_link_test(adapter, &data[4]))
+ if (e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* Offline tests aren't run; pass by default */
@@ -1603,7 +1632,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- switch(adapter->hw.device_id) {
+ switch (adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
@@ -1617,8 +1646,9 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
+ case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber */
- if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
+ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0;
wol->wolopts = 0;
return;
@@ -1630,13 +1660,13 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
WAKE_BCAST | WAKE_MAGIC;
wol->wolopts = 0;
- if(adapter->wol & E1000_WUFC_EX)
+ if (adapter->wol & E1000_WUFC_EX)
wol->wolopts |= WAKE_UCAST;
- if(adapter->wol & E1000_WUFC_MC)
+ if (adapter->wol & E1000_WUFC_MC)
wol->wolopts |= WAKE_MCAST;
- if(adapter->wol & E1000_WUFC_BC)
+ if (adapter->wol & E1000_WUFC_BC)
wol->wolopts |= WAKE_BCAST;
- if(adapter->wol & E1000_WUFC_MAG)
+ if (adapter->wol & E1000_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
return;
}
@@ -1648,7 +1678,7 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- switch(adapter->hw.device_id) {
+ switch (adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
@@ -1660,24 +1690,25 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
+ case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber */
- if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
return wol->wolopts ? -EOPNOTSUPP : 0;
/* Fall Through */
default:
- if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+ if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
adapter->wol = 0;
- if(wol->wolopts & WAKE_UCAST)
+ if (wol->wolopts & WAKE_UCAST)
adapter->wol |= E1000_WUFC_EX;
- if(wol->wolopts & WAKE_MCAST)
+ if (wol->wolopts & WAKE_MCAST)
adapter->wol |= E1000_WUFC_MC;
- if(wol->wolopts & WAKE_BCAST)
+ if (wol->wolopts & WAKE_BCAST)
adapter->wol |= E1000_WUFC_BC;
- if(wol->wolopts & WAKE_MAGIC)
+ if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
}
@@ -1695,7 +1726,7 @@ e1000_led_blink_callback(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
- if(test_and_change_bit(E1000_LED_ON, &adapter->led_status))
+ if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))
e1000_led_off(&adapter->hw);
else
e1000_led_on(&adapter->hw);
@@ -1708,11 +1739,11 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
+ if (!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
- if(adapter->hw.mac_type < e1000_82571) {
- if(!adapter->blink_timer.function) {
+ 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;
adapter->blink_timer.data = (unsigned long) adapter;
@@ -1721,21 +1752,21 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
- }
- else if(adapter->hw.mac_type < e1000_82573) {
- E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
- E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+ } else if (adapter->hw.mac_type < e1000_82573) {
+ E1000_WRITE_REG(&adapter->hw, LEDCTL,
+ (E1000_LEDCTL_LED2_BLINK_RATE |
+ E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
msleep_interruptible(data * 1000);
- }
- else {
- E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
- E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
+ } else {
+ E1000_WRITE_REG(&adapter->hw, LEDCTL,
+ (E1000_LEDCTL_LED2_BLINK_RATE |
+ E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
msleep_interruptible(data * 1000);
}
@@ -1750,50 +1781,89 @@ static int
e1000_nway_reset(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
}
return 0;
}
-static int
+static int
e1000_get_stats_count(struct net_device *netdev)
{
return E1000_STATS_LEN;
}
-static void
-e1000_get_ethtool_stats(struct net_device *netdev,
+static void
+e1000_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+#ifdef CONFIG_E1000_MQ
+ uint64_t *queue_stat;
+ int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t);
+ int j, k;
+#endif
int i;
e1000_update_stats(adapter);
- for(i = 0; i < E1000_STATS_LEN; i++) {
- char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
- data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
+ data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
}
+#ifdef CONFIG_E1000_MQ
+ for (j = 0; j < adapter->num_tx_queues; j++) {
+ queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats;
+ for (k = 0; k < stat_count; k++)
+ data[i + k] = queue_stat[k];
+ i += k;
+ }
+ for (j = 0; j < adapter->num_rx_queues; j++) {
+ queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats;
+ for (k = 0; k < stat_count; k++)
+ data[i + k] = queue_stat[k];
+ i += k;
+ }
+#endif
+/* BUG_ON(i != E1000_STATS_LEN); */
}
-static void
+static void
e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
{
+#ifdef CONFIG_E1000_MQ
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+#endif
+ uint8_t *p = data;
int i;
- switch(stringset) {
+ switch (stringset) {
case ETH_SS_TEST:
- memcpy(data, *e1000_gstrings_test,
+ memcpy(data, *e1000_gstrings_test,
E1000_TEST_LEN*ETH_GSTRING_LEN);
break;
case ETH_SS_STATS:
- for (i=0; i < E1000_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- e1000_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ memcpy(p, e1000_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
}
+#ifdef CONFIG_E1000_MQ
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ sprintf(p, "tx_queue_%u_packets", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "tx_queue_%u_bytes", i);
+ p += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ sprintf(p, "rx_queue_%u_packets", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "rx_queue_%u_bytes", i);
+ p += ETH_GSTRING_LEN;
+ }
+#endif
+/* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */
break;
}
}
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 136fc031e4a..beeec0fbbea 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -318,6 +318,8 @@ 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:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
@@ -639,6 +641,7 @@ e1000_init_hw(struct e1000_hw *hw)
uint16_t cmd_mmrbc;
uint16_t stat_mmrbc;
uint32_t mta_size;
+ uint32_t ctrl_ext;
DEBUGFUNC("e1000_init_hw");
@@ -735,7 +738,6 @@ e1000_init_hw(struct e1000_hw *hw)
break;
case e1000_82571:
case e1000_82572:
- ctrl |= (1 << 22);
case e1000_82573:
ctrl |= E1000_TXDCTL_COUNT_DESC;
break;
@@ -775,6 +777,15 @@ e1000_init_hw(struct e1000_hw *hw)
*/
e1000_clear_hw_cntrs(hw);
+ if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
+ hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ /* Relaxed ordering must be disabled to avoid a parity
+ * error crash in a PCI slot. */
+ ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ }
+
return ret_val;
}
@@ -838,6 +849,11 @@ e1000_setup_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_link");
+ /* In the case of the phy reset being blocked, we already have a link.
+ * We do not have to set it up again. */
+ if (e1000_check_phy_reset_block(hw))
+ return E1000_SUCCESS;
+
/* Read and store word 0x0F of the EEPROM. This word contains bits
* that determine the hardware's default PAUSE (flow control) mode,
* a bit that determines whether the HW defaults to enabling or
@@ -1584,10 +1600,10 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
if(ret_val)
return ret_val;
- /* Read the MII 1000Base-T Control Register (Address 9). */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
- if(ret_val)
- return ret_val;
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+ if(ret_val)
+ return ret_val;
/* Need to parse both autoneg_advertised and fc and set up
* the appropriate PHY registers. First we will parse for
@@ -1929,14 +1945,19 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
void
e1000_config_collision_dist(struct e1000_hw *hw)
{
- uint32_t tctl;
+ uint32_t tctl, coll_dist;
DEBUGFUNC("e1000_config_collision_dist");
+ if (hw->mac_type < e1000_82543)
+ coll_dist = E1000_COLLISION_DISTANCE_82542;
+ else
+ coll_dist = E1000_COLLISION_DISTANCE;
+
tctl = E1000_READ_REG(hw, TCTL);
tctl &= ~E1000_TCTL_COLD;
- tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+ tctl |= coll_dist << E1000_COLD_SHIFT;
E1000_WRITE_REG(hw, TCTL, tctl);
E1000_WRITE_FLUSH(hw);
@@ -2982,6 +3003,8 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
if (hw->mac_type < e1000_82571)
msec_delay(10);
+ else
+ udelay(100);
E1000_WRITE_REG(hw, CTRL, ctrl);
E1000_WRITE_FLUSH(hw);
@@ -3881,17 +3904,19 @@ e1000_read_eeprom(struct e1000_hw *hw,
return -E1000_ERR_EEPROM;
}
- /* FLASH reads without acquiring the semaphore are safe in 82573-based
- * controllers.
- */
- if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
- (hw->mac_type != e1000_82573)) {
- /* Prepare the EEPROM for reading */
- if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
+ /* FLASH reads without acquiring the semaphore are safe */
+ if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
+ hw->eeprom.use_eerd == FALSE) {
+ switch (hw->mac_type) {
+ default:
+ /* Prepare the EEPROM for reading */
+ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+ break;
+ }
}
- if(eeprom->use_eerd == TRUE) {
+ if (eeprom->use_eerd == TRUE) {
ret_val = e1000_read_eeprom_eerd(hw, offset, words, data);
if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
(hw->mac_type != e1000_82573))
@@ -4398,7 +4423,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
return -E1000_ERR_EEPROM;
}
- /* If STM opcode located in bits 15:8 of flop, reset firmware */
+ /* If STM opcode located in bits 15:8 of flop, reset firmware */
if ((flop & 0xFF00) == E1000_STM_OPCODE) {
E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
}
@@ -4406,7 +4431,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
/* Perform the flash update */
E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
- for (i=0; i < attempts; i++) {
+ for (i=0; i < attempts; i++) {
eecd = E1000_READ_REG(hw, EECD);
if ((eecd & E1000_EECD_FLUPD) == 0) {
break;
@@ -4479,6 +4504,7 @@ 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);
}
+
switch (hw->mac_type) {
default:
break;
@@ -6720,6 +6746,12 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
break;
}
+ /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
+ * Need to wait for PHY configuration completion before accessing NVM
+ * and PHY. */
+ if (hw->mac_type == e1000_82573)
+ msec_delay(25);
+
return E1000_SUCCESS;
}
@@ -6809,7 +6841,8 @@ int32_t
e1000_check_phy_reset_block(struct e1000_hw *hw)
{
uint32_t manc = 0;
- if(hw->mac_type > e1000_82547_rev_2)
+
+ if (hw->mac_type > e1000_82547_rev_2)
manc = E1000_READ_REG(hw, MANC);
return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
E1000_BLK_PHY_RESET : E1000_SUCCESS;
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 7caa35748ce..f1219dd9dba 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -377,6 +377,7 @@ int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
/* Filters (multicast, vlan, receive) */
+void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@@ -401,7 +402,9 @@ void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
/* Port I/O is only supported on 82544 and newer */
uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
+uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
+void e1000_enable_pciex_master(struct e1000_hw *hw);
int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
void e1000_release_software_semaphore(struct e1000_hw *hw);
@@ -439,6 +442,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#define E1000_DEV_ID_82546GB_FIBER 0x107A
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define E1000_DEV_ID_82547EI 0x1019
#define E1000_DEV_ID_82571EB_COPPER 0x105E
#define E1000_DEV_ID_82571EB_FIBER 0x105F
@@ -449,6 +453,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#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_KSP3 0x10B5
#define NODE_ADDRESS_SIZE 6
@@ -897,14 +902,14 @@ struct e1000_ffvt_entry {
#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */
#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
-#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
-#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
-#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
-#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
-#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
-#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
-#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
+#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
+#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
+#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
+#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
+#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
+#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
+#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
+#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
@@ -1497,6 +1502,7 @@ struct e1000_hw {
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */
#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000
@@ -1758,7 +1764,6 @@ struct e1000_hw {
#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
still to be processed. */
-
/* Transmit Configuration Word */
#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */
@@ -1954,6 +1959,23 @@ struct e1000_host_command_info {
#define E1000_MDALIGN 4096
+/* PCI-Ex registers */
+
+/* PCI-Ex Control Register */
+#define E1000_GCR_RXD_NO_SNOOP 0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004
+#define E1000_GCR_TXD_NO_SNOOP 0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020
+
+#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \
+ E1000_GCR_RXDSCW_NO_SNOOP | \
+ E1000_GCR_RXDSCR_NO_SNOOP | \
+ E1000_GCR TXD_NO_SNOOP | \
+ E1000_GCR_TXDSCW_NO_SNOOP | \
+ E1000_GCR_TXDSCR_NO_SNOOP)
+
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Function Active and Power State to MNG */
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
@@ -2077,7 +2099,10 @@ struct e1000_host_command_info {
/* Collision related configuration parameters */
#define E1000_COLLISION_THRESHOLD 15
#define E1000_CT_SHIFT 4
-#define E1000_COLLISION_DISTANCE 64
+/* Collision distance is a 0-based value that applies to
+ * half-duplex-capable hardware only. */
+#define E1000_COLLISION_DISTANCE 63
+#define E1000_COLLISION_DISTANCE_82542 64
#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_COLD_SHIFT 12
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 438a931fd55..31e332935e5 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -29,11 +29,71 @@
#include "e1000.h"
/* Change Log
- * 6.0.58 4/20/05
- * o Accepted ethtool cleanup patch from Stephen Hemminger
- * 6.0.44+ 2/15/05
- * o applied Anton's patch to resolve tx hang in hardware
- * o Applied Andrew Mortons patch - e1000 stops working after resume
+ * 6.3.9 12/16/2005
+ * o incorporate fix for recycled skbs from IBM LTC
+ * 6.3.7 11/18/2005
+ * o Honor eeprom setting for enabling/disabling Wake On Lan
+ * 6.3.5 11/17/2005
+ * o Fix memory leak in rx ring handling for PCI Express adapters
+ * 6.3.4 11/8/05
+ * o Patch from Jesper Juhl to remove redundant NULL checks for kfree
+ * 6.3.2 9/20/05
+ * o Render logic that sets/resets DRV_LOAD as inline functions to
+ * avoid code replication. If f/w is AMT then set DRV_LOAD only when
+ * network interface is open.
+ * o Handle DRV_LOAD set/reset in cases where AMT uses VLANs.
+ * o Adjust PBA partioning for Jumbo frames using MTU size and not
+ * rx_buffer_len
+ * 6.3.1 9/19/05
+ * o Use adapter->tx_timeout_factor in Tx Hung Detect logic
+ (e1000_clean_tx_irq)
+ * o Support for 8086:10B5 device (Quad Port)
+ * 6.2.14 9/15/05
+ * o In AMT enabled configurations, set/reset DRV_LOAD bit on interface
+ * open/close
+ * 6.2.13 9/14/05
+ * o Invoke e1000_check_mng_mode only for 8257x controllers since it
+ * accesses the FWSM that is not supported in other controllers
+ * 6.2.12 9/9/05
+ * o Add support for device id E1000_DEV_ID_82546GB_QUAD_COPPER
+ * o set RCTL:SECRC only for controllers newer than 82543.
+ * o When the n/w interface comes down reset DRV_LOAD bit to notify f/w.
+ * This code was moved from e1000_remove to e1000_close
+ * 6.2.10 9/6/05
+ * o Fix error in updating RDT in el1000_alloc_rx_buffers[_ps] -- one off.
+ * o Enable fc by default on 82573 controllers (do not read eeprom)
+ * o Fix rx_errors statistic not to include missed_packet_count
+ * o Fix rx_dropped statistic not to include missed_packet_count
+ (Padraig Brady)
+ * 6.2.9 8/30/05
+ * o Remove call to update statistics from the controller ib e1000_get_stats
+ * 6.2.8 8/30/05
+ * o Improved algorithm for rx buffer allocation/rdt update
+ * o Flow control watermarks relative to rx PBA size
+ * o Simplified 'Tx Hung' detect logic
+ * 6.2.7 8/17/05
+ * o Report rx buffer allocation failures and tx timeout counts in stats
+ * 6.2.6 8/16/05
+ * o Implement workaround for controller erratum -- linear non-tso packet
+ * following a TSO gets written back prematurely
+ * 6.2.5 8/15/05
+ * o Set netdev->tx_queue_len based on link speed/duplex settings.
+ * o Fix net_stats.rx_fifo_errors <p@draigBrady.com>
+ * o Do not power off PHY if SoL/IDER session is active
+ * 6.2.4 8/10/05
+ * o Fix loopback test setup/cleanup for 82571/3 controllers
+ * o Fix parsing of outgoing packets (e1000_transfer_dhcp_info) to treat
+ * all packets as raw
+ * o Prevent operations that will cause the PHY to be reset if SoL/IDER
+ * sessions are active and log a message
+ * 6.2.2 7/21/05
+ * o used fixed size descriptors for all MTU sizes, reduces memory load
+ * 6.1.2 4/13/05
+ * o Fixed ethtool diagnostics
+ * o Enabled flow control to take default eeprom settings
+ * o Added stats_lock around e1000_read_phy_reg commands to avoid concurrent
+ * calls, one from mii_ioctl and other from within update_stats while
+ * processing MIIREG ioctl.
*/
char e1000_driver_name[] = "e1000";
@@ -43,7 +103,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
+#define DRV_VERSION "6.3.9-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
@@ -97,7 +157,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
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),
+ INTEL_E1000_ETHERNET_DEVICE(0x10B5),
/* required last entry */
{0,}
};
@@ -171,9 +233,11 @@ 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,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
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);
@@ -291,7 +355,7 @@ e1000_irq_disable(struct e1000_adapter *adapter)
static inline void
e1000_irq_enable(struct e1000_adapter *adapter)
{
- if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
+ if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
E1000_WRITE_FLUSH(&adapter->hw);
}
@@ -303,23 +367,91 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
struct net_device *netdev = adapter->netdev;
uint16_t vid = adapter->hw.mng_cookie.vlan_id;
uint16_t old_vid = adapter->mng_vlan_id;
- if(adapter->vlgrp) {
- if(!adapter->vlgrp->vlan_devices[vid]) {
- if(adapter->hw.mng_cookie.status &
+ if (adapter->vlgrp) {
+ if (!adapter->vlgrp->vlan_devices[vid]) {
+ if (adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
e1000_vlan_rx_add_vid(netdev, vid);
adapter->mng_vlan_id = vid;
} else
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-
- if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
- (vid != old_vid) &&
+
+ if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
!adapter->vlgrp->vlan_devices[old_vid])
e1000_vlan_rx_kill_vid(netdev, old_vid);
}
}
}
-
+
+/**
+ * e1000_release_hw_control - release control of the h/w to f/w
+ * @adapter: address of board private structure
+ *
+ * e1000_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that the
+ * driver is no longer loaded. For AMT version (only with 82573) i
+ * of the f/w this means that the netowrk i/f is closed.
+ *
+ **/
+
+static inline void
+e1000_release_hw_control(struct e1000_adapter *adapter)
+{
+ uint32_t ctrl_ext;
+ uint32_t swsm;
+
+ /* Let firmware taken over control of h/w */
+ 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,
+ swsm & ~E1000_SWSM_DRV_LOAD);
+ default:
+ break;
+ }
+}
+
+/**
+ * e1000_get_hw_control - get control of the h/w from f/w
+ * @adapter: address of board private structure
+ *
+ * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that
+ * the driver is loaded. For AMT version (only with 82573)
+ * of the f/w this means that the netowrk i/f is open.
+ *
+ **/
+
+static inline void
+e1000_get_hw_control(struct e1000_adapter *adapter)
+{
+ uint32_t ctrl_ext;
+ uint32_t swsm;
+ /* 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,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+}
+
int
e1000_up(struct e1000_adapter *adapter)
{
@@ -329,10 +461,10 @@ e1000_up(struct e1000_adapter *adapter)
/* hardware has been reset, we need to reload some things */
/* Reset the PHY if it was previously powered down */
- if(adapter->hw.media_type == e1000_media_type_copper) {
+ if (adapter->hw.media_type == e1000_media_type_copper) {
uint16_t mii_reg;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
e1000_phy_reset(&adapter->hw);
}
@@ -343,20 +475,26 @@ e1000_up(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- for (i = 0; i < adapter->num_queues; i++)
- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
+ /* call E1000_DESC_UNUSED which always leaves
+ * at least 1 descriptor unused to make sure
+ * next_to_use != next_to_clean */
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ struct e1000_rx_ring *ring = &adapter->rx_ring[i];
+ adapter->alloc_rx_buf(adapter, ring,
+ E1000_DESC_UNUSED(ring));
+ }
#ifdef CONFIG_PCI_MSI
- if(adapter->hw.mac_type > e1000_82547_rev_2) {
+ if (adapter->hw.mac_type > e1000_82547_rev_2) {
adapter->have_msi = TRUE;
- if((err = pci_enable_msi(adapter->pdev))) {
+ if ((err = pci_enable_msi(adapter->pdev))) {
DPRINTK(PROBE, ERR,
"Unable to allocate MSI interrupt Error: %d\n", err);
adapter->have_msi = FALSE;
}
}
#endif
- if((err = request_irq(adapter->pdev->irq, &e1000_intr,
+ if ((err = request_irq(adapter->pdev->irq, &e1000_intr,
SA_SHIRQ | SA_SAMPLE_RANDOM,
netdev->name, netdev))) {
DPRINTK(PROBE, ERR,
@@ -364,6 +502,12 @@ e1000_up(struct e1000_adapter *adapter)
return err;
}
+#ifdef CONFIG_E1000_MQ
+ e1000_setup_queue_mapping(adapter);
+#endif
+
+ adapter->tx_queue_len = netdev->tx_queue_len;
+
mod_timer(&adapter->watchdog_timer, jiffies);
#ifdef CONFIG_E1000_NAPI
@@ -378,6 +522,8 @@ void
e1000_down(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) &&
+ e1000_check_mng_mode(&adapter->hw);
e1000_irq_disable(adapter);
#ifdef CONFIG_E1000_MQ
@@ -385,7 +531,7 @@ e1000_down(struct e1000_adapter *adapter)
#endif
free_irq(adapter->pdev->irq, netdev);
#ifdef CONFIG_PCI_MSI
- if(adapter->hw.mac_type > e1000_82547_rev_2 &&
+ if (adapter->hw.mac_type > e1000_82547_rev_2 &&
adapter->have_msi == TRUE)
pci_disable_msi(adapter->pdev);
#endif
@@ -396,6 +542,7 @@ e1000_down(struct e1000_adapter *adapter)
#ifdef CONFIG_E1000_NAPI
netif_poll_disable(netdev);
#endif
+ netdev->tx_queue_len = adapter->tx_queue_len;
adapter->link_speed = 0;
adapter->link_duplex = 0;
netif_carrier_off(netdev);
@@ -405,12 +552,16 @@ e1000_down(struct e1000_adapter *adapter)
e1000_clean_all_tx_rings(adapter);
e1000_clean_all_rx_rings(adapter);
- /* 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 &&
+ /* Power down the PHY so no link is implied when interface is down *
+ * The PHY cannot be powered down if any of the following is TRUE *
+ * (a) WoL is enabled
+ * (b) AMT is active
+ * (c) SoL/IDER session is active */
+ if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper &&
- !e1000_check_mng_mode(&adapter->hw) &&
- !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) {
+ !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) &&
+ !mng_mode_enabled &&
+ !e1000_check_phy_reset_block(&adapter->hw)) {
uint16_t mii_reg;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
@@ -422,10 +573,8 @@ e1000_down(struct e1000_adapter *adapter)
void
e1000_reset(struct e1000_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
uint32_t pba, manc;
uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
- uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF;
/* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required.
@@ -448,19 +597,12 @@ e1000_reset(struct e1000_adapter *adapter)
break;
}
- if((adapter->hw.mac_type != e1000_82573) &&
- (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) {
+ if ((adapter->hw.mac_type != e1000_82573) &&
+ (adapter->netdev->mtu > E1000_RXBUFFER_8192))
pba -= 8; /* allocate more FIFO for Tx */
- /* send an XOFF when there is enough space in the
- * Rx FIFO to hold one extra full size Rx packet
- */
- fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE +
- ETHERNET_FCS_SIZE + 1;
- fc_low_water_mark = fc_high_water_mark + 8;
- }
- if(adapter->hw.mac_type == e1000_82547) {
+ if (adapter->hw.mac_type == e1000_82547) {
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
adapter->tx_fifo_size =
@@ -471,19 +613,21 @@ e1000_reset(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, PBA, pba);
/* flow control settings */
- adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) -
- fc_high_water_mark;
- adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) -
- fc_low_water_mark;
+ /* Set the FC high water mark to 90% of the FIFO size.
+ * Required to clear last 3 LSB */
+ fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
+
+ adapter->hw.fc_high_water = fc_high_water_mark;
+ adapter->hw.fc_low_water = fc_high_water_mark - 8;
adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
adapter->hw.fc_send_xon = 1;
adapter->hw.fc = adapter->hw.original_fc;
/* Allow time for pending master requests to run */
e1000_reset_hw(&adapter->hw);
- if(adapter->hw.mac_type >= e1000_82544)
+ if (adapter->hw.mac_type >= e1000_82544)
E1000_WRITE_REG(&adapter->hw, WUC, 0);
- if(e1000_init_hw(&adapter->hw))
+ if (e1000_init_hw(&adapter->hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
e1000_update_mng_vlan(adapter);
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
@@ -517,33 +661,31 @@ 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;
int i, err, pci_using_dac;
uint16_t eeprom_data;
uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
- if((err = pci_enable_device(pdev)))
+ if ((err = pci_enable_device(pdev)))
return err;
- if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
pci_using_dac = 1;
} else {
- if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
E1000_ERR("No usable DMA configuration, aborting\n");
return err;
}
pci_using_dac = 0;
}
- if((err = pci_request_regions(pdev, e1000_driver_name)))
+ if ((err = pci_request_regions(pdev, e1000_driver_name)))
return err;
pci_set_master(pdev);
netdev = alloc_etherdev(sizeof(struct e1000_adapter));
- if(!netdev) {
+ if (!netdev) {
err = -ENOMEM;
goto err_alloc_etherdev;
}
@@ -562,15 +704,15 @@ e1000_probe(struct pci_dev *pdev,
mmio_len = pci_resource_len(pdev, BAR_0);
adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
- if(!adapter->hw.hw_addr) {
+ if (!adapter->hw.hw_addr) {
err = -EIO;
goto err_ioremap;
}
- for(i = BAR_1; i <= BAR_5; i++) {
- if(pci_resource_len(pdev, i) == 0)
+ for (i = BAR_1; i <= BAR_5; i++) {
+ if (pci_resource_len(pdev, i) == 0)
continue;
- if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+ if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
adapter->hw.io_base = pci_resource_start(pdev, i);
break;
}
@@ -607,13 +749,13 @@ e1000_probe(struct pci_dev *pdev,
/* setup the private structure */
- if((err = e1000_sw_init(adapter)))
+ if ((err = e1000_sw_init(adapter)))
goto err_sw_init;
- if((err = e1000_check_phy_reset_block(&adapter->hw)))
+ if ((err = e1000_check_phy_reset_block(&adapter->hw)))
DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
- if(adapter->hw.mac_type >= e1000_82543) {
+ if (adapter->hw.mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM |
NETIF_F_HW_VLAN_TX |
@@ -622,16 +764,16 @@ e1000_probe(struct pci_dev *pdev,
}
#ifdef NETIF_F_TSO
- if((adapter->hw.mac_type >= e1000_82544) &&
+ if ((adapter->hw.mac_type >= e1000_82544) &&
(adapter->hw.mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
#ifdef NETIF_F_TSO_IPV6
- if(adapter->hw.mac_type > e1000_82547_rev_2)
+ if (adapter->hw.mac_type > e1000_82547_rev_2)
netdev->features |= NETIF_F_TSO_IPV6;
#endif
#endif
- if(pci_using_dac)
+ if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
/* hard_start_xmit is safe against parallel locking */
@@ -639,14 +781,14 @@ e1000_probe(struct pci_dev *pdev,
adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
- /* before reading the EEPROM, reset the controller to
+ /* before reading the EEPROM, reset the controller to
* put the device in a known good starting state */
-
+
e1000_reset_hw(&adapter->hw);
/* make sure the EEPROM is good */
- if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
+ if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
err = -EIO;
goto err_eeprom;
@@ -654,12 +796,12 @@ e1000_probe(struct pci_dev *pdev,
/* copy the MAC address out of the EEPROM */
- if(e1000_read_mac_addr(&adapter->hw))
+ 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->perm_addr)) {
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
err = -EIO;
goto err_eeprom;
@@ -699,7 +841,7 @@ e1000_probe(struct pci_dev *pdev,
* enable the ACPI Magic Packet filter
*/
- switch(adapter->hw.mac_type) {
+ switch (adapter->hw.mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
@@ -712,8 +854,7 @@ e1000_probe(struct pci_dev *pdev,
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82571:
- if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
- && (adapter->hw.media_type == e1000_media_type_copper)) {
+ if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
e1000_read_eeprom(&adapter->hw,
EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
break;
@@ -724,31 +865,42 @@ e1000_probe(struct pci_dev *pdev,
EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
break;
}
- if(eeprom_data & eeprom_apme_mask)
+ if (eeprom_data & eeprom_apme_mask)
adapter->wol |= E1000_WUFC_MAG;
+ /* print bus type/speed/width info */
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
+ ((hw->bus_type == e1000_bus_type_pcix) ? "-X" :
+ (hw->bus_type == e1000_bus_type_pci_express ? " Express":"")),
+ ((hw->bus_speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
+ (hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
+ (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
+ (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
+ (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
+ ((hw->bus_width == e1000_bus_width_64) ? "64-bit" :
+ (hw->bus_width == e1000_bus_width_pciex_4) ? "Width x4" :
+ (hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
+ "32-bit"));
+ }
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", netdev->dev_addr[i], i == 5 ? '\n' : ':');
+
/* reset the hardware with the new settings */
e1000_reset(adapter);
- /* 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,
- swsm | E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* If the controller is 82573 and f/w is AMT, do not set
+ * DRV_LOAD until the interface is up. For all other cases,
+ * let the f/w know that the h/w is now under the control
+ * of the driver. */
+ if (adapter->hw.mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
strcpy(netdev->name, "eth%d");
- if((err = register_netdev(netdev)))
+ if ((err = register_netdev(netdev)))
goto err_register;
DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
@@ -782,47 +934,33 @@ 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;
+ uint32_t manc;
#ifdef CONFIG_E1000_NAPI
int i;
#endif
flush_scheduled_work();
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
- if(manc & E1000_MANC_SMBUS_EN) {
+ if (manc & E1000_MANC_SMBUS_EN) {
manc |= E1000_MANC_ARP_EN;
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
}
- 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,
- swsm & ~E1000_SWSM_DRV_LOAD);
- break;
-
- default:
- break;
- }
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
+ * would have already happened in close and is redundant. */
+ e1000_release_hw_control(adapter);
unregister_netdev(netdev);
#ifdef CONFIG_E1000_NAPI
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
__dev_put(&adapter->polling_netdev[i]);
#endif
- if(!e1000_check_phy_reset_block(&adapter->hw))
+ if (!e1000_check_phy_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw);
kfree(adapter->tx_ring);
@@ -881,19 +1019,19 @@ e1000_sw_init(struct e1000_adapter *adapter)
/* identify the MAC */
- if(e1000_set_mac_type(hw)) {
+ if (e1000_set_mac_type(hw)) {
DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
return -EIO;
}
/* initialize eeprom parameters */
- if(e1000_init_eeprom_params(hw)) {
+ if (e1000_init_eeprom_params(hw)) {
E1000_ERR("EEPROM initialization failed\n");
return -EIO;
}
- switch(hw->mac_type) {
+ switch (hw->mac_type) {
default:
break;
case e1000_82541:
@@ -912,7 +1050,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
/* Copper options */
- if(hw->media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
hw->mdix = AUTO_ALL_MODES;
hw->disable_polarity_correction = FALSE;
hw->master_slave = E1000_MASTER_SLAVE;
@@ -923,15 +1061,34 @@ e1000_sw_init(struct e1000_adapter *adapter)
switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
- adapter->num_queues = 2;
+ /* These controllers support 2 tx queues, but with a single
+ * qdisc implementation, multiple tx queues aren't quite as
+ * interesting. If we can find a logical way of mapping
+ * flows to a queue, then perhaps we can up the num_tx_queue
+ * count back to its default. Until then, we run the risk of
+ * terrible performance due to SACK overload. */
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 2;
break;
default:
- adapter->num_queues = 1;
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 1;
break;
}
- adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+ adapter->num_rx_queues = min(adapter->num_rx_queues, num_online_cpus());
+ adapter->num_tx_queues = min(adapter->num_tx_queues, num_online_cpus());
+ DPRINTK(DRV, INFO, "Multiqueue Enabled: Rx Queue count = %u %s\n",
+ adapter->num_rx_queues,
+ ((adapter->num_rx_queues == 1)
+ ? ((num_online_cpus() > 1)
+ ? "(due to unsupported feature in current adapter)"
+ : "(due to unsupported system configuration)")
+ : ""));
+ DPRINTK(DRV, INFO, "Multiqueue Enabled: Tx Queue count = %u\n",
+ adapter->num_tx_queues);
#else
- adapter->num_queues = 1;
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 1;
#endif
if (e1000_alloc_queues(adapter)) {
@@ -940,17 +1097,14 @@ e1000_sw_init(struct e1000_adapter *adapter)
}
#ifdef CONFIG_E1000_NAPI
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_rx_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);
+ spin_lock_init(&adapter->tx_queue_lock);
#endif
atomic_set(&adapter->irq_sem, 1);
@@ -973,13 +1127,13 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
{
int size;
- size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+ size = sizeof(struct e1000_tx_ring) * adapter->num_tx_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;
+ size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
adapter->rx_ring = kmalloc(size, GFP_KERNEL);
if (!adapter->rx_ring) {
kfree(adapter->tx_ring);
@@ -988,7 +1142,7 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
memset(adapter->rx_ring, 0, size);
#ifdef CONFIG_E1000_NAPI
- size = sizeof(struct net_device) * adapter->num_queues;
+ size = sizeof(struct net_device) * adapter->num_rx_queues;
adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
if (!adapter->polling_netdev) {
kfree(adapter->tx_ring);
@@ -998,6 +1152,14 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
memset(adapter->polling_netdev, 0, size);
#endif
+#ifdef CONFIG_E1000_MQ
+ adapter->rx_sched_call_data.func = e1000_rx_schedule;
+ adapter->rx_sched_call_data.info = adapter->netdev;
+
+ adapter->cpu_netdev = alloc_percpu(struct net_device *);
+ adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
+#endif
+
return E1000_SUCCESS;
}
@@ -1017,14 +1179,15 @@ e1000_setup_queue_mapping(struct e1000_adapter *adapter)
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];
+ *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_tx_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) {
+ if (i < adapter->num_rx_queues) {
*per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
- adapter->cpu_for_queue[i] = cpu;
+ adapter->rx_ring[i].cpu = cpu;
+ cpu_set(cpu, adapter->cpumask);
} else
*per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
@@ -1063,14 +1226,20 @@ e1000_open(struct net_device *netdev)
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
- if((err = e1000_up(adapter)))
+ if ((err = e1000_up(adapter)))
goto err_up;
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- if((adapter->hw.mng_cookie.status &
+ if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
e1000_update_mng_vlan(adapter);
}
+ /* If AMT is enabled, let the firmware know that the network
+ * interface is now open */
+ if (adapter->hw.mac_type == e1000_82573 &&
+ e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
+
return E1000_SUCCESS;
err_up:
@@ -1105,10 +1274,17 @@ e1000_close(struct net_device *netdev)
e1000_free_all_tx_resources(adapter);
e1000_free_all_rx_resources(adapter);
- if((adapter->hw.mng_cookie.status &
+ if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
}
+
+ /* If AMT is enabled, let the firmware know that the network
+ * interface is now closed */
+ if (adapter->hw.mac_type == e1000_82573 &&
+ e1000_check_mng_mode(&adapter->hw))
+ e1000_release_hw_control(adapter);
+
return 0;
}
@@ -1153,7 +1329,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_buffer) * txdr->count;
txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
- if(!txdr->buffer_info) {
+ if (!txdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
@@ -1166,7 +1342,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
E1000_ROUNDUP(txdr->size, 4096);
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if(!txdr->desc) {
+ if (!txdr->desc) {
setup_tx_desc_die:
vfree(txdr->buffer_info);
DPRINTK(PROBE, ERR,
@@ -1182,8 +1358,8 @@ setup_tx_desc_die:
"at %p\n", txdr->size, txdr->desc);
/* Try again, without freeing the previous */
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if(!txdr->desc) {
/* Failed allocation, critical failure */
+ if (!txdr->desc) {
pci_free_consistent(pdev, txdr->size, olddesc, olddma);
goto setup_tx_desc_die;
}
@@ -1229,7 +1405,7 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_tx_queues; i++) {
err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
if (err) {
DPRINTK(PROBE, ERR,
@@ -1254,10 +1430,11 @@ e1000_configure_tx(struct e1000_adapter *adapter)
uint64_t tdba;
struct e1000_hw *hw = &adapter->hw;
uint32_t tdlen, tctl, tipg, tarc;
+ uint32_t ipgr1, ipgr2;
/* Setup the HW Tx Head and Tail descriptor pointers */
- switch (adapter->num_queues) {
+ switch (adapter->num_tx_queues) {
case 2:
tdba = adapter->tx_ring[1].dma;
tdlen = adapter->tx_ring[1].count *
@@ -1287,22 +1464,26 @@ e1000_configure_tx(struct e1000_adapter *adapter)
/* Set the default values for the Tx Inter Packet Gap timer */
+ 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;
+
switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
tipg = DEFAULT_82542_TIPG_IPGT;
- tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
- tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+ ipgr1 = DEFAULT_82542_TIPG_IPGR1;
+ ipgr2 = DEFAULT_82542_TIPG_IPGR2;
break;
default:
- 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;
+ ipgr1 = DEFAULT_82543_TIPG_IPGR1;
+ ipgr2 = DEFAULT_82543_TIPG_IPGR2;
+ break;
}
+ tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
+ tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
E1000_WRITE_REG(hw, TIPG, tipg);
/* Set the Tx Interrupt Delay register */
@@ -1378,7 +1559,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_ps_page) * rxdr->count;
rxdr->ps_page = kmalloc(size, GFP_KERNEL);
- if(!rxdr->ps_page) {
+ if (!rxdr->ps_page) {
vfree(rxdr->buffer_info);
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
@@ -1388,7 +1569,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_ps_page_dma) * rxdr->count;
rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL);
- if(!rxdr->ps_page_dma) {
+ if (!rxdr->ps_page_dma) {
vfree(rxdr->buffer_info);
kfree(rxdr->ps_page);
DPRINTK(PROBE, ERR,
@@ -1397,7 +1578,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
}
memset(rxdr->ps_page_dma, 0, size);
- if(adapter->hw.mac_type <= e1000_82547_rev_2)
+ if (adapter->hw.mac_type <= e1000_82547_rev_2)
desc_len = sizeof(struct e1000_rx_desc);
else
desc_len = sizeof(union e1000_rx_desc_packet_split);
@@ -1454,6 +1635,8 @@ setup_rx_desc_die:
rxdr->next_to_clean = 0;
rxdr->next_to_use = 0;
+ rxdr->rx_skb_top = NULL;
+ rxdr->rx_skb_prev = NULL;
return 0;
}
@@ -1475,7 +1658,7 @@ e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_rx_queues; i++) {
err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
if (err) {
DPRINTK(PROBE, ERR,
@@ -1498,7 +1681,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
{
uint32_t rctl, rfctl;
uint32_t psrctl = 0;
-#ifdef CONFIG_E1000_PACKET_SPLIT
+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
uint32_t pages = 0;
#endif
@@ -1510,7 +1693,10 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
- if(adapter->hw.tbi_compatibility_on == 1)
+ if (adapter->hw.mac_type > e1000_82543)
+ rctl |= E1000_RCTL_SECRC;
+
+ if (adapter->hw.tbi_compatibility_on == 1)
rctl |= E1000_RCTL_SBP;
else
rctl &= ~E1000_RCTL_SBP;
@@ -1521,32 +1707,17 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
rctl |= E1000_RCTL_LPE;
/* Setup buffer sizes */
- if(adapter->hw.mac_type >= e1000_82571) {
+ 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;
} else {
rctl &= ~E1000_RCTL_SZ_4096;
- rctl |= E1000_RCTL_BSEX;
- switch (adapter->rx_buffer_len) {
- case E1000_RXBUFFER_2048:
- default:
- rctl |= E1000_RCTL_SZ_2048;
- rctl &= ~E1000_RCTL_BSEX;
- break;
- case E1000_RXBUFFER_4096:
- rctl |= E1000_RCTL_SZ_4096;
- break;
- case E1000_RXBUFFER_8192:
- rctl |= E1000_RCTL_SZ_8192;
- break;
- case E1000_RXBUFFER_16384:
- rctl |= E1000_RCTL_SZ_16384;
- break;
- }
+ rctl &= ~E1000_RCTL_BSEX;
+ rctl |= E1000_RCTL_SZ_2048;
}
-#ifdef CONFIG_E1000_PACKET_SPLIT
+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
/* 82571 and greater support packet-split where the protocol
* header is placed in skb->data and the packet data is
* placed in pages hanging off of skb_shinfo(skb)->nr_frags.
@@ -1570,7 +1741,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
-
+
psrctl |= adapter->rx_ps_bsize0 >>
E1000_PSRCTL_BSIZE0_SHIFT;
@@ -1632,22 +1803,27 @@ e1000_configure_rx(struct e1000_adapter *adapter)
if (hw->mac_type >= e1000_82540) {
E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
- if(adapter->itr > 1)
+ if (adapter->itr > 1)
E1000_WRITE_REG(hw, ITR,
1000000000 / (adapter->itr * 256));
}
if (hw->mac_type >= e1000_82571) {
- /* Reset delay timers after every interrupt */
ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ /* Reset delay timers after every interrupt */
ctrl_ext |= E1000_CTRL_EXT_CANC;
+#ifdef CONFIG_E1000_NAPI
+ /* Auto-Mask interrupts upon ICR read. */
+ ctrl_ext |= E1000_CTRL_EXT_IAME;
+#endif
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ E1000_WRITE_REG(hw, IAM, ~0);
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) {
+ switch (adapter->num_rx_queues) {
#ifdef CONFIG_E1000_MQ
case 2:
rdba = adapter->rx_ring[1].dma;
@@ -1674,7 +1850,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
}
#ifdef CONFIG_E1000_MQ
- if (adapter->num_queues > 1) {
+ if (adapter->num_rx_queues > 1) {
uint32_t random[10];
get_random_bytes(&random[0], 40);
@@ -1684,7 +1860,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
E1000_WRITE_REG(hw, RSSIM, 0);
}
- switch (adapter->num_queues) {
+ switch (adapter->num_rx_queues) {
case 2:
default:
reta = 0x00800080;
@@ -1716,13 +1892,13 @@ e1000_configure_rx(struct e1000_adapter *adapter)
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
if (hw->mac_type >= e1000_82543) {
rxcsum = E1000_READ_REG(hw, RXCSUM);
- if(adapter->rx_csum == TRUE) {
+ if (adapter->rx_csum == TRUE) {
rxcsum |= E1000_RXCSUM_TUOFL;
/* Enable 82571 IPv4 payload checksum for UDP fragments
* Must be used in conjunction with packet-split. */
- if ((hw->mac_type >= e1000_82571) &&
- (adapter->rx_ps_pages)) {
+ if ((hw->mac_type >= e1000_82571) &&
+ (adapter->rx_ps_pages)) {
rxcsum |= E1000_RXCSUM_IPPCSE;
}
} else {
@@ -1776,7 +1952,7 @@ e1000_free_all_tx_resources(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
}
@@ -1784,17 +1960,15 @@ static inline void
e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info)
{
- if(buffer_info->dma) {
+ if (buffer_info->dma) {
pci_unmap_page(adapter->pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_TODEVICE);
- buffer_info->dma = 0;
}
- if(buffer_info->skb) {
+ if (buffer_info->skb)
dev_kfree_skb_any(buffer_info->skb);
- buffer_info->skb = NULL;
- }
+ memset(buffer_info, 0, sizeof(struct e1000_buffer));
}
/**
@@ -1813,7 +1987,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
/* Free all the Tx ring sk_buffs */
- for(i = 0; i < tx_ring->count; i++) {
+ for (i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
}
@@ -1843,7 +2017,7 @@ e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
}
@@ -1887,7 +2061,7 @@ e1000_free_all_rx_resources(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
}
@@ -1909,12 +2083,9 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
unsigned int i, j;
/* Free all the Rx ring sk_buffs */
-
- for(i = 0; i < rx_ring->count; i++) {
+ for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
- if(buffer_info->skb) {
- ps_page = &rx_ring->ps_page[i];
- ps_page_dma = &rx_ring->ps_page_dma[i];
+ if (buffer_info->skb) {
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
@@ -1922,19 +2093,30 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
-
- 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],
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
- ps_page_dma->ps_page_dma[j] = 0;
- put_page(ps_page->ps_page[j]);
- ps_page->ps_page[j] = NULL;
- }
}
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+ for (j = 0; j < adapter->rx_ps_pages; j++) {
+ if (!ps_page->ps_page[j]) break;
+ pci_unmap_page(pdev,
+ ps_page_dma->ps_page_dma[j],
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ ps_page_dma->ps_page_dma[j] = 0;
+ put_page(ps_page->ps_page[j]);
+ ps_page->ps_page[j] = NULL;
+ }
+ }
+
+ /* there also may be some cached data in our adapter */
+ if (rx_ring->rx_skb_top) {
+ dev_kfree_skb(rx_ring->rx_skb_top);
+
+ /* rx_skb_prev will be wiped out by rx_skb_top */
+ rx_ring->rx_skb_top = NULL;
+ rx_ring->rx_skb_prev = NULL;
}
+
size = sizeof(struct e1000_buffer) * rx_ring->count;
memset(rx_ring->buffer_info, 0, size);
size = sizeof(struct e1000_ps_page) * rx_ring->count;
@@ -1963,7 +2145,7 @@ e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
}
@@ -1984,7 +2166,7 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter)
E1000_WRITE_FLUSH(&adapter->hw);
mdelay(5);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_clean_all_rx_rings(adapter);
}
@@ -2000,12 +2182,14 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
E1000_WRITE_FLUSH(&adapter->hw);
mdelay(5);
- if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
+ if (adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
e1000_pci_set_mwi(&adapter->hw);
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
+ /* No need to loop, because 82542 supports only 1 queue */
+ struct e1000_rx_ring *ring = &adapter->rx_ring[0];
e1000_configure_rx(adapter);
- e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
+ adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
}
}
@@ -2023,12 +2207,12 @@ e1000_set_mac(struct net_device *netdev, void *p)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
- if(!is_valid_ether_addr(addr->sa_data))
+ if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
/* 82542 2.0 needs to be in reset to write receive address registers */
- if(adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter);
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -2042,17 +2226,17 @@ e1000_set_mac(struct net_device *netdev, void *p)
/* 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
+ /* 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
+ * are dropped. Eventaully the LAA will be in RAR[0] and
* RAR[14] */
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
+ e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
E1000_RAR_ENTRIES - 1);
}
- if(adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
return 0;
@@ -2086,9 +2270,9 @@ e1000_set_multi(struct net_device *netdev)
rctl = E1000_READ_REG(hw, RCTL);
- if(netdev->flags & IFF_PROMISC) {
+ if (netdev->flags & IFF_PROMISC) {
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
- } else if(netdev->flags & IFF_ALLMULTI) {
+ } else if (netdev->flags & IFF_ALLMULTI) {
rctl |= E1000_RCTL_MPE;
rctl &= ~E1000_RCTL_UPE;
} else {
@@ -2099,7 +2283,7 @@ e1000_set_multi(struct net_device *netdev)
/* 82542 2.0 needs to be in reset to write receive address registers */
- if(hw->mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter);
/* load the first 14 multicast address into the exact filters 1-14
@@ -2109,7 +2293,7 @@ e1000_set_multi(struct net_device *netdev)
*/
mc_ptr = netdev->mc_list;
- for(i = 1; i < rar_entries; i++) {
+ for (i = 1; i < rar_entries; i++) {
if (mc_ptr) {
e1000_rar_set(hw, mc_ptr->dmi_addr, i);
mc_ptr = mc_ptr->next;
@@ -2121,17 +2305,17 @@ e1000_set_multi(struct net_device *netdev)
/* clear the old settings from the multicast hash table */
- for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
+ for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* load any remaining addresses into the hash table */
- for(; mc_ptr; mc_ptr = mc_ptr->next) {
+ for (; mc_ptr; mc_ptr = mc_ptr->next) {
hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr);
e1000_mta_set(hw, hash_value);
}
- if(hw->mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
}
@@ -2157,8 +2341,8 @@ e1000_82547_tx_fifo_stall(unsigned long data)
struct net_device *netdev = adapter->netdev;
uint32_t tctl;
- if(atomic_read(&adapter->tx_fifo_stall)) {
- if((E1000_READ_REG(&adapter->hw, TDT) ==
+ if (atomic_read(&adapter->tx_fifo_stall)) {
+ if ((E1000_READ_REG(&adapter->hw, TDT) ==
E1000_READ_REG(&adapter->hw, TDH)) &&
(E1000_READ_REG(&adapter->hw, TDFT) ==
E1000_READ_REG(&adapter->hw, TDFH)) &&
@@ -2204,24 +2388,24 @@ static void
e1000_watchdog_task(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
+ struct e1000_tx_ring *txdr = adapter->tx_ring;
uint32_t link;
e1000_check_for_link(&adapter->hw);
if (adapter->hw.mac_type == e1000_82573) {
e1000_enable_tx_pkt_filtering(&adapter->hw);
- if(adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+ if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
e1000_update_mng_vlan(adapter);
- }
+ }
- if((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
+ if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
!(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
link = !adapter->hw.serdes_link_down;
else
link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
- if(link) {
- if(!netif_carrier_ok(netdev)) {
+ if (link) {
+ if (!netif_carrier_ok(netdev)) {
e1000_get_speed_and_duplex(&adapter->hw,
&adapter->link_speed,
&adapter->link_duplex);
@@ -2231,13 +2415,28 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
adapter->link_duplex == FULL_DUPLEX ?
"Full Duplex" : "Half Duplex");
+ /* tweak tx_queue_len according to speed/duplex */
+ netdev->tx_queue_len = adapter->tx_queue_len;
+ adapter->tx_timeout_factor = 1;
+ if (adapter->link_duplex == HALF_DUPLEX) {
+ switch (adapter->link_speed) {
+ case SPEED_10:
+ netdev->tx_queue_len = 10;
+ adapter->tx_timeout_factor = 8;
+ break;
+ case SPEED_100:
+ netdev->tx_queue_len = 100;
+ break;
+ }
+ }
+
netif_carrier_on(netdev);
netif_wake_queue(netdev);
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
adapter->smartspeed = 0;
}
} else {
- if(netif_carrier_ok(netdev)) {
+ if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
DPRINTK(LINK, INFO, "NIC Link is Down\n");
@@ -2263,7 +2462,10 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
e1000_update_adaptive(&adapter->hw);
- if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
+#ifdef CONFIG_E1000_MQ
+ txdr = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+#endif
+ if (!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
@@ -2274,12 +2476,12 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
}
/* Dynamic mode for Interrupt Throttle Rate (ITR) */
- if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
+ if (adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
/* Symmetric Tx/Rx gets a reduced ITR=2000; Total
* asymmetrical Tx or Rx gets ITR=8000; everyone
* else is between 2000-8000. */
uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000;
- uint32_t dif = (adapter->gotcl > adapter->gorcl ?
+ uint32_t dif = (adapter->gotcl > adapter->gorcl ?
adapter->gotcl - adapter->gorcl :
adapter->gorcl - adapter->gotcl) / 10000;
uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
@@ -2292,7 +2494,7 @@ 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
+ /* 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);
@@ -2314,13 +2516,14 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
{
#ifdef NETIF_F_TSO
struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
unsigned int i;
uint32_t cmd_length = 0;
uint16_t ipcse = 0, tucse, mss;
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
int err;
- if(skb_shinfo(skb)->tso_size) {
+ if (skb_shinfo(skb)->tso_size) {
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
@@ -2329,7 +2532,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
- if(skb->protocol == ntohs(ETH_P_IP)) {
+ if (skb->protocol == ntohs(ETH_P_IP)) {
skb->nh.iph->tot_len = 0;
skb->nh.iph->check = 0;
skb->h.th->check =
@@ -2341,7 +2544,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
cmd_length = E1000_TXD_CMD_IP;
ipcse = skb->h.raw - skb->data - 1;
#ifdef NETIF_F_TSO_IPV6
- } else if(skb->protocol == ntohs(ETH_P_IPV6)) {
+ } else if (skb->protocol == ntohs(ETH_P_IPV6)) {
skb->nh.ipv6h->payload_len = 0;
skb->h.th->check =
~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -2363,6 +2566,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
i = tx_ring->next_to_use;
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+ buffer_info = &tx_ring->buffer_info[i];
context_desc->lower_setup.ip_fields.ipcss = ipcss;
context_desc->lower_setup.ip_fields.ipcso = ipcso;
@@ -2374,14 +2578,16 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
context_desc->cmd_and_length = cpu_to_le32(cmd_length);
+ buffer_info->time_stamp = jiffies;
+
if (++i == tx_ring->count) i = 0;
tx_ring->next_to_use = i;
- return 1;
+ return TRUE;
}
#endif
- return 0;
+ return FALSE;
}
static inline boolean_t
@@ -2389,13 +2595,15 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
unsigned int i;
uint8_t css;
- if(likely(skb->ip_summed == CHECKSUM_HW)) {
+ if (likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
i = tx_ring->next_to_use;
+ buffer_info = &tx_ring->buffer_info[i];
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->upper_setup.tcp_fields.tucss = css;
@@ -2404,6 +2612,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
+ buffer_info->time_stamp = jiffies;
+
if (unlikely(++i == tx_ring->count)) i = 0;
tx_ring->next_to_use = i;
@@ -2429,7 +2639,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
i = tx_ring->next_to_use;
- while(len) {
+ while (len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
@@ -2445,7 +2655,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
- if(unlikely(mss && !nr_frags && size == len && size > 8))
+ if (unlikely(mss && !nr_frags && size == len && size > 8))
size -= 4;
#endif
/* work-around for errata 10 and it applies
@@ -2453,13 +2663,13 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
* The fix is to make sure that the first descriptor of a
* packet is smaller than 2048 - 16 - 16 (or 2016) bytes
*/
- if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
(size > 2015) && count == 0))
size = 2015;
-
+
/* Workaround for potential 82544 hang in PCI-X. Avoid
* terminating buffers within evenly-aligned dwords. */
- if(unlikely(adapter->pcix_82544 &&
+ if (unlikely(adapter->pcix_82544 &&
!((unsigned long)(skb->data + offset + size - 1) & 4) &&
size > 4))
size -= 4;
@@ -2475,29 +2685,29 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
len -= size;
offset += size;
count++;
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
- for(f = 0; f < nr_frags; f++) {
+ for (f = 0; f < nr_frags; f++) {
struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
offset = frag->page_offset;
- while(len) {
+ while (len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
- if(unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
+ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
size -= 4;
#endif
/* Workaround for potential 82544 hang in PCI-X.
* Avoid terminating buffers within evenly-aligned
* dwords. */
- if(unlikely(adapter->pcix_82544 &&
+ if (unlikely(adapter->pcix_82544 &&
!((unsigned long)(frag->page+offset+size-1) & 4) &&
size > 4))
size -= 4;
@@ -2514,7 +2724,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
len -= size;
offset += size;
count++;
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
}
@@ -2534,35 +2744,35 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
unsigned int i;
- if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
+ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
E1000_TXD_CMD_TSE;
txd_upper |= E1000_TXD_POPTS_TXSM << 8;
- if(likely(tx_flags & E1000_TX_FLAGS_IPV4))
+ if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
txd_upper |= E1000_TXD_POPTS_IXSM << 8;
}
- if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
+ if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
txd_upper |= E1000_TXD_POPTS_TXSM << 8;
}
- if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
+ if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
txd_lower |= E1000_TXD_CMD_VLE;
txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
}
i = tx_ring->next_to_use;
- while(count--) {
+ while (count--) {
buffer_info = &tx_ring->buffer_info[i];
tx_desc = E1000_TX_DESC(*tx_ring, i);
tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
tx_desc->lower.data =
cpu_to_le32(txd_lower | buffer_info->length);
tx_desc->upper.data = cpu_to_le32(txd_upper);
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
@@ -2597,20 +2807,20 @@ e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR);
- if(adapter->link_duplex != HALF_DUPLEX)
+ if (adapter->link_duplex != HALF_DUPLEX)
goto no_fifo_stall_required;
- if(atomic_read(&adapter->tx_fifo_stall))
+ if (atomic_read(&adapter->tx_fifo_stall))
return 1;
- if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
+ if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
atomic_set(&adapter->tx_fifo_stall, 1);
return 1;
}
no_fifo_stall_required:
adapter->tx_fifo_head += skb_fifo_len;
- if(adapter->tx_fifo_head >= adapter->tx_fifo_size)
+ if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
adapter->tx_fifo_head -= adapter->tx_fifo_size;
return 0;
}
@@ -2621,27 +2831,27 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
{
struct e1000_hw *hw = &adapter->hw;
uint16_t length, offset;
- if(vlan_tx_tag_present(skb)) {
- if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+ if (vlan_tx_tag_present(skb)) {
+ if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
( adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
return 0;
}
- if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+ if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
struct ethhdr *eth = (struct ethhdr *) skb->data;
- if((htons(ETH_P_IP) == eth->h_proto)) {
- const struct iphdr *ip =
+ if ((htons(ETH_P_IP) == eth->h_proto)) {
+ const struct iphdr *ip =
(struct iphdr *)((uint8_t *)skb->data+14);
- if(IPPROTO_UDP == ip->protocol) {
- struct udphdr *udp =
- (struct udphdr *)((uint8_t *)ip +
+ if (IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp =
+ (struct udphdr *)((uint8_t *)ip +
(ip->ihl << 2));
- if(ntohs(udp->dest) == 67) {
+ if (ntohs(udp->dest) == 67) {
offset = (uint8_t *)udp + 8 - skb->data;
length = skb->len - offset;
return e1000_mng_write_dhcp_info(hw,
- (uint8_t *)udp + 8,
+ (uint8_t *)udp + 8,
length);
}
}
@@ -2664,7 +2874,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned int nr_frags = 0;
unsigned int mss = 0;
int count = 0;
- int tso;
+ int tso;
unsigned int f;
len -= skb->data_len;
@@ -2687,16 +2897,35 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* 4 = ceil(buffer len/mss). To make sure we don't
* overrun the FIFO, adjust the max buffer len if mss
* drops. */
- if(mss) {
+ if (mss) {
+ uint8_t hdr_len;
max_per_txd = min(mss << 2, max_per_txd);
max_txd_pwr = fls(max_per_txd) - 1;
+
+ /* TSO Workaround for 82571/2 Controllers -- if skb->data
+ * points to just header, pull a few bytes of payload from
+ * frags into skb->data */
+ 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;
+ }
+ len = skb->len - skb->data_len;
+ }
}
- if((mss) || (skb->ip_summed == CHECKSUM_HW))
+ /* reserve a descriptor for the offload context */
+ if ((mss) || (skb->ip_summed == CHECKSUM_HW))
count++;
count++;
#else
- if(skb->ip_summed == CHECKSUM_HW)
+ if (skb->ip_summed == CHECKSUM_HW)
count++;
#endif
@@ -2709,45 +2938,24 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
count += TXD_USE_COUNT(len, max_txd_pwr);
- if(adapter->pcix_82544)
+ if (adapter->pcix_82544)
count++;
- /* work-around for errata 10 and it applies to all controllers
+ /* work-around for errata 10 and it applies to all controllers
* in PCI-X mode, so add one more descriptor to the count
*/
- if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
(len > 2015)))
count++;
nr_frags = skb_shinfo(skb)->nr_frags;
- for(f = 0; f < nr_frags; f++)
+ for (f = 0; f < nr_frags; f++)
count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
max_txd_pwr);
- if(adapter->pcix_82544)
+ if (adapter->pcix_82544)
count += nr_frags;
-#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) )
+ if (adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
e1000_transfer_dhcp_info(adapter, skb);
local_irq_save(flags);
@@ -2765,8 +2973,8 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY;
}
- if(unlikely(adapter->hw.mac_type == e1000_82547)) {
- if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
+ if (unlikely(adapter->hw.mac_type == e1000_82547)) {
+ if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
@@ -2774,13 +2982,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
}
- if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
tx_flags |= E1000_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
first = tx_ring->next_to_use;
-
+
tso = e1000_tso(adapter, tx_ring, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
@@ -2833,6 +3041,7 @@ e1000_tx_timeout_task(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ adapter->tx_timeout_count++;
e1000_down(adapter);
e1000_up(adapter);
}
@@ -2850,7 +3059,7 @@ e1000_get_stats(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- e1000_update_stats(adapter);
+ /* only return the current stats */
return &adapter->net_stats;
}
@@ -2868,56 +3077,57 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
struct e1000_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
- if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
- return -EINVAL;
- }
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
- /* might want this to be bigger enum check... */
- /* 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");
+ if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
return -EINVAL;
}
- if(adapter->hw.mac_type > e1000_82547_rev_2) {
- adapter->rx_buffer_len = max_frame;
- E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
- } else {
- if(unlikely((adapter->hw.mac_type < e1000_82543) &&
- (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
- DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
- "on 82542\n");
+ /* Adapter-specific max frame size limits. */
+ switch (adapter->hw.mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82573:
+ if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
+ return -EINVAL;
+ }
+ break;
+ case e1000_82571:
+ case e1000_82572:
+#define MAX_STD_JUMBO_FRAME_SIZE 9234
+ if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n");
return -EINVAL;
-
- } else {
- if(max_frame <= E1000_RXBUFFER_2048) {
- adapter->rx_buffer_len = E1000_RXBUFFER_2048;
- } else if(max_frame <= E1000_RXBUFFER_4096) {
- adapter->rx_buffer_len = E1000_RXBUFFER_4096;
- } else if(max_frame <= E1000_RXBUFFER_8192) {
- adapter->rx_buffer_len = E1000_RXBUFFER_8192;
- } else if(max_frame <= E1000_RXBUFFER_16384) {
- adapter->rx_buffer_len = E1000_RXBUFFER_16384;
- }
}
+ break;
+ default:
+ /* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
+ break;
}
+ /* since the driver code now supports splitting a packet across
+ * multiple descriptors, most of the fifo related limitations on
+ * jumbo frame traffic have gone away.
+ * simply use 2k descriptors for everything.
+ *
+ * NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+ * means we reserve 2 more, this pushes us to allocate from the next
+ * larger slab size
+ * i.e. RXBUFFER_2048 --> size-4096 slab */
+
+ /* recent hardware supports 1KB granularity */
+ if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ adapter->rx_buffer_len =
+ ((max_frame < E1000_RXBUFFER_2048) ?
+ max_frame : E1000_RXBUFFER_2048);
+ E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
+ } else
+ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+
netdev->mtu = new_mtu;
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
}
@@ -3004,7 +3214,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
hw->collision_delta = E1000_READ_REG(hw, COLC);
adapter->stats.colc += hw->collision_delta;
- if(hw->mac_type >= e1000_82543) {
+ if (hw->mac_type >= e1000_82543) {
adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
@@ -3012,7 +3222,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
}
- if(hw->mac_type > e1000_82547_rev_2) {
+ if (hw->mac_type > e1000_82547_rev_2) {
adapter->stats.iac += E1000_READ_REG(hw, IAC);
adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
@@ -3037,12 +3247,11 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->net_stats.rx_errors = adapter->stats.rxerrc +
adapter->stats.crcerrs + adapter->stats.algnerrc +
- adapter->stats.rlec + adapter->stats.mpc +
- adapter->stats.cexterr;
+ adapter->stats.rlec + adapter->stats.cexterr;
+ adapter->net_stats.rx_dropped = 0;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
- adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
/* Tx Errors */
@@ -3057,14 +3266,14 @@ e1000_update_stats(struct e1000_adapter *adapter)
/* Phy Stats */
- if(hw->media_type == e1000_media_type_copper) {
- if((adapter->link_speed == SPEED_1000) &&
+ if (hw->media_type == e1000_media_type_copper) {
+ if ((adapter->link_speed == SPEED_1000) &&
(!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
adapter->phy_stats.idle_errors += phy_tmp;
}
- if((hw->mac_type <= e1000_82546) &&
+ if ((hw->mac_type <= e1000_82546) &&
(hw->phy_type == e1000_phy_m88) &&
!e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
adapter->phy_stats.receive_errors += phy_tmp;
@@ -3110,32 +3319,44 @@ 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);
-#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
+#ifndef CONFIG_E1000_NAPI
int i;
+#else
+ /* Interrupt Auto-Mask...upon reading ICR,
+ * interrupts are masked. No need for the
+ * IMC write, but it does mean we should
+ * account for it ASAP. */
+ if (likely(hw->mac_type >= e1000_82571))
+ atomic_inc(&adapter->irq_sem);
#endif
- if(unlikely(!icr))
+ if (unlikely(!icr)) {
+#ifdef CONFIG_E1000_NAPI
+ if (hw->mac_type >= e1000_82571)
+ e1000_irq_enable(adapter);
+#endif
return IRQ_NONE; /* Not our interrupt */
+ }
- if(unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
+ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
hw->get_link_status = 1;
mod_timer(&adapter->watchdog_timer, jiffies);
}
#ifdef CONFIG_E1000_NAPI
- atomic_inc(&adapter->irq_sem);
- E1000_WRITE_REG(hw, IMC, ~0);
- E1000_WRITE_FLUSH(hw);
+ if (unlikely(hw->mac_type < e1000_82571)) {
+ 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);
+ /* We must setup the cpumask once count == 0 since
+ * each cpu bit is cleared when the work is done. */
+ adapter->rx_sched_call_data.cpumask = adapter->cpumask;
+ atomic_add(adapter->num_rx_queues - 1, &adapter->irq_sem);
+ atomic_set(&adapter->rx_sched_call_data.count,
+ adapter->num_rx_queues);
smp_call_async_mask(&adapter->rx_sched_call_data);
} else {
printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
@@ -3149,26 +3370,26 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
#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.
- When an interrupt assertion message is generated later,
- two messages are re-ordered and sent out.
- That causes APIC to think 82547 is in de-assertion
- state, while 82547 is in assertion state, resulting
- in dead lock. Writing IMC forces 82547 into
- de-assertion state.
- */
- if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){
+ * Due to Hub Link bus being occupied, an interrupt
+ * de-assertion message is not able to be sent.
+ * When an interrupt assertion message is generated later,
+ * two messages are re-ordered and sent out.
+ * That causes APIC to think 82547 is in de-assertion
+ * state, while 82547 is in assertion state, resulting
+ * in dead lock. Writing IMC forces 82547 into
+ * de-assertion state.
+ */
+ if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) {
atomic_inc(&adapter->irq_sem);
E1000_WRITE_REG(hw, IMC, ~0);
}
- for(i = 0; i < E1000_MAX_INTR; i++)
- if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+ for (i = 0; i < E1000_MAX_INTR; i++)
+ 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)
+ if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
e1000_irq_enable(adapter);
#endif /* CONFIG_E1000_NAPI */
@@ -3187,7 +3408,7 @@ e1000_clean(struct net_device *poll_dev, int *budget)
{
struct e1000_adapter *adapter;
int work_to_do = min(*budget, poll_dev->quota);
- int tx_cleaned, i = 0, work_done = 0;
+ int tx_cleaned = 0, i = 0, work_done = 0;
/* Must NOT use netdev_priv macro here. */
adapter = poll_dev->priv;
@@ -3198,19 +3419,31 @@ e1000_clean(struct net_device *poll_dev, int *budget)
while (poll_dev != &adapter->polling_netdev[i]) {
i++;
- if (unlikely(i == adapter->num_queues))
+ if (unlikely(i == adapter->num_rx_queues))
BUG();
}
- tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+ if (likely(adapter->num_tx_queues == 1)) {
+ /* e1000_clean is called per-cpu. This lock protects
+ * tx_ring[0] from being cleaned by multiple cpus
+ * simultaneously. A failure obtaining the lock means
+ * tx_ring[0] is currently being cleaned anyway. */
+ if (spin_trylock(&adapter->tx_queue_lock)) {
+ tx_cleaned = e1000_clean_tx_irq(adapter,
+ &adapter->tx_ring[0]);
+ spin_unlock(&adapter->tx_queue_lock);
+ }
+ } else
+ 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;
poll_dev->quota -= work_done;
-
+
/* If no Tx and not enough Rx work done, exit the polling mode */
- if((!tx_cleaned && (work_done == 0)) ||
+ if ((!tx_cleaned && (work_done == 0)) ||
!netif_running(adapter->netdev)) {
quit_polling:
netif_rx_complete(poll_dev);
@@ -3242,22 +3475,24 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
eop_desc = E1000_TX_DESC(*tx_ring, eop);
while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
- for(cleaned = FALSE; !cleaned; ) {
+ for (cleaned = FALSE; !cleaned; ) {
tx_desc = E1000_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
cleaned = (i == eop);
+#ifdef CONFIG_E1000_MQ
+ tx_ring->tx_stats.bytes += buffer_info->length;
+#endif
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
+ memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
- tx_desc->buffer_addr = 0;
- tx_desc->lower.data = 0;
- tx_desc->upper.data = 0;
-
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
- tx_ring->pkt++;
-
+#ifdef CONFIG_E1000_MQ
+ tx_ring->tx_stats.packets++;
+#endif
+
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
}
@@ -3266,7 +3501,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
spin_lock(&tx_ring->tx_lock);
- if(unlikely(cleaned && netif_queue_stopped(netdev) &&
+ if (unlikely(cleaned && netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev)))
netif_wake_queue(netdev);
@@ -3276,32 +3511,31 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
/* 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;
- if (tx_ring->buffer_info[i].dma &&
- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+ if (tx_ring->buffer_info[eop].dma &&
+ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
+ adapter->tx_timeout_factor * HZ)
&& !(E1000_READ_REG(&adapter->hw, STATUS) &
- E1000_STATUS_TXOFF)) {
+ E1000_STATUS_TXOFF)) {
/* detected Tx unit hang */
- i = tx_ring->next_to_clean;
- eop = tx_ring->buffer_info[i].next_to_watch;
- eop_desc = E1000_TX_DESC(*tx_ring, eop);
DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+ " Tx Queue <%lu>\n"
" TDH <%x>\n"
" TDT <%x>\n"
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n"
- " dma <%llx>\n"
" time_stamp <%lx>\n"
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
" next_to_watch.status <%x>\n",
+ (unsigned long)((tx_ring - adapter->tx_ring) /
+ sizeof(struct e1000_tx_ring)),
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,
- tx_ring->buffer_info[i].time_stamp,
+ tx_ring->next_to_clean,
+ tx_ring->buffer_info[eop].time_stamp,
eop,
jiffies,
eop_desc->upper.fields.status);
@@ -3329,21 +3563,21 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
skb->ip_summed = CHECKSUM_NONE;
/* 82543 or newer only */
- if(unlikely(adapter->hw.mac_type < e1000_82543)) return;
+ if (unlikely(adapter->hw.mac_type < e1000_82543)) return;
/* Ignore Checksum bit is set */
- if(unlikely(status & E1000_RXD_STAT_IXSM)) return;
+ if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
/* TCP/UDP checksum error bit is set */
- if(unlikely(errors & E1000_RXD_ERR_TCPE)) {
+ if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
/* let the stack verify checksum errors */
adapter->hw_csum_err++;
return;
}
/* TCP/UDP Checksum has not been calculated */
- if(adapter->hw.mac_type <= e1000_82547_rev_2) {
- if(!(status & E1000_RXD_STAT_TCPCS))
+ if (adapter->hw.mac_type <= e1000_82547_rev_2) {
+ if (!(status & E1000_RXD_STAT_TCPCS))
return;
} else {
- if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
+ if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
return;
}
/* It must be a TCP or UDP packet with a valid checksum */
@@ -3379,46 +3613,87 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_rx_desc *rx_desc;
- struct e1000_buffer *buffer_info;
- struct sk_buff *skb;
+ struct e1000_rx_desc *rx_desc, *next_rxd;
+ struct e1000_buffer *buffer_info, *next_buffer;
unsigned long flags;
uint32_t length;
uint8_t last_byte;
unsigned int i;
- boolean_t cleaned = FALSE;
+ int cleaned_count = 0;
+ boolean_t cleaned = FALSE, multi_descriptor = FALSE;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i);
+ buffer_info = &rx_ring->buffer_info[i];
- while(rx_desc->status & E1000_RXD_STAT_DD) {
- buffer_info = &rx_ring->buffer_info[i];
+ while (rx_desc->status & E1000_RXD_STAT_DD) {
+ struct sk_buff *skb, *next_skb;
+ u8 status;
#ifdef CONFIG_E1000_NAPI
- if(*work_done >= work_to_do)
+ if (*work_done >= work_to_do)
break;
(*work_done)++;
#endif
- cleaned = TRUE;
+ status = rx_desc->status;
+ skb = buffer_info->skb;
+ buffer_info->skb = NULL;
+
+ if (++i == rx_ring->count) i = 0;
+ next_rxd = E1000_RX_DESC(*rx_ring, i);
+ next_buffer = &rx_ring->buffer_info[i];
+ next_skb = next_buffer->skb;
+ cleaned = TRUE;
+ cleaned_count++;
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_FROMDEVICE);
- skb = buffer_info->skb;
length = le16_to_cpu(rx_desc->length);
- if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
- /* All receives must fit into a single buffer */
- E1000_DBG("%s: Receive packet consumed multiple"
- " buffers\n", netdev->name);
- dev_kfree_skb_irq(skb);
+ skb_put(skb, length);
+
+ if (!(status & E1000_RXD_STAT_EOP)) {
+ if (!rx_ring->rx_skb_top) {
+ rx_ring->rx_skb_top = skb;
+ rx_ring->rx_skb_top->len = length;
+ rx_ring->rx_skb_prev = skb;
+ } else {
+ if (skb_shinfo(rx_ring->rx_skb_top)->frag_list) {
+ rx_ring->rx_skb_prev->next = skb;
+ skb->prev = rx_ring->rx_skb_prev;
+ } else {
+ skb_shinfo(rx_ring->rx_skb_top)->frag_list = skb;
+ }
+ rx_ring->rx_skb_prev = skb;
+ rx_ring->rx_skb_top->data_len += length;
+ }
goto next_desc;
+ } else {
+ if (rx_ring->rx_skb_top) {
+ if (skb_shinfo(rx_ring->rx_skb_top)
+ ->frag_list) {
+ rx_ring->rx_skb_prev->next = skb;
+ skb->prev = rx_ring->rx_skb_prev;
+ } else
+ skb_shinfo(rx_ring->rx_skb_top)
+ ->frag_list = skb;
+
+ rx_ring->rx_skb_top->data_len += length;
+ rx_ring->rx_skb_top->len +=
+ rx_ring->rx_skb_top->data_len;
+
+ skb = rx_ring->rx_skb_top;
+ multi_descriptor = TRUE;
+ rx_ring->rx_skb_top = NULL;
+ rx_ring->rx_skb_prev = NULL;
+ }
}
- if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
+ if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
last_byte = *(skb->data + length - 1);
- if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
+ if (TBI_ACCEPT(&adapter->hw, status,
rx_desc->errors, length, last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
e1000_tbi_adjust_stats(&adapter->hw,
@@ -3433,18 +3708,41 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
}
- /* Good Receive */
- skb_put(skb, length - ETHERNET_FCS_SIZE);
+ /* code added for copybreak, this should improve
+ * performance for small packets with large amounts
+ * of reassembly being done in the stack */
+#define E1000_CB_LENGTH 256
+ if ((length < E1000_CB_LENGTH) &&
+ !rx_ring->rx_skb_top &&
+ /* or maybe (status & E1000_RXD_STAT_EOP) && */
+ !multi_descriptor) {
+ struct sk_buff *new_skb =
+ dev_alloc_skb(length + NET_IP_ALIGN);
+ if (new_skb) {
+ skb_reserve(new_skb, NET_IP_ALIGN);
+ new_skb->dev = netdev;
+ memcpy(new_skb->data - NET_IP_ALIGN,
+ skb->data - NET_IP_ALIGN,
+ length + NET_IP_ALIGN);
+ /* save the skb in buffer_info as good */
+ buffer_info->skb = skb;
+ skb = new_skb;
+ skb_put(skb, length);
+ }
+ }
+
+ /* end copybreak code */
/* Receive Checksum Offload */
e1000_rx_checksum(adapter,
- (uint32_t)(rx_desc->status) |
+ (uint32_t)(status) |
((uint32_t)(rx_desc->errors) << 24),
rx_desc->csum, skb);
+
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_E1000_NAPI
- if(unlikely(adapter->vlgrp &&
- (rx_desc->status & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp &&
+ (status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->special) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3452,8 +3750,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
- if(unlikely(adapter->vlgrp &&
- (rx_desc->status & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp &&
+ (status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->special) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3462,17 +3760,28 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
+#ifdef CONFIG_E1000_MQ
+ rx_ring->rx_stats.packets++;
+ rx_ring->rx_stats.bytes += length;
+#endif
next_desc:
rx_desc->status = 0;
- buffer_info->skb = NULL;
- if(unlikely(++i == rx_ring->count)) i = 0;
- rx_desc = E1000_RX_DESC(*rx_ring, i);
+ /* return some buffers to hardware, one at a time is too slow */
+ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ cleaned_count = 0;
+ }
+
+ rx_desc = next_rxd;
+ buffer_info = next_buffer;
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter, rx_ring);
+
+ cleaned_count = E1000_DESC_UNUSED(rx_ring);
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
return cleaned;
}
@@ -3492,52 +3801,59 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring)
#endif
{
- union e1000_rx_desc_packet_split *rx_desc;
+ union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_buffer *buffer_info;
+ struct e1000_buffer *buffer_info, *next_buffer;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
- struct sk_buff *skb;
+ struct sk_buff *skb, *next_skb;
unsigned int i, j;
uint32_t length, staterr;
+ int cleaned_count = 0;
boolean_t cleaned = FALSE;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+ buffer_info = &rx_ring->buffer_info[i];
- while(staterr & E1000_RXD_STAT_DD) {
- buffer_info = &rx_ring->buffer_info[i];
+ while (staterr & E1000_RXD_STAT_DD) {
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
#ifdef CONFIG_E1000_NAPI
- if(unlikely(*work_done >= work_to_do))
+ if (unlikely(*work_done >= work_to_do))
break;
(*work_done)++;
#endif
+ skb = buffer_info->skb;
+
+ if (++i == rx_ring->count) i = 0;
+ next_rxd = E1000_RX_DESC_PS(*rx_ring, i);
+ next_buffer = &rx_ring->buffer_info[i];
+ next_skb = next_buffer->skb;
+
cleaned = TRUE;
+ cleaned_count++;
pci_unmap_single(pdev, buffer_info->dma,
buffer_info->length,
PCI_DMA_FROMDEVICE);
- skb = buffer_info->skb;
-
- if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
+ if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
E1000_DBG("%s: Packet Split buffers didn't pick up"
" the full packet\n", netdev->name);
dev_kfree_skb_irq(skb);
goto next_desc;
}
- if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+ if (unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
dev_kfree_skb_irq(skb);
goto next_desc;
}
length = le16_to_cpu(rx_desc->wb.middle.length0);
- if(unlikely(!length)) {
+ if (unlikely(!length)) {
E1000_DBG("%s: Last part of the packet spanning"
" multiple descriptors\n", netdev->name);
dev_kfree_skb_irq(skb);
@@ -3547,8 +3863,8 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
/* Good Receive */
skb_put(skb, length);
- for(j = 0; j < adapter->rx_ps_pages; j++) {
- if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
+ for (j = 0; j < adapter->rx_ps_pages; j++) {
+ if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
break;
pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
@@ -3568,15 +3884,11 @@ 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);
- if(likely(rx_desc->wb.upper.header_status &
- E1000_RXDPS_HDRSTAT_HDRSP)) {
+ if (likely(rx_desc->wb.upper.header_status &
+ 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))) {
+ if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->wb.middle.vlan) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3584,7 +3896,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->wb.middle.vlan) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3593,18 +3905,31 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
+#ifdef CONFIG_E1000_MQ
+ rx_ring->rx_stats.packets++;
+ rx_ring->rx_stats.bytes += length;
+#endif
next_desc:
rx_desc->wb.middle.status_error &= ~0xFF;
buffer_info->skb = NULL;
- if(unlikely(++i == rx_ring->count)) i = 0;
- rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+ /* return some buffers to hardware, one at a time is too slow */
+ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ cleaned_count = 0;
+ }
+
+ rx_desc = next_rxd;
+ buffer_info = next_buffer;
+
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter, rx_ring);
+
+ cleaned_count = E1000_DESC_UNUSED(rx_ring);
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
return cleaned;
}
@@ -3616,7 +3941,8 @@ next_desc:
static void
e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3629,11 +3955,18 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
i = rx_ring->next_to_use;
buffer_info = &rx_ring->buffer_info[i];
- while(!buffer_info->skb) {
- skb = dev_alloc_skb(bufsz);
+ while (cleaned_count--) {
+ if (!(skb = buffer_info->skb))
+ skb = dev_alloc_skb(bufsz);
+ else {
+ skb_trim(skb, 0);
+ goto map_skb;
+ }
+
- if(unlikely(!skb)) {
+ if (unlikely(!skb)) {
/* Better luck next round */
+ adapter->alloc_rx_buff_failed++;
break;
}
@@ -3670,6 +4003,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
buffer_info->skb = skb;
buffer_info->length = adapter->rx_buffer_len;
+map_skb:
buffer_info->dma = pci_map_single(pdev,
skb->data,
adapter->rx_buffer_len,
@@ -3695,20 +4029,23 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
rx_desc = E1000_RX_DESC(*rx_ring, i);
rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64). */
- wmb();
- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
- }
-
- if(unlikely(++i == rx_ring->count)) i = 0;
+ if (unlikely(++i == rx_ring->count))
+ i = 0;
buffer_info = &rx_ring->buffer_info[i];
}
- rx_ring->next_to_use = i;
+ if (likely(rx_ring->next_to_use != i)) {
+ rx_ring->next_to_use = i;
+ if (unlikely(i-- == 0))
+ i = (rx_ring->count - 1);
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+ }
}
/**
@@ -3718,7 +4055,8 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
static void
e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3734,16 +4072,18 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
- while(!buffer_info->skb) {
+ while (cleaned_count--) {
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
- for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ for (j = 0; j < PS_PAGE_BUFFERS; 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]))
+ if (unlikely(!ps_page->ps_page[j])) {
+ adapter->alloc_rx_buff_failed++;
goto no_buffers;
+ }
ps_page_dma->ps_page_dma[j] =
pci_map_page(pdev,
ps_page->ps_page[j],
@@ -3751,7 +4091,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
PCI_DMA_FROMDEVICE);
}
/* Refresh the desc even if buffer_addrs didn't
- * change because each write-back erases
+ * change because each write-back erases
* this info.
*/
rx_desc->read.buffer_addr[j+1] =
@@ -3762,8 +4102,10 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
- if(unlikely(!skb))
+ if (unlikely(!skb)) {
+ adapter->alloc_rx_buff_failed++;
break;
+ }
/* Make buffer alignment 2 beyond a 16 byte boundary
* this will result in a 16 byte aligned IP header after
@@ -3781,27 +4123,28 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64). */
- wmb();
- /* Hardware increments by 16 bytes, but packet split
- * descriptors are 32 bytes...so we increment tail
- * twice as much.
- */
- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
- }
-
- if(unlikely(++i == rx_ring->count)) i = 0;
+ if (unlikely(++i == rx_ring->count)) i = 0;
buffer_info = &rx_ring->buffer_info[i];
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
}
no_buffers:
- rx_ring->next_to_use = i;
+ if (likely(rx_ring->next_to_use != i)) {
+ rx_ring->next_to_use = i;
+ if (unlikely(i-- == 0)) i = (rx_ring->count - 1);
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ /* Hardware increments by 16 bytes, but packet split
+ * descriptors are 32 bytes...so we increment tail
+ * twice as much.
+ */
+ writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+ }
}
/**
@@ -3815,24 +4158,24 @@ e1000_smartspeed(struct e1000_adapter *adapter)
uint16_t phy_status;
uint16_t phy_ctrl;
- if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
+ if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
!(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
return;
- if(adapter->smartspeed == 0) {
+ if (adapter->smartspeed == 0) {
/* If Master/Slave config fault is asserted twice,
* we assume back-to-back */
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
- if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
+ if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
- if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
+ if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
- if(phy_ctrl & CR_1000T_MS_ENABLE) {
+ if (phy_ctrl & CR_1000T_MS_ENABLE) {
phy_ctrl &= ~CR_1000T_MS_ENABLE;
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
phy_ctrl);
adapter->smartspeed++;
- if(!e1000_phy_setup_autoneg(&adapter->hw) &&
+ if (!e1000_phy_setup_autoneg(&adapter->hw) &&
!e1000_read_phy_reg(&adapter->hw, PHY_CTRL,
&phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
@@ -3842,12 +4185,12 @@ e1000_smartspeed(struct e1000_adapter *adapter)
}
}
return;
- } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
+ } else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
/* If still no link, perhaps using 2/3 pair cable */
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
phy_ctrl |= CR_1000T_MS_ENABLE;
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
- if(!e1000_phy_setup_autoneg(&adapter->hw) &&
+ if (!e1000_phy_setup_autoneg(&adapter->hw) &&
!e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
@@ -3855,7 +4198,7 @@ e1000_smartspeed(struct e1000_adapter *adapter)
}
}
/* Restart process after E1000_SMARTSPEED_MAX iterations */
- if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
+ if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
adapter->smartspeed = 0;
}
@@ -3896,7 +4239,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
uint16_t spddplx;
unsigned long flags;
- if(adapter->hw.media_type != e1000_media_type_copper)
+ if (adapter->hw.media_type != e1000_media_type_copper)
return -EOPNOTSUPP;
switch (cmd) {
@@ -3904,10 +4247,10 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
data->phy_id = adapter->hw.phy_addr;
break;
case SIOCGMIIREG:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
&data->val_out)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
@@ -3915,23 +4258,23 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
case SIOCSMIIREG:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if(data->reg_num & ~(0x1F))
+ if (data->reg_num & ~(0x1F))
return -EFAULT;
mii_reg = data->val_in;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if(e1000_write_phy_reg(&adapter->hw, data->reg_num,
+ if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
mii_reg)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
- if(adapter->hw.phy_type == e1000_phy_m88) {
+ if (adapter->hw.phy_type == e1000_phy_m88) {
switch (data->reg_num) {
case PHY_CTRL:
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
break;
- if(mii_reg & MII_CR_AUTO_NEG_EN) {
+ if (mii_reg & MII_CR_AUTO_NEG_EN) {
adapter->hw.autoneg = 1;
adapter->hw.autoneg_advertised = 0x2F;
} else {
@@ -3946,14 +4289,14 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
HALF_DUPLEX;
retval = e1000_set_spd_dplx(adapter,
spddplx);
- if(retval) {
+ if (retval) {
spin_unlock_irqrestore(
- &adapter->stats_lock,
+ &adapter->stats_lock,
flags);
return retval;
}
}
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
@@ -3961,7 +4304,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if(e1000_phy_reset(&adapter->hw)) {
+ if (e1000_phy_reset(&adapter->hw)) {
spin_unlock_irqrestore(
&adapter->stats_lock, flags);
return -EIO;
@@ -3971,9 +4314,9 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
} else {
switch (data->reg_num) {
case PHY_CTRL:
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
break;
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
@@ -3995,7 +4338,7 @@ e1000_pci_set_mwi(struct e1000_hw *hw)
struct e1000_adapter *adapter = hw->back;
int ret_val = pci_set_mwi(adapter->pdev);
- if(ret_val)
+ if (ret_val)
DPRINTK(PROBE, ERR, "Error in setting MWI\n");
}
@@ -4044,7 +4387,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
e1000_irq_disable(adapter);
adapter->vlgrp = grp;
- if(grp) {
+ if (grp) {
/* enable VLAN tag insert/strip */
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
ctrl |= E1000_CTRL_VME;
@@ -4066,7 +4409,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl &= ~E1000_RCTL_VFE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
+ if (adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
}
@@ -4080,9 +4423,10 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
- if((adapter->hw.mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
- (vid == adapter->mng_vlan_id))
+
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id))
return;
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
@@ -4099,15 +4443,19 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
e1000_irq_disable(adapter);
- if(adapter->vlgrp)
+ if (adapter->vlgrp)
adapter->vlgrp->vlan_devices[vid] = NULL;
e1000_irq_enable(adapter);
- if((adapter->hw.mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
- (vid == adapter->mng_vlan_id))
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id)) {
+ /* release control to f/w */
+ e1000_release_hw_control(adapter);
return;
+ }
+
/* remove VID from filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -4120,10 +4468,10 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
{
e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
- if(adapter->vlgrp) {
+ if (adapter->vlgrp) {
uint16_t vid;
- for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
- if(!adapter->vlgrp->vlan_devices[vid])
+ for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ if (!adapter->vlgrp->vlan_devices[vid])
continue;
e1000_vlan_rx_add_vid(adapter->netdev, vid);
}
@@ -4136,13 +4484,13 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
adapter->hw.autoneg = 0;
/* Fiber NICs only allow 1000 gbps Full duplex */
- if((adapter->hw.media_type == e1000_media_type_fiber) &&
+ if ((adapter->hw.media_type == e1000_media_type_fiber) &&
spddplx != (SPEED_1000 + DUPLEX_FULL)) {
DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
return -EINVAL;
}
- switch(spddplx) {
+ switch (spddplx) {
case SPEED_10 + DUPLEX_HALF:
adapter->hw.forced_speed_duplex = e1000_10_half;
break;
@@ -4168,35 +4516,92 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
}
#ifdef CONFIG_PM
+/* these functions save and restore 16 or 64 dwords (64-256 bytes) of config
+ * space versus the 64 bytes that pci_[save|restore]_state handle
+ */
+#define PCIE_CONFIG_SPACE_LEN 256
+#define PCI_CONFIG_SPACE_LEN 64
+static int
+e1000_pci_save_state(struct e1000_adapter *adapter)
+{
+ struct pci_dev *dev = adapter->pdev;
+ int size;
+ int i;
+ if (adapter->hw.mac_type >= e1000_82571)
+ size = PCIE_CONFIG_SPACE_LEN;
+ else
+ size = PCI_CONFIG_SPACE_LEN;
+
+ WARN_ON(adapter->config_space != NULL);
+
+ adapter->config_space = kmalloc(size, GFP_KERNEL);
+ if (!adapter->config_space) {
+ DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size);
+ return -ENOMEM;
+ }
+ for (i = 0; i < (size / 4); i++)
+ pci_read_config_dword(dev, i * 4, &adapter->config_space[i]);
+ return 0;
+}
+
+static void
+e1000_pci_restore_state(struct e1000_adapter *adapter)
+{
+ struct pci_dev *dev = adapter->pdev;
+ int size;
+ int i;
+ if (adapter->config_space == NULL)
+ return;
+ if (adapter->hw.mac_type >= e1000_82571)
+ size = PCIE_CONFIG_SPACE_LEN;
+ else
+ size = PCI_CONFIG_SPACE_LEN;
+ for (i = 0; i < (size / 4); i++)
+ pci_write_config_dword(dev, i * 4, adapter->config_space[i]);
+ kfree(adapter->config_space);
+ adapter->config_space = NULL;
+ return;
+}
+#endif /* CONFIG_PM */
+
static int
e1000_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
+ uint32_t ctrl, ctrl_ext, rctl, manc, status;
uint32_t wufc = adapter->wol;
+ int retval = 0;
netif_device_detach(netdev);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_down(adapter);
+#ifdef CONFIG_PM
+ /* implement our own version of pci_save_state(pdev) because pci
+ * express adapters have larger 256 byte config spaces */
+ retval = e1000_pci_save_state(adapter);
+ if (retval)
+ return retval;
+#endif
+
status = E1000_READ_REG(&adapter->hw, STATUS);
- if(status & E1000_STATUS_LU)
+ if (status & E1000_STATUS_LU)
wufc &= ~E1000_WUFC_LNKC;
- if(wufc) {
+ if (wufc) {
e1000_setup_rctl(adapter);
e1000_set_multi(netdev);
/* turn on all-multi mode if wake on multicast is enabled */
- if(adapter->wol & E1000_WUFC_MC) {
+ if (adapter->wol & E1000_WUFC_MC) {
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
}
- if(adapter->hw.mac_type >= e1000_82540) {
+ if (adapter->hw.mac_type >= e1000_82540) {
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
/* advertise wake from D3Cold */
#define E1000_CTRL_ADVD3WUC 0x00100000
@@ -4207,7 +4612,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
}
- if(adapter->hw.media_type == e1000_media_type_fiber ||
+ if (adapter->hw.media_type == e1000_media_type_fiber ||
adapter->hw.media_type == e1000_media_type_internal_serdes) {
/* keep the laser running in D3 */
ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
@@ -4220,96 +4625,96 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
- pci_enable_wake(pdev, 3, 1);
- pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
} else {
E1000_WRITE_REG(&adapter->hw, WUC, 0);
E1000_WRITE_REG(&adapter->hw, WUFC, 0);
- pci_enable_wake(pdev, 3, 0);
- pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
}
- pci_save_state(pdev);
-
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
- if(manc & E1000_MANC_SMBUS_EN) {
+ if (manc & E1000_MANC_SMBUS_EN) {
manc |= E1000_MANC_ARP_EN;
E1000_WRITE_REG(&adapter->hw, MANC, manc);
- pci_enable_wake(pdev, 3, 1);
- pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
}
}
- 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,
- swsm & ~E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
+ * would have already happened in close and is redundant. */
+ e1000_release_hw_control(adapter);
pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error in setting power state\n");
return 0;
}
+#ifdef CONFIG_PM
static int
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;
+ int retval;
+ uint32_t manc, ret_val;
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
+ retval = pci_set_power_state(pdev, PCI_D0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error in setting power state\n");
+ e1000_pci_restore_state(adapter);
ret_val = pci_enable_device(pdev);
pci_set_master(pdev);
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
+ retval = pci_enable_wake(pdev, PCI_D3hot, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
e1000_reset(adapter);
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_up(adapter);
netif_device_attach(netdev);
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
manc &= ~(E1000_MANC_ARP_EN);
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
- 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,
- swsm | E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* If the controller is 82573 and f/w is AMT, do not set
+ * DRV_LOAD until the interface is up. For all other cases,
+ * let the f/w know that the h/w is now under the control
+ * of the driver. */
+ if (adapter->hw.mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
return 0;
}
@@ -4327,6 +4732,9 @@ e1000_netpoll(struct net_device *netdev)
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
e1000_clean_tx_irq(adapter, adapter->tx_ring);
+#ifndef CONFIG_E1000_NAPI
+ adapter->clean_rx(adapter, adapter->rx_ring);
+#endif
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index aac64de6143..9790db974dc 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -47,7 +47,7 @@
BUG(); \
} else { \
msleep(x); \
- } } while(0)
+ } } while (0)
/* Some workarounds require millisecond delays and are run during interrupt
* context. Most notably, when establishing link, the phy may need tweaking
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index ccbbe5ad8e0..3768d83cd57 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -177,7 +177,7 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
*
* Valid Range: 100-100000 (0=off, 1=dynamic)
*
- * Default Value: 1
+ * Default Value: 8000
*/
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
@@ -227,7 +227,7 @@ static int __devinit
e1000_validate_option(int *value, struct e1000_option *opt,
struct e1000_adapter *adapter)
{
- if(*value == OPTION_UNSET) {
+ if (*value == OPTION_UNSET) {
*value = opt->def;
return 0;
}
@@ -244,7 +244,7 @@ e1000_validate_option(int *value, struct e1000_option *opt,
}
break;
case range_option:
- if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
DPRINTK(PROBE, INFO,
"%s set to %i\n", opt->name, *value);
return 0;
@@ -254,10 +254,10 @@ e1000_validate_option(int *value, struct e1000_option *opt,
int i;
struct e1000_opt_list *ent;
- for(i = 0; i < opt->arg.l.nr; i++) {
+ for (i = 0; i < opt->arg.l.nr; i++) {
ent = &opt->arg.l.p[i];
- if(*value == ent->i) {
- if(ent->str[0] != '\0')
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
DPRINTK(PROBE, INFO, "%s\n", ent->str);
return 0;
}
@@ -291,7 +291,7 @@ void __devinit
e1000_check_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
- if(bd >= E1000_MAX_NIC) {
+ if (bd >= E1000_MAX_NIC) {
DPRINTK(PROBE, NOTICE,
"Warning: no configuration for board #%i\n", bd);
DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
@@ -315,12 +315,12 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxDescriptors > bd) {
tx_ring->count = TxDescriptors[bd];
e1000_validate_option(&tx_ring->count, &opt, adapter);
- E1000_ROUNDUP(tx_ring->count,
+ E1000_ROUNDUP(tx_ring->count,
REQ_TX_DESCRIPTOR_MULTIPLE);
} else {
tx_ring->count = opt.def;
}
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
tx_ring[i].count = tx_ring->count;
}
{ /* Receive Descriptor Count */
@@ -341,12 +341,12 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxDescriptors > bd) {
rx_ring->count = RxDescriptors[bd];
e1000_validate_option(&rx_ring->count, &opt, adapter);
- E1000_ROUNDUP(rx_ring->count,
+ E1000_ROUNDUP(rx_ring->count,
REQ_RX_DESCRIPTOR_MULTIPLE);
} else {
rx_ring->count = opt.def;
}
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
rx_ring[i].count = rx_ring->count;
}
{ /* Checksum Offload Enable/Disable */
@@ -388,7 +388,7 @@ e1000_check_options(struct e1000_adapter *adapter)
e1000_validate_option(&fc, &opt, adapter);
adapter->hw.fc = adapter->hw.original_fc = fc;
} else {
- adapter->hw.fc = opt.def;
+ adapter->hw.fc = adapter->hw.original_fc = opt.def;
}
}
{ /* Transmit Interrupt Delay */
@@ -403,7 +403,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxIntDelay > bd) {
adapter->tx_int_delay = TxIntDelay[bd];
- e1000_validate_option(&adapter->tx_int_delay, &opt,
+ e1000_validate_option(&adapter->tx_int_delay, &opt,
adapter);
} else {
adapter->tx_int_delay = opt.def;
@@ -421,7 +421,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxAbsIntDelay > bd) {
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
- e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
+ e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
adapter);
} else {
adapter->tx_abs_int_delay = opt.def;
@@ -439,7 +439,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxIntDelay > bd) {
adapter->rx_int_delay = RxIntDelay[bd];
- e1000_validate_option(&adapter->rx_int_delay, &opt,
+ e1000_validate_option(&adapter->rx_int_delay, &opt,
adapter);
} else {
adapter->rx_int_delay = opt.def;
@@ -457,7 +457,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxAbsIntDelay > bd) {
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
- e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
+ e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
adapter);
} else {
adapter->rx_abs_int_delay = opt.def;
@@ -475,17 +475,17 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_InterruptThrottleRate > bd) {
adapter->itr = InterruptThrottleRate[bd];
- switch(adapter->itr) {
+ switch (adapter->itr) {
case 0:
- DPRINTK(PROBE, INFO, "%s turned off\n",
+ DPRINTK(PROBE, INFO, "%s turned off\n",
opt.name);
break;
case 1:
- DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
+ DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
opt.name);
break;
default:
- e1000_validate_option(&adapter->itr, &opt,
+ e1000_validate_option(&adapter->itr, &opt,
adapter);
break;
}
@@ -494,7 +494,7 @@ e1000_check_options(struct e1000_adapter *adapter)
}
}
- switch(adapter->hw.media_type) {
+ switch (adapter->hw.media_type) {
case e1000_media_type_fiber:
case e1000_media_type_internal_serdes:
e1000_check_fiber_options(adapter);
@@ -518,17 +518,17 @@ static void __devinit
e1000_check_fiber_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
- if(num_Speed > bd) {
+ if (num_Speed > bd) {
DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
"parameter ignored\n");
}
- if(num_Duplex > bd) {
+ if (num_Duplex > bd) {
DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
"parameter ignored\n");
}
- if((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
+ if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
"not valid for fiber adapters, "
"parameter ignored\n");
@@ -584,6 +584,12 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.p = dplx_list }}
};
+ if (e1000_check_phy_reset_block(&adapter->hw)) {
+ DPRINTK(PROBE, INFO,
+ "Link active due to SoL/IDER Session. "
+ "Speed/Duplex/AutoNeg parameter ignored.\n");
+ return;
+ }
if (num_Duplex > bd) {
dplx = Duplex[bd];
e1000_validate_option(&dplx, &opt, adapter);
@@ -592,7 +598,7 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
}
}
- if((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
+ if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
DPRINTK(PROBE, INFO,
"AutoNeg specified along with Speed or Duplex, "
"parameter ignored\n");
@@ -653,7 +659,7 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
switch (speed + dplx) {
case 0:
adapter->hw.autoneg = adapter->fc_autoneg = 1;
- if((num_Speed > bd) && (speed != 0 || dplx != 0))
+ if ((num_Speed > bd) && (speed != 0 || dplx != 0))
DPRINTK(PROBE, INFO,
"Speed and duplex autonegotiation enabled\n");
break;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0c18dbd67d3..0e8e3fcde9f 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -199,8 +199,7 @@ static int gfar_probe(struct platform_device *pdev)
/* get a pointer to the register memory */
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->regs = (struct gfar *)
- ioremap(r->start, sizeof (struct gfar));
+ priv->regs = ioremap(r->start, sizeof (struct gfar));
if (NULL == priv->regs) {
err = -ENOMEM;
@@ -369,7 +368,7 @@ static int gfar_probe(struct platform_device *pdev)
return 0;
register_fail:
- iounmap((void *) priv->regs);
+ iounmap(priv->regs);
regs_fail:
free_netdev(dev);
return err;
@@ -382,7 +381,7 @@ static int gfar_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
- iounmap((void *) priv->regs);
+ iounmap(priv->regs);
free_netdev(dev);
return 0;
@@ -454,8 +453,7 @@ static void init_registers(struct net_device *dev)
/* Zero out the rmon mib registers if it has them */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
- memset((void *) &(priv->regs->rmon), 0,
- sizeof (struct rmon_mib));
+ memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib));
/* Mask off the CAM interrupts */
gfar_write(&priv->regs->rmon.cam1, 0xffffffff);
@@ -477,7 +475,7 @@ static void init_registers(struct net_device *dev)
void gfar_halt(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
u32 tempval;
/* Mask all interrupts */
@@ -507,7 +505,7 @@ void gfar_halt(struct net_device *dev)
void stop_gfar(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
unsigned long flags;
phy_stop(priv->phydev);
@@ -590,7 +588,7 @@ static void free_skb_resources(struct gfar_private *priv)
void gfar_start(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
u32 tempval;
/* Enable Rx and Tx in MACCFG1 */
@@ -624,7 +622,7 @@ int startup_gfar(struct net_device *dev)
unsigned long vaddr;
int i;
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
int err = 0;
u32 rctrl = 0;
u32 attrs = 0;
@@ -1622,7 +1620,7 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void adjust_link(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
unsigned long flags;
struct phy_device *phydev = priv->phydev;
int new_state = 0;
@@ -1703,7 +1701,7 @@ static void gfar_set_multi(struct net_device *dev)
{
struct dev_mc_list *mc_ptr;
struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
+ struct gfar __iomem *regs = priv->regs;
u32 tempval;
if(dev->flags & IFF_PROMISC) {
@@ -1842,7 +1840,7 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr)
int idx;
char tmpbuf[MAC_ADDR_LEN];
u32 tempval;
- u32 *macptr = &priv->regs->macstnaddr1;
+ u32 __iomem *macptr = &priv->regs->macstnaddr1;
macptr += num*2;
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index cb9d66ac3ab..d37d5401be6 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -682,8 +682,8 @@ struct gfar_private {
struct rxbd8 *cur_rx; /* Next free rx ring entry */
struct txbd8 *cur_tx; /* Next free ring entry */
struct txbd8 *dirty_tx; /* The Ring entry to be freed. */
- struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
- u32 *hash_regs[16];
+ struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */
+ u32 __iomem *hash_regs[16];
int hash_width;
struct net_device_stats stats; /* linux network statistics */
struct gfar_extra_stats extra_stats;
@@ -718,14 +718,14 @@ struct gfar_private {
uint32_t msg_enable;
};
-static inline u32 gfar_read(volatile unsigned *addr)
+static inline u32 gfar_read(volatile unsigned __iomem *addr)
{
u32 val;
val = in_be32(addr);
return val;
}
-static inline void gfar_write(volatile unsigned *addr, u32 val)
+static inline void gfar_write(volatile unsigned __iomem *addr, u32 val)
{
out_be32(addr, val);
}
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 765e810620f..5de7b2e259d 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -144,11 +144,11 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
u64 *extra = (u64 *) & priv->extra_stats;
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
- u32 *rmon = (u32 *) & priv->regs->rmon;
+ u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon;
struct gfar_stats *stats = (struct gfar_stats *) buf;
for (i = 0; i < GFAR_RMON_LEN; i++)
- stats->rmon[i] = (u64) (rmon[i]);
+ stats->rmon[i] = (u64) gfar_read(&rmon[i]);
for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
stats->extra[i] = extra[i];
@@ -221,11 +221,11 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi
{
int i;
struct gfar_private *priv = netdev_priv(dev);
- u32 *theregs = (u32 *) priv->regs;
+ u32 __iomem *theregs = (u32 __iomem *) priv->regs;
u32 *buf = (u32 *) regbuf;
for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++)
- buf[i] = theregs[i];
+ buf[i] = gfar_read(&theregs[i]);
}
/* Convert microseconds to ethernet clock ticks, which changes
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 74e52fcbf80..c6b725529af 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -50,7 +50,7 @@
* 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;
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
/* Set the PHY address and the register address we want to write */
gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
@@ -70,7 +70,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
* 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;
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
u16 value;
/* Set the PHY address and the register address we want to read */
@@ -94,7 +94,7 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
/* 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;
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
unsigned int timeout = PHY_INIT_TIMEOUT;
spin_lock_bh(&bus->mdio_lock);
@@ -126,7 +126,7 @@ 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 gfar_mii __iomem *regs;
struct mii_bus *new_bus;
struct resource *r;
int err = 0;
@@ -155,15 +155,14 @@ int gfar_mdio_probe(struct device *dev)
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
/* Set the PHY base address */
- regs = (struct gfar_mii *) ioremap(r->start,
- sizeof (struct gfar_mii));
+ regs = ioremap(r->start, sizeof (struct gfar_mii));
if (NULL == regs) {
err = -ENOMEM;
goto reg_map_fail;
}
- new_bus->priv = regs;
+ new_bus->priv = (void __force *)regs;
new_bus->irq = pdata->irq;
@@ -181,7 +180,7 @@ int gfar_mdio_probe(struct device *dev)
return 0;
bus_register_fail:
- iounmap((void *) regs);
+ iounmap(regs);
reg_map_fail:
kfree(new_bus);
@@ -197,7 +196,7 @@ int gfar_mdio_remove(struct device *dev)
dev_set_drvdata(dev, NULL);
- iounmap((void *) (&bus->priv));
+ iounmap((void __iomem *)bus->priv);
bus->priv = NULL;
kfree(bus);
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index 3b1bef1ee21..77411a00d1e 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -86,7 +86,6 @@
#include <linux/bitops.h>
#include <linux/jiffies.h>
-#include <asm/bug.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index fa176ffb4ad..8936058a3cc 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -108,6 +108,7 @@ static void irda_usb_close(struct irda_usb_cb *self);
static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void write_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void irda_usb_receive(struct urb *urb, struct pt_regs *regs);
+static void irda_usb_rx_defer_expired(unsigned long data);
static int irda_usb_net_open(struct net_device *dev);
static int irda_usb_net_close(struct net_device *dev);
static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -677,6 +678,12 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* on the interrupt pipe and hang the Rx URB only when an interrupt is
* received.
* Jean II
+ *
+ * Note : don't read the above as what we are currently doing, but as
+ * something we could do with KC dongle. Also don't forget that the
+ * interrupt pipe is not part of the original standard, so this would
+ * need to be optional...
+ * Jean II
*/
/*------------------------------------------------------------------*/
@@ -704,10 +711,8 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc
/* Reinitialize URB */
usb_fill_bulk_urb(urb, self->usbdev,
usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep),
- skb->data, skb->truesize,
+ skb->data, IRDA_SKB_MAX_MTU,
irda_usb_receive, skb);
- /* Note : unlink *must* be synchronous because of the code in
- * irda_usb_net_close() -> free the skb - Jean II */
urb->status = 0;
/* Can be called from irda_usb_receive (irq handler) -> GFP_ATOMIC */
@@ -734,6 +739,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
struct irda_skb_cb *cb;
struct sk_buff *newskb;
struct sk_buff *dataskb;
+ struct urb *next_urb;
int docopy;
IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);
@@ -755,20 +761,37 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
if (urb->status != 0) {
switch (urb->status) {
case -EILSEQ:
- self->stats.rx_errors++;
self->stats.rx_crc_errors++;
- break;
+ /* Also precursor to a hot-unplug on UHCI. */
+ /* Fallthrough... */
case -ECONNRESET: /* -104 */
- IRDA_DEBUG(0, "%s(), Connection Reset (-104), transfer_flags 0x%04X \n", __FUNCTION__, urb->transfer_flags);
+ /* Random error, if I remember correctly */
/* uhci_cleanup_unlink() is going to kill the Rx
* URB just after we return. No problem, at this
* point the URB will be idle ;-) - Jean II */
- break;
+ case -ESHUTDOWN: /* -108 */
+ /* That's usually a hot-unplug. Submit will fail... */
+ case -ETIMEDOUT: /* -110 */
+ /* Usually precursor to a hot-unplug on OHCI. */
default:
- IRDA_DEBUG(0, "%s(), RX status %d,transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags);
+ self->stats.rx_errors++;
+ IRDA_DEBUG(0, "%s(), RX status %d, transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags);
break;
}
- goto done;
+ /* If we received an error, we don't want to resubmit the
+ * Rx URB straight away but to give the USB layer a little
+ * bit of breathing room.
+ * We are in the USB thread context, therefore there is a
+ * danger of recursion (new URB we submit fails, we come
+ * back here).
+ * With recent USB stack (2.6.15+), I'm seeing that on
+ * hot unplug of the dongle...
+ * Lowest effective timer is 10ms...
+ * Jean II */
+ self->rx_defer_timer.function = &irda_usb_rx_defer_expired;
+ self->rx_defer_timer.data = (unsigned long) urb;
+ mod_timer(&self->rx_defer_timer, jiffies + (10 * HZ / 1000));
+ return;
}
/* Check for empty frames */
@@ -845,13 +868,45 @@ done:
* idle slot....
* Jean II */
/* Note : with this scheme, we could submit the idle URB before
- * processing the Rx URB. Another time... Jean II */
+ * processing the Rx URB. I don't think it would buy us anything as
+ * we are running in the USB thread context. Jean II */
+ next_urb = self->idle_rx_urb;
- /* Submit the idle URB to replace the URB we've just received */
- irda_usb_submit(self, skb, self->idle_rx_urb);
/* Recycle Rx URB : Now, the idle URB is the present one */
urb->context = NULL;
self->idle_rx_urb = urb;
+
+ /* Submit the idle URB to replace the URB we've just received.
+ * Do it last to avoid race conditions... Jean II */
+ irda_usb_submit(self, skb, next_urb);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * In case of errors, we want the USB layer to have time to recover.
+ * Now, it is time to resubmit ouur Rx URB...
+ */
+static void irda_usb_rx_defer_expired(unsigned long data)
+{
+ struct urb *urb = (struct urb *) data;
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
+ struct irda_usb_cb *self;
+ struct irda_skb_cb *cb;
+ struct urb *next_urb;
+
+ IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
+ /* Find ourselves */
+ cb = (struct irda_skb_cb *) skb->cb;
+ IRDA_ASSERT(cb != NULL, return;);
+ self = (struct irda_usb_cb *) cb->context;
+ IRDA_ASSERT(self != NULL, return;);
+
+ /* Same stuff as when Rx is done, see above... */
+ next_urb = self->idle_rx_urb;
+ urb->context = NULL;
+ self->idle_rx_urb = urb;
+ irda_usb_submit(self, skb, next_urb);
}
/*------------------------------------------------------------------*/
@@ -990,6 +1045,9 @@ static int irda_usb_net_close(struct net_device *netdev)
/* Stop network Tx queue */
netif_stop_queue(netdev);
+ /* Kill defered Rx URB */
+ del_timer(&self->rx_defer_timer);
+
/* Deallocate all the Rx path buffers (URBs and skb) */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
struct urb *urb = self->rx_urb[i];
@@ -1365,6 +1423,7 @@ static int irda_usb_probe(struct usb_interface *intf,
self = net->priv;
self->netdev = net;
spin_lock_init(&self->lock);
+ init_timer(&self->rx_defer_timer);
/* Create all of the needed urbs */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
@@ -1498,6 +1557,9 @@ static void irda_usb_disconnect(struct usb_interface *intf)
* This will stop/desactivate the Tx path. - Jean II */
self->present = 0;
+ /* Kill defered Rx URB */
+ del_timer(&self->rx_defer_timer);
+
/* We need to have irq enabled to unlink the URBs. That's OK,
* at this point the Tx path is gone - Jean II */
spin_unlock_irqrestore(&self->lock, flags);
@@ -1507,11 +1569,11 @@ static void irda_usb_disconnect(struct usb_interface *intf)
/* Accept no more transmissions */
/*netif_device_detach(self->netdev);*/
netif_stop_queue(self->netdev);
- /* Stop all the receive URBs */
+ /* Stop all the receive URBs. Must be synchronous. */
for (i = 0; i < IU_MAX_RX_URBS; i++)
usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
- * Toggle flags to make sure it's synchronous. */
+ * Make sure it's synchronous to avoid races. */
usb_kill_urb(self->tx_urb);
usb_kill_urb(self->speed_urb);
}
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index bd8f6654232..4026af42dd4 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -136,8 +136,6 @@ struct irda_usb_cb {
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
__u8 bulk_int_ep; /* Interrupt Endpoint assignments */
- wait_queue_head_t wait_q; /* for timeouts */
-
struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */
struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */
struct urb *tx_urb; /* URB used to send data frames */
@@ -147,17 +145,18 @@ struct irda_usb_cb {
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos;
- hashbin_t *tx_list; /* Queued transmit skb's */
char *speed_buff; /* Buffer for speed changes */
struct timeval stamp;
struct timeval now;
- spinlock_t lock; /* For serializing operations */
+ spinlock_t lock; /* For serializing Tx operations */
__u16 xbofs; /* Current xbofs setting */
__s16 new_xbofs; /* xbofs we need to set */
__u32 speed; /* Current speed */
__s32 new_speed; /* speed we need to set */
+
+ struct timer_list rx_defer_timer; /* Wait for Rx error to clear */
};
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 6139f06d7d2..94d5ea1ce8b 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -56,8 +56,6 @@ PORT SIZE ACTION MEANING
All other communication is through memory!
*/
-#define SLOW_DOWN_IO udelay(5)
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 22c3a37bba5..c0998ef938e 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -32,9 +32,13 @@
*/
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/bitops.h>
#include <linux/delay.h>
@@ -55,13 +59,15 @@
/* Constants */
#define VLAN_HLEN 4
#define FCS_LEN 4
-#define WRAP NET_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
+#define DMA_ALIGN 8 /* hw requires 8-byte alignment */
+#define HW_IP_ALIGN 2 /* hw aligns IP header */
+#define WRAP HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
#define RX_SKB_SIZE ((dev->mtu + WRAP + 7) & ~0x7)
-#define INT_CAUSE_UNMASK_ALL 0x0007ffff
-#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff
-#define INT_CAUSE_MASK_ALL 0x00000000
-#define INT_CAUSE_MASK_ALL_EXT 0x00000000
+#define INT_UNMASK_ALL 0x0007ffff
+#define INT_UNMASK_ALL_EXT 0x0011ffff
+#define INT_MASK_ALL 0x00000000
+#define INT_MASK_ALL_EXT 0x00000000
#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL
#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT
@@ -78,8 +84,9 @@
static int eth_port_link_is_up(unsigned int eth_port_num);
static void eth_port_uc_addr_get(struct net_device *dev,
unsigned char *MacAddr);
-static int mv643xx_eth_real_open(struct net_device *);
-static int mv643xx_eth_real_stop(struct net_device *);
+static void eth_port_set_multicast_list(struct net_device *);
+static int mv643xx_eth_open(struct net_device *);
+static int mv643xx_eth_stop(struct net_device *);
static int mv643xx_eth_change_mtu(struct net_device *, int);
static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *);
static void eth_port_init_mac_tables(unsigned int eth_port_num);
@@ -124,15 +131,8 @@ static inline void mv_write(int offset, u32 data)
*/
static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
{
- struct mv643xx_private *mp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&mp->lock, flags);
-
- if ((new_mtu > 9500) || (new_mtu < 64)) {
- spin_unlock_irqrestore(&mp->lock, flags);
+ if ((new_mtu > 9500) || (new_mtu < 64))
return -EINVAL;
- }
dev->mtu = new_mtu;
/*
@@ -142,17 +142,13 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
* to memory is full, which might fail the open function.
*/
if (netif_running(dev)) {
- if (mv643xx_eth_real_stop(dev))
- printk(KERN_ERR
- "%s: Fatal error on stopping device\n",
- dev->name);
- if (mv643xx_eth_real_open(dev))
+ mv643xx_eth_stop(dev);
+ if (mv643xx_eth_open(dev))
printk(KERN_ERR
"%s: Fatal error on opening device\n",
dev->name);
}
- spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
@@ -170,15 +166,19 @@ static void mv643xx_eth_rx_task(void *data)
struct mv643xx_private *mp = netdev_priv(dev);
struct pkt_info pkt_info;
struct sk_buff *skb;
+ int unaligned;
if (test_and_set_bit(0, &mp->rx_task_busy))
panic("%s: Error in test_set_bit / clear_bit", dev->name);
while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
- skb = dev_alloc_skb(RX_SKB_SIZE);
+ skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN);
if (!skb)
break;
mp->rx_ring_skbs++;
+ unaligned = (u32)skb->data & (DMA_ALIGN - 1);
+ if (unaligned)
+ skb_reserve(skb, DMA_ALIGN - unaligned);
pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
pkt_info.byte_cnt = RX_SKB_SIZE;
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE,
@@ -189,7 +189,7 @@ static void mv643xx_eth_rx_task(void *data)
"%s: Error allocating RX Ring\n", dev->name);
break;
}
- skb_reserve(skb, 2);
+ skb_reserve(skb, HW_IP_ALIGN);
}
clear_bit(0, &mp->rx_task_busy);
/*
@@ -207,7 +207,7 @@ static void mv643xx_eth_rx_task(void *data)
else {
/* Return interrupts */
mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num),
- INT_CAUSE_UNMASK_ALL);
+ INT_UNMASK_ALL);
}
#endif
}
@@ -267,6 +267,8 @@ static void mv643xx_eth_set_rx_mode(struct net_device *dev)
mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
+
+ eth_port_set_multicast_list(dev);
}
/*
@@ -342,8 +344,6 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
if (!(eth_int_cause_ext & (BIT0 | BIT8)))
return released;
- spin_lock(&mp->lock);
-
/* Check only queue 0 */
while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
if (pkt_info.cmd_sts & BIT0) {
@@ -351,31 +351,21 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
stats->tx_errors++;
}
- /*
- * If return_info is different than 0, release the skb.
- * The case where return_info is not 0 is only in case
- * when transmitted a scatter/gather packet, where only
- * last skb releases the whole chain.
- */
- if (pkt_info.return_info) {
- if (skb_shinfo(pkt_info.return_info)->nr_frags)
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
- else
- dma_unmap_single(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
+ if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
+ dma_unmap_single(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ if (pkt_info.return_info) {
dev_kfree_skb_irq(pkt_info.return_info);
released = 0;
- } else
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt, DMA_TO_DEVICE);
+ }
}
- spin_unlock(&mp->lock);
-
return released;
}
@@ -456,6 +446,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
netif_rx(skb);
#endif
}
+ dev->last_rx = jiffies;
}
return received_packets;
@@ -473,7 +464,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
*/
static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
- struct pt_regs *regs)
+ struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
struct mv643xx_private *mp = netdev_priv(dev);
@@ -482,12 +473,12 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
/* Read interrupt cause registers */
eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
- INT_CAUSE_UNMASK_ALL;
+ INT_UNMASK_ALL;
if (eth_int_cause & BIT1)
eth_int_cause_ext = mv_read(
MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
- INT_CAUSE_UNMASK_ALL_EXT;
+ INT_UNMASK_ALL_EXT;
#ifdef MV643XX_NAPI
if (!(eth_int_cause & 0x0007fffd)) {
@@ -512,9 +503,10 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
} else {
if (netif_rx_schedule_prep(dev)) {
/* Mask all the interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG
- (port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
__netif_rx_schedule(dev);
}
#else
@@ -527,9 +519,12 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
* with skb's.
*/
#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
- /* Unmask all interrupts on ethernet port */
+ /* Mask all interrupts on ethernet port */
mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_MASK_ALL);
+ INT_MASK_ALL);
+ /* wait for previous write to take effect */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
queue_task(&mp->rx_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#else
@@ -636,56 +631,6 @@ static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
}
/*
- * mv643xx_eth_open
- *
- * This function is called when openning the network device. The function
- * should initialize all the hardware, initialize cyclic Rx/Tx
- * descriptors chain and buffers and allocate an IRQ to the network
- * device.
- *
- * Input : a pointer to the network device structure
- *
- * Output : zero of success , nonzero if fails.
- */
-
-static int mv643xx_eth_open(struct net_device *dev)
-{
- struct mv643xx_private *mp = netdev_priv(dev);
- unsigned int port_num = mp->port_num;
- int err;
-
- spin_lock_irq(&mp->lock);
-
- err = request_irq(dev->irq, mv643xx_eth_int_handler,
- SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
-
- if (err) {
- printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
- port_num);
- err = -EAGAIN;
- goto out;
- }
-
- if (mv643xx_eth_real_open(dev)) {
- printk("%s: Error opening interface\n", dev->name);
- err = -EBUSY;
- goto out_free;
- }
-
- spin_unlock_irq(&mp->lock);
-
- return 0;
-
-out_free:
- free_irq(dev->irq, dev);
-
-out:
- spin_unlock_irq(&mp->lock);
-
- return err;
-}
-
-/*
* ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
*
* DESCRIPTION:
@@ -777,28 +722,37 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp)
mp->port_tx_queue_command |= 1;
}
-/* Helper function for mv643xx_eth_open */
-static int mv643xx_eth_real_open(struct net_device *dev)
+/*
+ * mv643xx_eth_open
+ *
+ * This function is called when openning the network device. The function
+ * should initialize all the hardware, initialize cyclic Rx/Tx
+ * descriptors chain and buffers and allocate an IRQ to the network
+ * device.
+ *
+ * Input : a pointer to the network device structure
+ *
+ * Output : zero of success , nonzero if fails.
+ */
+
+static int mv643xx_eth_open(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
unsigned int size;
+ int err;
+
+ err = request_irq(dev->irq, mv643xx_eth_int_handler,
+ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ if (err) {
+ printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
+ port_num);
+ return -EAGAIN;
+ }
/* Stop RX Queues */
mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
- /* Clear the ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
- /* Unmask RX buffer and TX end interrupt */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL);
-
- /* Unmask phy and link status changes interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL_EXT);
-
/* Set the MAC Address */
memcpy(mp->port_mac_addr, dev->dev_addr, 6);
@@ -818,14 +772,15 @@ static int mv643xx_eth_real_open(struct net_device *dev)
GFP_KERNEL);
if (!mp->rx_skb) {
printk(KERN_ERR "%s: Cannot allocate Rx skb ring\n", dev->name);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_irq;
}
mp->tx_skb = kmalloc(sizeof(*mp->tx_skb) * mp->tx_ring_size,
GFP_KERNEL);
if (!mp->tx_skb) {
printk(KERN_ERR "%s: Cannot allocate Tx skb ring\n", dev->name);
- kfree(mp->rx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_rx_skb;
}
/* Allocate TX ring */
@@ -845,9 +800,8 @@ static int mv643xx_eth_real_open(struct net_device *dev)
if (!mp->p_tx_desc_area) {
printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
dev->name, size);
- kfree(mp->rx_skb);
- kfree(mp->tx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_tx_skb;
}
BUG_ON((u32) mp->p_tx_desc_area & 0xf); /* check 16-byte alignment */
memset((void *)mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
@@ -874,13 +828,12 @@ static int mv643xx_eth_real_open(struct net_device *dev)
printk(KERN_ERR "%s: Freeing previously allocated TX queues...",
dev->name);
if (mp->rx_sram_size)
- iounmap(mp->p_rx_desc_area);
+ iounmap(mp->p_tx_desc_area);
else
dma_free_coherent(NULL, mp->tx_desc_area_size,
mp->p_tx_desc_area, mp->tx_desc_dma);
- kfree(mp->rx_skb);
- kfree(mp->tx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_tx_skb;
}
memset((void *)mp->p_rx_desc_area, 0, size);
@@ -900,9 +853,26 @@ static int mv643xx_eth_real_open(struct net_device *dev)
mp->tx_int_coal =
eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
- netif_start_queue(dev);
+ /* Clear any pending ethernet port interrupts */
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+
+ /* Unmask phy and link status changes interrupts */
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_UNMASK_ALL_EXT);
+ /* Unmask RX buffer and TX end interrupt */
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
return 0;
+
+out_free_tx_skb:
+ kfree(mp->tx_skb);
+out_free_rx_skb:
+ kfree(mp->rx_skb);
+out_free_irq:
+ free_irq(dev->irq, dev);
+
+ return err;
}
static void mv643xx_eth_free_tx_rings(struct net_device *dev)
@@ -910,14 +880,17 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev)
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
unsigned int curr;
+ struct sk_buff *skb;
/* Stop Tx Queues */
mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
/* Free outstanding skb's on TX rings */
for (curr = 0; mp->tx_ring_skbs && curr < mp->tx_ring_size; curr++) {
- if (mp->tx_skb[curr]) {
- dev_kfree_skb(mp->tx_skb[curr]);
+ skb = mp->tx_skb[curr];
+ if (skb) {
+ mp->tx_ring_skbs -= skb_shinfo(skb)->nr_frags;
+ dev_kfree_skb(skb);
mp->tx_ring_skbs--;
}
}
@@ -973,44 +946,32 @@ static void mv643xx_eth_free_rx_rings(struct net_device *dev)
* Output : zero if success , nonzero if fails
*/
-/* Helper function for mv643xx_eth_stop */
-
-static int mv643xx_eth_real_stop(struct net_device *dev)
+static int mv643xx_eth_stop(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
+ /* Mask all interrupts on ethernet port */
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
+#ifdef MV643XX_NAPI
+ netif_poll_disable(dev);
+#endif
netif_carrier_off(dev);
netif_stop_queue(dev);
- mv643xx_eth_free_tx_rings(dev);
- mv643xx_eth_free_rx_rings(dev);
-
eth_port_reset(mp->port_num);
- /* Disable ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
- /* Mask RX buffer and TX end interrupt */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
-
- /* Mask phy and link status changes interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
-
- return 0;
-}
-
-static int mv643xx_eth_stop(struct net_device *dev)
-{
- struct mv643xx_private *mp = netdev_priv(dev);
-
- spin_lock_irq(&mp->lock);
+ mv643xx_eth_free_tx_rings(dev);
+ mv643xx_eth_free_rx_rings(dev);
- mv643xx_eth_real_stop(dev);
+#ifdef MV643XX_NAPI
+ netif_poll_enable(dev);
+#endif
free_irq(dev->irq, dev);
- spin_unlock_irq(&mp->lock);
return 0;
}
@@ -1022,20 +983,17 @@ static void mv643xx_tx(struct net_device *dev)
struct pkt_info pkt_info;
while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
- if (pkt_info.return_info) {
- if (skb_shinfo(pkt_info.return_info)->nr_frags)
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
- else
- dma_unmap_single(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
+ if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
+ dma_unmap_single(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ if (pkt_info.return_info)
dev_kfree_skb_irq(pkt_info.return_info);
- } else
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt, DMA_TO_DEVICE);
}
if (netif_queue_stopped(dev) &&
@@ -1053,14 +1011,11 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
struct mv643xx_private *mp = netdev_priv(dev);
int done = 1, orig_budget, work_done;
unsigned int port_num = mp->port_num;
- unsigned long flags;
#ifdef MV643XX_TX_FAST_REFILL
if (++mp->tx_clean_threshold > 5) {
- spin_lock_irqsave(&mp->lock, flags);
mv643xx_tx(dev);
mp->tx_clean_threshold = 0;
- spin_unlock_irqrestore(&mp->lock, flags);
}
#endif
@@ -1078,21 +1033,35 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
}
if (done) {
- spin_lock_irqsave(&mp->lock, flags);
- __netif_rx_complete(dev);
+ netif_rx_complete(dev);
mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL);
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL_EXT);
- spin_unlock_irqrestore(&mp->lock, flags);
+ INT_UNMASK_ALL);
}
return done ? 0 : 1;
}
#endif
+/* Hardware can't handle unaligned fragments smaller than 9 bytes.
+ * This helper function detects that case.
+ */
+
+static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
+{
+ unsigned int frag;
+ skb_frag_t *fragp;
+
+ for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+ fragp = &skb_shinfo(skb)->frags[frag];
+ if (fragp->size <= 8 && fragp->page_offset & 0x7)
+ return 1;
+ }
+ return 0;
+}
+
+
/*
* mv643xx_eth_start_xmit
*
@@ -1136,12 +1105,19 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ if (has_tiny_unaligned_frags(skb)) {
+ if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+ stats->tx_dropped++;
+ printk(KERN_DEBUG "%s: failed to linearize tiny "
+ "unaligned fragment\n", dev->name);
+ return 1;
+ }
+ }
+
spin_lock_irqsave(&mp->lock, flags);
- /* Update packet info data structure -- DMA owned, first last */
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
if (!skb_shinfo(skb)->nr_frags) {
-linear:
if (skb->ip_summed != CHECKSUM_HW) {
/* Errata BTS #50, IHL must be 5 if no HW checksum */
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
@@ -1150,7 +1126,6 @@ linear:
5 << ETH_TX_IHL_SHIFT;
pkt_info.l4i_chk = 0;
} else {
-
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC |
@@ -1158,14 +1133,16 @@ linear:
ETH_GEN_IP_V_4_CHECKSUM |
skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */
- if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_UDP) ) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
pkt_info.l4i_chk = skb->h.uh->check;
- } else if (skb->nh.iph->protocol == IPPROTO_TCP)
+ } else if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_TCP))
pkt_info.l4i_chk = skb->h.th->check;
else {
printk(KERN_ERR
- "%s: chksum proto != TCP or UDP\n",
+ "%s: chksum proto != IPv4 TCP or UDP\n",
dev->name);
spin_unlock_irqrestore(&mp->lock, flags);
return 1;
@@ -1183,26 +1160,6 @@ linear:
} else {
unsigned int frag;
- /* Since hardware can't handle unaligned fragments smaller
- * than 9 bytes, if we find any, we linearize the skb
- * and start again. When I've seen it, it's always been
- * the first frag (probably near the end of the page),
- * but we check all frags to be safe.
- */
- for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *fragp;
-
- fragp = &skb_shinfo(skb)->frags[frag];
- if (fragp->size <= 8 && fragp->page_offset & 0x7) {
- skb_linearize(skb, GFP_ATOMIC);
- printk(KERN_DEBUG "%s: unaligned tiny fragment"
- "%d of %d, fixed\n",
- dev->name, frag,
- skb_shinfo(skb)->nr_frags);
- goto linear;
- }
- }
-
/* first frag which is skb header */
pkt_info.byte_cnt = skb_headlen(skb);
pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
@@ -1221,14 +1178,16 @@ linear:
ETH_GEN_IP_V_4_CHECKSUM |
skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */
- if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_UDP)) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
pkt_info.l4i_chk = skb->h.uh->check;
- } else if (skb->nh.iph->protocol == IPPROTO_TCP)
+ } else if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_TCP))
pkt_info.l4i_chk = skb->h.th->check;
else {
printk(KERN_ERR
- "%s: chksum proto != TCP or UDP\n",
+ "%s: chksum proto != IPv4 TCP or UDP\n",
dev->name);
spin_unlock_irqrestore(&mp->lock, flags);
return 1;
@@ -1288,6 +1247,8 @@ linear:
}
}
#else
+ spin_lock_irqsave(&mp->lock, flags);
+
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC;
pkt_info.l4i_chk = 0;
@@ -1340,39 +1301,18 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
}
#ifdef CONFIG_NET_POLL_CONTROLLER
-static inline void mv643xx_enable_irq(struct mv643xx_private *mp)
-{
- int port_num = mp->port_num;
- unsigned long flags;
-
- spin_lock_irqsave(&mp->lock, flags);
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL);
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL_EXT);
- spin_unlock_irqrestore(&mp->lock, flags);
-}
-
-static inline void mv643xx_disable_irq(struct mv643xx_private *mp)
-{
- int port_num = mp->port_num;
- unsigned long flags;
-
- spin_lock_irqsave(&mp->lock, flags);
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_MASK_ALL);
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- INT_CAUSE_MASK_ALL_EXT);
- spin_unlock_irqrestore(&mp->lock, flags);
-}
-
static void mv643xx_netpoll(struct net_device *netdev)
{
struct mv643xx_private *mp = netdev_priv(netdev);
+ int port_num = mp->port_num;
+
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
- mv643xx_disable_irq(mp);
mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
- mv643xx_enable_irq(mp);
+
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
}
#endif
@@ -1441,7 +1381,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
* Zero copy can only work if we use Discovery II memory. Else, we will
* have to map the buffers to ISA memory which is only 16 MB
*/
- dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_CSUM;
+ dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
#endif
#endif
@@ -2054,6 +1994,196 @@ static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
}
/*
+ * The entries in each table are indexed by a hash of a packet's MAC
+ * address. One bit in each entry determines whether the packet is
+ * accepted. There are 4 entries (each 8 bits wide) in each register
+ * of the table. The bits in each entry are defined as follows:
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue (ETH_Q0=0)
+ * 7-4 Reserved = 0;
+ */
+static void eth_port_set_filter_table_entry(int table, unsigned char entry)
+{
+ unsigned int table_reg;
+ unsigned int tbl_offset;
+ unsigned int reg_offset;
+
+ tbl_offset = (entry / 4) * 4; /* Register offset of DA table entry */
+ reg_offset = entry % 4; /* Entry offset within the register */
+
+ /* Set "accepts frame bit" at specified table entry */
+ table_reg = mv_read(table + tbl_offset);
+ table_reg |= 0x01 << (8 * reg_offset);
+ mv_write(table + tbl_offset, table_reg);
+}
+
+/*
+ * eth_port_mc_addr - Multicast address settings.
+ *
+ * The MV device supports multicast using two tables:
+ * 1) Special Multicast Table for MAC addresses of the form
+ * 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_FF).
+ * The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+ * Table entries in the DA-Filter table.
+ * 2) Other Multicast Table for multicast of another type. A CRC-8bit
+ * is used as an index to the Other Multicast Table entries in the
+ * DA-Filter table. This function calculates the CRC-8bit value.
+ * In either case, eth_port_set_filter_table_entry() is then called
+ * to set to set the actual table entry.
+ */
+static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
+{
+ unsigned int mac_h;
+ unsigned int mac_l;
+ unsigned char crc_result = 0;
+ int table;
+ int mac_array[48];
+ int crc[8];
+ int i;
+
+ if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
+ (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
+ table = MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num);
+ eth_port_set_filter_table_entry(table, p_addr[5]);
+ return;
+ }
+
+ /* Calculate CRC-8 out of the given address */
+ mac_h = (p_addr[0] << 8) | (p_addr[1]);
+ mac_l = (p_addr[2] << 24) | (p_addr[3] << 16) |
+ (p_addr[4] << 8) | (p_addr[5] << 0);
+
+ for (i = 0; i < 32; i++)
+ mac_array[i] = (mac_l >> i) & 0x1;
+ for (i = 32; i < 48; i++)
+ mac_array[i] = (mac_h >> (i - 32)) & 0x1;
+
+ crc[0] = mac_array[45] ^ mac_array[43] ^ mac_array[40] ^ mac_array[39] ^
+ mac_array[35] ^ mac_array[34] ^ mac_array[31] ^ mac_array[30] ^
+ mac_array[28] ^ mac_array[23] ^ mac_array[21] ^ mac_array[19] ^
+ mac_array[18] ^ mac_array[16] ^ mac_array[14] ^ mac_array[12] ^
+ mac_array[8] ^ mac_array[7] ^ mac_array[6] ^ mac_array[0];
+
+ crc[1] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[41] ^ mac_array[39] ^ mac_array[36] ^ mac_array[34] ^
+ mac_array[32] ^ mac_array[30] ^ mac_array[29] ^ mac_array[28] ^
+ mac_array[24] ^ mac_array[23] ^ mac_array[22] ^ mac_array[21] ^
+ mac_array[20] ^ mac_array[18] ^ mac_array[17] ^ mac_array[16] ^
+ mac_array[15] ^ mac_array[14] ^ mac_array[13] ^ mac_array[12] ^
+ mac_array[9] ^ mac_array[6] ^ mac_array[1] ^ mac_array[0];
+
+ crc[2] = mac_array[47] ^ mac_array[46] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[42] ^ mac_array[39] ^ mac_array[37] ^ mac_array[34] ^
+ mac_array[33] ^ mac_array[29] ^ mac_array[28] ^ mac_array[25] ^
+ mac_array[24] ^ mac_array[22] ^ mac_array[17] ^ mac_array[15] ^
+ mac_array[13] ^ mac_array[12] ^ mac_array[10] ^ mac_array[8] ^
+ mac_array[6] ^ mac_array[2] ^ mac_array[1] ^ mac_array[0];
+
+ crc[3] = mac_array[47] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[40] ^ mac_array[38] ^ mac_array[35] ^ mac_array[34] ^
+ mac_array[30] ^ mac_array[29] ^ mac_array[26] ^ mac_array[25] ^
+ mac_array[23] ^ mac_array[18] ^ mac_array[16] ^ mac_array[14] ^
+ mac_array[13] ^ mac_array[11] ^ mac_array[9] ^ mac_array[7] ^
+ mac_array[3] ^ mac_array[2] ^ mac_array[1];
+
+ crc[4] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[41] ^
+ mac_array[39] ^ mac_array[36] ^ mac_array[35] ^ mac_array[31] ^
+ mac_array[30] ^ mac_array[27] ^ mac_array[26] ^ mac_array[24] ^
+ mac_array[19] ^ mac_array[17] ^ mac_array[15] ^ mac_array[14] ^
+ mac_array[12] ^ mac_array[10] ^ mac_array[8] ^ mac_array[4] ^
+ mac_array[3] ^ mac_array[2];
+
+ crc[5] = mac_array[47] ^ mac_array[46] ^ mac_array[45] ^ mac_array[42] ^
+ mac_array[40] ^ mac_array[37] ^ mac_array[36] ^ mac_array[32] ^
+ mac_array[31] ^ mac_array[28] ^ mac_array[27] ^ mac_array[25] ^
+ mac_array[20] ^ mac_array[18] ^ mac_array[16] ^ mac_array[15] ^
+ mac_array[13] ^ mac_array[11] ^ mac_array[9] ^ mac_array[5] ^
+ mac_array[4] ^ mac_array[3];
+
+ crc[6] = mac_array[47] ^ mac_array[46] ^ mac_array[43] ^ mac_array[41] ^
+ mac_array[38] ^ mac_array[37] ^ mac_array[33] ^ mac_array[32] ^
+ mac_array[29] ^ mac_array[28] ^ mac_array[26] ^ mac_array[21] ^
+ mac_array[19] ^ mac_array[17] ^ mac_array[16] ^ mac_array[14] ^
+ mac_array[12] ^ mac_array[10] ^ mac_array[6] ^ mac_array[5] ^
+ mac_array[4];
+
+ crc[7] = mac_array[47] ^ mac_array[44] ^ mac_array[42] ^ mac_array[39] ^
+ mac_array[38] ^ mac_array[34] ^ mac_array[33] ^ mac_array[30] ^
+ mac_array[29] ^ mac_array[27] ^ mac_array[22] ^ mac_array[20] ^
+ mac_array[18] ^ mac_array[17] ^ mac_array[15] ^ mac_array[13] ^
+ mac_array[11] ^ mac_array[7] ^ mac_array[6] ^ mac_array[5];
+
+ for (i = 0; i < 8; i++)
+ crc_result = crc_result | (crc[i] << i);
+
+ table = MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
+ eth_port_set_filter_table_entry(table, crc_result);
+}
+
+/*
+ * Set the entire multicast list based on dev->mc_list.
+ */
+static void eth_port_set_multicast_list(struct net_device *dev)
+{
+
+ struct dev_mc_list *mc_list;
+ int i;
+ int table_index;
+ struct mv643xx_private *mp = netdev_priv(dev);
+ unsigned int eth_port_num = mp->port_num;
+
+ /* If the device is in promiscuous mode or in all multicast mode,
+ * we will fully populate both multicast tables with accept.
+ * This is guaranteed to yield a match on all multicast addresses...
+ */
+ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) {
+ for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ /* Set all entries in DA filter special multicast
+ * table (Ex_dFSMT)
+ * Set for ETH_Q0 for now
+ * Bits
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue ETH_Q0=0
+ * 7-4 Reserved = 0;
+ */
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+
+ /* Set all entries in DA filter other multicast
+ * table (Ex_dFOMT)
+ * Set for ETH_Q0 for now
+ * Bits
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue ETH_Q0=0
+ * 7-4 Reserved = 0;
+ */
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ }
+ return;
+ }
+
+ /* We will clear out multicast tables every time we get the list.
+ * Then add the entire new list...
+ */
+ for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ /* Clear DA filter special multicast table (Ex_dFSMT) */
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
+
+ /* Clear DA filter other multicast table (Ex_dFOMT) */
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
+ }
+
+ /* Get pointer to net_device multicast list and add each one... */
+ for (i = 0, mc_list = dev->mc_list;
+ (i < 256) && (mc_list != NULL) && (i < dev->mc_count);
+ i++, mc_list = mc_list->next)
+ if (mc_list->dmi_addrlen == 6)
+ eth_port_mc_addr(eth_port_num, mc_list->dmi_addr);
+}
+
+/*
* eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
*
* DESCRIPTION:
@@ -2080,11 +2210,11 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
for (table_index = 0; table_index <= 0xFC; table_index += 4) {
/* Clear DA filter special multicast table (Ex_dFSMT) */
- mv_write((MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
- (eth_port_num) + table_index), 0);
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
/* Clear DA filter other multicast table (Ex_dFOMT) */
- mv_write((MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
- (eth_port_num) + table_index), 0);
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
}
}
@@ -2629,23 +2759,27 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
* Tx ring 'first' and 'used' indexes are updated.
*
* RETURN:
- * ETH_ERROR in case the routine can not access Tx desc ring.
- * ETH_RETRY in case there is transmission in process.
- * ETH_END_OF_JOB if the routine has nothing to release.
- * ETH_OK otherwise.
+ * ETH_OK on success
+ * ETH_ERROR otherwise.
*
*/
static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
struct pkt_info *p_pkt_info)
{
int tx_desc_used;
+ int tx_busy_desc;
+ struct eth_tx_desc *p_tx_desc_used;
+ unsigned int command_status;
+ unsigned long flags;
+ int err = ETH_OK;
+
+ spin_lock_irqsave(&mp->lock, flags);
+
#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
- int tx_busy_desc = mp->tx_first_desc_q;
+ tx_busy_desc = mp->tx_first_desc_q;
#else
- int tx_busy_desc = mp->tx_curr_desc_q;
+ tx_busy_desc = mp->tx_curr_desc_q;
#endif
- struct eth_tx_desc *p_tx_desc_used;
- unsigned int command_status;
/* Get the Tx Desc ring indexes */
tx_desc_used = mp->tx_used_desc_q;
@@ -2653,22 +2787,30 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
/* Sanity check */
- if (p_tx_desc_used == NULL)
- return ETH_ERROR;
+ if (p_tx_desc_used == NULL) {
+ err = ETH_ERROR;
+ goto out;
+ }
/* Stop release. About to overlap the current available Tx descriptor */
- if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err)
- return ETH_END_OF_JOB;
+ if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err) {
+ err = ETH_ERROR;
+ goto out;
+ }
command_status = p_tx_desc_used->cmd_sts;
/* Still transmitting... */
- if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
- return ETH_RETRY;
+ if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+ err = ETH_ERROR;
+ goto out;
+ }
/* Pass the packet information to the caller */
p_pkt_info->cmd_sts = command_status;
p_pkt_info->return_info = mp->tx_skb[tx_desc_used];
+ p_pkt_info->buf_ptr = p_tx_desc_used->buf_ptr;
+ p_pkt_info->byte_cnt = p_tx_desc_used->byte_cnt;
mp->tx_skb[tx_desc_used] = NULL;
/* Update the next descriptor to release. */
@@ -2680,7 +2822,10 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
BUG_ON(mp->tx_ring_skbs == 0);
mp->tx_ring_skbs--;
- return ETH_OK;
+out:
+ spin_unlock_irqrestore(&mp->lock, flags);
+
+ return err;
}
/*
@@ -2712,11 +2857,14 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
volatile struct eth_rx_desc *p_rx_desc;
unsigned int command_status;
+ unsigned long flags;
/* Do not process Rx ring in case of Rx ring resource error */
if (mp->rx_resource_err)
return ETH_QUEUE_FULL;
+ spin_lock_irqsave(&mp->lock, flags);
+
/* Get the Rx Desc ring 'curr and 'used' indexes */
rx_curr_desc = mp->rx_curr_desc_q;
rx_used_desc = mp->rx_used_desc_q;
@@ -2728,8 +2876,10 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
rmb();
/* Nothing to receive... */
- if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+ if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+ spin_unlock_irqrestore(&mp->lock, flags);
return ETH_END_OF_JOB;
+ }
p_pkt_info->byte_cnt = (p_rx_desc->byte_cnt) - RX_BUF_OFFSET;
p_pkt_info->cmd_sts = command_status;
@@ -2737,8 +2887,10 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
p_pkt_info->return_info = mp->rx_skb[rx_curr_desc];
p_pkt_info->l4i_chk = p_rx_desc->buf_size;
- /* Clean the return info field to indicate that the packet has been */
- /* moved to the upper layers */
+ /*
+ * Clean the return info field to indicate that the
+ * packet has been moved to the upper layers
+ */
mp->rx_skb[rx_curr_desc] = NULL;
/* Update current index in data structure */
@@ -2749,6 +2901,8 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
if (rx_next_curr_desc == rx_used_desc)
mp->rx_resource_err = 1;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_OK;
}
@@ -2777,6 +2931,9 @@ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
{
int used_rx_desc; /* Where to return Rx resource */
volatile struct eth_rx_desc *p_used_rx_desc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
/* Get 'used' Rx descriptor */
used_rx_desc = mp->rx_used_desc_q;
@@ -2800,6 +2957,8 @@ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
/* Any Rx return cancels the Rx resource error status */
mp->rx_resource_err = 0;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_OK;
}
@@ -2812,7 +2971,7 @@ struct mv643xx_stats {
};
#define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \
- offsetof(struct mv643xx_private, m)
+ offsetof(struct mv643xx_private, m)
static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
{ "rx_packets", MV643XX_STAT(stats.rx_packets) },
@@ -2963,9 +3122,8 @@ mv643xx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
return 0;
}
-static void
-mv643xx_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
+static void mv643xx_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
{
strncpy(drvinfo->driver, mv643xx_driver_name, 32);
strncpy(drvinfo->version, mv643xx_driver_version, 32);
@@ -2974,39 +3132,37 @@ mv643xx_get_drvinfo(struct net_device *netdev,
drvinfo->n_stats = MV643XX_STATS_LEN;
}
-static int
-mv643xx_get_stats_count(struct net_device *netdev)
+static int mv643xx_get_stats_count(struct net_device *netdev)
{
return MV643XX_STATS_LEN;
}
-static void
-mv643xx_get_ethtool_stats(struct net_device *netdev,
- struct ethtool_stats *stats, uint64_t *data)
+static void mv643xx_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, uint64_t *data)
{
struct mv643xx_private *mp = netdev->priv;
int i;
eth_update_mib_counters(mp);
- for(i = 0; i < MV643XX_STATS_LEN; i++) {
+ for (i = 0; i < MV643XX_STATS_LEN; i++) {
char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset;
- data[i] = (mv643xx_gstrings_stats[i].sizeof_stat ==
+ data[i] = (mv643xx_gstrings_stats[i].sizeof_stat ==
sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
}
}
-static void
-mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
+static void mv643xx_get_strings(struct net_device *netdev, uint32_t stringset,
+ uint8_t *data)
{
int i;
switch(stringset) {
case ETH_SS_STATS:
for (i=0; i < MV643XX_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- mv643xx_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ memcpy(data + i * ETH_GSTRING_LEN,
+ mv643xx_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
}
break;
}
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 1c6d328165b..0245e40b51a 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1610,6 +1610,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
}
else if (!pskb_may_pull(skb, skb->len))
goto err;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2);
if (len <= 0) {
@@ -1690,6 +1692,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
kfree_skb(skb);
} else {
skb_pull(skb, 2); /* chop off protocol */
+ skb_postpull_rcsum(skb, skb->data - 2, 2);
skb->dev = ppp->dev;
skb->protocol = htons(npindex_to_ethertype[npi]);
skb->mac.raw = skb->data;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 2e1bed153c3..6e1018448ee 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -484,13 +484,12 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
int i;
RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
- udelay(1000);
- for (i = 2000; i > 0; i--) {
+ for (i = 20; i > 0; i--) {
/* Check if the RTL8169 has completed writing to the specified MII register */
if (!(RTL_R32(PHYAR) & 0x80000000))
break;
- udelay(100);
+ udelay(25);
}
}
@@ -499,15 +498,14 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr)
int i, value = -1;
RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
- udelay(1000);
- for (i = 2000; i > 0; i--) {
+ for (i = 20; i > 0; i--) {
/* Check if the RTL8169 has completed retrieving data from the specified MII register */
if (RTL_R32(PHYAR) & 0x80000000) {
value = (int) (RTL_R32(PHYAR) & 0xFFFF);
break;
}
- udelay(100);
+ udelay(25);
}
return value;
}
@@ -677,6 +675,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
if (duplex == DUPLEX_HALF)
auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
+
+ if (duplex == DUPLEX_FULL)
+ auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half);
}
tp->phy_auto_nego_reg = auto_nego;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 89c46787676..49b597cbc19 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -3586,7 +3586,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
txdp->Buffer_Pointer = (u64) pci_map_page
(sp->pdev, frag->page, frag->page_offset,
frag->size, PCI_DMA_TODEVICE);
- txdp->Control_1 |= TXD_BUFFER0_SIZE(frag->size);
+ txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
if (skb_shinfo(skb)->ufo_size)
txdp->Control_1 |= TXD_UFO_EN;
}
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index b420182eec4..ed4bc91638d 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -1791,6 +1791,8 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
goto out;
}
+ pci_set_drvdata(pdev, dev);
+
tp = netdev_priv(dev);
ioaddr = tp->mmio_addr;
@@ -1827,8 +1829,6 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
if (rc < 0)
goto err_remove_mii;
- pci_set_drvdata(pdev, dev);
-
net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
pci_name(pdev), sis_chip_info[ent->driver_data].name,
diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h
index 4233ea55670..50323941e3c 100644
--- a/drivers/net/sis900.h
+++ b/drivers/net/sis900.h
@@ -33,7 +33,6 @@ enum sis900_registers {
rxcfg=0x34, //Receive Configuration Register
flctrl=0x38, //Flow Control Register
rxlen=0x3c, //Receive Packet Length Register
- cfgpmcsr=0x44, //Configuration Power Management Control/Status Register
rfcr=0x48, //Receive Filter Control Register
rfdr=0x4C, //Receive Filter Data Register
pmctrl=0xB0, //Power Management Control Register
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index b538e303805..67fb19b8fde 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -1697,6 +1697,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR);
skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+
if (skge->autoneg == AUTONEG_DISABLE) {
reg = GM_GPCR_AU_ALL_DIS;
gma_write16(hw, port, GM_GP_CTRL,
@@ -1704,16 +1705,23 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
switch (skge->speed) {
case SPEED_1000:
+ reg &= ~GM_GPCR_SPEED_100;
reg |= GM_GPCR_SPEED_1000;
- /* fallthru */
+ break;
case SPEED_100:
+ reg &= ~GM_GPCR_SPEED_1000;
reg |= GM_GPCR_SPEED_100;
+ break;
+ case SPEED_10:
+ reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
+ break;
}
if (skge->duplex == DUPLEX_FULL)
reg |= GM_GPCR_DUP_FULL;
} else
reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
+
switch (skge->flow_control) {
case FLOW_MODE_NONE:
skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -3243,12 +3251,22 @@ static int __devinit skge_probe(struct pci_dev *pdev,
pci_set_master(pdev);
- if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)))
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
using_dac = 1;
- else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
- printk(KERN_ERR PFX "%s no usable DMA configuration\n",
- pci_name(pdev));
- goto err_out_free_regions;
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err < 0) {
+ printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto err_out_free_regions;
+ }
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+ pci_name(pdev));
+ goto err_out_free_regions;
+ }
}
#ifdef __BIG_ENDIAN
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index f5d697c0c03..bfeba5b9cd7 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -23,12 +23,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/*
- * TOTEST
- * - speed setting
- * - suspend/resume
- */
-
#include <linux/config.h>
#include <linux/crc32.h>
#include <linux/kernel.h>
@@ -57,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "0.11"
+#define DRV_VERSION "0.15"
#define PFX DRV_NAME " "
/*
@@ -75,6 +69,7 @@
#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
#define RX_DEF_PENDING RX_MAX_PENDING
+#define RX_SKB_ALIGN 8
#define TX_RING_SIZE 512
#define TX_DEF_PENDING (TX_RING_SIZE - 1)
@@ -91,7 +86,7 @@
static const u32 default_msg =
NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
| NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
- | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_INTR;
+ | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
static int debug = -1; /* defaults above */
module_param(debug, int, 0);
@@ -101,6 +96,10 @@ static int copybreak __read_mostly = 256;
module_param(copybreak, int, 0);
MODULE_PARM_DESC(copybreak, "Receive copy threshold");
+static int disable_msi = 0;
+module_param(disable_msi, int, 0);
+MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
+
static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
@@ -197,7 +196,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control);
- vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
+ vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
(power_control & PCI_PM_CAP_PME_D3cold);
pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control);
@@ -521,10 +520,16 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
switch (sky2->speed) {
case SPEED_1000:
+ reg &= ~GM_GPCR_SPEED_100;
reg |= GM_GPCR_SPEED_1000;
- /* fallthru */
+ break;
case SPEED_100:
+ reg &= ~GM_GPCR_SPEED_1000;
reg |= GM_GPCR_SPEED_100;
+ break;
+ case SPEED_10:
+ reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
+ break;
}
if (sky2->duplex == DUPLEX_FULL)
@@ -624,13 +629,16 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
}
-static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, size_t len)
+/* Assign Ram Buffer allocation.
+ * start and end are in units of 4k bytes
+ * ram registers are in units of 64bit words
+ */
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk)
{
- u32 end;
+ u32 start, end;
- start /= 8;
- len /= 8;
- end = start + len - 1;
+ start = startk * 4096/8;
+ end = (endk * 4096/8) - 1;
sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
sky2_write32(hw, RB_ADDR(q, RB_START), start);
@@ -639,14 +647,19 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, size_t len)
sky2_write32(hw, RB_ADDR(q, RB_RP), start);
if (q == Q_R1 || q == Q_R2) {
- u32 rxup, rxlo;
+ u32 space = (endk - startk) * 4096/8;
+ u32 tp = space - space/4;
- rxlo = len/2;
- rxup = rxlo + len/4;
+ /* On receive queue's set the thresholds
+ * give receiver priority when > 3/4 full
+ * send pause when down to 2K
+ */
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
- /* Set thresholds on receive queue's */
- sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), rxup);
- sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), rxlo);
+ tp = space - 2048/8;
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
} else {
/* Enable store & forward on Tx queue's because
* Tx FIFO is only 1K on Yukon
@@ -695,9 +708,10 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
* This is a workaround code taken from SysKonnect sk98lin driver
* to deal with chip bug on Yukon EC rev 0 in the wraparound case.
*/
-static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q,
+static void sky2_put_idx(struct sky2_hw *hw, unsigned q,
u16 idx, u16 *last, u16 size)
{
+ wmb();
if (is_ec_a1(hw) && idx < *last) {
u16 hwget = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX));
@@ -721,6 +735,7 @@ setnew:
sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
}
*last = idx;
+ mmiowb();
}
@@ -734,11 +749,11 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
/* Return high part of DMA address (could be 32 or 64 bit) */
static inline u32 high32(dma_addr_t a)
{
- return (a >> 16) >> 16;
+ return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
}
/* Build description to hardware about buffer */
-static inline void sky2_rx_add(struct sky2_port *sky2, dma_addr_t map)
+static void sky2_rx_add(struct sky2_port *sky2, dma_addr_t map)
{
struct sky2_rx_le *le;
u32 hi = high32(map);
@@ -878,13 +893,13 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
struct sky2_hw *hw = sky2->hw;
u16 port = sky2->port;
- spin_lock(&sky2->tx_lock);
+ spin_lock_bh(&sky2->tx_lock);
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON);
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON);
sky2->vlgrp = grp;
- spin_unlock(&sky2->tx_lock);
+ spin_unlock_bh(&sky2->tx_lock);
}
static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
@@ -893,27 +908,42 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
struct sky2_hw *hw = sky2->hw;
u16 port = sky2->port;
- spin_lock(&sky2->tx_lock);
+ spin_lock_bh(&sky2->tx_lock);
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF);
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF);
if (sky2->vlgrp)
sky2->vlgrp->vlan_devices[vid] = NULL;
- spin_unlock(&sky2->tx_lock);
+ spin_unlock_bh(&sky2->tx_lock);
}
#endif
/*
+ * It appears the hardware has a bug in the FIFO logic that
+ * cause it to hang if the FIFO gets overrun and the receive buffer
+ * is not aligned. ALso alloc_skb() won't align properly if slab
+ * debugging is enabled.
+ */
+static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
+ if (likely(skb)) {
+ unsigned long p = (unsigned long) skb->data;
+ skb_reserve(skb,
+ ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p);
+ }
+
+ return skb;
+}
+
+/*
* Allocate and setup receiver buffer pool.
* In case of 64 bit dma, there are 2X as many list elements
* available as ring entries
* and need to reserve one list element so we don't wrap around.
- *
- * It appears the hardware has a bug in the FIFO logic that
- * cause it to hang if the FIFO gets overrun and the receive buffer
- * is not aligned. This means we can't use skb_reserve to align
- * the IP header.
*/
static int sky2_rx_start(struct sky2_port *sky2)
{
@@ -929,7 +959,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
for (i = 0; i < sky2->rx_pending; i++) {
struct ring_info *re = sky2->rx_ring + i;
- re->skb = dev_alloc_skb(sky2->rx_bufsize);
+ re->skb = sky2_alloc_skb(sky2->rx_bufsize, GFP_KERNEL);
if (!re->skb)
goto nomem;
@@ -986,19 +1016,19 @@ static int sky2_up(struct net_device *dev)
sky2_mac_init(hw, port);
- /* Configure RAM buffers */
- if (hw->chip_id == CHIP_ID_YUKON_FE ||
- (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == 2))
- ramsize = 4096;
- else {
- u8 e0 = sky2_read8(hw, B2_E_0);
- ramsize = (e0 == 0) ? (128 * 1024) : (e0 * 4096);
- }
+ /* Determine available ram buffer space (in 4K blocks).
+ * Note: not sure about the FE setting below yet
+ */
+ if (hw->chip_id == CHIP_ID_YUKON_FE)
+ ramsize = 4;
+ else
+ ramsize = sky2_read8(hw, B2_E_0);
+
+ /* Give transmitter one third (rounded up) */
+ rxspace = ramsize - (ramsize + 2) / 3;
- /* 2/3 for Rx */
- rxspace = (2 * ramsize) / 3;
sky2_ramset(hw, rxqaddr[port], 0, rxspace);
- sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace);
+ sky2_ramset(hw, txqaddr[port], rxspace, ramsize);
/* Make sure SyncQ is disabled */
sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
@@ -1054,7 +1084,7 @@ static inline int tx_avail(const struct sky2_port *sky2)
}
/* Estimate of number of transmit list elements required */
-static inline unsigned tx_le_req(const struct sk_buff *skb)
+static unsigned tx_le_req(const struct sk_buff *skb)
{
unsigned count;
@@ -1090,6 +1120,10 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
u16 mss;
u8 ctrl;
+ /* No BH disabling for tx_lock here. We are running in BH disabled
+ * context and TX reclaim runs via poll inside of a software
+ * interrupt, and no related locks in IRQ processing.
+ */
if (!spin_trylock(&sky2->tx_lock))
return NETDEV_TX_LOCKED;
@@ -1099,8 +1133,9 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
*/
if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
- printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
- dev->name);
+ if (net_ratelimit())
+ printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
+ dev->name);
}
spin_unlock(&sky2->tx_lock);
@@ -1199,7 +1234,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
frag->size, PCI_DMA_TODEVICE);
- addr64 = (mapping >> 16) >> 16;
+ addr64 = high32(mapping);
if (addr64 != sky2->tx_addr64) {
le = get_tx_le(sky2);
le->tx.addr = cpu_to_le32(addr64);
@@ -1229,7 +1264,6 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
out_unlock:
- mmiowb();
spin_unlock(&sky2->tx_lock);
dev->trans_start = jiffies;
@@ -1282,17 +1316,17 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
dev_kfree_skb_any(skb);
}
- spin_lock(&sky2->tx_lock);
sky2->tx_cons = put;
if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE)
netif_wake_queue(dev);
- spin_unlock(&sky2->tx_lock);
}
/* Cleanup all untransmitted buffers, assume transmitter not running */
static void sky2_tx_clean(struct sky2_port *sky2)
{
+ spin_lock_bh(&sky2->tx_lock);
sky2_tx_complete(sky2, sky2->tx_prod);
+ spin_unlock_bh(&sky2->tx_lock);
}
/* Network shutdown */
@@ -1418,6 +1452,29 @@ static void sky2_link_up(struct sky2_port *sky2)
sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
reg = gma_read16(hw, port, GM_GP_CTRL);
+ if (sky2->autoneg == AUTONEG_DISABLE) {
+ reg |= GM_GPCR_AU_ALL_DIS;
+
+ /* Is write/read necessary? Copied from sky2_mac_init */
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+ gma_read16(hw, port, GM_GP_CTRL);
+
+ switch (sky2->speed) {
+ case SPEED_1000:
+ reg &= ~GM_GPCR_SPEED_100;
+ reg |= GM_GPCR_SPEED_1000;
+ break;
+ case SPEED_100:
+ reg &= ~GM_GPCR_SPEED_1000;
+ reg |= GM_GPCR_SPEED_100;
+ break;
+ case SPEED_10:
+ reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100);
+ break;
+ }
+ } else
+ reg &= ~GM_GPCR_AU_ALL_DIS;
+
if (sky2->duplex == DUPLEX_FULL || sky2->autoneg == AUTONEG_ENABLE)
reg |= GM_GPCR_DUP_FULL;
@@ -1582,28 +1639,40 @@ out:
local_irq_enable();
}
+
+/* Transmit timeout is only called if we are running, carries is up
+ * and tx queue is full (stopped).
+ */
static void sky2_tx_timeout(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
unsigned txq = txqaddr[sky2->port];
+ u16 ridx;
+
+ /* Maybe we just missed an status interrupt */
+ spin_lock(&sky2->tx_lock);
+ ridx = sky2_read16(hw,
+ sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX);
+ sky2_tx_complete(sky2, ridx);
+ spin_unlock(&sky2->tx_lock);
+
+ if (!netif_queue_stopped(dev)) {
+ if (net_ratelimit())
+ pr_info(PFX "transmit interrupt missed? recovered\n");
+ return;
+ }
if (netif_msg_timer(sky2))
printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
- netif_stop_queue(dev);
-
sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP);
- sky2_read32(hw, Q_ADDR(txq, Q_CSR));
-
sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
sky2_tx_clean(sky2);
sky2_qset(hw, txq);
sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
-
- netif_wake_queue(dev);
}
@@ -1713,7 +1782,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2,
} else {
struct sk_buff *nskb;
- nskb = dev_alloc_skb(sky2->rx_bufsize);
+ nskb = sky2_alloc_skb(sky2->rx_bufsize, GFP_ATOMIC);
if (!nskb)
goto resubmit;
@@ -1745,7 +1814,7 @@ oversize:
error:
++sky2->net_stats.rx_errors;
- if (netif_msg_rx_err(sky2))
+ if (netif_msg_rx_err(sky2) && net_ratelimit())
printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n",
sky2->netdev->name, status, length);
@@ -1766,13 +1835,16 @@ error:
*/
#define TX_NO_STATUS 0xffff
-static inline void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
+static void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
{
if (last != TX_NO_STATUS) {
struct net_device *dev = hw->dev[port];
if (dev && netif_running(dev)) {
struct sky2_port *sky2 = netdev_priv(dev);
+
+ spin_lock(&sky2->tx_lock);
sky2_tx_complete(sky2, last);
+ spin_unlock(&sky2->tx_lock);
}
}
}
@@ -1789,6 +1861,8 @@ static int sky2_poll(struct net_device *dev0, int *budget)
u16 hwidx;
u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS };
+ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
hwidx = sky2_read16(hw, STAT_PUT_IDX);
BUG_ON(hwidx >= STATUS_RING_SIZE);
rmb();
@@ -1800,7 +1874,6 @@ static int sky2_poll(struct net_device *dev0, int *budget)
struct sk_buff *skb;
u32 status;
u16 length;
- u8 op;
le = hw->st_le + hw->st_idx;
hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
@@ -1814,10 +1887,8 @@ static int sky2_poll(struct net_device *dev0, int *budget)
sky2 = netdev_priv(dev);
status = le32_to_cpu(le->status);
length = le16_to_cpu(le->length);
- op = le->opcode & ~HW_OWNER;
- le->opcode = 0;
- switch (op) {
+ switch (le->opcode & ~HW_OWNER) {
case OP_RXSTAT:
skb = sky2_receive(sky2, length, status);
if (!skb)
@@ -1865,19 +1936,16 @@ static int sky2_poll(struct net_device *dev0, int *budget)
default:
if (net_ratelimit())
printk(KERN_WARNING PFX
- "unknown status opcode 0x%x\n", op);
+ "unknown status opcode 0x%x\n", le->opcode);
break;
}
}
exit_loop:
- sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
- mmiowb();
-
sky2_tx_check(hw, 0, tx_done[0]);
sky2_tx_check(hw, 1, tx_done[1]);
- if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) {
+ if (likely(work_done < to_do)) {
/* need to restart TX timer */
if (is_ec_a1(hw)) {
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
@@ -1887,7 +1955,6 @@ exit_loop:
netif_rx_complete(dev0);
hw->intr_mask |= Y2_IS_STAT_BMU;
sky2_write32(hw, B0_IMSK, hw->intr_mask);
- mmiowb();
return 0;
} else {
*budget -= work_done;
@@ -1900,35 +1967,42 @@ static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)
{
struct net_device *dev = hw->dev[port];
- printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n",
- dev->name, status);
+ if (net_ratelimit())
+ printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n",
+ dev->name, status);
if (status & Y2_IS_PAR_RD1) {
- printk(KERN_ERR PFX "%s: ram data read parity error\n",
- dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: ram data read parity error\n",
+ dev->name);
/* Clear IRQ */
sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR);
}
if (status & Y2_IS_PAR_WR1) {
- printk(KERN_ERR PFX "%s: ram data write parity error\n",
- dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: ram data write parity error\n",
+ dev->name);
sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR);
}
if (status & Y2_IS_PAR_MAC1) {
- printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name);
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
}
if (status & Y2_IS_PAR_RX1) {
- printk(KERN_ERR PFX "%s: RX parity error\n", dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: RX parity error\n", dev->name);
sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR);
}
if (status & Y2_IS_TCP_TXA1) {
- printk(KERN_ERR PFX "%s: TCP segmentation error\n", dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: TCP segmentation error\n",
+ dev->name);
sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP);
}
}
@@ -1944,8 +2018,9 @@ static void sky2_hw_intr(struct sky2_hw *hw)
u16 pci_err;
pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err);
- printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
- pci_name(hw->pdev), pci_err);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
+ pci_name(hw->pdev), pci_err);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
pci_write_config_word(hw->pdev, PCI_STATUS,
@@ -1959,8 +2034,9 @@ static void sky2_hw_intr(struct sky2_hw *hw)
pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err);
- printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
- pci_name(hw->pdev), pex_err);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
+ pci_name(hw->pdev), pex_err);
/* clear the interrupt */
sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
@@ -2092,14 +2168,12 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
static int sky2_reset(struct sky2_hw *hw)
{
- u32 ctst;
u16 status;
u8 t8, pmd_type;
- int i;
-
- ctst = sky2_read32(hw, B0_CTST);
+ int i, err;
sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n",
@@ -2107,12 +2181,6 @@ static int sky2_reset(struct sky2_hw *hw)
return -EOPNOTSUPP;
}
- /* ring for status responses */
- hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
- &hw->st_dma);
- if (!hw->st_le)
- return -ENOMEM;
-
/* disable ASF */
if (hw->chip_id <= CHIP_ID_YUKON_EC) {
sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
@@ -2124,19 +2192,24 @@ static int sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, B0_CTST, CS_RST_CLR);
/* clear PCI errors, if any */
- pci_read_config_word(hw->pdev, PCI_STATUS, &status);
+ err = pci_read_config_word(hw->pdev, PCI_STATUS, &status);
+ if (err)
+ goto pci_err;
+
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- pci_write_config_word(hw->pdev, PCI_STATUS,
- status | PCI_STATUS_ERROR_BITS);
+ err = pci_write_config_word(hw->pdev, PCI_STATUS,
+ status | PCI_STATUS_ERROR_BITS);
+ if (err)
+ goto pci_err;
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
/* clear any PEX errors */
- if (is_pciex(hw)) {
- u16 lstat;
- pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
- 0xffffffffUL);
- pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat);
+ if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) {
+ err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
+ 0xffffffffUL);
+ if (err)
+ goto pci_err;
}
pmd_type = sky2_read8(hw, B2_PMD_TYP);
@@ -2248,9 +2321,17 @@ static int sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
return 0;
+
+pci_err:
+ /* This is to catch a BIOS bug workaround where
+ * mmconfig table doesn't have other buses.
+ */
+ printk(KERN_ERR PFX "%s: can't access PCI config space\n",
+ pci_name(hw->pdev));
+ return err;
}
-static inline u32 sky2_supported_modes(const struct sky2_hw *hw)
+static u32 sky2_supported_modes(const struct sky2_hw *hw)
{
u32 modes;
if (hw->copper) {
@@ -2502,19 +2583,24 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev)
static int sky2_set_mac_address(struct net_device *dev, void *p)
{
struct sky2_port *sky2 = netdev_priv(dev);
- struct sockaddr *addr = p;
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ const struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
- memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8,
+ memcpy_toio(hw->regs + B2_MAC_1 + port * 8,
dev->dev_addr, ETH_ALEN);
- memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8,
+ memcpy_toio(hw->regs + B2_MAC_2 + port * 8,
dev->dev_addr, ETH_ALEN);
- if (netif_running(dev))
- sky2_phy_reinit(sky2);
+ /* virtual address for data */
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
+
+ /* physical address: used for pause frames */
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
return 0;
}
@@ -2794,7 +2880,7 @@ static int sky2_set_coalesce(struct net_device *dev,
if (ecmd->rx_coalesce_usecs_irq == 0)
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP);
else {
- sky2_write32(hw, STAT_TX_TIMER_INI,
+ sky2_write32(hw, STAT_ISR_TIMER_INI,
sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq));
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
}
@@ -2995,7 +3081,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
return dev;
}
-static inline void sky2_show_addr(struct net_device *dev)
+static void __devinit sky2_show_addr(struct net_device *dev)
{
const struct sky2_port *sky2 = netdev_priv(dev);
@@ -3006,6 +3092,61 @@ static inline void sky2_show_addr(struct net_device *dev)
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
}
+/* Handle software interrupt used during MSI test */
+static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct sky2_hw *hw = dev_id;
+ u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
+
+ if (status == 0)
+ return IRQ_NONE;
+
+ if (status & Y2_IS_IRQ_SW) {
+ sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
+ hw->msi = 1;
+ }
+ sky2_write32(hw, B0_Y2_SP_ICR, 2);
+
+ sky2_read32(hw, B0_IMSK);
+ return IRQ_HANDLED;
+}
+
+/* Test interrupt path by forcing a a software IRQ */
+static int __devinit sky2_test_msi(struct sky2_hw *hw)
+{
+ struct pci_dev *pdev = hw->pdev;
+ int i, err;
+
+ sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
+
+ err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw);
+ if (err) {
+ printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
+ pci_name(pdev), pdev->irq);
+ return err;
+ }
+
+ sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
+ wmb();
+
+ for (i = 0; i < 10; i++) {
+ barrier();
+ if (hw->msi)
+ goto found;
+ mdelay(1);
+ }
+
+ err = -EOPNOTSUPP;
+ sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
+ found:
+ sky2_write32(hw, B0_IMSK, 0);
+
+ free_irq(pdev->irq, hw);
+
+ return err;
+}
+
static int __devinit sky2_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -3038,13 +3179,17 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_regions;
}
- if (sizeof(dma_addr_t) > sizeof(u32)) {
- err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
- if (!err)
- using_dac = 1;
- }
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ using_dac = 1;
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err < 0) {
+ printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto err_out_free_regions;
+ }
- if (!using_dac) {
+ } else {
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
printk(KERN_ERR PFX "%s no usable DMA configuration\n",
@@ -3052,6 +3197,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_regions;
}
}
+
#ifdef __BIG_ENDIAN
/* byte swap descriptors in hardware */
{
@@ -3064,14 +3210,13 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
#endif
err = -ENOMEM;
- hw = kmalloc(sizeof(*hw), GFP_KERNEL);
+ hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw) {
printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n",
pci_name(pdev));
goto err_out_free_regions;
}
- memset(hw, 0, sizeof(*hw));
hw->pdev = pdev;
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
@@ -3082,6 +3227,12 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
}
hw->pm_cap = pm_cap;
+ /* ring for status responses */
+ hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
+ &hw->st_dma);
+ if (!hw->st_le)
+ goto err_out_iounmap;
+
err = sky2_reset(hw);
if (err)
goto err_out_iounmap;
@@ -3116,7 +3267,22 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
}
}
- err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw);
+ if (!disable_msi && pci_enable_msi(pdev) == 0) {
+ err = sky2_test_msi(hw);
+ if (err == -EOPNOTSUPP) {
+ /* MSI test failed, go back to INTx mode */
+ printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, "
+ "switching to INTx mode. Please report this failure to "
+ "the PCI maintainer and include system chipset information.\n",
+ pci_name(pdev));
+ pci_disable_msi(pdev);
+ }
+ else if (err)
+ goto err_out_unregister;
+ }
+
+ err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
+ DRV_NAME, hw);
if (err) {
printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
pci_name(pdev), pdev->irq);
@@ -3131,6 +3297,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
return 0;
err_out_unregister:
+ if (hw->msi)
+ pci_disable_msi(pdev);
if (dev1) {
unregister_netdev(dev1);
free_netdev(dev1);
@@ -3173,6 +3341,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
sky2_read8(hw, B0_CTST);
free_irq(pdev->irq, hw);
+ if (hw->msi)
+ pci_disable_msi(pdev);
pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -3210,25 +3380,33 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
static int sky2_resume(struct pci_dev *pdev)
{
struct sky2_hw *hw = pci_get_drvdata(pdev);
- int i;
+ int i, err;
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D0, 0);
- sky2_set_power_state(hw, PCI_D0);
+ err = sky2_set_power_state(hw, PCI_D0);
+ if (err)
+ goto out;
- sky2_reset(hw);
+ err = sky2_reset(hw);
+ if (err)
+ goto out;
for (i = 0; i < 2; i++) {
struct net_device *dev = hw->dev[i];
- if (dev) {
- if (netif_running(dev)) {
- netif_device_attach(dev);
- if (sky2_up(dev))
- dev_close(dev);
+ if (dev && netif_running(dev)) {
+ netif_device_attach(dev);
+ err = sky2_up(dev);
+ if (err) {
+ printk(KERN_ERR PFX "%s: could not up: %d\n",
+ dev->name, err);
+ dev_close(dev);
+ break;
}
}
}
- return 0;
+out:
+ return err;
}
#endif
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 95518921001..fd12c289a23 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1841,6 +1841,7 @@ struct sky2_hw {
struct net_device *dev[2];
int pm_cap;
+ int msi;
u8 chip_id;
u8 chip_rev;
u8 copper;
@@ -1867,14 +1868,6 @@ static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg)
return readb(hw->regs + reg);
}
-/* This should probably go away, bus based tweeks suck */
-static inline int is_pciex(const struct sky2_hw *hw)
-{
- u32 status;
- pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status);
- return (status & PCI_OS_PCI_X) == 0;
-}
-
static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val)
{
writel(val, hw->regs + reg);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 0d765f1733b..1f5975a61e1 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -22,7 +22,6 @@
*/
#include <linux/config.h>
-
#include <linux/compiler.h>
#include <linux/crc32.h>
#include <linux/delay.h>
@@ -30,6 +29,7 @@
#include <linux/ethtool.h>
#include <linux/firmware.h>
#include <linux/if_vlan.h>
+#include <linux/in.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/ip.h>
@@ -43,6 +43,7 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
+#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <asm/bitops.h>
@@ -108,42 +109,6 @@ spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
writel(value, card->regs + reg);
}
-/**
- * spider_net_write_reg_sync - writes to an SMMIO register of a card
- * @card: device structure
- * @reg: register to write to
- * @value: value to write into the specified SMMIO register
- *
- * Unlike spider_net_write_reg, this will also make sure the
- * data arrives on the card by reading the reg again.
- */
-static void
-spider_net_write_reg_sync(struct spider_net_card *card, u32 reg, u32 value)
-{
- value = cpu_to_le32(value);
- writel(value, card->regs + reg);
- (void)readl(card->regs + reg);
-}
-
-/**
- * spider_net_rx_irq_off - switch off rx irq on this spider card
- * @card: device structure
- *
- * switches off rx irq by masking them out in the GHIINTnMSK register
- */
-static void
-spider_net_rx_irq_off(struct spider_net_card *card)
-{
- u32 regvalue;
- unsigned long flags;
-
- spin_lock_irqsave(&card->intmask_lock, flags);
- regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
- regvalue &= ~SPIDER_NET_RXINT;
- spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
- spin_unlock_irqrestore(&card->intmask_lock, flags);
-}
-
/** spider_net_write_phy - write to phy register
* @netdev: adapter to be written to
* @mii_id: id of MII
@@ -199,60 +164,33 @@ spider_net_read_phy(struct net_device *netdev, int mii_id, int reg)
}
/**
- * spider_net_rx_irq_on - switch on rx irq on this spider card
- * @card: device structure
- *
- * switches on rx irq by enabling them in the GHIINTnMSK register
- */
-static void
-spider_net_rx_irq_on(struct spider_net_card *card)
-{
- u32 regvalue;
- unsigned long flags;
-
- spin_lock_irqsave(&card->intmask_lock, flags);
- regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
- regvalue |= SPIDER_NET_RXINT;
- spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
- spin_unlock_irqrestore(&card->intmask_lock, flags);
-}
-
-/**
- * spider_net_tx_irq_off - switch off tx irq on this spider card
+ * spider_net_rx_irq_off - switch off rx irq on this spider card
* @card: device structure
*
- * switches off tx irq by masking them out in the GHIINTnMSK register
+ * switches off rx irq by masking them out in the GHIINTnMSK register
*/
static void
-spider_net_tx_irq_off(struct spider_net_card *card)
+spider_net_rx_irq_off(struct spider_net_card *card)
{
u32 regvalue;
- unsigned long flags;
- spin_lock_irqsave(&card->intmask_lock, flags);
- regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
- regvalue &= ~SPIDER_NET_TXINT;
- spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
- spin_unlock_irqrestore(&card->intmask_lock, flags);
+ regvalue = SPIDER_NET_INT0_MASK_VALUE & (~SPIDER_NET_RXINT);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
}
/**
- * spider_net_tx_irq_on - switch on tx irq on this spider card
+ * spider_net_rx_irq_on - switch on rx irq on this spider card
* @card: device structure
*
- * switches on tx irq by enabling them in the GHIINTnMSK register
+ * switches on rx irq by enabling them in the GHIINTnMSK register
*/
static void
-spider_net_tx_irq_on(struct spider_net_card *card)
+spider_net_rx_irq_on(struct spider_net_card *card)
{
u32 regvalue;
- unsigned long flags;
- spin_lock_irqsave(&card->intmask_lock, flags);
- regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
- regvalue |= SPIDER_NET_TXINT;
- spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
- spin_unlock_irqrestore(&card->intmask_lock, flags);
+ regvalue = SPIDER_NET_INT0_MASK_VALUE | SPIDER_NET_RXINT;
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
}
/**
@@ -326,9 +264,8 @@ static enum spider_net_descr_status
spider_net_get_descr_status(struct spider_net_descr *descr)
{
u32 cmd_status;
- rmb();
+
cmd_status = descr->dmac_cmd_status;
- rmb();
cmd_status >>= SPIDER_NET_DESCR_IND_PROC_SHIFT;
/* no need to mask out any bits, as cmd_status is 32 bits wide only
* (and unsigned) */
@@ -349,7 +286,6 @@ spider_net_set_descr_status(struct spider_net_descr *descr,
{
u32 cmd_status;
/* read the status */
- mb();
cmd_status = descr->dmac_cmd_status;
/* clean the upper 4 bits */
cmd_status &= SPIDER_NET_DESCR_IND_PROC_MASKO;
@@ -357,7 +293,6 @@ spider_net_set_descr_status(struct spider_net_descr *descr,
cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
/* and write it back */
descr->dmac_cmd_status = cmd_status;
- wmb();
}
/**
@@ -398,8 +333,9 @@ spider_net_init_chain(struct spider_net_card *card,
{
int i;
struct spider_net_descr *descr;
+ dma_addr_t buf;
- spin_lock_init(&card->chain_lock);
+ atomic_set(&card->rx_chain_refill,0);
descr = start_descr;
memset(descr, 0, sizeof(*descr) * no);
@@ -408,14 +344,14 @@ spider_net_init_chain(struct spider_net_card *card,
for (i=0; i<no; i++, descr++) {
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
- descr->bus_addr =
- pci_map_single(card->pdev, descr,
- SPIDER_NET_DESCR_SIZE,
- PCI_DMA_BIDIRECTIONAL);
+ buf = pci_map_single(card->pdev, descr,
+ SPIDER_NET_DESCR_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
- if (descr->bus_addr == DMA_ERROR_CODE)
+ if (buf == DMA_ERROR_CODE)
goto iommu_error;
+ descr->bus_addr = buf;
descr->next = descr + 1;
descr->prev = descr - 1;
@@ -439,7 +375,8 @@ iommu_error:
for (i=0; i < no; i++, descr++)
if (descr->bus_addr)
pci_unmap_single(card->pdev, descr->bus_addr,
- SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL);
+ SPIDER_NET_DESCR_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
return -ENOMEM;
}
@@ -459,7 +396,7 @@ spider_net_free_rx_chain_contents(struct spider_net_card *card)
if (descr->skb) {
dev_kfree_skb(descr->skb);
pci_unmap_single(card->pdev, descr->buf_addr,
- SPIDER_NET_MAX_MTU,
+ SPIDER_NET_MAX_FRAME,
PCI_DMA_BIDIRECTIONAL);
}
descr = descr->next;
@@ -480,12 +417,13 @@ static int
spider_net_prepare_rx_descr(struct spider_net_card *card,
struct spider_net_descr *descr)
{
+ dma_addr_t buf;
int error = 0;
int offset;
int bufsize;
/* we need to round up the buffer size to a multiple of 128 */
- bufsize = (SPIDER_NET_MAX_MTU + SPIDER_NET_RXBUF_ALIGN - 1) &
+ bufsize = (SPIDER_NET_MAX_FRAME + SPIDER_NET_RXBUF_ALIGN - 1) &
(~(SPIDER_NET_RXBUF_ALIGN - 1));
/* and we need to have it 128 byte aligned, therefore we allocate a
@@ -493,10 +431,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
/* allocate an skb */
descr->skb = dev_alloc_skb(bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
if (!descr->skb) {
- if (net_ratelimit())
- if (netif_msg_rx_err(card))
- pr_err("Not enough memory to allocate "
- "rx buffer\n");
+ if (netif_msg_rx_err(card) && net_ratelimit())
+ pr_err("Not enough memory to allocate rx buffer\n");
return -ENOMEM;
}
descr->buf_size = bufsize;
@@ -510,12 +446,12 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
if (offset)
skb_reserve(descr->skb, SPIDER_NET_RXBUF_ALIGN - offset);
/* io-mmu-map the skb */
- descr->buf_addr = pci_map_single(card->pdev, descr->skb->data,
- SPIDER_NET_MAX_MTU,
- PCI_DMA_BIDIRECTIONAL);
- if (descr->buf_addr == DMA_ERROR_CODE) {
+ buf = pci_map_single(card->pdev, descr->skb->data,
+ SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+ descr->buf_addr = buf;
+ if (buf == DMA_ERROR_CODE) {
dev_kfree_skb_any(descr->skb);
- if (netif_msg_rx_err(card))
+ if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Could not iommu-map rx buffer\n");
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
} else {
@@ -526,10 +462,10 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
}
/**
- * spider_net_enable_rxctails - sets RX dmac chain tail addresses
+ * spider_net_enable_rxchtails - sets RX dmac chain tail addresses
* @card: card structure
*
- * spider_net_enable_rxctails sets the RX DMAC chain tail adresses in the
+ * spider_net_enable_rxchtails sets the RX DMAC chain tail adresses in the
* chip by writing to the appropriate register. DMA is enabled in
* spider_net_enable_rxdmac.
*/
@@ -551,6 +487,7 @@ spider_net_enable_rxchtails(struct spider_net_card *card)
static void
spider_net_enable_rxdmac(struct spider_net_card *card)
{
+ wmb();
spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
SPIDER_NET_DMA_RX_VALUE);
}
@@ -559,32 +496,28 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
* spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
* @card: card structure
*
- * refills descriptors in all chains (last used chain first): allocates skbs
- * and iommu-maps them.
+ * refills descriptors in the rx chain: allocates skbs and iommu-maps them.
*/
static void
spider_net_refill_rx_chain(struct spider_net_card *card)
{
struct spider_net_descr_chain *chain;
- int count = 0;
- unsigned long flags;
chain = &card->rx_chain;
- spin_lock_irqsave(&card->chain_lock, flags);
- while (spider_net_get_descr_status(chain->head) ==
- SPIDER_NET_DESCR_NOT_IN_USE) {
- if (spider_net_prepare_rx_descr(card, chain->head))
- break;
- count++;
- chain->head = chain->head->next;
- }
- spin_unlock_irqrestore(&card->chain_lock, flags);
+ /* one context doing the refill (and a second context seeing that
+ * and omitting it) is ok. If called by NAPI, we'll be called again
+ * as spider_net_decode_one_descr is called several times. If some
+ * interrupt calls us, the NAPI is about to clean up anyway. */
+ if (atomic_inc_return(&card->rx_chain_refill) == 1)
+ while (spider_net_get_descr_status(chain->head) ==
+ SPIDER_NET_DESCR_NOT_IN_USE) {
+ if (spider_net_prepare_rx_descr(card, chain->head))
+ break;
+ chain->head = chain->head->next;
+ }
- /* could be optimized, only do that, if we know the DMA processing
- * has terminated */
- if (count)
- spider_net_enable_rxdmac(card);
+ atomic_dec(&card->rx_chain_refill);
}
/**
@@ -613,6 +546,7 @@ spider_net_alloc_rx_skbs(struct spider_net_card *card)
/* this will allocate the rest of the rx buffers; if not, it's
* business as usual later on */
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
return 0;
error:
@@ -649,24 +583,30 @@ spider_net_release_tx_descr(struct spider_net_card *card,
* @card: adapter structure
* @brutal: if set, don't care about whether descriptor seems to be in use
*
- * releases the tx descriptors that spider has finished with (if non-brutal)
- * or simply release tx descriptors (if brutal)
+ * returns 0 if the tx ring is empty, otherwise 1.
+ *
+ * spider_net_release_tx_chain releases the tx descriptors that spider has
+ * finished with (if non-brutal) or simply release tx descriptors (if brutal).
+ * If some other context is calling this function, we return 1 so that we're
+ * scheduled again (if we were scheduled) and will not loose initiative.
*/
-static void
+static int
spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
{
struct spider_net_descr_chain *tx_chain = &card->tx_chain;
enum spider_net_descr_status status;
- spider_net_tx_irq_off(card);
+ if (atomic_inc_return(&card->tx_chain_release) != 1) {
+ atomic_dec(&card->tx_chain_release);
+ return 1;
+ }
- /* no lock for chain needed, if this is only executed once at a time */
-again:
for (;;) {
status = spider_net_get_descr_status(tx_chain->tail);
switch (status) {
case SPIDER_NET_DESCR_CARDOWNED:
- if (!brutal) goto out;
+ if (!brutal)
+ goto out;
/* fallthrough, if we release the descriptors
* brutally (then we don't care about
* SPIDER_NET_DESCR_CARDOWNED) */
@@ -693,25 +633,30 @@ again:
tx_chain->tail = tx_chain->tail->next;
}
out:
+ atomic_dec(&card->tx_chain_release);
+
netif_wake_queue(card->netdev);
- if (!brutal) {
- /* switch on tx irqs (while we are still in the interrupt
- * handler, so we don't get an interrupt), check again
- * for done descriptors. This results in fewer interrupts */
- spider_net_tx_irq_on(card);
- status = spider_net_get_descr_status(tx_chain->tail);
- switch (status) {
- case SPIDER_NET_DESCR_RESPONSE_ERROR:
- case SPIDER_NET_DESCR_PROTECTION_ERROR:
- case SPIDER_NET_DESCR_FORCE_END:
- case SPIDER_NET_DESCR_COMPLETE:
- goto again;
- default:
- break;
- }
- }
+ if (status == SPIDER_NET_DESCR_CARDOWNED)
+ return 1;
+ return 0;
+}
+/**
+ * spider_net_cleanup_tx_ring - cleans up the TX ring
+ * @card: card structure
+ *
+ * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
+ * interrupts to cleanup our TX ring) and returns sent packets to the stack
+ * by freeing them
+ */
+static void
+spider_net_cleanup_tx_ring(struct spider_net_card *card)
+{
+ if ( (spider_net_release_tx_chain(card, 0)) &&
+ (card->netdev->flags & IFF_UP) ) {
+ mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
+ }
}
/**
@@ -726,16 +671,22 @@ out:
static u8
spider_net_get_multicast_hash(struct net_device *netdev, __u8 *addr)
{
- /* FIXME: an addr of 01:00:5e:00:00:01 must result in 0xa9,
- * ff:ff:ff:ff:ff:ff must result in 0xfd */
u32 crc;
u8 hash;
+ char addr_for_crc[ETH_ALEN] = { 0, };
+ int i, bit;
- crc = crc32_be(~0, addr, netdev->addr_len);
+ for (i = 0; i < ETH_ALEN * 8; i++) {
+ bit = (addr[i / 8] >> (i % 8)) & 1;
+ addr_for_crc[ETH_ALEN - 1 - i / 8] += bit << (7 - (i % 8));
+ }
+
+ crc = crc32_be(~0, addr_for_crc, netdev->addr_len);
hash = (crc >> 27);
hash <<= 3;
hash |= crc & 7;
+ hash &= 0xff;
return hash;
}
@@ -821,9 +772,11 @@ spider_net_stop(struct net_device *netdev)
{
struct spider_net_card *card = netdev_priv(netdev);
+ tasklet_kill(&card->rxram_full_tl);
netif_poll_disable(netdev);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
+ del_timer_sync(&card->tx_timer);
/* disable/mask all interrupts */
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
@@ -872,13 +825,15 @@ spider_net_get_next_tx_descr(struct spider_net_card *card)
* @skb: packet to consider
*
* fills out the command and status field of the descriptor structure,
- * depending on hardware checksum settings. This function assumes a wmb()
- * has executed before.
+ * depending on hardware checksum settings.
*/
static void
spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
struct sk_buff *skb)
{
+ /* make sure the other fields in the descriptor are written */
+ wmb();
+
if (skb->ip_summed != CHECKSUM_HW) {
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
return;
@@ -887,14 +842,13 @@ spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
/* is packet ip?
* if yes: tcp? udp? */
if (skb->protocol == htons(ETH_P_IP)) {
- if (skb->nh.iph->protocol == IPPROTO_TCP) {
+ if (skb->nh.iph->protocol == IPPROTO_TCP)
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
- } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ else if (skb->nh.iph->protocol == IPPROTO_UDP)
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_UDPCS;
- } else { /* the stack should checksum non-tcp and non-udp
- packets on his own: NETIF_F_IP_CSUM */
+ else /* the stack should checksum non-tcp and non-udp
+ packets on his own: NETIF_F_IP_CSUM */
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
- }
}
}
@@ -914,23 +868,22 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
struct spider_net_descr *descr,
struct sk_buff *skb)
{
- descr->buf_addr = pci_map_single(card->pdev, skb->data,
- skb->len, PCI_DMA_BIDIRECTIONAL);
- if (descr->buf_addr == DMA_ERROR_CODE) {
- if (netif_msg_tx_err(card))
+ dma_addr_t buf;
+
+ buf = pci_map_single(card->pdev, skb->data,
+ skb->len, PCI_DMA_BIDIRECTIONAL);
+ if (buf == DMA_ERROR_CODE) {
+ if (netif_msg_tx_err(card) && net_ratelimit())
pr_err("could not iommu-map packet (%p, %i). "
"Dropping packet\n", skb->data, skb->len);
return -ENOMEM;
}
+ descr->buf_addr = buf;
descr->buf_size = skb->len;
descr->skb = skb;
descr->data_status = 0;
- /* make sure the above values are in memory before we change the
- * status */
- wmb();
-
spider_net_set_txdescr_cmdstat(descr,skb);
return 0;
@@ -972,17 +925,12 @@ spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
struct spider_net_descr *descr;
int result;
- descr = spider_net_get_next_tx_descr(card);
+ spider_net_release_tx_chain(card, 0);
- if (!descr) {
- netif_stop_queue(netdev);
+ descr = spider_net_get_next_tx_descr(card);
- descr = spider_net_get_next_tx_descr(card);
- if (!descr)
- goto error;
- else
- netif_start_queue(netdev);
- }
+ if (!descr)
+ goto error;
result = spider_net_prepare_tx_descr(card, descr, skb);
if (result)
@@ -990,19 +938,25 @@ spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
card->tx_chain.head = card->tx_chain.head->next;
- /* make sure the status from spider_net_prepare_tx_descr is in
- * memory before we check out the previous descriptor */
- wmb();
-
if (spider_net_get_descr_status(descr->prev) !=
- SPIDER_NET_DESCR_CARDOWNED)
- spider_net_kick_tx_dma(card, descr);
+ SPIDER_NET_DESCR_CARDOWNED) {
+ /* make sure the current descriptor is in memory. Then
+ * kicking it on again makes sense, if the previous is not
+ * card-owned anymore. Check the previous descriptor twice
+ * to omit an mb() in heavy traffic cases */
+ mb();
+ if (spider_net_get_descr_status(descr->prev) !=
+ SPIDER_NET_DESCR_CARDOWNED)
+ spider_net_kick_tx_dma(card, descr);
+ }
+
+ mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
return NETDEV_TX_OK;
error:
card->netdev_stats.tx_dropped++;
- return NETDEV_TX_LOCKED;
+ return NETDEV_TX_BUSY;
}
/**
@@ -1027,6 +981,7 @@ spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
* spider_net_pass_skb_up - takes an skb from a descriptor and passes it on
* @descr: descriptor to process
* @card: card structure
+ * @napi: whether caller is in NAPI context
*
* returns 1 on success, 0 if no packet was passed to the stack
*
@@ -1035,7 +990,7 @@ spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
*/
static int
spider_net_pass_skb_up(struct spider_net_descr *descr,
- struct spider_net_card *card)
+ struct spider_net_card *card, int napi)
{
struct sk_buff *skb;
struct net_device *netdev;
@@ -1046,22 +1001,20 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
netdev = card->netdev;
- /* check for errors in the data_error flag */
- if ((data_error & SPIDER_NET_DATA_ERROR_MASK) &&
- netif_msg_rx_err(card))
- pr_err("error in received descriptor found, "
- "data_status=x%08x, data_error=x%08x\n",
- data_status, data_error);
-
- /* prepare skb, unmap descriptor */
- skb = descr->skb;
- pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_MTU,
+ /* unmap descriptor */
+ pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_FRAME,
PCI_DMA_BIDIRECTIONAL);
/* the cases we'll throw away the packet immediately */
- if (data_error & SPIDER_NET_DESTROY_RX_FLAGS)
+ if (data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
+ if (netif_msg_rx_err(card))
+ pr_err("error in received descriptor found, "
+ "data_status=x%08x, data_error=x%08x\n",
+ data_status, data_error);
return 0;
+ }
+ skb = descr->skb;
skb->dev = netdev;
skb_put(skb, descr->valid_size);
@@ -1073,14 +1026,14 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
/* checksum offload */
if (card->options.rx_csum) {
- if ( (data_status & SPIDER_NET_DATA_STATUS_CHK_MASK) &&
- (!(data_error & SPIDER_NET_DATA_ERROR_CHK_MASK)) )
+ if ( ( (data_status & SPIDER_NET_DATA_STATUS_CKSUM_MASK) ==
+ SPIDER_NET_DATA_STATUS_CKSUM_MASK) &&
+ !(data_error & SPIDER_NET_DATA_ERR_CKSUM_MASK))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
- } else {
+ } else
skb->ip_summed = CHECKSUM_NONE;
- }
if (data_status & SPIDER_NET_VLAN_PACKET) {
/* further enhancements: HW-accel VLAN
@@ -1089,7 +1042,10 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
}
/* pass skb up to stack */
- netif_receive_skb(skb);
+ if (napi)
+ netif_receive_skb(skb);
+ else
+ netif_rx_ni(skb);
/* update netdevice statistics */
card->netdev_stats.rx_packets++;
@@ -1099,16 +1055,18 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
}
/**
- * spider_net_decode_descr - processes an rx descriptor
+ * spider_net_decode_one_descr - processes an rx descriptor
* @card: card structure
+ * @napi: whether caller is in NAPI context
*
* returns 1 if a packet has been sent to the stack, otherwise 0
*
* processes an rx descriptor by iommu-unmapping the data buffer and passing
- * the packet up to the stack
+ * the packet up to the stack. This function is called in softirq
+ * context, e.g. either bottom half from interrupt or NAPI polling context
*/
static int
-spider_net_decode_one_descr(struct spider_net_card *card)
+spider_net_decode_one_descr(struct spider_net_card *card, int napi)
{
enum spider_net_descr_status status;
struct spider_net_descr *descr;
@@ -1122,17 +1080,19 @@ spider_net_decode_one_descr(struct spider_net_card *card)
if (status == SPIDER_NET_DESCR_CARDOWNED) {
/* nothing in the descriptor yet */
- return 0;
+ result=0;
+ goto out;
}
if (status == SPIDER_NET_DESCR_NOT_IN_USE) {
- /* not initialized yet, I bet chain->tail == chain->head
- * and the ring is empty */
+ /* not initialized yet, the ring must be empty */
spider_net_refill_rx_chain(card);
- return 0;
+ spider_net_enable_rxdmac(card);
+ result=0;
+ goto out;
}
- /* descriptor definitively used -- move on head */
+ /* descriptor definitively used -- move on tail */
chain->tail = descr->next;
result = 0;
@@ -1143,6 +1103,9 @@ spider_net_decode_one_descr(struct spider_net_card *card)
pr_err("%s: dropping RX descriptor with state %d\n",
card->netdev->name, status);
card->netdev_stats.rx_dropped++;
+ pci_unmap_single(card->pdev, descr->buf_addr,
+ SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+ dev_kfree_skb_irq(descr->skb);
goto refill;
}
@@ -1155,12 +1118,13 @@ spider_net_decode_one_descr(struct spider_net_card *card)
}
/* ok, we've got a packet in descr */
- result = spider_net_pass_skb_up(descr, card);
+ result = spider_net_pass_skb_up(descr, card, napi);
refill:
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
/* change the descriptor state: */
- spider_net_refill_rx_chain(card);
-
+ if (!napi)
+ spider_net_refill_rx_chain(card);
+out:
return result;
}
@@ -1186,7 +1150,7 @@ spider_net_poll(struct net_device *netdev, int *budget)
packets_to_do = min(*budget, netdev->quota);
while (packets_to_do) {
- if (spider_net_decode_one_descr(card)) {
+ if (spider_net_decode_one_descr(card, 1)) {
packets_done++;
packets_to_do--;
} else {
@@ -1198,6 +1162,7 @@ spider_net_poll(struct net_device *netdev, int *budget)
netdev->quota -= packets_done;
*budget -= packets_done;
+ spider_net_refill_rx_chain(card);
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
@@ -1342,6 +1307,24 @@ spider_net_enable_txdmac(struct spider_net_card *card)
}
/**
+ * spider_net_handle_rxram_full - cleans up RX ring upon RX RAM full interrupt
+ * @card: card structure
+ *
+ * spider_net_handle_rxram_full empties the RX ring so that spider can put
+ * more packets in it and empty its RX RAM. This is called in bottom half
+ * context
+ */
+static void
+spider_net_handle_rxram_full(struct spider_net_card *card)
+{
+ while (spider_net_decode_one_descr(card, 0))
+ ;
+ spider_net_enable_rxchtails(card);
+ spider_net_enable_rxdmac(card);
+ netif_rx_schedule(card->netdev);
+}
+
+/**
* spider_net_handle_error_irq - handles errors raised by an interrupt
* @card: card structure
* @status_reg: interrupt status register 0 (GHIINT0STS)
@@ -1449,17 +1432,21 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
switch (i)
{
case SPIDER_NET_GTMFLLINT:
- if (netif_msg_intr(card))
+ if (netif_msg_intr(card) && net_ratelimit())
pr_err("Spider TX RAM full\n");
show_error = 0;
break;
+ case SPIDER_NET_GRFDFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFCFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFBFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFAFLLINT: /* fallthrough */
case SPIDER_NET_GRMFLLINT:
- if (netif_msg_intr(card))
+ if (netif_msg_intr(card) && net_ratelimit())
pr_err("Spider RX RAM full, incoming packets "
- "might be discarded !\n");
- netif_rx_schedule(card->netdev);
- spider_net_enable_rxchtails(card);
- spider_net_enable_rxdmac(card);
+ "might be discarded!\n");
+ spider_net_rx_irq_off(card);
+ tasklet_schedule(&card->rxram_full_tl);
+ show_error = 0;
break;
/* case SPIDER_NET_GTMSHTINT: problem, print a message */
@@ -1467,10 +1454,6 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
/* allrighty. tx from previous descr ok */
show_error = 0;
break;
- /* case SPIDER_NET_GRFDFLLINT: print a message down there */
- /* case SPIDER_NET_GRFCFLLINT: print a message down there */
- /* case SPIDER_NET_GRFBFLLINT: print a message down there */
- /* case SPIDER_NET_GRFAFLLINT: print a message down there */
/* chain end */
case SPIDER_NET_GDDDCEINT: /* fallthrough */
@@ -1482,6 +1465,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
"restarting DMAC %c.\n",
'D'+i-SPIDER_NET_GDDDCEINT);
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
show_error = 0;
break;
@@ -1492,6 +1476,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GDAINVDINT:
/* could happen when rx chain is full */
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
show_error = 0;
break;
@@ -1580,17 +1565,13 @@ spider_net_interrupt(int irq, void *ptr, struct pt_regs *regs)
if (!status_reg)
return IRQ_NONE;
- if (status_reg & SPIDER_NET_TXINT)
- spider_net_release_tx_chain(card, 0);
-
if (status_reg & SPIDER_NET_RXINT ) {
spider_net_rx_irq_off(card);
netif_rx_schedule(netdev);
}
- /* we do this after rx and tx processing, as we want the tx chain
- * processed to see, whether we should restart tx dma processing */
- spider_net_handle_error_irq(card, status_reg);
+ if (status_reg & SPIDER_NET_ERRINT )
+ spider_net_handle_error_irq(card, status_reg);
/* clear interrupt sources */
spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
@@ -1831,34 +1812,40 @@ spider_net_setup_phy(struct spider_net_card *card)
/**
* spider_net_download_firmware - loads firmware into the adapter
* @card: card structure
- * @firmware: firmware pointer
+ * @firmware_ptr: pointer to firmware data
*
- * spider_net_download_firmware loads the firmware opened by
- * spider_net_init_firmware into the adapter.
+ * spider_net_download_firmware loads the firmware data into the
+ * adapter. It assumes the length etc. to be allright.
*/
-static void
+static int
spider_net_download_firmware(struct spider_net_card *card,
- const struct firmware *firmware)
+ u8 *firmware_ptr)
{
int sequencer, i;
- u32 *fw_ptr = (u32 *)firmware->data;
+ u32 *fw_ptr = (u32 *)firmware_ptr;
/* stop sequencers */
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_STOP_SEQ_VALUE);
- for (sequencer = 0; sequencer < 6; sequencer++) {
+ for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
+ sequencer++) {
spider_net_write_reg(card,
SPIDER_NET_GSnPRGADR + sequencer * 8, 0);
- for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, *fw_ptr);
fw_ptr++;
}
}
+ if (spider_net_read_reg(card, SPIDER_NET_GSINIT))
+ return -EIO;
+
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_RUN_SEQ_VALUE);
+
+ return 0;
}
/**
@@ -1890,31 +1877,53 @@ spider_net_download_firmware(struct spider_net_card *card,
static int
spider_net_init_firmware(struct spider_net_card *card)
{
- const struct firmware *firmware;
- int err = -EIO;
+ struct firmware *firmware = NULL;
+ struct device_node *dn;
+ u8 *fw_prop = NULL;
+ int err = -ENOENT;
+ int fw_size;
+
+ if (request_firmware((const struct firmware **)&firmware,
+ SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
+ if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
+ netif_msg_probe(card) ) {
+ pr_err("Incorrect size of spidernet firmware in " \
+ "filesystem. Looking in host firmware...\n");
+ goto try_host_fw;
+ }
+ err = spider_net_download_firmware(card, firmware->data);
- if (request_firmware(&firmware,
- SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) < 0) {
- if (netif_msg_probe(card))
- pr_err("Couldn't read in sequencer data file %s.\n",
- SPIDER_NET_FIRMWARE_NAME);
- firmware = NULL;
- goto out;
- }
+ release_firmware(firmware);
+ if (err)
+ goto try_host_fw;
- if (firmware->size != 6 * SPIDER_NET_FIRMWARE_LEN * sizeof(u32)) {
- if (netif_msg_probe(card))
- pr_err("Invalid size of sequencer data file %s.\n",
- SPIDER_NET_FIRMWARE_NAME);
- goto out;
+ goto done;
}
- spider_net_download_firmware(card, firmware);
+try_host_fw:
+ dn = pci_device_to_OF_node(card->pdev);
+ if (!dn)
+ goto out_err;
- err = 0;
-out:
- release_firmware(firmware);
+ fw_prop = (u8 *)get_property(dn, "firmware", &fw_size);
+ if (!fw_prop)
+ goto out_err;
+
+ if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
+ netif_msg_probe(card) ) {
+ pr_err("Incorrect size of spidernet firmware in " \
+ "host firmware\n");
+ goto done;
+ }
+ err = spider_net_download_firmware(card, fw_prop);
+
+done:
+ return err;
+out_err:
+ if (netif_msg_probe(card))
+ pr_err("Couldn't find spidernet firmware in filesystem " \
+ "or host firmware\n");
return err;
}
@@ -1934,10 +1943,11 @@ spider_net_workaround_rxramfull(struct spider_net_card *card)
SPIDER_NET_CKRCTRL_RUN_VALUE);
/* empty sequencer data */
- for (sequencer = 0; sequencer < 6; sequencer++) {
+ for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
+ sequencer++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, 0x0);
- for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, 0x0);
}
@@ -2061,7 +2071,15 @@ spider_net_setup_netdev(struct spider_net_card *card)
SET_NETDEV_DEV(netdev, &card->pdev->dev);
pci_set_drvdata(card->pdev, netdev);
- spin_lock_init(&card->intmask_lock);
+
+ atomic_set(&card->tx_chain_release,0);
+ card->rxram_full_tl.data = (unsigned long) card;
+ card->rxram_full_tl.func =
+ (void (*)(unsigned long)) spider_net_handle_rxram_full;
+ init_timer(&card->tx_timer);
+ card->tx_timer.function =
+ (void (*)(unsigned long)) spider_net_cleanup_tx_ring;
+ card->tx_timer.data = (unsigned long) card;
netdev->irq = card->pdev->irq;
card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 22b2f234735..5922b529a04 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -33,25 +33,32 @@ extern struct ethtool_ops spider_net_ethtool_ops;
extern char spider_net_driver_name[];
-#define SPIDER_NET_MAX_MTU 2308
+#define SPIDER_NET_MAX_FRAME 2312
+#define SPIDER_NET_MAX_MTU 2294
#define SPIDER_NET_MIN_MTU 64
#define SPIDER_NET_RXBUF_ALIGN 128
-#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT 256
#define SPIDER_NET_RX_DESCRIPTORS_MIN 16
-#define SPIDER_NET_RX_DESCRIPTORS_MAX 256
+#define SPIDER_NET_RX_DESCRIPTORS_MAX 512
-#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT 256
#define SPIDER_NET_TX_DESCRIPTORS_MIN 16
-#define SPIDER_NET_TX_DESCRIPTORS_MAX 256
+#define SPIDER_NET_TX_DESCRIPTORS_MAX 512
+
+#define SPIDER_NET_TX_TIMER 20
#define SPIDER_NET_RX_CSUM_DEFAULT 1
-#define SPIDER_NET_WATCHDOG_TIMEOUT 5*HZ
-#define SPIDER_NET_NAPI_WEIGHT 64
+#define SPIDER_NET_WATCHDOG_TIMEOUT 50*HZ
+#define SPIDER_NET_NAPI_WEIGHT 64
-#define SPIDER_NET_FIRMWARE_LEN 1024
+#define SPIDER_NET_FIRMWARE_SEQS 6
+#define SPIDER_NET_FIRMWARE_SEQWORDS 1024
+#define SPIDER_NET_FIRMWARE_LEN (SPIDER_NET_FIRMWARE_SEQS * \
+ SPIDER_NET_FIRMWARE_SEQWORDS * \
+ sizeof(u32))
#define SPIDER_NET_FIRMWARE_NAME "spider_fw.bin"
/** spider_net SMMIO registers */
@@ -142,14 +149,12 @@ extern char spider_net_driver_name[];
/** SCONFIG registers */
#define SPIDER_NET_SCONFIG_IOACTE 0x00002810
-/** hardcoded register values */
-#define SPIDER_NET_INT0_MASK_VALUE 0x3f7fe3ff
-#define SPIDER_NET_INT1_MASK_VALUE 0xffffffff
+/** interrupt mask registers */
+#define SPIDER_NET_INT0_MASK_VALUE 0x3f7fe2c7
+#define SPIDER_NET_INT1_MASK_VALUE 0xffff7ff7
/* no MAC aborts -> auto retransmission */
-#define SPIDER_NET_INT2_MASK_VALUE 0xfffffff1
+#define SPIDER_NET_INT2_MASK_VALUE 0xffef7ff1
-/* clear counter when interrupt sources are cleared
-#define SPIDER_NET_FRAMENUM_VALUE 0x0001f001 */
/* we rely on flagged descriptor interrupts */
#define SPIDER_NET_FRAMENUM_VALUE 0x00000000
/* set this first, then the FRAMENUM_VALUE */
@@ -168,7 +173,7 @@ extern char spider_net_driver_name[];
#if 0
#define SPIDER_NET_WOL_VALUE 0x00000000
#endif
-#define SPIDER_NET_IPSECINIT_VALUE 0x00f000f8
+#define SPIDER_NET_IPSECINIT_VALUE 0x6f716f71
/* pause frames: automatic, no upper retransmission count */
/* outside loopback mode: ETOMOD signal dont matter, not connected */
@@ -318,6 +323,10 @@ enum spider_net_int2_status {
#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) | \
(1 << SPIDER_NET_GRMFLLINT) )
+#define SPIDER_NET_ERRINT ( 0xffffffff & \
+ (~SPIDER_NET_TXINT) & \
+ (~SPIDER_NET_RXINT) )
+
#define SPIDER_NET_GPREXEC 0x80000000
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
@@ -358,9 +367,6 @@ enum spider_net_int2_status {
/* descr ready, descr is in middle of chain, get interrupt on completion */
#define SPIDER_NET_DMAC_RX_CARDOWNED 0xa0800000
-/* multicast is no problem */
-#define SPIDER_NET_DATA_ERROR_MASK 0xffffbfff
-
enum spider_net_descr_status {
SPIDER_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */
SPIDER_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */
@@ -373,9 +379,9 @@ enum spider_net_descr_status {
struct spider_net_descr {
/* as defined by the hardware */
- dma_addr_t buf_addr;
+ u32 buf_addr;
u32 buf_size;
- dma_addr_t next_descr_addr;
+ u32 next_descr_addr;
u32 dmac_cmd_status;
u32 result_size;
u32 valid_size; /* all zeroes for tx */
@@ -384,7 +390,7 @@ struct spider_net_descr {
/* used in the driver */
struct sk_buff *skb;
- dma_addr_t bus_addr;
+ u32 bus_addr;
struct spider_net_descr *next;
struct spider_net_descr *prev;
} __attribute__((aligned(32)));
@@ -396,21 +402,21 @@ struct spider_net_descr_chain {
};
/* descriptor data_status bits */
-#define SPIDER_NET_RXIPCHK 29
-#define SPIDER_NET_TCPUDPIPCHK 28
-#define SPIDER_NET_DATA_STATUS_CHK_MASK (1 << SPIDER_NET_RXIPCHK | \
- 1 << SPIDER_NET_TCPUDPIPCHK)
-
+#define SPIDER_NET_RX_IPCHK 29
+#define SPIDER_NET_RX_TCPCHK 28
#define SPIDER_NET_VLAN_PACKET 21
+#define SPIDER_NET_DATA_STATUS_CKSUM_MASK ( (1 << SPIDER_NET_RX_IPCHK) | \
+ (1 << SPIDER_NET_RX_TCPCHK) )
/* descriptor data_error bits */
-#define SPIDER_NET_RXIPCHKERR 27
-#define SPIDER_NET_RXTCPCHKERR 26
-#define SPIDER_NET_DATA_ERROR_CHK_MASK (1 << SPIDER_NET_RXIPCHKERR | \
- 1 << SPIDER_NET_RXTCPCHKERR)
+#define SPIDER_NET_RX_IPCHKERR 27
+#define SPIDER_NET_RX_RXTCPCHKERR 28
+
+#define SPIDER_NET_DATA_ERR_CKSUM_MASK (1 << SPIDER_NET_RX_IPCHKERR)
-/* the cases we don't pass the packet to the stack */
-#define SPIDER_NET_DESTROY_RX_FLAGS 0x70138000
+/* the cases we don't pass the packet to the stack.
+ * 701b8000 would be correct, but every packets gets that flag */
+#define SPIDER_NET_DESTROY_RX_FLAGS 0x700b8000
#define SPIDER_NET_DESCR_SIZE 32
@@ -445,13 +451,16 @@ struct spider_net_card {
struct spider_net_descr_chain tx_chain;
struct spider_net_descr_chain rx_chain;
- spinlock_t chain_lock;
+ atomic_t rx_chain_refill;
+ atomic_t tx_chain_release;
struct net_device_stats netdev_stats;
struct spider_net_options options;
spinlock_t intmask_lock;
+ struct tasklet_struct rxram_full_tl;
+ struct timer_list tx_timer;
struct work_struct tx_timeout_task;
atomic_t tx_timeout_task_counter;
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index d42e60ba74c..a5bb0b7633a 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -113,6 +113,23 @@ spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n)
return 0;
}
+static uint32_t
+spider_net_ethtool_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static int
+spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+ if (data)
+ netdev->features |= NETIF_F_HW_CSUM;
+ else
+ netdev->features &= ~NETIF_F_HW_CSUM;
+
+ return 0;
+}
+
struct ethtool_ops spider_net_ethtool_ops = {
.get_settings = spider_net_ethtool_get_settings,
.get_drvinfo = spider_net_ethtool_get_drvinfo,
@@ -122,5 +139,7 @@ struct ethtool_ops spider_net_ethtool_ops = {
.nway_reset = spider_net_ethtool_nway_reset,
.get_rx_csum = spider_net_ethtool_get_rx_csum,
.set_rx_csum = spider_net_ethtool_set_rx_csum,
+ .get_tx_csum = spider_net_ethtool_get_tx_csum,
+ .set_tx_csum = spider_net_ethtool_set_tx_csum,
};
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index eb86b059809..e7dc653d5bd 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.47"
-#define DRV_MODULE_RELDATE "Dec 28, 2005"
+#define DRV_MODULE_VERSION "3.49"
+#define DRV_MODULE_RELDATE "Feb 2, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -1325,10 +1325,12 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
tw32(0x7d00, val);
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
- tg3_nvram_lock(tp);
+ int err;
+
+ err = tg3_nvram_lock(tp);
tg3_halt_cpu(tp, RX_CPU_BASE);
- tw32_f(NVRAM_SWARB, SWARB_REQ_CLR0);
- tg3_nvram_unlock(tp);
+ if (!err)
+ tg3_nvram_unlock(tp);
}
}
@@ -3480,6 +3482,17 @@ static void tg3_reset_task(void *_data)
struct tg3 *tp = _data;
unsigned int restart_timer;
+ tg3_full_lock(tp, 0);
+ tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK;
+
+ if (!netif_running(tp->dev)) {
+ tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
+ tg3_full_unlock(tp);
+ return;
+ }
+
+ tg3_full_unlock(tp);
+
tg3_netif_stop(tp);
tg3_full_lock(tp, 1);
@@ -3492,10 +3505,12 @@ static void tg3_reset_task(void *_data)
tg3_netif_start(tp);
- tg3_full_unlock(tp);
-
if (restart_timer)
mod_timer(&tp->timer, jiffies + 1);
+
+ tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
+
+ tg3_full_unlock(tp);
}
static void tg3_tx_timeout(struct net_device *dev)
@@ -4193,14 +4208,19 @@ static int tg3_nvram_lock(struct tg3 *tp)
if (tp->tg3_flags & TG3_FLAG_NVRAM) {
int i;
- tw32(NVRAM_SWARB, SWARB_REQ_SET1);
- for (i = 0; i < 8000; i++) {
- if (tr32(NVRAM_SWARB) & SWARB_GNT1)
- break;
- udelay(20);
+ if (tp->nvram_lock_cnt == 0) {
+ tw32(NVRAM_SWARB, SWARB_REQ_SET1);
+ for (i = 0; i < 8000; i++) {
+ if (tr32(NVRAM_SWARB) & SWARB_GNT1)
+ break;
+ udelay(20);
+ }
+ if (i == 8000) {
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
+ return -ENODEV;
+ }
}
- if (i == 8000)
- return -ENODEV;
+ tp->nvram_lock_cnt++;
}
return 0;
}
@@ -4208,8 +4228,12 @@ static int tg3_nvram_lock(struct tg3 *tp)
/* tp->lock is held. */
static void tg3_nvram_unlock(struct tg3 *tp)
{
- if (tp->tg3_flags & TG3_FLAG_NVRAM)
- tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+ if (tp->tg3_flags & TG3_FLAG_NVRAM) {
+ if (tp->nvram_lock_cnt > 0)
+ tp->nvram_lock_cnt--;
+ if (tp->nvram_lock_cnt == 0)
+ tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+ }
}
/* tp->lock is held. */
@@ -4320,8 +4344,13 @@ static int tg3_chip_reset(struct tg3 *tp)
void (*write_op)(struct tg3 *, u32, u32);
int i;
- if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
tg3_nvram_lock(tp);
+ /* No matching tg3_nvram_unlock() after this because
+ * chip reset below will undo the nvram lock.
+ */
+ tp->nvram_lock_cnt = 0;
+ }
/*
* We must avoid the readl() that normally takes place.
@@ -4717,6 +4746,10 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
(offset == RX_CPU_BASE ? "RX" : "TX"));
return -ENODEV;
}
+
+ /* Clear firmware's nvram arbitration. */
+ if (tp->tg3_flags & TG3_FLAG_NVRAM)
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
return 0;
}
@@ -4736,7 +4769,7 @@ struct fw_info {
static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base,
int cpu_scratch_size, struct fw_info *info)
{
- int err, i;
+ int err, lock_err, i;
void (*write_op)(struct tg3 *, u32, u32);
if (cpu_base == TX_CPU_BASE &&
@@ -4755,9 +4788,10 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
/* It is possible that bootcode is still loading at this point.
* Get the nvram lock first before halting the cpu.
*/
- tg3_nvram_lock(tp);
+ lock_err = tg3_nvram_lock(tp);
err = tg3_halt_cpu(tp, cpu_base);
- tg3_nvram_unlock(tp);
+ if (!lock_err)
+ tg3_nvram_unlock(tp);
if (err)
goto out;
@@ -6765,6 +6799,13 @@ static int tg3_close(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
+ /* Calling flush_scheduled_work() may deadlock because
+ * linkwatch_event() may be on the workqueue and it will try to get
+ * the rtnl_lock which we are holding.
+ */
+ while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK)
+ msleep(1);
+
netif_stop_queue(dev);
del_timer_sync(&tp->timer);
@@ -8182,7 +8223,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
data[1] = 1;
}
if (etest->flags & ETH_TEST_FL_OFFLINE) {
- int irq_sync = 0;
+ int err, irq_sync = 0;
if (netif_running(dev)) {
tg3_netif_stop(tp);
@@ -8192,11 +8233,12 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
tg3_full_lock(tp, irq_sync);
tg3_halt(tp, RESET_KIND_SUSPEND, 1);
- tg3_nvram_lock(tp);
+ err = tg3_nvram_lock(tp);
tg3_halt_cpu(tp, RX_CPU_BASE);
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
tg3_halt_cpu(tp, TX_CPU_BASE);
- tg3_nvram_unlock(tp);
+ if (!err)
+ tg3_nvram_unlock(tp);
if (tg3_test_registers(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
@@ -8588,7 +8630,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
tp->tg3_flags |= TG3_FLAG_NVRAM;
- tg3_nvram_lock(tp);
+ if (tg3_nvram_lock(tp)) {
+ printk(KERN_WARNING PFX "%s: Cannot get nvarm lock, "
+ "tg3_nvram_init failed.\n", tp->dev->name);
+ return;
+ }
tg3_enable_nvram_access(tp);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
@@ -8686,7 +8732,9 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
if (offset > NVRAM_ADDR_MSK)
return -EINVAL;
- tg3_nvram_lock(tp);
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
tg3_enable_nvram_access(tp);
@@ -8785,10 +8833,6 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
offset = offset + (pagesize - page_off);
- /* Nvram lock released by tg3_nvram_read() above,
- * so need to get it again.
- */
- tg3_nvram_lock(tp);
tg3_enable_nvram_access(tp);
/*
@@ -8925,7 +8969,9 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
else {
u32 grc_mode;
- tg3_nvram_lock(tp);
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
tg3_enable_nvram_access(tp);
if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
@@ -10854,6 +10900,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
if (dev) {
struct tg3 *tp = netdev_priv(dev);
+ flush_scheduled_work();
unregister_netdev(dev);
if (tp->regs) {
iounmap(tp->regs);
@@ -10875,6 +10922,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
if (!netif_running(dev))
return 0;
+ flush_scheduled_work();
tg3_netif_stop(tp);
del_timer_sync(&tp->timer);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 890e1635996..7f4b7f6ac40 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2162,6 +2162,7 @@ struct tg3 {
#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000
#define TG3_FLAG_10_100_ONLY 0x01000000
#define TG3_FLAG_PAUSE_AUTONEG 0x02000000
+#define TG3_FLAG_IN_RESET_TASK 0x04000000
#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000
#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
#define TG3_FLAG_SPLIT_MODE 0x40000000
@@ -2275,6 +2276,7 @@ struct tg3 {
dma_addr_t stats_mapping;
struct work_struct reset_task;
+ int nvram_lock_cnt;
u32 nvram_size;
u32 nvram_pagesize;
u32 nvram_jedecnum;
diff --git a/drivers/net/tokenring/smctr.h b/drivers/net/tokenring/smctr.h
index b306c7e4c79..88dfa2e01d6 100644
--- a/drivers/net/tokenring/smctr.h
+++ b/drivers/net/tokenring/smctr.h
@@ -1042,7 +1042,7 @@ typedef struct net_local {
__u16 functional_address[2];
__u16 bitwise_group_address[2];
- __u8 *ptr_ucode;
+ const __u8 *ptr_ucode;
__u8 cleanup;
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 98398166680..238e9c72cb3 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -214,7 +214,7 @@ static u32 uli526x_cr6_user_set;
/* For module input parameter */
static int debug;
static u32 cr6set;
-static unsigned char mode = 8;
+static int mode = 8;
/* function declaration ------------------------------------- */
static int uli526x_open(struct net_device *);
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 2f61a47b471..1ff5de076d2 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -1943,7 +1943,7 @@ static int dscc4_init_ring(struct net_device *dev)
(++i%TX_RING_SIZE)*sizeof(*tx_fd));
} while (i < TX_RING_SIZE);
- if (dscc4_init_dummy_skb(dpriv) < 0)
+ if (!dscc4_init_dummy_skb(dpriv))
goto err_free_dma_tx;
memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE);
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index 8dea07b4799..eba8e5cfacc 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -29,7 +29,7 @@
#include <linux/netdevice.h>
#include <linux/hdlc.h>
#include <linux/pci.h>
-#include <asm/delay.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include "hd64572.h"
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 9c1e10602f2..9d3b51c3ef5 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -27,8 +27,8 @@
#include <linux/hdlc.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <linux/delay.h>
#include <asm/io.h>
-#include <asm/delay.h>
#include "wanxl.h"
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 233a4f60808..ef85d76575a 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -148,7 +148,7 @@ config IPW2100
In order to use this driver, you will need a firmware image for it.
You can obtain the firmware from
<http://ipw2100.sf.net/>. Once you have the firmware image, you
- will need to place it in /etc/firmware.
+ will need to place it in /lib/firmware.
You will also very likely need the Wireless Tools in order to
configure your card:
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index ee866fd6957..a4c7ae94614 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -5668,13 +5668,13 @@ static int airo_set_freq(struct net_device *dev,
int channel = fwrq->m;
/* We should do a better check than that,
* based on the card capability !!! */
- if((channel < 1) || (channel > 16)) {
+ if((channel < 1) || (channel > 14)) {
printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m);
rc = -EINVAL;
} else {
readConfigRid(local, 1);
/* Yes ! We can set it !!! */
- local->config.channelSet = (u16)(channel - 1);
+ local->config.channelSet = (u16) channel;
set_bit (FLAG_COMMIT, &local->flags);
}
}
@@ -5692,6 +5692,7 @@ static int airo_get_freq(struct net_device *dev,
{
struct airo_info *local = dev->priv;
StatusRid status_rid; /* Card status info */
+ int ch;
readConfigRid(local, 1);
if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
@@ -5699,16 +5700,14 @@ static int airo_get_freq(struct net_device *dev,
else
readStatusRid(local, &status_rid, 1);
-#ifdef WEXT_USECHANNELS
- fwrq->m = ((int)status_rid.channel) + 1;
- fwrq->e = 0;
-#else
- {
- int f = (int)status_rid.channel;
- fwrq->m = frequency_list[f] * 100000;
+ ch = (int)status_rid.channel;
+ if((ch > 0) && (ch < 15)) {
+ fwrq->m = frequency_list[ch - 1] * 100000;
fwrq->e = 1;
+ } else {
+ fwrq->m = ch;
+ fwrq->e = 0;
}
-#endif
return 0;
}
@@ -5783,7 +5782,7 @@ static int airo_get_essid(struct net_device *dev,
/* If none, we may want to get the one that was set */
/* Push it out ! */
- dwrq->length = status_rid.SSIDlen + 1;
+ dwrq->length = status_rid.SSIDlen;
dwrq->flags = 1; /* active */
return 0;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index f0ccfef6644..dfc24016ba8 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -1718,11 +1718,11 @@ static int atmel_get_essid(struct net_device *dev,
if (priv->new_SSID_size != 0) {
memcpy(extra, priv->new_SSID, priv->new_SSID_size);
extra[priv->new_SSID_size] = '\0';
- dwrq->length = priv->new_SSID_size + 1;
+ dwrq->length = priv->new_SSID_size;
} else {
memcpy(extra, priv->SSID, priv->SSID_size);
extra[priv->SSID_size] = '\0';
- dwrq->length = priv->SSID_size + 1;
+ dwrq->length = priv->SSID_size;
}
dwrq->flags = !priv->connect_to_any_BSS; /* active */
@@ -1872,7 +1872,7 @@ static int atmel_set_encodeext(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev);
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- int idx, key_len;
+ int idx, key_len, alg = ext->alg, set_key = 1;
/* Determine and validate the key index */
idx = encoding->flags & IW_ENCODE_INDEX;
@@ -1883,39 +1883,42 @@ static int atmel_set_encodeext(struct net_device *dev,
} else
idx = priv->default_key;
- if ((encoding->flags & IW_ENCODE_DISABLED) ||
- ext->alg == IW_ENCODE_ALG_NONE) {
- priv->wep_is_on = 0;
- priv->encryption_level = 0;
- priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
- }
+ if (encoding->flags & IW_ENCODE_DISABLED)
+ alg = IW_ENCODE_ALG_NONE;
- if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
priv->default_key = idx;
+ set_key = ext->key_len > 0 ? 1 : 0;
+ }
- /* Set the requested key */
- switch (ext->alg) {
- case IW_ENCODE_ALG_NONE:
- break;
- case IW_ENCODE_ALG_WEP:
- if (ext->key_len > 5) {
- priv->wep_key_len[idx] = 13;
- priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
- priv->encryption_level = 2;
- } else if (ext->key_len > 0) {
- priv->wep_key_len[idx] = 5;
- priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
- priv->encryption_level = 1;
- } else {
+ if (set_key) {
+ /* Set the requested key first */
+ switch (alg) {
+ case IW_ENCODE_ALG_NONE:
+ priv->wep_is_on = 0;
+ priv->encryption_level = 0;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (ext->key_len > 5) {
+ priv->wep_key_len[idx] = 13;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
+ priv->encryption_level = 2;
+ } else if (ext->key_len > 0) {
+ priv->wep_key_len[idx] = 5;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
+ priv->encryption_level = 1;
+ } else {
+ return -EINVAL;
+ }
+ priv->wep_is_on = 1;
+ memset(priv->wep_keys[idx], 0, 13);
+ key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
+ memcpy(priv->wep_keys[idx], ext->key, key_len);
+ break;
+ default:
return -EINVAL;
}
- priv->wep_is_on = 1;
- memset(priv->wep_keys[idx], 0, 13);
- key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
- memcpy(priv->wep_keys[idx], ext->key, key_len);
- break;
- default:
- return -EINVAL;
}
return -EINPROGRESS;
@@ -3061,17 +3064,26 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
}
if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
+ int should_associate = 0;
/* WEP */
if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
return;
- if (trans_seq_no == 0x0002 &&
- auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
- send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
- return;
+ if (system == C80211_MGMT_AAN_OPENSYSTEM) {
+ if (trans_seq_no == 0x0002) {
+ should_associate = 1;
+ }
+ } else if (system == C80211_MGMT_AAN_SHAREDKEY) {
+ if (trans_seq_no == 0x0002 &&
+ auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
+ send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
+ return;
+ } else if (trans_seq_no == 0x0004) {
+ should_associate = 1;
+ }
}
- if (trans_seq_no == 0x0004) {
+ if (should_associate) {
if(priv->station_was_associated) {
atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
send_association_request(priv, 1);
@@ -3084,11 +3096,13 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
}
}
- if (status == C80211_MGMT_SC_AuthAlgNotSupported) {
+ if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
/* Do opensystem first, then try sharedkey */
- if (system == C80211_MGMT_AAN_OPENSYSTEM) {
+ if (system == WLAN_AUTH_OPEN) {
priv->CurrentAuthentTransactionSeqNum = 0x001;
- send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
+ priv->exclude_unencrypted = 1;
+ send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0);
+ return;
} else if (priv->connect_to_any_BSS) {
int bss_index;
@@ -3439,10 +3453,13 @@ static void atmel_management_timer(u_long a)
priv->AuthenticationRequestRetryCnt = 0;
restart_search(priv);
} else {
+ int auth = C80211_MGMT_AAN_OPENSYSTEM;
priv->AuthenticationRequestRetryCnt++;
priv->CurrentAuthentTransactionSeqNum = 0x0001;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
- send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
+ if (priv->wep_is_on && priv->exclude_unencrypted)
+ auth = C80211_MGMT_AAN_SHAREDKEY;
+ send_authentication_request(priv, auth, NULL, 0);
}
break;
@@ -3541,12 +3558,15 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->station_was_associated = priv->station_is_associated;
atmel_enter_state(priv, STATION_STATE_READY);
} else {
+ int auth = C80211_MGMT_AAN_OPENSYSTEM;
priv->AuthenticationRequestRetryCnt = 0;
atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
priv->CurrentAuthentTransactionSeqNum = 0x0001;
- send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
+ if (priv->wep_is_on && priv->exclude_unencrypted)
+ auth = C80211_MGMT_AAN_SHAREDKEY;
+ send_authentication_request(priv, auth, NULL, 0);
}
return;
}
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index 56f41c714d3..308f773ad56 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -26,11 +26,25 @@ config HOSTAP_FIRMWARE
depends on HOSTAP
---help---
Configure Host AP driver to include support for firmware image
- download. Current version supports only downloading to volatile, i.e.,
- RAM memory. Flash upgrade is not yet supported.
+ download. This option by itself only enables downloading to the
+ volatile memory, i.e. the card RAM. This option is required to
+ support cards that don't have firmware in flash, such as D-Link
+ DWL-520 rev E and D-Link DWL-650 rev P.
- Firmware image downloading needs user space tool, prism2_srec. It is
- available from http://hostap.epitest.fi/.
+ Firmware image downloading needs a user space tool, prism2_srec.
+ It is available from http://hostap.epitest.fi/.
+
+config HOSTAP_FIRMWARE_NVRAM
+ bool "Support for non-volatile firmware download"
+ depends on HOSTAP_FIRMWARE
+ ---help---
+ Allow Host AP driver to write firmware images to the non-volatile
+ card memory, i.e. flash memory that survives power cycling.
+ Enable this option if you want to be able to change card firmware
+ permanently.
+
+ Firmware image downloading needs a user space tool, prism2_srec.
+ It is available from http://hostap.epitest.fi/.
config HOSTAP_PLX
tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors"
@@ -61,7 +75,7 @@ config HOSTAP_PCI
config HOSTAP_CS
tristate "Host AP driver for Prism2/2.5/3 PC Cards"
- depends on PCMCIA!=n && HOSTAP
+ depends on PCMCIA && HOSTAP
---help---
Host AP driver's version for Prism2/2.5/3 PC Cards.
diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile
index 353ccb93134..b8e41a702c0 100644
--- a/drivers/net/wireless/hostap/Makefile
+++ b/drivers/net/wireless/hostap/Makefile
@@ -1,4 +1,5 @@
-hostap-y := hostap_main.o
+hostap-y := hostap_80211_rx.o hostap_80211_tx.o hostap_ap.o hostap_info.o \
+ hostap_ioctl.o hostap_main.o hostap_proc.o
obj-$(CONFIG_HOSTAP) += hostap.o
obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
index 5fac89b8ce3..5e63765219f 100644
--- a/drivers/net/wireless/hostap/hostap.h
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -1,6 +1,15 @@
#ifndef HOSTAP_H
#define HOSTAP_H
+#include <linux/ethtool.h>
+
+#include "hostap_wlan.h"
+#include "hostap_ap.h"
+
+static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
+
/* hostap.c */
extern struct proc_dir_entry *hostap_proc;
@@ -40,6 +49,26 @@ int prism2_update_comms_qual(struct net_device *dev);
int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype,
u8 *body, size_t bodylen);
int prism2_sta_deauth(local_info_t *local, u16 reason);
+int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked);
+int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked, int do_not_remove);
+
+
+/* hostap_ap.c */
+
+int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac);
+int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac);
+void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
+int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac);
+void ap_control_kickall(struct ap_data *ap);
+void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt);
+int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+ struct iw_quality qual[], int buf_size,
+ int aplist);
+int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
+int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param);
/* hostap_proc.c */
@@ -54,4 +83,12 @@ void hostap_info_init(local_info_t *local);
void hostap_info_process(local_info_t *local, struct sk_buff *skb);
+/* hostap_ioctl.c */
+
+extern const struct iw_handler_def hostap_iw_handler_def;
+extern struct ethtool_ops prism2_ethtool_ops;
+
+int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+
+
#endif /* HOSTAP_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index bf506f50d72..1fc72fe511e 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -1,6 +1,9 @@
#ifndef HOSTAP_80211_H
#define HOSTAP_80211_H
+#include <linux/types.h>
+#include <net/ieee80211_crypt.h>
+
struct hostap_ieee80211_mgmt {
u16 frame_control;
u16 duration;
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index 4b13b76425c..7e04dc94b3b 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -1,7 +1,18 @@
#include <linux/etherdevice.h>
+#include <net/ieee80211_crypt.h>
#include "hostap_80211.h"
#include "hostap.h"
+#include "hostap_ap.h"
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 9d24f8a38ac..4a85e63906f 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -1,3 +1,18 @@
+#include "hostap_80211.h"
+#include "hostap_common.h"
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
+
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
{
struct ieee80211_hdr_4addr *hdr;
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 9da94ab7f05..753a1de6664 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -16,6 +16,14 @@
* (8802.11: 5.5)
*/
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
static int other_ap_policy[MAX_PARM_DEVICES] = { AP_OTHER_AP_SKIP_ALL,
DEF_INTS };
module_param_array(other_ap_policy, int, NULL, 0444);
@@ -360,8 +368,7 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
}
-static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
- u8 *mac)
+int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
{
struct mac_entry *entry;
@@ -380,8 +387,7 @@ static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
}
-static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
- u8 *mac)
+int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
{
struct list_head *ptr;
struct mac_entry *entry;
@@ -433,7 +439,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
}
-static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
+void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
{
struct list_head *ptr, *n;
struct mac_entry *entry;
@@ -454,8 +460,7 @@ static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
}
-static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
- u8 *mac)
+int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac)
{
struct sta_info *sta;
u16 resp;
@@ -486,7 +491,7 @@ static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
-static void ap_control_kickall(struct ap_data *ap)
+void ap_control_kickall(struct ap_data *ap)
{
struct list_head *ptr, *n;
struct sta_info *sta;
@@ -2321,9 +2326,9 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
}
-static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
- struct iw_quality qual[], int buf_size,
- int aplist)
+int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+ struct iw_quality qual[], int buf_size,
+ int aplist)
{
struct ap_data *ap = local->ap;
struct list_head *ptr;
@@ -2363,7 +2368,7 @@ static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
/* Translate our list of Access Points & Stations to a card independant
* format that the Wireless Tools will understand - Jean II */
-static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
+int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
{
struct hostap_interface *iface;
local_info_t *local;
@@ -2608,8 +2613,7 @@ static int prism2_hostapd_sta_clear_stats(struct ap_data *ap,
}
-static int prism2_hostapd(struct ap_data *ap,
- struct prism2_hostapd_param *param)
+int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param)
{
switch (param->cmd) {
case PRISM2_HOSTAPD_FLUSH:
@@ -3207,8 +3211,8 @@ void hostap_update_rates(local_info_t *local)
}
-static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
- struct ieee80211_crypt_data ***crypt)
+void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt)
{
struct sta_info *sta;
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 6d00df69c2e..2fa2452b6b0 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -1,6 +1,8 @@
#ifndef HOSTAP_AP_H
#define HOSTAP_AP_H
+#include "hostap_80211.h"
+
/* AP data structures for STAs */
/* maximum number of frames to buffer per STA */
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index 6f4fa9dc308..01624005d80 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -1,6 +1,9 @@
#ifndef HOSTAP_COMMON_H
#define HOSTAP_COMMON_H
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
#define BIT(x) (1 << (x))
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index 7ed3425d08c..c090a5aebb5 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -21,15 +21,10 @@
#define PRISM2_DOWNLOAD_SUPPORT
#endif
-#ifdef PRISM2_DOWNLOAD_SUPPORT
-/* Allow writing firmware images into flash, i.e., to non-volatile storage.
- * Before you enable this option, you should make absolutely sure that you are
- * using prism2_srec utility that comes with THIS version of the driver!
- * In addition, please note that it is possible to kill your card with
- * non-volatile download if you are using incorrect image. This feature has not
- * been fully tested, so please be careful with it. */
-/* #define PRISM2_NON_VOLATILE_DOWNLOAD */
-#endif /* PRISM2_DOWNLOAD_SUPPORT */
+/* Allow kernel configuration to enable non-volatile download support. */
+#ifdef CONFIG_HOSTAP_FIRMWARE_NVRAM
+#define PRISM2_NON_VOLATILE_DOWNLOAD
+#endif
/* Save low-level I/O for debugging. This should not be enabled in normal use.
*/
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index 5aa998fdf1c..50f72d831cf 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -1,5 +1,8 @@
/* Host AP driver Info Frame processing (part of hostap.o module) */
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
/* Called only as a tasklet (software IRQ) */
static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 2617d70bcda..f3e0ce1ee03 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1,11 +1,13 @@
/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
-#ifdef in_atomic
-/* Get kernel_locked() for in_atomic() */
+#include <linux/types.h>
#include <linux/smp_lock.h>
-#endif
#include <linux/ethtool.h>
+#include <net/ieee80211_crypt.h>
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
{
@@ -3910,7 +3912,7 @@ static void prism2_get_drvinfo(struct net_device *dev,
local->sta_fw_ver & 0xff);
}
-static struct ethtool_ops prism2_ethtool_ops = {
+struct ethtool_ops prism2_ethtool_ops = {
.get_drvinfo = prism2_get_drvinfo
};
@@ -3985,7 +3987,7 @@ static const iw_handler prism2_private_handler[] =
(iw_handler) prism2_ioctl_priv_readmif, /* 3 */
};
-static const struct iw_handler_def hostap_iw_handler_def =
+const struct iw_handler_def hostap_iw_handler_def =
{
.num_standard = sizeof(prism2_handler) / sizeof(iw_handler),
.num_private = sizeof(prism2_private_handler) / sizeof(iw_handler),
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 3d2ea61033b..8dd4c4446a6 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -24,6 +24,7 @@
#include <linux/kmod.h>
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
+#include <linux/etherdevice.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
#include <net/ieee80211_crypt.h>
@@ -47,57 +48,6 @@ MODULE_VERSION(PRISM2_VERSION);
#define PRISM2_MAX_MTU (PRISM2_MAX_FRAME_SIZE - (6 /* LLC */ + 8 /* WEP */))
-/* hostap.c */
-static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
- int rtnl_locked);
-static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
- int rtnl_locked, int do_not_remove);
-
-/* hostap_ap.c */
-static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
- struct iw_quality qual[], int buf_size,
- int aplist);
-static int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
-static int prism2_hostapd(struct ap_data *ap,
- struct prism2_hostapd_param *param);
-static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
- struct ieee80211_crypt_data ***crypt);
-static void ap_control_kickall(struct ap_data *ap);
-#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
-static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
- u8 *mac);
-static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
- u8 *mac);
-static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
-static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
- u8 *mac);
-#endif /* !PRISM2_NO_KERNEL_IEEE80211_MGMT */
-
-
-static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
- 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
-
-
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
-/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
-static unsigned char rfc1042_header[] =
-{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-static unsigned char bridge_tunnel_header[] =
-{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-/* No encapsulation header if EtherType < 0x600 (=length) */
-
-
-/* FIX: these could be compiled separately and linked together to hostap.o */
-#include "hostap_ap.c"
-#include "hostap_info.c"
-#include "hostap_ioctl.c"
-#include "hostap_proc.c"
-#include "hostap_80211_rx.c"
-#include "hostap_80211_tx.c"
-
-
struct net_device * hostap_add_interface(struct local_info *local,
int type, int rtnl_locked,
const char *prefix,
@@ -196,8 +146,8 @@ static inline int prism2_wds_special_addr(u8 *addr)
}
-static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
- int rtnl_locked)
+int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked)
{
struct net_device *dev;
struct list_head *ptr;
@@ -258,8 +208,8 @@ static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
}
-static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
- int rtnl_locked, int do_not_remove)
+int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked, int do_not_remove)
{
unsigned long flags;
struct list_head *ptr;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index a0a4cbd4937..d1d8ce022e6 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -1,5 +1,12 @@
/* /proc routines for Host AP driver */
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <net/ieee80211_crypt.h>
+
+#include "hostap_wlan.h"
+#include "hostap.h"
+
#define PROC_LIMIT (PAGE_SIZE - 80)
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index cfd80155949..87a54aa6f4d 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -1,6 +1,10 @@
#ifndef HOSTAP_WLAN_H
#define HOSTAP_WLAN_H
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <net/iw_handler.h>
+
#include "hostap_config.h"
#include "hostap_common.h"
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 7518384f34d..6290c9f7e93 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -2201,6 +2201,17 @@ static int ipw2100_alloc_skb(struct ipw2100_priv *priv,
#define SEARCH_SNAPSHOT 1
#define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff))
+static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
+{
+ int i;
+ if (!priv->snapshot[0])
+ return;
+ for (i = 0; i < 0x30; i++)
+ kfree(priv->snapshot[i]);
+ priv->snapshot[0] = NULL;
+}
+
+#ifdef CONFIG_IPW2100_DEBUG_C3
static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
{
int i;
@@ -2221,16 +2232,6 @@ static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
return 1;
}
-static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
-{
- int i;
- if (!priv->snapshot[0])
- return;
- for (i = 0; i < 0x30; i++)
- kfree(priv->snapshot[i]);
- priv->snapshot[0] = NULL;
-}
-
static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
size_t len, int mode)
{
@@ -2269,6 +2270,7 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
return ret;
}
+#endif
/*
*
@@ -5735,70 +5737,6 @@ static struct net_device_stats *ipw2100_stats(struct net_device *dev)
return &priv->ieee->stats;
}
-#if WIRELESS_EXT < 18
-/* Support for wpa_supplicant before WE-18, deprecated. */
-
-/* following definitions must match definitions in driver_ipw.c */
-
-#define IPW2100_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
-
-#define IPW2100_CMD_SET_WPA_PARAM 1
-#define IPW2100_CMD_SET_WPA_IE 2
-#define IPW2100_CMD_SET_ENCRYPTION 3
-#define IPW2100_CMD_MLME 4
-
-#define IPW2100_PARAM_WPA_ENABLED 1
-#define IPW2100_PARAM_TKIP_COUNTERMEASURES 2
-#define IPW2100_PARAM_DROP_UNENCRYPTED 3
-#define IPW2100_PARAM_PRIVACY_INVOKED 4
-#define IPW2100_PARAM_AUTH_ALGS 5
-#define IPW2100_PARAM_IEEE_802_1X 6
-
-#define IPW2100_MLME_STA_DEAUTH 1
-#define IPW2100_MLME_STA_DISASSOC 2
-
-#define IPW2100_CRYPT_ERR_UNKNOWN_ALG 2
-#define IPW2100_CRYPT_ERR_UNKNOWN_ADDR 3
-#define IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define IPW2100_CRYPT_ERR_KEY_SET_FAILED 5
-#define IPW2100_CRYPT_ERR_TX_KEY_SET_FAILED 6
-#define IPW2100_CRYPT_ERR_CARD_CONF_FAILED 7
-
-#define IPW2100_CRYPT_ALG_NAME_LEN 16
-
-struct ipw2100_param {
- u32 cmd;
- u8 sta_addr[ETH_ALEN];
- union {
- struct {
- u8 name;
- u32 value;
- } wpa_param;
- struct {
- u32 len;
- u8 reserved[32];
- u8 data[0];
- } wpa_ie;
- struct {
- u32 command;
- u32 reason_code;
- } mlme;
- struct {
- u8 alg[IPW2100_CRYPT_ALG_NAME_LEN];
- u8 set_tx;
- u32 err;
- u8 idx;
- u8 seq[8]; /* sequence counter (set: RX, get: TX) */
- u16 key_len;
- u8 key[0];
- } crypt;
-
- } u;
-};
-
-/* end of driver_ipw.c code */
-#endif /* WIRELESS_EXT < 18 */
-
static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
{
/* This is called when wpa_supplicant loads and closes the driver
@@ -5807,11 +5745,6 @@ static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
return 0;
}
-#if WIRELESS_EXT < 18
-#define IW_AUTH_ALG_OPEN_SYSTEM 0x1
-#define IW_AUTH_ALG_SHARED_KEY 0x2
-#endif
-
static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
{
@@ -5855,360 +5788,6 @@ void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
ipw2100_set_wpa_ie(priv, &frame, 0);
}
-#if WIRELESS_EXT < 18
-static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
- struct ipw2100_priv *priv = ieee80211_priv(dev);
- struct ieee80211_crypt_data *crypt;
- unsigned long flags;
- int ret = 0;
-
- switch (name) {
- case IPW2100_PARAM_WPA_ENABLED:
- ret = ipw2100_wpa_enable(priv, value);
- break;
-
- case IPW2100_PARAM_TKIP_COUNTERMEASURES:
- crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
- if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
- break;
-
- flags = crypt->ops->get_flags(crypt->priv);
-
- if (value)
- flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
- else
- flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
-
- crypt->ops->set_flags(flags, crypt->priv);
-
- break;
-
- case IPW2100_PARAM_DROP_UNENCRYPTED:{
- /* See IW_AUTH_DROP_UNENCRYPTED handling for details */
- struct ieee80211_security sec = {
- .flags = SEC_ENABLED,
- .enabled = value,
- };
- priv->ieee->drop_unencrypted = value;
- /* We only change SEC_LEVEL for open mode. Others
- * are set by ipw_wpa_set_encryption.
- */
- if (!value) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_0;
- } else {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- }
- if (priv->ieee->set_security)
- priv->ieee->set_security(priv->ieee->dev, &sec);
- break;
- }
-
- case IPW2100_PARAM_PRIVACY_INVOKED:
- priv->ieee->privacy_invoked = value;
- break;
-
- case IPW2100_PARAM_AUTH_ALGS:
- ret = ipw2100_wpa_set_auth_algs(priv, value);
- break;
-
- case IPW2100_PARAM_IEEE_802_1X:
- priv->ieee->ieee802_1x = value;
- break;
-
- default:
- printk(KERN_ERR DRV_NAME ": %s: Unknown WPA param: %d\n",
- dev->name, name);
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int ipw2100_wpa_mlme(struct net_device *dev, int command, int reason)
-{
-
- struct ipw2100_priv *priv = ieee80211_priv(dev);
- int ret = 0;
-
- switch (command) {
- case IPW2100_MLME_STA_DEAUTH:
- // silently ignore
- break;
-
- case IPW2100_MLME_STA_DISASSOC:
- ipw2100_disassociate_bssid(priv);
- break;
-
- default:
- printk(KERN_ERR DRV_NAME ": %s: Unknown MLME request: %d\n",
- dev->name, command);
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int ipw2100_wpa_set_wpa_ie(struct net_device *dev,
- struct ipw2100_param *param, int plen)
-{
-
- struct ipw2100_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee;
- u8 *buf;
-
- if (!ieee->wpa_enabled)
- return -EOPNOTSUPP;
-
- if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
- (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
- return -EINVAL;
-
- if (param->u.wpa_ie.len) {
- buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
-
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = buf;
- ieee->wpa_ie_len = param->u.wpa_ie.len;
-
- } else {
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = NULL;
- ieee->wpa_ie_len = 0;
- }
-
- ipw2100_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
-
- return 0;
-}
-
-/* implementation borrowed from hostap driver */
-
-static int ipw2100_wpa_set_encryption(struct net_device *dev,
- struct ipw2100_param *param,
- int param_len)
-{
- int ret = 0;
- struct ipw2100_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee;
- struct ieee80211_crypto_ops *ops;
- struct ieee80211_crypt_data **crypt;
-
- struct ieee80211_security sec = {
- .flags = 0,
- };
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IPW2100_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
- if (param_len !=
- (int)((char *)param->u.crypt.key - (char *)param) +
- param->u.crypt.key_len) {
- IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len,
- param->u.crypt.key_len);
- return -EINVAL;
- }
- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
- if (param->u.crypt.idx >= WEP_KEYS)
- return -EINVAL;
- crypt = &ieee->crypt[param->u.crypt.idx];
- } else {
- return -EINVAL;
- }
-
- sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
- if (strcmp(param->u.crypt.alg, "none") == 0) {
- if (crypt) {
- sec.enabled = 0;
- sec.encrypt = 0;
- sec.level = SEC_LEVEL_0;
- sec.flags |= SEC_LEVEL;
- ieee80211_crypt_delayed_deinit(ieee, crypt);
- }
- goto done;
- }
- sec.enabled = 1;
- sec.encrypt = 1;
-
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
- request_module("ieee80211_crypt_wep");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
- request_module("ieee80211_crypt_tkip");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
- request_module("ieee80211_crypt_ccmp");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- }
- if (ops == NULL) {
- IPW_DEBUG_INFO("%s: unknown crypto alg '%s'\n",
- dev->name, param->u.crypt.alg);
- param->u.crypt.err = IPW2100_CRYPT_ERR_UNKNOWN_ALG;
- ret = -EINVAL;
- goto done;
- }
-
- if (*crypt == NULL || (*crypt)->ops != ops) {
- struct ieee80211_crypt_data *new_crypt;
-
- ieee80211_crypt_delayed_deinit(ieee, crypt);
-
- new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL);
- if (new_crypt == NULL) {
- ret = -ENOMEM;
- goto done;
- }
- new_crypt->ops = ops;
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
- new_crypt->priv =
- new_crypt->ops->init(param->u.crypt.idx);
-
- if (new_crypt->priv == NULL) {
- kfree(new_crypt);
- param->u.crypt.err =
- IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED;
- ret = -EINVAL;
- goto done;
- }
-
- *crypt = new_crypt;
- }
-
- if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
- (*crypt)->ops->set_key(param->u.crypt.key,
- param->u.crypt.key_len, param->u.crypt.seq,
- (*crypt)->priv) < 0) {
- IPW_DEBUG_INFO("%s: key setting failed\n", dev->name);
- param->u.crypt.err = IPW2100_CRYPT_ERR_KEY_SET_FAILED;
- ret = -EINVAL;
- goto done;
- }
-
- if (param->u.crypt.set_tx) {
- ieee->tx_keyidx = param->u.crypt.idx;
- sec.active_key = param->u.crypt.idx;
- sec.flags |= SEC_ACTIVE_KEY;
- }
-
- if (ops->name != NULL) {
-
- if (strcmp(ops->name, "WEP") == 0) {
- memcpy(sec.keys[param->u.crypt.idx],
- param->u.crypt.key, param->u.crypt.key_len);
- sec.key_sizes[param->u.crypt.idx] =
- param->u.crypt.key_len;
- sec.flags |= (1 << param->u.crypt.idx);
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- } else if (strcmp(ops->name, "TKIP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_2;
- } else if (strcmp(ops->name, "CCMP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_3;
- }
- }
- done:
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
-
- /* Do not reset port if card is in Managed mode since resetting will
- * generate new IEEE 802.11 authentication which may end up in looping
- * with IEEE 802.1X. If your hardware requires a reset after WEP
- * configuration (for example... Prism2), implement the reset_port in
- * the callbacks structures used to initialize the 802.11 stack. */
- if (ieee->reset_on_keychange &&
- ieee->iw_mode != IW_MODE_INFRA &&
- ieee->reset_port && ieee->reset_port(dev)) {
- IPW_DEBUG_INFO("%s: reset_port failed\n", dev->name);
- param->u.crypt.err = IPW2100_CRYPT_ERR_CARD_CONF_FAILED;
- return -EINVAL;
- }
-
- return ret;
-}
-
-static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p)
-{
-
- struct ipw2100_param *param;
- int ret = 0;
-
- IPW_DEBUG_IOCTL("wpa_supplicant: len=%d\n", p->length);
-
- if (p->length < sizeof(struct ipw2100_param) || !p->pointer)
- return -EINVAL;
-
- param = (struct ipw2100_param *)kmalloc(p->length, GFP_KERNEL);
- if (param == NULL)
- return -ENOMEM;
-
- if (copy_from_user(param, p->pointer, p->length)) {
- kfree(param);
- return -EFAULT;
- }
-
- switch (param->cmd) {
-
- case IPW2100_CMD_SET_WPA_PARAM:
- ret = ipw2100_wpa_set_param(dev, param->u.wpa_param.name,
- param->u.wpa_param.value);
- break;
-
- case IPW2100_CMD_SET_WPA_IE:
- ret = ipw2100_wpa_set_wpa_ie(dev, param, p->length);
- break;
-
- case IPW2100_CMD_SET_ENCRYPTION:
- ret = ipw2100_wpa_set_encryption(dev, param, p->length);
- break;
-
- case IPW2100_CMD_MLME:
- ret = ipw2100_wpa_mlme(dev, param->u.mlme.command,
- param->u.mlme.reason_code);
- break;
-
- default:
- printk(KERN_ERR DRV_NAME
- ": %s: Unknown WPA supplicant request: %d\n", dev->name,
- param->cmd);
- ret = -EOPNOTSUPP;
-
- }
-
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
-
- kfree(param);
- return ret;
-}
-
-static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct iwreq *wrq = (struct iwreq *)rq;
- int ret = -1;
- switch (cmd) {
- case IPW2100_IOCTL_WPA_SUPPLICANT:
- ret = ipw2100_wpa_supplicant(dev, &wrq->u.data);
- return ret;
-
- default:
- return -EOPNOTSUPP;
- }
-
- return -EOPNOTSUPP;
-}
-#endif /* WIRELESS_EXT < 18 */
-
static void ipw_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -6337,9 +5916,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
dev->open = ipw2100_open;
dev->stop = ipw2100_close;
dev->init = ipw2100_net_init;
-#if WIRELESS_EXT < 18
- dev->do_ioctl = ipw2100_ioctl;
-#endif
dev->get_stats = ipw2100_stats;
dev->ethtool_ops = &ipw2100_ethtool_ops;
dev->tx_timeout = ipw2100_tx_timeout;
@@ -7538,11 +7114,17 @@ static int ipw2100_wx_set_txpow(struct net_device *dev,
{
struct ipw2100_priv *priv = ieee80211_priv(dev);
int err = 0, value;
+
+ if (ipw_radio_kill_sw(priv, wrqu->txpower.disabled))
+ return -EINPROGRESS;
if (priv->ieee->iw_mode != IW_MODE_ADHOC)
+ return 0;
+
+ if ((wrqu->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
return -EINVAL;
- if (wrqu->txpower.disabled == 1 || wrqu->txpower.fixed == 0)
+ if (wrqu->txpower.fixed == 0)
value = IPW_TX_POWER_DEFAULT;
else {
if (wrqu->txpower.value < IPW_TX_POWER_MIN_DBM ||
@@ -7577,24 +7159,19 @@ static int ipw2100_wx_get_txpow(struct net_device *dev,
struct ipw2100_priv *priv = ieee80211_priv(dev);
- if (priv->ieee->iw_mode != IW_MODE_ADHOC) {
- wrqu->power.disabled = 1;
- return 0;
- }
+ wrqu->txpower.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
if (priv->tx_power == IPW_TX_POWER_DEFAULT) {
- wrqu->power.fixed = 0;
- wrqu->power.value = IPW_TX_POWER_MAX_DBM;
- wrqu->power.disabled = 1;
+ wrqu->txpower.fixed = 0;
+ wrqu->txpower.value = IPW_TX_POWER_MAX_DBM;
} else {
- wrqu->power.disabled = 0;
- wrqu->power.fixed = 1;
- wrqu->power.value = priv->tx_power;
+ wrqu->txpower.fixed = 1;
+ wrqu->txpower.value = priv->tx_power;
}
- wrqu->power.flags = IW_TXPOW_DBM;
+ wrqu->txpower.flags = IW_TXPOW_DBM;
- IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->power.value);
+ IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->txpower.value);
return 0;
}
@@ -7855,7 +7432,6 @@ static int ipw2100_wx_get_power(struct net_device *dev,
return 0;
}
-#if WIRELESS_EXT > 17
/*
* WE-18 WPA support
*/
@@ -8117,7 +7693,6 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
}
return 0;
}
-#endif /* WIRELESS_EXT > 17 */
/*
*
@@ -8350,11 +7925,7 @@ static iw_handler ipw2100_wx_handlers[] = {
NULL, /* SIOCWIWTHRSPY */
ipw2100_wx_set_wap, /* SIOCSIWAP */
ipw2100_wx_get_wap, /* SIOCGIWAP */
-#if WIRELESS_EXT > 17
ipw2100_wx_set_mlme, /* SIOCSIWMLME */
-#else
- NULL, /* -- hole -- */
-#endif
NULL, /* SIOCGIWAPLIST -- deprecated */
ipw2100_wx_set_scan, /* SIOCSIWSCAN */
ipw2100_wx_get_scan, /* SIOCGIWSCAN */
@@ -8378,7 +7949,6 @@ static iw_handler ipw2100_wx_handlers[] = {
ipw2100_wx_get_encode, /* SIOCGIWENCODE */
ipw2100_wx_set_power, /* SIOCSIWPOWER */
ipw2100_wx_get_power, /* SIOCGIWPOWER */
-#if WIRELESS_EXT > 17
NULL, /* -- hole -- */
NULL, /* -- hole -- */
ipw2100_wx_set_genie, /* SIOCSIWGENIE */
@@ -8388,7 +7958,6 @@ static iw_handler ipw2100_wx_handlers[] = {
ipw2100_wx_set_encodeext, /* SIOCSIWENCODEEXT */
ipw2100_wx_get_encodeext, /* SIOCGIWENCODEEXT */
NULL, /* SIOCSIWPMKSA */
-#endif
};
#define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 819be2b6b7d..287676ad80d 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -2456,7 +2456,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv)
copy. Otherwise let the firmware know to perform the operation
on it's own
*/
- if ((priv->eeprom + EEPROM_VERSION) != 0) {
+ if (priv->eeprom[EEPROM_VERSION] != 0) {
IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n");
/* write the eeprom data to sram */
@@ -4616,9 +4616,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
}
default:
- IPW_ERROR("Unknown notification: "
- "subtype=%d,flags=0x%2x,size=%d\n",
- notif->subtype, notif->flags, notif->size);
+ IPW_DEBUG_NOTIF("Unknown notification: "
+ "subtype=%d,flags=0x%2x,size=%d\n",
+ notif->subtype, notif->flags, notif->size);
}
}
@@ -8012,6 +8012,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init)
else
IPW_DEBUG_INFO("Auto adhoc creation disabled.\n");
+ priv->config &= ~CFG_STATIC_ESSID;
+ priv->essid_len = 0;
+ memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
+
if (disable) {
priv->status |= STATUS_RF_KILL_SW;
IPW_DEBUG_INFO("Radio disabled.\n");
@@ -8936,14 +8940,12 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
IPW_DEBUG_HC("starting request direct scan!\n");
if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
- err = wait_event_interruptible(priv->wait_state,
- !(priv->
- status & (STATUS_SCANNING |
- STATUS_SCAN_ABORTING)));
- if (err) {
- IPW_DEBUG_HC("aborting direct scan");
- goto done;
- }
+ /* We should not sleep here; otherwise we will block most
+ * of the system (for instance, we hold rtnl_lock when we
+ * get here).
+ */
+ err = -EAGAIN;
+ goto done;
}
memset(&scan, 0, sizeof(scan));
@@ -11037,7 +11039,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
net_dev->set_multicast_list = ipw_net_set_multicast_list;
net_dev->set_mac_address = ipw_net_set_mac_address;
priv->wireless_data.spy_data = &priv->ieee->spy_data;
- priv->wireless_data.ieee80211 = priv->ieee;
net_dev->wireless_data = &priv->wireless_data;
net_dev->wireless_handlers = &ipw_wx_handler_def;
net_dev->ethtool_ops = &ipw_ethtool_ops;
@@ -11123,8 +11124,8 @@ static void ipw_pci_remove(struct pci_dev *pdev)
/* Free MAC hash list for ADHOC */
for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) {
list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
- kfree(list_entry(p, struct ipw_ibss_seq, list));
list_del(p);
+ kfree(list_entry(p, struct ipw_ibss_seq, list));
}
}
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index b664708481c..ec6f2a48895 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -261,13 +261,13 @@ orinoco_cs_config(dev_link_t *link)
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}
} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
+ DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
if(!ignore_cis_vcc)
goto next_entry;
}
@@ -590,6 +590,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
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_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
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),
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 135a156db25..e5bb9f5ae42 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -748,7 +748,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
if (essid->length) {
dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */
/* if it is to big, trunk it */
- dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length + 1);
+ dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length);
} else {
dwrq->flags = 0;
dwrq->length = 0;
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 33d64d2ee53..a8261d8454d 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -177,7 +177,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
#endif
newskb->dev = skb->dev;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
skb = newskb;
}
}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 319180ca7e7..7880d8c31aa 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -1256,7 +1256,7 @@ static int ray_get_essid(struct net_device *dev,
extra[IW_ESSID_MAX_SIZE] = '\0';
/* Push it out ! */
- dwrq->length = strlen(extra) + 1;
+ dwrq->length = strlen(extra);
dwrq->flags = 1; /* active */
return 0;
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 7e2039f52c4..98122f3a4bc 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -950,16 +950,8 @@ wv_82593_cmd(struct net_device * dev,
static inline int
wv_diag(struct net_device * dev)
{
- int ret = FALSE;
-
- if(wv_82593_cmd(dev, "wv_diag(): diagnose",
- OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED))
- ret = TRUE;
-
-#ifdef DEBUG_CONFIG_ERRORS
- printk(KERN_INFO "wavelan_cs: i82593 Self Test failed!\n");
-#endif
- return(ret);
+ return(wv_82593_cmd(dev, "wv_diag(): diagnose",
+ OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED));
} /* wv_diag */
/*------------------------------------------------------------------*/
@@ -2280,7 +2272,7 @@ static int wavelan_get_essid(struct net_device *dev,
extra[IW_ESSID_MAX_SIZE] = '\0';
/* Set the length */
- wrqu->data.length = strlen(extra) + 1;
+ wrqu->data.length = strlen(extra);
return 0;
}
@@ -3604,8 +3596,8 @@ wv_82593_config(struct net_device * dev)
cfblk.lin_prio = 0; /* conform to 802.3 backoff algoritm */
cfblk.exp_prio = 5; /* conform to 802.3 backoff algoritm */
cfblk.bof_met = 1; /* conform to 802.3 backoff algoritm */
- cfblk.ifrm_spc = 0x20; /* 32 bit times interframe spacing */
- cfblk.slottim_low = 0x20; /* 32 bit times slot time */
+ cfblk.ifrm_spc = 0x20 >> 4; /* 32 bit times interframe spacing */
+ cfblk.slottim_low = 0x20 >> 5; /* 32 bit times slot time */
cfblk.slottim_hi = 0x0;
cfblk.max_retr = 15;
cfblk.prmisc = ((lp->promiscuous) ? TRUE: FALSE); /* Promiscuous mode */
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 9e0229f7e25..93f8a8fa889 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -40,6 +40,8 @@
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/reboot.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/byteorder.h>
#include <asm/cache.h> /* for L1_CACHE_BYTES */
@@ -1019,62 +1021,33 @@ static struct hppa_dma_ops ccio_ops = {
};
#ifdef CONFIG_PROC_FS
-static int proc_append(char *src, int len, char **dst, off_t *offset, int *max)
-{
- if (len < *offset) {
- *offset -= len;
- return 0;
- }
- if (*offset > 0) {
- src += *offset;
- len -= *offset;
- *offset = 0;
- }
- if (len > *max) {
- len = *max;
- }
- memcpy(*dst, src, len);
- *dst += len;
- *max -= len;
- return (*max == 0);
-}
-
-static int ccio_proc_info(char *buf, char **start, off_t offset, int count,
- int *eof, void *data)
+static int ccio_proc_info(struct seq_file *m, void *p)
{
- int max = count;
- char tmp[80]; /* width of an ANSI-standard terminal */
+ int len = 0;
struct ioc *ioc = ioc_list;
while (ioc != NULL) {
unsigned int total_pages = ioc->res_size << 3;
unsigned long avg = 0, min, max;
- int j, len;
+ int j;
- len = sprintf(tmp, "%s\n", ioc->name);
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "%s\n", ioc->name);
- len = sprintf(tmp, "Cujo 2.0 bug : %s\n",
- (ioc->cujo20_bug ? "yes" : "no"));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "Cujo 2.0 bug : %s\n",
+ (ioc->cujo20_bug ? "yes" : "no"));
- len = sprintf(tmp, "IO PDIR size : %d bytes (%d entries)\n",
- total_pages * 8, total_pages);
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n",
+ total_pages * 8, total_pages);
+
#ifdef CCIO_MAP_STATS
- len = sprintf(tmp, "IO PDIR entries : %ld free %ld used (%d%%)\n",
- total_pages - ioc->used_pages, ioc->used_pages,
- (int)(ioc->used_pages * 100 / total_pages));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n",
+ total_pages - ioc->used_pages, ioc->used_pages,
+ (int)(ioc->used_pages * 100 / total_pages));
#endif
- len = sprintf(tmp, "Resource bitmap : %d bytes (%d pages)\n",
- ioc->res_size, total_pages);
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+
+ len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n",
+ ioc->res_size, total_pages);
+
#ifdef CCIO_SEARCH_TIME
min = max = ioc->avg_search[0];
for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) {
@@ -1085,70 +1058,83 @@ static int ccio_proc_info(char *buf, char **start, off_t offset, int count,
min = ioc->avg_search[j];
}
avg /= CCIO_SEARCH_SAMPLE;
- len = sprintf(tmp, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
- min, avg, max);
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+ min, avg, max);
#endif
#ifdef CCIO_MAP_STATS
- len = sprintf(tmp, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n",
- ioc->msingle_calls, ioc->msingle_pages,
- (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
-
+ len += seq_printf(m, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n",
+ ioc->msingle_calls, ioc->msingle_pages,
+ (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
/* KLUGE - unmap_sg calls unmap_single for each mapped page */
min = ioc->usingle_calls - ioc->usg_calls;
max = ioc->usingle_pages - ioc->usg_pages;
- len = sprintf(tmp, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
- min, max, (int)((max * 1000)/min));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
+ min, max, (int)((max * 1000)/min));
- len = sprintf(tmp, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
- ioc->msg_calls, ioc->msg_pages,
- (int)((ioc->msg_pages * 1000)/ioc->msg_calls));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
- len = sprintf(tmp, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n",
- ioc->usg_calls, ioc->usg_pages,
- (int)((ioc->usg_pages * 1000)/ioc->usg_calls));
- if (proc_append(tmp, len, &buf, &offset, &count))
- break;
+ len += seq_printf(m, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
+ ioc->msg_calls, ioc->msg_pages,
+ (int)((ioc->msg_pages * 1000)/ioc->msg_calls));
+
+ len += seq_printf(m, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n",
+ ioc->usg_calls, ioc->usg_pages,
+ (int)((ioc->usg_pages * 1000)/ioc->usg_calls));
#endif /* CCIO_MAP_STATS */
+
ioc = ioc->next;
}
- if (count == 0) {
- *eof = 1;
- }
- return (max - count);
+ return 0;
+}
+
+static int ccio_proc_info_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, &ccio_proc_info, NULL);
}
-static int ccio_resource_map(char *buf, char **start, off_t offset, int len,
- int *eof, void *data)
+static struct file_operations ccio_proc_info_fops = {
+ .owner = THIS_MODULE,
+ .open = ccio_proc_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int ccio_proc_bitmap_info(struct seq_file *m, void *p)
{
+ int len = 0;
struct ioc *ioc = ioc_list;
- buf[0] = '\0';
while (ioc != NULL) {
u32 *res_ptr = (u32 *)ioc->res_map;
int j;
for (j = 0; j < (ioc->res_size / sizeof(u32)); j++) {
if ((j & 7) == 0)
- strcat(buf,"\n ");
- sprintf(buf, "%s %08x", buf, *res_ptr);
+ len += seq_puts(m, "\n ");
+ len += seq_printf(m, "%08x", *res_ptr);
res_ptr++;
}
- strcat(buf, "\n\n");
+ len += seq_puts(m, "\n\n");
ioc = ioc->next;
break; /* XXX - remove me */
}
- return strlen(buf);
+ return 0;
}
+
+static int ccio_proc_bitmap_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, &ccio_proc_bitmap_info, NULL);
+}
+
+static struct file_operations ccio_proc_bitmap_fops = {
+ .owner = THIS_MODULE,
+ .open = ccio_proc_bitmap_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif
/**
@@ -1423,7 +1409,7 @@ static void __init ccio_init_resources(struct ioc *ioc)
struct resource *res = ioc->mmio_region;
char *name = kmalloc(14, GFP_KERNEL);
- sprintf(name, "GSC Bus [%d/]", ioc->hw_path);
+ snprintf(name, 14, "GSC Bus [%d/]", ioc->hw_path);
ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
@@ -1556,13 +1542,13 @@ static int ccio_probe(struct parisc_device *dev)
{
int i;
struct ioc *ioc, **ioc_p = &ioc_list;
+ struct proc_dir_entry *info_entry, *bitmap_entry;
- ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL);
+ ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL);
if (ioc == NULL) {
printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
return 1;
}
- memset(ioc, 0, sizeof(struct ioc));
ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn";
@@ -1578,19 +1564,20 @@ static int ccio_probe(struct parisc_device *dev)
ccio_ioc_init(ioc);
ccio_init_resources(ioc);
hppa_dma_ops = &ccio_ops;
- dev->dev.platform_data = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
+ dev->dev.platform_data = kzalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
/* if this fails, no I/O cards will work, so may as well bug */
BUG_ON(dev->dev.platform_data == NULL);
HBA_DATA(dev->dev.platform_data)->iommu = ioc;
-
if (ioc_count == 0) {
- /* FIXME: Create separate entries for each ioc */
- create_proc_read_entry(MODULE_NAME, S_IRWXU, proc_runway_root,
- ccio_proc_info, NULL);
- create_proc_read_entry(MODULE_NAME"-bitmap", S_IRWXU,
- proc_runway_root, ccio_resource_map, NULL);
+ info_entry = create_proc_entry(MODULE_NAME, 0, proc_runway_root);
+ if (info_entry)
+ info_entry->proc_fops = &ccio_proc_info_fops;
+
+ bitmap_entry = create_proc_entry(MODULE_NAME"-bitmap", 0, proc_runway_root);
+ if (bitmap_entry)
+ bitmap_entry->proc_fops = &ccio_proc_bitmap_fops;
}
ioc_count++;
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 216d1d85932..3d1a7f98c67 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -989,14 +989,12 @@ static int __init dino_probe(struct parisc_device *dev)
*/
}
- dino_dev = kmalloc(sizeof(struct dino_device), GFP_KERNEL);
+ dino_dev = kzalloc(sizeof(struct dino_device), GFP_KERNEL);
if (!dino_dev) {
printk("dino_init_chip - couldn't alloc dino_device\n");
return 1;
}
- memset(dino_dev, 0, sizeof(struct dino_device));
-
dino_dev->hba.dev = dev;
dino_dev->hba.base_addr = ioremap(hpa, 4096);
dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index 5edf93f8075..07dc2b6d4e9 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -60,12 +60,11 @@ static int hppb_probe(struct parisc_device *dev)
}
if(card->hpa) {
- card->next = kmalloc(sizeof(struct hppb_card), GFP_KERNEL);
+ card->next = kzalloc(sizeof(struct hppb_card), GFP_KERNEL);
if(!card->next) {
printk(KERN_ERR "HP-PB: Unable to allocate memory.\n");
return 1;
}
- memset(card->next, '\0', sizeof(struct hppb_card));
card = card->next;
}
printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start);
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 19657efa8dc..8d7a36392eb 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -873,28 +873,24 @@ void *iosapic_register(unsigned long hpa)
return NULL;
}
- isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+ isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
if (!isi) {
BUG();
return NULL;
}
- memset(isi, 0, sizeof(struct iosapic_info));
-
isi->addr = ioremap(hpa, 4096);
isi->isi_hpa = hpa;
isi->isi_version = iosapic_rd_version(isi);
isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
vip = isi->isi_vector = (struct vector_info *)
- kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
+ kzalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
if (vip == NULL) {
kfree(isi);
return NULL;
}
- memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
-
for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
vip->irqline = (unsigned char) cnt;
vip->iosapic = isi;
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index 2b3ba1dcf33..cb3d2817612 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -166,11 +166,12 @@ static void lasi_power_off(void)
int __init
lasi_init_chip(struct parisc_device *dev)
{
+ extern void (*chassis_power_off)(void);
struct gsc_asic *lasi;
struct gsc_irq gsc_irq;
int ret;
- lasi = kmalloc(sizeof(*lasi), GFP_KERNEL);
+ lasi = kzalloc(sizeof(*lasi), GFP_KERNEL);
if (!lasi)
return -ENOMEM;
@@ -222,7 +223,7 @@ lasi_init_chip(struct parisc_device *dev)
* ensure that only the first LASI (the one controlling the power off)
* should set the HPA here */
lasi_power_off_hpa = lasi->hpa;
- pm_power_off = lasi_power_off;
+ chassis_power_off = lasi_power_off;
return ret;
}
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index cbae8c8963f..e8a2a4a852f 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1565,7 +1565,7 @@ lba_driver_probe(struct parisc_device *dev)
} else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) {
func_class &= 0xff;
version = kmalloc(6, GFP_KERNEL);
- sprintf(version,"TR%d.%d",(func_class >> 4),(func_class & 0xf));
+ snprintf(version, 6, "TR%d.%d",(func_class >> 4),(func_class & 0xf));
/* We could use one printk for both Elroy and Mercury,
* but for the mask for func_class.
*/
@@ -1586,14 +1586,12 @@ lba_driver_probe(struct parisc_device *dev)
** have an IRT entry will get NULL back from iosapic code.
*/
- lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
+ lba_dev = kzalloc(sizeof(struct lba_device), GFP_KERNEL);
if (!lba_dev) {
printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n");
return(1);
}
- memset(lba_dev, 0, sizeof(struct lba_device));
-
/* ---------- First : initialize data we already have --------- */
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 42a3c54e8e6..a28e17898fb 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -1,7 +1,7 @@
/*
* Interfaces to retrieve and set PDC Stable options (firmware)
*
- * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright (C) 2005-2006 Thibaut VARENE <varenet@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 published by
@@ -26,11 +26,19 @@
*
* Since locations between 96 and 192 are the various paths, most (if not
* all) PA-RISC machines should have them. Anyway, for safety reasons, the
- * following code can deal with only 96 bytes of Stable Storage, and all
+ * following code can deal with just 96 bytes of Stable Storage, and all
* sizes between 96 and 192 bytes (provided they are multiple of struct
* device_path size, eg: 128, 160 and 192) to provide full information.
* The code makes no use of data above 192 bytes. One last word: there's one
* path we can always count on: the primary path.
+ *
+ * The current policy wrt file permissions is:
+ * - write: root only
+ * - read: (reading triggers PDC calls) ? root only : everyone
+ * The rationale is that PDC calls could hog (DoS) the machine.
+ *
+ * TODO:
+ * - timer/fastsize write calls
*/
#undef PDCS_DEBUG
@@ -50,13 +58,15 @@
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/errno.h>
+#include <linux/spinlock.h>
#include <asm/pdc.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
-#define PDCS_VERSION "0.10"
+#define PDCS_VERSION "0.22"
+#define PDCS_PREFIX "PDC Stable Storage"
#define PDCS_ADDR_PPRI 0x00
#define PDCS_ADDR_OSID 0x40
@@ -70,10 +80,12 @@ MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
MODULE_LICENSE("GPL");
MODULE_VERSION(PDCS_VERSION);
+/* holds Stable Storage size. Initialized once and for all, no lock needed */
static unsigned long pdcs_size __read_mostly;
/* This struct defines what we need to deal with a parisc pdc path entry */
struct pdcspath_entry {
+ rwlock_t rw_lock; /* to protect path entry access */
short ready; /* entry record is valid if != 0 */
unsigned long addr; /* entry address in stable storage */
char *name; /* entry name */
@@ -121,6 +133,8 @@ struct pdcspath_attribute paths_attr_##_name = { \
* content of the stable storage WRT various paths in these structs. We read
* these structs when reading the files, and we will write to these structs when
* writing to the files, and only then write them back to the Stable Storage.
+ *
+ * This function expects to be called with @entry->rw_lock write-hold.
*/
static int
pdcspath_fetch(struct pdcspath_entry *entry)
@@ -160,14 +174,15 @@ pdcspath_fetch(struct pdcspath_entry *entry)
* pointer, from which it'll find out the corresponding hardware path.
* For now we do not handle the case where there's an error in writing to the
* Stable Storage area, so you'd better not mess up the data :P
+ *
+ * This function expects to be called with @entry->rw_lock write-hold.
*/
-static int
+static void
pdcspath_store(struct pdcspath_entry *entry)
{
struct device_path *devpath;
- if (!entry)
- return -EINVAL;
+ BUG_ON(!entry);
devpath = &entry->devpath;
@@ -176,10 +191,8 @@ pdcspath_store(struct pdcspath_entry *entry)
First case, we don't have a preset hwpath... */
if (!entry->ready) {
/* ...but we have a device, map it */
- if (entry->dev)
- device_to_hwpath(entry->dev, (struct hardware_path *)devpath);
- else
- return -EINVAL;
+ BUG_ON(!entry->dev);
+ device_to_hwpath(entry->dev, (struct hardware_path *)devpath);
}
/* else, we expect the provided hwpath to be valid. */
@@ -191,15 +204,13 @@ pdcspath_store(struct pdcspath_entry *entry)
printk(KERN_ERR "%s: an error occured when writing to PDC.\n"
"It is likely that the Stable Storage data has been corrupted.\n"
"Please check it carefully upon next reboot.\n", __func__);
- return -EIO;
+ WARN_ON(1);
}
/* kobject is already registered */
entry->ready = 2;
DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
-
- return 0;
}
/**
@@ -214,14 +225,17 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf)
{
char *out = buf;
struct device_path *devpath;
- unsigned short i;
+ short i;
if (!entry || !buf)
return -EINVAL;
+ read_lock(&entry->rw_lock);
devpath = &entry->devpath;
+ i = entry->ready;
+ read_unlock(&entry->rw_lock);
- if (!entry->ready)
+ if (!i) /* entry is not ready */
return -ENODATA;
for (i = 0; i < 6; i++) {
@@ -242,7 +256,7 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf)
*
* We will call this function to change the current hardware path.
* Hardware paths are to be given '/'-delimited, without brackets.
- * We take care to make sure that the provided path actually maps to an existing
+ * We make sure that the provided path actually maps to an existing
* device, BUT nothing would prevent some foolish user to set the path to some
* PCI bridge or even a CPU...
* A better work around would be to make sure we are at the end of a device tree
@@ -298,17 +312,19 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun
}
/* So far so good, let's get in deep */
+ write_lock(&entry->rw_lock);
entry->ready = 0;
entry->dev = dev;
/* Now, dive in. Write back to the hardware */
- WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */
+ pdcspath_store(entry);
/* Update the symlink to the real device */
sysfs_remove_link(&entry->kobj, "device");
sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ write_unlock(&entry->rw_lock);
- printk(KERN_INFO "PDC Stable Storage: changed \"%s\" path to \"%s\"\n",
+ printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n",
entry->name, buf);
return count;
@@ -326,14 +342,17 @@ pdcspath_layer_read(struct pdcspath_entry *entry, char *buf)
{
char *out = buf;
struct device_path *devpath;
- unsigned short i;
+ short i;
if (!entry || !buf)
return -EINVAL;
+ read_lock(&entry->rw_lock);
devpath = &entry->devpath;
+ i = entry->ready;
+ read_unlock(&entry->rw_lock);
- if (!entry->ready)
+ if (!i) /* entry is not ready */
return -ENODATA;
for (i = 0; devpath->layers[i] && (likely(i < 6)); i++)
@@ -388,15 +407,17 @@ pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count
}
/* So far so good, let's get in deep */
+ write_lock(&entry->rw_lock);
/* First, overwrite the current layers with the new ones, not touching
the hardware path. */
memcpy(&entry->devpath.layers, &layers, sizeof(layers));
/* Now, dive in. Write back to the hardware */
- WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */
+ pdcspath_store(entry);
+ write_unlock(&entry->rw_lock);
- printk(KERN_INFO "PDC Stable Storage: changed \"%s\" layers to \"%s\"\n",
+ printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" layers to \"%s\"\n",
entry->name, buf);
return count;
@@ -415,9 +436,6 @@ pdcspath_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr);
ssize_t ret = 0;
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
if (pdcs_attr->show)
ret = pdcs_attr->show(entry, buf);
@@ -454,8 +472,8 @@ static struct sysfs_ops pdcspath_attr_ops = {
};
/* These are the two attributes of any PDC path. */
-static PATHS_ATTR(hwpath, 0600, pdcspath_hwpath_read, pdcspath_hwpath_write);
-static PATHS_ATTR(layer, 0600, pdcspath_layer_read, pdcspath_layer_write);
+static PATHS_ATTR(hwpath, 0644, pdcspath_hwpath_read, pdcspath_hwpath_write);
+static PATHS_ATTR(layer, 0644, pdcspath_layer_read, pdcspath_layer_write);
static struct attribute *paths_subsys_attrs[] = {
&paths_attr_hwpath.attr,
@@ -484,36 +502,119 @@ static struct pdcspath_entry *pdcspath_entries[] = {
NULL,
};
+
+/* For more insight of what's going on here, refer to PDC Procedures doc,
+ * Section PDC_STABLE */
+
/**
- * pdcs_info_read - Pretty printing of the remaining useful data.
+ * pdcs_size_read - Stable Storage size output.
* @entry: An allocated and populated subsytem struct. We don't use it tho.
* @buf: The output buffer to write to.
- *
- * We will call this function to format the output of the 'info' attribute file.
- * Please refer to PDC Procedures documentation, section PDC_STABLE to get a
- * better insight of what we're doing here.
*/
static ssize_t
-pdcs_info_read(struct subsystem *entry, char *buf)
+pdcs_size_read(struct subsystem *entry, char *buf)
{
char *out = buf;
- __u32 result;
- struct device_path devpath;
- char *tmpstr = NULL;
if (!entry || !buf)
return -EINVAL;
/* show the size of the stable storage */
- out += sprintf(out, "Stable Storage size: %ld bytes\n", pdcs_size);
+ out += sprintf(out, "%ld\n", pdcs_size);
- /* deal with flags */
- if (pdc_stable_read(PDCS_ADDR_PPRI, &devpath, sizeof(devpath)) != PDC_OK)
- return -EIO;
+ return out - buf;
+}
+
+/**
+ * pdcs_auto_read - Stable Storage autoboot/search flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
+ */
+static ssize_t
+pdcs_auto_read(struct subsystem *entry, char *buf, int knob)
+{
+ char *out = buf;
+ struct pdcspath_entry *pathentry;
- out += sprintf(out, "Autoboot: %s\n", (devpath.flags & PF_AUTOBOOT) ? "On" : "Off");
- out += sprintf(out, "Autosearch: %s\n", (devpath.flags & PF_AUTOSEARCH) ? "On" : "Off");
- out += sprintf(out, "Timer: %u s\n", (devpath.flags & PF_TIMER) ? (1 << (devpath.flags & PF_TIMER)) : 0);
+ if (!entry || !buf)
+ return -EINVAL;
+
+ /* Current flags are stored in primary boot path entry */
+ pathentry = &pdcspath_entry_primary;
+
+ read_lock(&pathentry->rw_lock);
+ out += sprintf(out, "%s\n", (pathentry->devpath.flags & knob) ?
+ "On" : "Off");
+ read_unlock(&pathentry->rw_lock);
+
+ return out - buf;
+}
+
+/**
+ * pdcs_autoboot_read - Stable Storage autoboot flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static inline ssize_t
+pdcs_autoboot_read(struct subsystem *entry, char *buf)
+{
+ return pdcs_auto_read(entry, buf, PF_AUTOBOOT);
+}
+
+/**
+ * pdcs_autosearch_read - Stable Storage autoboot flag output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static inline ssize_t
+pdcs_autosearch_read(struct subsystem *entry, char *buf)
+{
+ return pdcs_auto_read(entry, buf, PF_AUTOSEARCH);
+}
+
+/**
+ * pdcs_timer_read - Stable Storage timer count output (in seconds).
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * The value of the timer field correponds to a number of seconds in powers of 2.
+ */
+static ssize_t
+pdcs_timer_read(struct subsystem *entry, char *buf)
+{
+ char *out = buf;
+ struct pdcspath_entry *pathentry;
+
+ if (!entry || !buf)
+ return -EINVAL;
+
+ /* Current flags are stored in primary boot path entry */
+ pathentry = &pdcspath_entry_primary;
+
+ /* print the timer value in seconds */
+ read_lock(&pathentry->rw_lock);
+ out += sprintf(out, "%u\n", (pathentry->devpath.flags & PF_TIMER) ?
+ (1 << (pathentry->devpath.flags & PF_TIMER)) : 0);
+ read_unlock(&pathentry->rw_lock);
+
+ return out - buf;
+}
+
+/**
+ * pdcs_osid_read - Stable Storage OS ID register output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ */
+static ssize_t
+pdcs_osid_read(struct subsystem *entry, char *buf)
+{
+ char *out = buf;
+ __u32 result;
+ char *tmpstr = NULL;
+
+ if (!entry || !buf)
+ return -EINVAL;
/* get OSID */
if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
@@ -529,13 +630,31 @@ pdcs_info_read(struct subsystem *entry, char *buf)
case 0x0005: tmpstr = "Novell Netware dependent data"; break;
default: tmpstr = "Unknown"; break;
}
- out += sprintf(out, "OS ID: %s (0x%.4x)\n", tmpstr, (result >> 16));
+ out += sprintf(out, "%s (0x%.4x)\n", tmpstr, (result >> 16));
+
+ return out - buf;
+}
+
+/**
+ * pdcs_fastsize_read - Stable Storage FastSize register output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * This register holds the amount of system RAM to be tested during boot sequence.
+ */
+static ssize_t
+pdcs_fastsize_read(struct subsystem *entry, char *buf)
+{
+ char *out = buf;
+ __u32 result;
+
+ if (!entry || !buf)
+ return -EINVAL;
/* get fast-size */
if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK)
return -EIO;
- out += sprintf(out, "Memory tested: ");
if ((result & 0x0F) < 0x0E)
out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256);
else
@@ -546,22 +665,18 @@ pdcs_info_read(struct subsystem *entry, char *buf)
}
/**
- * pdcs_info_write - This function handles boot flag modifying.
+ * pdcs_auto_write - This function handles autoboot/search flag modifying.
* @entry: An allocated and populated subsytem struct. We don't use it tho.
* @buf: The input buffer to read from.
* @count: The number of bytes to be read.
+ * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
*
- * We will call this function to change the current boot flags.
+ * We will call this function to change the current autoboot flag.
* We expect a precise syntax:
- * \"n n\" (n == 0 or 1) to toggle respectively AutoBoot and AutoSearch
- *
- * As of now there is no incentive on my side to provide more "knobs" to that
- * interface, since modifying the rest of the data is pretty meaningless when
- * the machine is running and for the expected use of that facility, such as
- * PALO setting up the boot disk when installing a Linux distribution...
+ * \"n\" (n == 0 or 1) to toggle AutoBoot Off or On
*/
static ssize_t
-pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob)
{
struct pdcspath_entry *pathentry;
unsigned char flags;
@@ -582,7 +697,9 @@ pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
pathentry = &pdcspath_entry_primary;
/* Be nice to the existing flag record */
+ read_lock(&pathentry->rw_lock);
flags = pathentry->devpath.flags;
+ read_unlock(&pathentry->rw_lock);
DPRINTK("%s: flags before: 0x%X\n", __func__, flags);
@@ -595,50 +712,85 @@ pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
if ((c != 0) && (c != 1))
goto parse_error;
if (c == 0)
- flags &= ~PF_AUTOBOOT;
+ flags &= ~knob;
else
- flags |= PF_AUTOBOOT;
-
- if (*temp++ != ' ')
- goto parse_error;
-
- c = *temp++ - '0';
- if ((c != 0) && (c != 1))
- goto parse_error;
- if (c == 0)
- flags &= ~PF_AUTOSEARCH;
- else
- flags |= PF_AUTOSEARCH;
+ flags |= knob;
DPRINTK("%s: flags after: 0x%X\n", __func__, flags);
/* So far so good, let's get in deep */
+ write_lock(&pathentry->rw_lock);
/* Change the path entry flags first */
pathentry->devpath.flags = flags;
/* Now, dive in. Write back to the hardware */
- WARN_ON(pdcspath_store(pathentry)); /* this warn should *NEVER* happen */
+ pdcspath_store(pathentry);
+ write_unlock(&pathentry->rw_lock);
- printk(KERN_INFO "PDC Stable Storage: changed flags to \"%s\"\n", buf);
+ printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" to \"%s\"\n",
+ (knob & PF_AUTOBOOT) ? "autoboot" : "autosearch",
+ (flags & knob) ? "On" : "Off");
return count;
parse_error:
- printk(KERN_WARNING "%s: Parse error: expect \"n n\" (n == 0 or 1) for AB and AS\n", __func__);
+ printk(KERN_WARNING "%s: Parse error: expect \"n\" (n == 0 or 1)\n", __func__);
return -EINVAL;
}
-/* The last attribute (the 'root' one actually) with all remaining data. */
-static PDCS_ATTR(info, 0600, pdcs_info_read, pdcs_info_write);
+/**
+ * pdcs_autoboot_write - This function handles autoboot flag modifying.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current boot flags.
+ * We expect a precise syntax:
+ * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On
+ */
+static inline ssize_t
+pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count)
+{
+ return pdcs_auto_write(entry, buf, count, PF_AUTOBOOT);
+}
+
+/**
+ * pdcs_autosearch_write - This function handles autosearch flag modifying.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current boot flags.
+ * We expect a precise syntax:
+ * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On
+ */
+static inline ssize_t
+pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count)
+{
+ return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH);
+}
+
+/* The remaining attributes. */
+static PDCS_ATTR(size, 0444, pdcs_size_read, NULL);
+static PDCS_ATTR(autoboot, 0644, pdcs_autoboot_read, pdcs_autoboot_write);
+static PDCS_ATTR(autosearch, 0644, pdcs_autosearch_read, pdcs_autosearch_write);
+static PDCS_ATTR(timer, 0444, pdcs_timer_read, NULL);
+static PDCS_ATTR(osid, 0400, pdcs_osid_read, NULL);
+static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL);
static struct subsys_attribute *pdcs_subsys_attrs[] = {
- &pdcs_attr_info,
- NULL, /* maybe more in the future? */
+ &pdcs_attr_size,
+ &pdcs_attr_autoboot,
+ &pdcs_attr_autosearch,
+ &pdcs_attr_timer,
+ &pdcs_attr_osid,
+ &pdcs_attr_fastsize,
+ NULL,
};
static decl_subsys(paths, &ktype_pdcspath, NULL);
-static decl_subsys(pdc, NULL, NULL);
+static decl_subsys(stable, NULL, NULL);
/**
* pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage.
@@ -656,8 +808,16 @@ pdcs_register_pathentries(void)
struct pdcspath_entry *entry;
int err;
+ /* Initialize the entries rw_lock before anything else */
+ for (i = 0; (entry = pdcspath_entries[i]); i++)
+ rwlock_init(&entry->rw_lock);
+
for (i = 0; (entry = pdcspath_entries[i]); i++) {
- if (pdcspath_fetch(entry) < 0)
+ write_lock(&entry->rw_lock);
+ err = pdcspath_fetch(entry);
+ write_unlock(&entry->rw_lock);
+
+ if (err < 0)
continue;
if ((err = kobject_set_name(&entry->kobj, "%s", entry->name)))
@@ -667,13 +827,14 @@ pdcs_register_pathentries(void)
return err;
/* kobject is now registered */
+ write_lock(&entry->rw_lock);
entry->ready = 2;
- if (!entry->dev)
- continue;
-
/* Add a nice symlink to the real device */
- sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ if (entry->dev)
+ sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+
+ write_unlock(&entry->rw_lock);
}
return 0;
@@ -688,14 +849,17 @@ pdcs_unregister_pathentries(void)
unsigned short i;
struct pdcspath_entry *entry;
- for (i = 0; (entry = pdcspath_entries[i]); i++)
+ for (i = 0; (entry = pdcspath_entries[i]); i++) {
+ read_lock(&entry->rw_lock);
if (entry->ready >= 2)
- kobject_unregister(&entry->kobj);
+ kobject_unregister(&entry->kobj);
+ read_unlock(&entry->rw_lock);
+ }
}
/*
- * For now we register the pdc subsystem with the firmware subsystem
- * and the paths subsystem with the pdc subsystem
+ * For now we register the stable subsystem with the firmware subsystem
+ * and the paths subsystem with the stable subsystem
*/
static int __init
pdc_stable_init(void)
@@ -707,19 +871,23 @@ pdc_stable_init(void)
if (pdc_stable_get_size(&pdcs_size) != PDC_OK)
return -ENODEV;
- printk(KERN_INFO "PDC Stable Storage facility v%s\n", PDCS_VERSION);
+ /* make sure we have enough data */
+ if (pdcs_size < 96)
+ return -ENODATA;
+
+ printk(KERN_INFO PDCS_PREFIX " facility v%s\n", PDCS_VERSION);
- /* For now we'll register the pdc subsys within this driver */
- if ((rc = firmware_register(&pdc_subsys)))
+ /* For now we'll register the stable subsys within this driver */
+ if ((rc = firmware_register(&stable_subsys)))
goto fail_firmreg;
- /* Don't forget the info entry */
+ /* Don't forget the root entries */
for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
if (attr->show)
- error = subsys_create_file(&pdc_subsys, attr);
+ error = subsys_create_file(&stable_subsys, attr);
- /* register the paths subsys as a subsystem of pdc subsys */
- kset_set_kset_s(&paths_subsys, pdc_subsys);
+ /* register the paths subsys as a subsystem of stable subsys */
+ kset_set_kset_s(&paths_subsys, stable_subsys);
if ((rc= subsystem_register(&paths_subsys)))
goto fail_subsysreg;
@@ -734,10 +902,10 @@ fail_pdcsreg:
subsystem_unregister(&paths_subsys);
fail_subsysreg:
- firmware_unregister(&pdc_subsys);
+ firmware_unregister(&stable_subsys);
fail_firmreg:
- printk(KERN_INFO "PDC Stable Storage bailing out\n");
+ printk(KERN_INFO PDCS_PREFIX " bailing out\n");
return rc;
}
@@ -747,7 +915,7 @@ pdc_stable_exit(void)
pdcs_unregister_pathentries();
subsystem_unregister(&paths_subsys);
- firmware_unregister(&pdc_subsys);
+ firmware_unregister(&stable_subsys);
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index c85653f315a..5d47c5965c5 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -37,6 +37,8 @@
#include <asm/hardware.h> /* for register_parisc_driver() stuff */
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
#include <asm/runway.h> /* for proc_runway_root */
#include <asm/pdc.h> /* for PDC_MODEL_* */
#include <asm/pdcpat.h> /* for is_pdc_pat() */
@@ -1892,46 +1894,43 @@ sba_common_init(struct sba_device *sba_dev)
}
#ifdef CONFIG_PROC_FS
-static int sba_proc_info(char *buf, char **start, off_t offset, int len)
+static int sba_proc_info(struct seq_file *m, void *p)
{
struct sba_device *sba_dev = sba_list;
struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */
int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
- unsigned long i;
#ifdef SBA_COLLECT_STATS
unsigned long avg = 0, min, max;
#endif
+ int i, len = 0;
- sprintf(buf, "%s rev %d.%d\n",
+ len += seq_printf(m, "%s rev %d.%d\n",
sba_dev->name,
(sba_dev->hw_rev & 0x7) + 1,
(sba_dev->hw_rev & 0x18) >> 3
);
- sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n",
- buf,
+ len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n",
(int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */
total_pages);
- sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
- buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
+ len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n",
+ ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
- sprintf(buf, "%sLMMIO_BASE/MASK/ROUTE %08x %08x %08x\n",
- buf,
+ len += seq_printf(m, "LMMIO_BASE/MASK/ROUTE %08x %08x %08x\n",
READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_BASE),
READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_MASK),
READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_ROUTE)
);
for (i=0; i<4; i++)
- sprintf(buf, "%sDIR%ld_BASE/MASK/ROUTE %08x %08x %08x\n",
- buf, i,
+ len += seq_printf(m, "DIR%d_BASE/MASK/ROUTE %08x %08x %08x\n", i,
READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_BASE + i*0x18),
READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_MASK + i*0x18),
READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_ROUTE + i*0x18)
);
#ifdef SBA_COLLECT_STATS
- sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf,
+ len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n",
total_pages - ioc->used_pages, ioc->used_pages,
(int) (ioc->used_pages * 100 / total_pages));
@@ -1942,53 +1941,76 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len)
if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
}
avg /= SBA_SEARCH_SAMPLE;
- sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
- buf, min, avg, max);
+ len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+ min, avg, max);
- sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n",
- buf, ioc->msingle_calls, ioc->msingle_pages,
+ len += seq_printf(m, "pci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n",
+ ioc->msingle_calls, ioc->msingle_pages,
(int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
/* KLUGE - unmap_sg calls unmap_single for each mapped page */
min = ioc->usingle_calls;
max = ioc->usingle_pages - ioc->usg_pages;
- sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n",
- buf, min, max,
- (int) ((max * 1000)/min));
+ len += seq_printf(m, "pci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n",
+ min, max, (int) ((max * 1000)/min));
- sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
- buf, ioc->msg_calls, ioc->msg_pages,
+ len += seq_printf(m, "pci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
+ ioc->msg_calls, ioc->msg_pages,
(int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
- sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
- buf, ioc->usg_calls, ioc->usg_pages,
+ len += seq_printf(m, "pci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
+ ioc->usg_calls, ioc->usg_pages,
(int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
#endif
- return strlen(buf);
+ return 0;
}
-#if 0
-/* XXX too much output - exceeds 4k limit and needs to be re-written */
static int
-sba_resource_map(char *buf, char **start, off_t offset, int len)
+sba_proc_open(struct inode *i, struct file *f)
+{
+ return single_open(f, &sba_proc_info, NULL);
+}
+
+static struct file_operations sba_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = sba_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int
+sba_proc_bitmap_info(struct seq_file *m, void *p)
{
struct sba_device *sba_dev = sba_list;
- struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Mutli-IOC suppoer! */
+ struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */
unsigned int *res_ptr = (unsigned int *)ioc->res_map;
- int i;
+ int i, len = 0;
- buf[0] = '\0';
- for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) {
+ for (i = 0; i < (ioc->res_size/sizeof(unsigned int)); ++i, ++res_ptr) {
if ((i & 7) == 0)
- strcat(buf,"\n ");
- sprintf(buf, "%s %08x", buf, *res_ptr);
+ len += seq_printf(m, "\n ");
+ len += seq_printf(m, " %08x", *res_ptr);
}
- strcat(buf, "\n");
+ len += seq_printf(m, "\n");
- return strlen(buf);
+ return 0;
}
-#endif /* 0 */
+
+static int
+sba_proc_bitmap_open(struct inode *i, struct file *f)
+{
+ return single_open(f, &sba_proc_bitmap_info, NULL);
+}
+
+static struct file_operations sba_proc_bitmap_fops = {
+ .owner = THIS_MODULE,
+ .open = sba_proc_bitmap_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif /* CONFIG_PROC_FS */
static struct parisc_device_id sba_tbl[] = {
@@ -2021,6 +2043,7 @@ sba_driver_callback(struct parisc_device *dev)
int i;
char *version;
void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
+ struct proc_dir_entry *info_entry, *bitmap_entry, *root;
sba_dump_ranges(sba_addr);
@@ -2064,14 +2087,13 @@ sba_driver_callback(struct parisc_device *dev)
printk(KERN_INFO "%s found %s at 0x%lx\n",
MODULE_NAME, version, dev->hpa.start);
- sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
+ sba_dev = kzalloc(sizeof(struct sba_device), GFP_KERNEL);
if (!sba_dev) {
printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
return -ENOMEM;
}
parisc_set_drvdata(dev, sba_dev);
- memset(sba_dev, 0, sizeof(struct sba_device));
for(i=0; i<MAX_IOC; i++)
spin_lock_init(&(sba_dev->ioc[i].res_lock));
@@ -2089,19 +2111,27 @@ sba_driver_callback(struct parisc_device *dev)
hppa_dma_ops = &sba_ops;
#ifdef CONFIG_PROC_FS
- if (IS_ASTRO(&dev->id)) {
- create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info);
- } else if (IS_IKE(&dev->id)) {
- create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info);
- } else if (IS_PLUTO(&dev->id)) {
- create_proc_info_entry("Pluto", 0, proc_mckinley_root, sba_proc_info);
- } else {
- create_proc_info_entry("Reo", 0, proc_runway_root, sba_proc_info);
+ switch (dev->id.hversion) {
+ case PLUTO_MCKINLEY_PORT:
+ root = proc_mckinley_root;
+ break;
+ case ASTRO_RUNWAY_PORT:
+ case IKE_MERCED_PORT:
+ default:
+ root = proc_runway_root;
+ break;
}
-#if 0
- create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map);
-#endif
+
+ info_entry = create_proc_entry("sba_iommu", 0, root);
+ bitmap_entry = create_proc_entry("sba_iommu-bitmap", 0, root);
+
+ if (info_entry)
+ info_entry->proc_fops = &sba_proc_fops;
+
+ if (bitmap_entry)
+ bitmap_entry->proc_fops = &sba_proc_bitmap_fops;
#endif
+
parisc_vmerge_boundary = IOVP_SIZE;
parisc_vmerge_max_size = IOVP_SIZE * BITS_PER_LONG;
parisc_has_iommu();
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index d14888e149b..ba971fecd0d 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -89,6 +89,9 @@ static struct superio_device sio_dev;
#define DBG_INIT(x...)
#endif
+#define SUPERIO "SuperIO"
+#define PFX SUPERIO ": "
+
static irqreturn_t
superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
{
@@ -117,7 +120,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
local_irq = results & 0x0f;
if (local_irq == 2 || local_irq > 7) {
- printk(KERN_ERR "SuperIO: slave interrupted!\n");
+ printk(KERN_ERR PFX "slave interrupted!\n");
return IRQ_HANDLED;
}
@@ -128,7 +131,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
outb(OCW3_ISR,IC_PIC1+0);
results = inb(IC_PIC1+0);
if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */
- printk(KERN_WARNING "SuperIO: spurious interrupt!\n");
+ printk(KERN_WARNING PFX "spurious interrupt!\n");
return IRQ_HANDLED;
}
}
@@ -163,27 +166,27 @@ superio_init(struct pci_dev *pcidev)
/* ...then properly fixup the USB to point at suckyio PIC */
sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev);
- printk(KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
+ printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
pci_name(pdev), pdev->irq);
pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base);
sio->sp1_base &= ~1;
- printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base);
+ printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base);
pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base);
sio->sp2_base &= ~1;
- printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base);
+ printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base);
pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base);
sio->pp_base &= ~1;
- printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base);
+ printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base);
pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base);
sio->fdc_base &= ~1;
- printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base);
+ printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base);
pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base);
sio->acpi_base &= ~1;
- printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base);
+ printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base);
request_region (IC_PIC1, 0x1f, "pic1");
request_region (IC_PIC2, 0x1f, "pic2");
@@ -263,14 +266,14 @@ superio_init(struct pci_dev *pcidev)
/* Setup USB power regulation */
outb(1, sio->acpi_base + USB_REG_CR);
if (inb(sio->acpi_base + USB_REG_CR) & 1)
- printk(KERN_INFO "SuperIO: USB regulator enabled\n");
+ printk(KERN_INFO PFX "USB regulator enabled\n");
else
- printk(KERN_ERR "USB regulator not initialized!\n");
+ printk(KERN_ERR PFX "USB regulator not initialized!\n");
if (request_irq(pdev->irq, superio_interrupt, SA_INTERRUPT,
- "SuperIO", (void *)sio)) {
+ SUPERIO, (void *)sio)) {
- printk(KERN_ERR "SuperIO: could not get irq\n");
+ printk(KERN_ERR PFX "could not get irq\n");
BUG();
return;
}
@@ -284,7 +287,7 @@ static void superio_disable_irq(unsigned int irq)
u8 r8;
if ((irq < 1) || (irq == 2) || (irq > 7)) {
- printk(KERN_ERR "SuperIO: Illegal irq number.\n");
+ printk(KERN_ERR PFX "Illegal irq number.\n");
BUG();
return;
}
@@ -301,7 +304,7 @@ static void superio_enable_irq(unsigned int irq)
u8 r8;
if ((irq < 1) || (irq == 2) || (irq > 7)) {
- printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", irq);
+ printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq);
BUG();
return;
}
@@ -319,7 +322,7 @@ static unsigned int superio_startup_irq(unsigned int irq)
}
static struct hw_interrupt_type superio_interrupt_type = {
- .typename = "SuperIO",
+ .typename = SUPERIO,
.startup = superio_startup_irq,
.shutdown = superio_disable_irq,
.enable = superio_enable_irq,
@@ -413,7 +416,7 @@ static void __devinit superio_serial_init(void)
retval = early_serial_setup(&serial[0]);
if (retval < 0) {
- printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n");
+ printk(KERN_WARNING PFX "Register Serial #0 failed.\n");
return;
}
@@ -423,7 +426,7 @@ static void __devinit superio_serial_init(void)
retval = early_serial_setup(&serial[1]);
if (retval < 0)
- printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n");
+ printk(KERN_WARNING PFX "Register Serial #1 failed.\n");
#endif /* CONFIG_SERIAL_8250 */
}
@@ -437,7 +440,7 @@ static void __devinit superio_parport_init(void)
PARPORT_DMA_NONE /* dma */,
NULL /*struct pci_dev* */) )
- printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n");
+ printk(KERN_WARNING PFX "Probing parallel port failed.\n");
#endif /* CONFIG_PARPORT_PC */
}
@@ -499,7 +502,7 @@ static struct pci_device_id superio_tbl[] = {
};
static struct pci_driver superio_driver = {
- .name = "SuperIO",
+ .name = SUPERIO,
.id_table = superio_tbl,
.probe = superio_probe,
};
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index 17dce2adf7f..813c2c24ab1 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -76,7 +76,7 @@ wax_init_chip(struct parisc_device *dev)
struct gsc_irq gsc_irq;
int ret;
- wax = kmalloc(sizeof(*wax), GFP_KERNEL);
+ wax = kzalloc(sizeof(*wax), GFP_KERNEL);
if (!wax)
return -ENOMEM;
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index f605dea5722..f63c387976c 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -90,6 +90,15 @@ config PARPORT_ARC
depends on ARM && PARPORT
select PARPORT_NOT_PC
+config PARPORT_IP32
+ tristate "SGI IP32 builtin port (EXPERIMENTAL)"
+ depends on SGI_IP32 && PARPORT && EXPERIMENTAL
+ select PARPORT_NOT_PC
+ help
+ Say Y here if you need support for the parallel port on
+ SGI O2 machines. This code is also available as a module (say M),
+ called parport_ip32. If in doubt, saying N is the safe plan.
+
config PARPORT_AMIGA
tristate "Amiga builtin port"
depends on AMIGA && PARPORT
diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile
index 5372212bb9d..a19de35f8de 100644
--- a/drivers/parport/Makefile
+++ b/drivers/parport/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o
obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o
obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o
obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o
+obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index 5b887ba5aaf..690b239ad3a 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -61,10 +61,10 @@ static void timeout_waiting_on_port (unsigned long cookie)
* set to zero, it returns immediately.
*
* If an interrupt occurs before the timeout period elapses, this
- * function returns one immediately. If it times out, it returns
- * a value greater than zero. An error code less than zero
- * indicates an error (most likely a pending signal), and the
- * calling code should finish what it's doing as soon as it can.
+ * function returns zero immediately. If it times out, it returns
+ * one. An error code less than zero indicates an error (most
+ * likely a pending signal), and the calling code should finish
+ * what it's doing as soon as it can.
*/
int parport_wait_event (struct parport *port, signed long timeout)
@@ -110,7 +110,7 @@ int parport_wait_event (struct parport *port, signed long timeout)
*
* If the status lines take on the desired values before the
* timeout period elapses, parport_poll_peripheral() returns zero
- * immediately. A zero return value greater than zero indicates
+ * immediately. A return value greater than zero indicates
* a timeout. An error code (less than zero) indicates an error,
* most likely a signal that arrived, and the caller should
* finish what it is doing as soon as possible.
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index fde29a75f88..1de52d9febf 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -249,7 +249,7 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
struct parport tmp;
struct parport *p = &tmp;
- priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL);
+ priv = kzalloc (sizeof (struct parport_gsc_private), GFP_KERNEL);
if (!priv) {
printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
return NULL;
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c
new file mode 100644
index 00000000000..46e06e596d7
--- /dev/null
+++ b/drivers/parport/parport_ip32.c
@@ -0,0 +1,2253 @@
+/* Low-level parallel port routines for built-in port on SGI IP32
+ *
+ * Author: Arnaud Giersch <arnaud.giersch@free.fr>
+ *
+ * Based on parport_pc.c by
+ * Phil Blundell, Tim Waugh, Jose Renau, David Campbell,
+ * Andrea Arcangeli, et al.
+ *
+ * Thanks to Ilya A. Volynets-Evenbakh for his help.
+ *
+ * Copyright (C) 2005, 2006 Arnaud Giersch.
+ *
+ * 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.
+ */
+
+/* Current status:
+ *
+ * Basic SPP and PS2 modes are supported.
+ * Support for parallel port IRQ is present.
+ * Hardware SPP (a.k.a. compatibility), EPP, and ECP modes are
+ * supported.
+ * SPP/ECP FIFO can be driven in PIO or DMA mode. PIO mode can work with
+ * or without interrupt support.
+ *
+ * Hardware ECP mode is not fully implemented (ecp_read_data and
+ * ecp_write_addr are actually missing).
+ *
+ * To do:
+ *
+ * Fully implement ECP mode.
+ * EPP and ECP mode need to be tested. I currently do not own any
+ * peripheral supporting these extended mode, and cannot test them.
+ * If DMA mode works well, decide if support for PIO FIFO modes should be
+ * dropped.
+ * Use the io{read,write} family functions when they become available in
+ * the linux-mips.org tree. Note: the MIPS specific functions readsb()
+ * and writesb() are to be translated by ioread8_rep() and iowrite8_rep()
+ * respectively.
+ */
+
+/* The built-in parallel port on the SGI 02 workstation (a.k.a. IP32) is an
+ * IEEE 1284 parallel port driven by a Texas Instrument TL16PIR552PH chip[1].
+ * This chip supports SPP, bidirectional, EPP and ECP modes. It has a 16 byte
+ * FIFO buffer and supports DMA transfers.
+ *
+ * [1] http://focus.ti.com/docs/prod/folders/print/tl16pir552.html
+ *
+ * Theoretically, we could simply use the parport_pc module. It is however
+ * not so simple. The parport_pc code assumes that the parallel port
+ * registers are port-mapped. On the O2, they are memory-mapped.
+ * Furthermore, each register is replicated on 256 consecutive addresses (as
+ * it is for the built-in serial ports on the same chip).
+ */
+
+/*--- Some configuration defines ---------------------------------------*/
+
+/* DEBUG_PARPORT_IP32
+ * 0 disable debug
+ * 1 standard level: pr_debug1 is enabled
+ * 2 parport_ip32_dump_state is enabled
+ * >=3 verbose level: pr_debug is enabled
+ */
+#if !defined(DEBUG_PARPORT_IP32)
+# define DEBUG_PARPORT_IP32 0 /* 0 (disabled) for production */
+#endif
+
+/*----------------------------------------------------------------------*/
+
+/* Setup DEBUG macros. This is done before any includes, just in case we
+ * activate pr_debug() with DEBUG_PARPORT_IP32 >= 3.
+ */
+#if DEBUG_PARPORT_IP32 == 1
+# warning DEBUG_PARPORT_IP32 == 1
+#elif DEBUG_PARPORT_IP32 == 2
+# warning DEBUG_PARPORT_IP32 == 2
+#elif DEBUG_PARPORT_IP32 >= 3
+# warning DEBUG_PARPORT_IP32 >= 3
+# if !defined(DEBUG)
+# define DEBUG /* enable pr_debug() in kernel.h */
+# endif
+#endif
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/parport.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/ip32/ip32_ints.h>
+#include <asm/ip32/mace.h>
+
+/*--- Global variables -------------------------------------------------*/
+
+/* Verbose probing on by default for debugging. */
+#if DEBUG_PARPORT_IP32 >= 1
+# define DEFAULT_VERBOSE_PROBING 1
+#else
+# define DEFAULT_VERBOSE_PROBING 0
+#endif
+
+/* Default prefix for printk */
+#define PPIP32 "parport_ip32: "
+
+/*
+ * These are the module parameters:
+ * @features: bit mask of features to enable/disable
+ * (all enabled by default)
+ * @verbose_probing: log chit-chat during initialization
+ */
+#define PARPORT_IP32_ENABLE_IRQ (1U << 0)
+#define PARPORT_IP32_ENABLE_DMA (1U << 1)
+#define PARPORT_IP32_ENABLE_SPP (1U << 2)
+#define PARPORT_IP32_ENABLE_EPP (1U << 3)
+#define PARPORT_IP32_ENABLE_ECP (1U << 4)
+static unsigned int features = ~0U;
+static int verbose_probing = DEFAULT_VERBOSE_PROBING;
+
+/* We do not support more than one port. */
+static struct parport *this_port = NULL;
+
+/* Timing constants for FIFO modes. */
+#define FIFO_NFAULT_TIMEOUT 100 /* milliseconds */
+#define FIFO_POLLING_INTERVAL 50 /* microseconds */
+
+/*--- I/O register definitions -----------------------------------------*/
+
+/**
+ * struct parport_ip32_regs - virtual addresses of parallel port registers
+ * @data: Data Register
+ * @dsr: Device Status Register
+ * @dcr: Device Control Register
+ * @eppAddr: EPP Address Register
+ * @eppData0: EPP Data Register 0
+ * @eppData1: EPP Data Register 1
+ * @eppData2: EPP Data Register 2
+ * @eppData3: EPP Data Register 3
+ * @ecpAFifo: ECP Address FIFO
+ * @fifo: General FIFO register. The same address is used for:
+ * - cFifo, the Parallel Port DATA FIFO
+ * - ecpDFifo, the ECP Data FIFO
+ * - tFifo, the ECP Test FIFO
+ * @cnfgA: Configuration Register A
+ * @cnfgB: Configuration Register B
+ * @ecr: Extended Control Register
+ */
+struct parport_ip32_regs {
+ void __iomem *data;
+ void __iomem *dsr;
+ void __iomem *dcr;
+ void __iomem *eppAddr;
+ void __iomem *eppData0;
+ void __iomem *eppData1;
+ void __iomem *eppData2;
+ void __iomem *eppData3;
+ void __iomem *ecpAFifo;
+ void __iomem *fifo;
+ void __iomem *cnfgA;
+ void __iomem *cnfgB;
+ void __iomem *ecr;
+};
+
+/* Device Status Register */
+#define DSR_nBUSY (1U << 7) /* PARPORT_STATUS_BUSY */
+#define DSR_nACK (1U << 6) /* PARPORT_STATUS_ACK */
+#define DSR_PERROR (1U << 5) /* PARPORT_STATUS_PAPEROUT */
+#define DSR_SELECT (1U << 4) /* PARPORT_STATUS_SELECT */
+#define DSR_nFAULT (1U << 3) /* PARPORT_STATUS_ERROR */
+#define DSR_nPRINT (1U << 2) /* specific to TL16PIR552 */
+/* #define DSR_reserved (1U << 1) */
+#define DSR_TIMEOUT (1U << 0) /* EPP timeout */
+
+/* Device Control Register */
+/* #define DCR_reserved (1U << 7) | (1U << 6) */
+#define DCR_DIR (1U << 5) /* direction */
+#define DCR_IRQ (1U << 4) /* interrupt on nAck */
+#define DCR_SELECT (1U << 3) /* PARPORT_CONTROL_SELECT */
+#define DCR_nINIT (1U << 2) /* PARPORT_CONTROL_INIT */
+#define DCR_AUTOFD (1U << 1) /* PARPORT_CONTROL_AUTOFD */
+#define DCR_STROBE (1U << 0) /* PARPORT_CONTROL_STROBE */
+
+/* ECP Configuration Register A */
+#define CNFGA_IRQ (1U << 7)
+#define CNFGA_ID_MASK ((1U << 6) | (1U << 5) | (1U << 4))
+#define CNFGA_ID_SHIFT 4
+#define CNFGA_ID_16 (00U << CNFGA_ID_SHIFT)
+#define CNFGA_ID_8 (01U << CNFGA_ID_SHIFT)
+#define CNFGA_ID_32 (02U << CNFGA_ID_SHIFT)
+/* #define CNFGA_reserved (1U << 3) */
+#define CNFGA_nBYTEINTRANS (1U << 2)
+#define CNFGA_PWORDLEFT ((1U << 1) | (1U << 0))
+
+/* ECP Configuration Register B */
+#define CNFGB_COMPRESS (1U << 7)
+#define CNFGB_INTRVAL (1U << 6)
+#define CNFGB_IRQ_MASK ((1U << 5) | (1U << 4) | (1U << 3))
+#define CNFGB_IRQ_SHIFT 3
+#define CNFGB_DMA_MASK ((1U << 2) | (1U << 1) | (1U << 0))
+#define CNFGB_DMA_SHIFT 0
+
+/* Extended Control Register */
+#define ECR_MODE_MASK ((1U << 7) | (1U << 6) | (1U << 5))
+#define ECR_MODE_SHIFT 5
+#define ECR_MODE_SPP (00U << ECR_MODE_SHIFT)
+#define ECR_MODE_PS2 (01U << ECR_MODE_SHIFT)
+#define ECR_MODE_PPF (02U << ECR_MODE_SHIFT)
+#define ECR_MODE_ECP (03U << ECR_MODE_SHIFT)
+#define ECR_MODE_EPP (04U << ECR_MODE_SHIFT)
+/* #define ECR_MODE_reserved (05U << ECR_MODE_SHIFT) */
+#define ECR_MODE_TST (06U << ECR_MODE_SHIFT)
+#define ECR_MODE_CFG (07U << ECR_MODE_SHIFT)
+#define ECR_nERRINTR (1U << 4)
+#define ECR_DMAEN (1U << 3)
+#define ECR_SERVINTR (1U << 2)
+#define ECR_F_FULL (1U << 1)
+#define ECR_F_EMPTY (1U << 0)
+
+/*--- Private data -----------------------------------------------------*/
+
+/**
+ * enum parport_ip32_irq_mode - operation mode of interrupt handler
+ * @PARPORT_IP32_IRQ_FWD: forward interrupt to the upper parport layer
+ * @PARPORT_IP32_IRQ_HERE: interrupt is handled locally
+ */
+enum parport_ip32_irq_mode { PARPORT_IP32_IRQ_FWD, PARPORT_IP32_IRQ_HERE };
+
+/**
+ * struct parport_ip32_private - private stuff for &struct parport
+ * @regs: register addresses
+ * @dcr_cache: cached contents of DCR
+ * @dcr_writable: bit mask of writable DCR bits
+ * @pword: number of bytes per PWord
+ * @fifo_depth: number of PWords that FIFO will hold
+ * @readIntrThreshold: minimum number of PWords we can read
+ * if we get an interrupt
+ * @writeIntrThreshold: minimum number of PWords we can write
+ * if we get an interrupt
+ * @irq_mode: operation mode of interrupt handler for this port
+ * @irq_complete: mutex used to wait for an interrupt to occur
+ */
+struct parport_ip32_private {
+ struct parport_ip32_regs regs;
+ unsigned int dcr_cache;
+ unsigned int dcr_writable;
+ unsigned int pword;
+ unsigned int fifo_depth;
+ unsigned int readIntrThreshold;
+ unsigned int writeIntrThreshold;
+ enum parport_ip32_irq_mode irq_mode;
+ struct completion irq_complete;
+};
+
+/*--- Debug code -------------------------------------------------------*/
+
+/*
+ * pr_debug1 - print debug messages
+ *
+ * This is like pr_debug(), but is defined for %DEBUG_PARPORT_IP32 >= 1
+ */
+#if DEBUG_PARPORT_IP32 >= 1
+# define pr_debug1(...) printk(KERN_DEBUG __VA_ARGS__)
+#else /* DEBUG_PARPORT_IP32 < 1 */
+# define pr_debug1(...) do { } while (0)
+#endif
+
+/*
+ * pr_trace, pr_trace1 - trace function calls
+ * @p: pointer to &struct parport
+ * @fmt: printk format string
+ * @...: parameters for format string
+ *
+ * Macros used to trace function calls. The given string is formatted after
+ * function name. pr_trace() uses pr_debug(), and pr_trace1() uses
+ * pr_debug1(). __pr_trace() is the low-level macro and is not to be used
+ * directly.
+ */
+#define __pr_trace(pr, p, fmt, ...) \
+ pr("%s: %s" fmt "\n", \
+ ({ const struct parport *__p = (p); \
+ __p ? __p->name : "parport_ip32"; }), \
+ __func__ , ##__VA_ARGS__)
+#define pr_trace(p, fmt, ...) __pr_trace(pr_debug, p, fmt , ##__VA_ARGS__)
+#define pr_trace1(p, fmt, ...) __pr_trace(pr_debug1, p, fmt , ##__VA_ARGS__)
+
+/*
+ * __pr_probe, pr_probe - print message if @verbose_probing is true
+ * @p: pointer to &struct parport
+ * @fmt: printk format string
+ * @...: parameters for format string
+ *
+ * For new lines, use pr_probe(). Use __pr_probe() for continued lines.
+ */
+#define __pr_probe(...) \
+ do { if (verbose_probing) printk(__VA_ARGS__); } while (0)
+#define pr_probe(p, fmt, ...) \
+ __pr_probe(KERN_INFO PPIP32 "0x%lx: " fmt, (p)->base , ##__VA_ARGS__)
+
+/*
+ * parport_ip32_dump_state - print register status of parport
+ * @p: pointer to &struct parport
+ * @str: string to add in message
+ * @show_ecp_config: shall we dump ECP configuration registers too?
+ *
+ * This function is only here for debugging purpose, and should be used with
+ * care. Reading the parallel port registers may have undesired side effects.
+ * Especially if @show_ecp_config is true, the parallel port is resetted.
+ * This function is only defined if %DEBUG_PARPORT_IP32 >= 2.
+ */
+#if DEBUG_PARPORT_IP32 >= 2
+static void parport_ip32_dump_state(struct parport *p, char *str,
+ unsigned int show_ecp_config)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ unsigned int i;
+
+ printk(KERN_DEBUG PPIP32 "%s: state (%s):\n", p->name, str);
+ {
+ static const char ecr_modes[8][4] = {"SPP", "PS2", "PPF",
+ "ECP", "EPP", "???",
+ "TST", "CFG"};
+ unsigned int ecr = readb(priv->regs.ecr);
+ printk(KERN_DEBUG PPIP32 " ecr=0x%02x", ecr);
+ printk(" %s",
+ ecr_modes[(ecr & ECR_MODE_MASK) >> ECR_MODE_SHIFT]);
+ if (ecr & ECR_nERRINTR)
+ printk(",nErrIntrEn");
+ if (ecr & ECR_DMAEN)
+ printk(",dmaEn");
+ if (ecr & ECR_SERVINTR)
+ printk(",serviceIntr");
+ if (ecr & ECR_F_FULL)
+ printk(",f_full");
+ if (ecr & ECR_F_EMPTY)
+ printk(",f_empty");
+ printk("\n");
+ }
+ if (show_ecp_config) {
+ unsigned int oecr, cnfgA, cnfgB;
+ oecr = readb(priv->regs.ecr);
+ writeb(ECR_MODE_PS2, priv->regs.ecr);
+ writeb(ECR_MODE_CFG, priv->regs.ecr);
+ cnfgA = readb(priv->regs.cnfgA);
+ cnfgB = readb(priv->regs.cnfgB);
+ writeb(ECR_MODE_PS2, priv->regs.ecr);
+ writeb(oecr, priv->regs.ecr);
+ printk(KERN_DEBUG PPIP32 " cnfgA=0x%02x", cnfgA);
+ printk(" ISA-%s", (cnfgA & CNFGA_IRQ) ? "Level" : "Pulses");
+ switch (cnfgA & CNFGA_ID_MASK) {
+ case CNFGA_ID_8:
+ printk(",8 bits");
+ break;
+ case CNFGA_ID_16:
+ printk(",16 bits");
+ break;
+ case CNFGA_ID_32:
+ printk(",32 bits");
+ break;
+ default:
+ printk(",unknown ID");
+ break;
+ }
+ if (!(cnfgA & CNFGA_nBYTEINTRANS))
+ printk(",ByteInTrans");
+ if ((cnfgA & CNFGA_ID_MASK) != CNFGA_ID_8)
+ printk(",%d byte%s left", cnfgA & CNFGA_PWORDLEFT,
+ ((cnfgA & CNFGA_PWORDLEFT) > 1) ? "s" : "");
+ printk("\n");
+ printk(KERN_DEBUG PPIP32 " cnfgB=0x%02x", cnfgB);
+ printk(" irq=%u,dma=%u",
+ (cnfgB & CNFGB_IRQ_MASK) >> CNFGB_IRQ_SHIFT,
+ (cnfgB & CNFGB_DMA_MASK) >> CNFGB_DMA_SHIFT);
+ printk(",intrValue=%d", !!(cnfgB & CNFGB_INTRVAL));
+ if (cnfgB & CNFGB_COMPRESS)
+ printk(",compress");
+ printk("\n");
+ }
+ for (i = 0; i < 2; i++) {
+ unsigned int dcr = i ? priv->dcr_cache : readb(priv->regs.dcr);
+ printk(KERN_DEBUG PPIP32 " dcr(%s)=0x%02x",
+ i ? "soft" : "hard", dcr);
+ printk(" %s", (dcr & DCR_DIR) ? "rev" : "fwd");
+ if (dcr & DCR_IRQ)
+ printk(",ackIntEn");
+ if (!(dcr & DCR_SELECT))
+ printk(",nSelectIn");
+ if (dcr & DCR_nINIT)
+ printk(",nInit");
+ if (!(dcr & DCR_AUTOFD))
+ printk(",nAutoFD");
+ if (!(dcr & DCR_STROBE))
+ printk(",nStrobe");
+ printk("\n");
+ }
+#define sep (f++ ? ',' : ' ')
+ {
+ unsigned int f = 0;
+ unsigned int dsr = readb(priv->regs.dsr);
+ printk(KERN_DEBUG PPIP32 " dsr=0x%02x", dsr);
+ if (!(dsr & DSR_nBUSY))
+ printk("%cBusy", sep);
+ if (dsr & DSR_nACK)
+ printk("%cnAck", sep);
+ if (dsr & DSR_PERROR)
+ printk("%cPError", sep);
+ if (dsr & DSR_SELECT)
+ printk("%cSelect", sep);
+ if (dsr & DSR_nFAULT)
+ printk("%cnFault", sep);
+ if (!(dsr & DSR_nPRINT))
+ printk("%c(Print)", sep);
+ if (dsr & DSR_TIMEOUT)
+ printk("%cTimeout", sep);
+ printk("\n");
+ }
+#undef sep
+}
+#else /* DEBUG_PARPORT_IP32 < 2 */
+#define parport_ip32_dump_state(...) do { } while (0)
+#endif
+
+/*
+ * CHECK_EXTRA_BITS - track and log extra bits
+ * @p: pointer to &struct parport
+ * @b: byte to inspect
+ * @m: bit mask of authorized bits
+ *
+ * This is used to track and log extra bits that should not be there in
+ * parport_ip32_write_control() and parport_ip32_frob_control(). It is only
+ * defined if %DEBUG_PARPORT_IP32 >= 1.
+ */
+#if DEBUG_PARPORT_IP32 >= 1
+#define CHECK_EXTRA_BITS(p, b, m) \
+ do { \
+ unsigned int __b = (b), __m = (m); \
+ if (__b & ~__m) \
+ pr_debug1(PPIP32 "%s: extra bits in %s(%s): " \
+ "0x%02x/0x%02x\n", \
+ (p)->name, __func__, #b, __b, __m); \
+ } while (0)
+#else /* DEBUG_PARPORT_IP32 < 1 */
+#define CHECK_EXTRA_BITS(...) do { } while (0)
+#endif
+
+/*--- IP32 parallel port DMA operations --------------------------------*/
+
+/**
+ * struct parport_ip32_dma_data - private data needed for DMA operation
+ * @dir: DMA direction (from or to device)
+ * @buf: buffer physical address
+ * @len: buffer length
+ * @next: address of next bytes to DMA transfer
+ * @left: number of bytes remaining
+ * @ctx: next context to write (0: context_a; 1: context_b)
+ * @irq_on: are the DMA IRQs currently enabled?
+ * @lock: spinlock to protect access to the structure
+ */
+struct parport_ip32_dma_data {
+ enum dma_data_direction dir;
+ dma_addr_t buf;
+ dma_addr_t next;
+ size_t len;
+ size_t left;
+ unsigned int ctx;
+ unsigned int irq_on;
+ spinlock_t lock;
+};
+static struct parport_ip32_dma_data parport_ip32_dma;
+
+/**
+ * parport_ip32_dma_setup_context - setup next DMA context
+ * @limit: maximum data size for the context
+ *
+ * The alignment constraints must be verified in caller function, and the
+ * parameter @limit must be set accordingly.
+ */
+static void parport_ip32_dma_setup_context(unsigned int limit)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&parport_ip32_dma.lock, flags);
+ if (parport_ip32_dma.left > 0) {
+ /* Note: ctxreg is "volatile" here only because
+ * mace->perif.ctrl.parport.context_a and context_b are
+ * "volatile". */
+ volatile u64 __iomem *ctxreg = (parport_ip32_dma.ctx == 0) ?
+ &mace->perif.ctrl.parport.context_a :
+ &mace->perif.ctrl.parport.context_b;
+ u64 count;
+ u64 ctxval;
+ if (parport_ip32_dma.left <= limit) {
+ count = parport_ip32_dma.left;
+ ctxval = MACEPAR_CONTEXT_LASTFLAG;
+ } else {
+ count = limit;
+ ctxval = 0;
+ }
+
+ pr_trace(NULL,
+ "(%u): 0x%04x:0x%04x, %u -> %u%s",
+ limit,
+ (unsigned int)parport_ip32_dma.buf,
+ (unsigned int)parport_ip32_dma.next,
+ (unsigned int)count,
+ parport_ip32_dma.ctx, ctxval ? "*" : "");
+
+ ctxval |= parport_ip32_dma.next &
+ MACEPAR_CONTEXT_BASEADDR_MASK;
+ ctxval |= ((count - 1) << MACEPAR_CONTEXT_DATALEN_SHIFT) &
+ MACEPAR_CONTEXT_DATALEN_MASK;
+ writeq(ctxval, ctxreg);
+ parport_ip32_dma.next += count;
+ parport_ip32_dma.left -= count;
+ parport_ip32_dma.ctx ^= 1U;
+ }
+ /* If there is nothing more to send, disable IRQs to avoid to
+ * face an IRQ storm which can lock the machine. Disable them
+ * only once. */
+ if (parport_ip32_dma.left == 0 && parport_ip32_dma.irq_on) {
+ pr_debug(PPIP32 "IRQ off (ctx)\n");
+ disable_irq_nosync(MACEISA_PAR_CTXA_IRQ);
+ disable_irq_nosync(MACEISA_PAR_CTXB_IRQ);
+ parport_ip32_dma.irq_on = 0;
+ }
+ spin_unlock_irqrestore(&parport_ip32_dma.lock, flags);
+}
+
+/**
+ * parport_ip32_dma_interrupt - DMA interrupt handler
+ * @irq: interrupt number
+ * @dev_id: unused
+ * @regs: pointer to &struct pt_regs
+ */
+static irqreturn_t parport_ip32_dma_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ if (parport_ip32_dma.left)
+ pr_trace(NULL, "(%d): ctx=%d", irq, parport_ip32_dma.ctx);
+ parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND);
+ return IRQ_HANDLED;
+}
+
+#if DEBUG_PARPORT_IP32
+static irqreturn_t parport_ip32_merr_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ pr_trace1(NULL, "(%d)", irq);
+ return IRQ_HANDLED;
+}
+#endif
+
+/**
+ * parport_ip32_dma_start - begins a DMA transfer
+ * @dir: DMA direction: DMA_TO_DEVICE or DMA_FROM_DEVICE
+ * @addr: pointer to data buffer
+ * @count: buffer size
+ *
+ * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be
+ * correctly balanced.
+ */
+static int parport_ip32_dma_start(enum dma_data_direction dir,
+ void *addr, size_t count)
+{
+ unsigned int limit;
+ u64 ctrl;
+
+ pr_trace(NULL, "(%d, %lu)", dir, (unsigned long)count);
+
+ /* FIXME - add support for DMA_FROM_DEVICE. In this case, buffer must
+ * be 64 bytes aligned. */
+ BUG_ON(dir != DMA_TO_DEVICE);
+
+ /* Reset DMA controller */
+ ctrl = MACEPAR_CTLSTAT_RESET;
+ writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+
+ /* DMA IRQs should normally be enabled */
+ if (!parport_ip32_dma.irq_on) {
+ WARN_ON(1);
+ enable_irq(MACEISA_PAR_CTXA_IRQ);
+ enable_irq(MACEISA_PAR_CTXB_IRQ);
+ parport_ip32_dma.irq_on = 1;
+ }
+
+ /* Prepare DMA pointers */
+ parport_ip32_dma.dir = dir;
+ parport_ip32_dma.buf = dma_map_single(NULL, addr, count, dir);
+ parport_ip32_dma.len = count;
+ parport_ip32_dma.next = parport_ip32_dma.buf;
+ parport_ip32_dma.left = parport_ip32_dma.len;
+ parport_ip32_dma.ctx = 0;
+
+ /* Setup DMA direction and first two contexts */
+ ctrl = (dir == DMA_TO_DEVICE) ? 0 : MACEPAR_CTLSTAT_DIRECTION;
+ writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+ /* Single transfer should not cross a 4K page boundary */
+ limit = MACEPAR_CONTEXT_DATA_BOUND -
+ (parport_ip32_dma.next & (MACEPAR_CONTEXT_DATA_BOUND - 1));
+ parport_ip32_dma_setup_context(limit);
+ parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND);
+
+ /* Real start of DMA transfer */
+ ctrl |= MACEPAR_CTLSTAT_ENABLE;
+ writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+
+ return 0;
+}
+
+/**
+ * parport_ip32_dma_stop - ends a running DMA transfer
+ *
+ * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be
+ * correctly balanced.
+ */
+static void parport_ip32_dma_stop(void)
+{
+ u64 ctx_a;
+ u64 ctx_b;
+ u64 ctrl;
+ u64 diag;
+ size_t res[2]; /* {[0] = res_a, [1] = res_b} */
+
+ pr_trace(NULL, "()");
+
+ /* Disable IRQs */
+ spin_lock_irq(&parport_ip32_dma.lock);
+ if (parport_ip32_dma.irq_on) {
+ pr_debug(PPIP32 "IRQ off (stop)\n");
+ disable_irq_nosync(MACEISA_PAR_CTXA_IRQ);
+ disable_irq_nosync(MACEISA_PAR_CTXB_IRQ);
+ parport_ip32_dma.irq_on = 0;
+ }
+ spin_unlock_irq(&parport_ip32_dma.lock);
+ /* Force IRQ synchronization, even if the IRQs were disabled
+ * elsewhere. */
+ synchronize_irq(MACEISA_PAR_CTXA_IRQ);
+ synchronize_irq(MACEISA_PAR_CTXB_IRQ);
+
+ /* Stop DMA transfer */
+ ctrl = readq(&mace->perif.ctrl.parport.cntlstat);
+ ctrl &= ~MACEPAR_CTLSTAT_ENABLE;
+ writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+
+ /* Adjust residue (parport_ip32_dma.left) */
+ ctx_a = readq(&mace->perif.ctrl.parport.context_a);
+ ctx_b = readq(&mace->perif.ctrl.parport.context_b);
+ ctrl = readq(&mace->perif.ctrl.parport.cntlstat);
+ diag = readq(&mace->perif.ctrl.parport.diagnostic);
+ res[0] = (ctrl & MACEPAR_CTLSTAT_CTXA_VALID) ?
+ 1 + ((ctx_a & MACEPAR_CONTEXT_DATALEN_MASK) >>
+ MACEPAR_CONTEXT_DATALEN_SHIFT) :
+ 0;
+ res[1] = (ctrl & MACEPAR_CTLSTAT_CTXB_VALID) ?
+ 1 + ((ctx_b & MACEPAR_CONTEXT_DATALEN_MASK) >>
+ MACEPAR_CONTEXT_DATALEN_SHIFT) :
+ 0;
+ if (diag & MACEPAR_DIAG_DMACTIVE)
+ res[(diag & MACEPAR_DIAG_CTXINUSE) != 0] =
+ 1 + ((diag & MACEPAR_DIAG_CTRMASK) >>
+ MACEPAR_DIAG_CTRSHIFT);
+ parport_ip32_dma.left += res[0] + res[1];
+
+ /* Reset DMA controller, and re-enable IRQs */
+ ctrl = MACEPAR_CTLSTAT_RESET;
+ writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
+ pr_debug(PPIP32 "IRQ on (stop)\n");
+ enable_irq(MACEISA_PAR_CTXA_IRQ);
+ enable_irq(MACEISA_PAR_CTXB_IRQ);
+ parport_ip32_dma.irq_on = 1;
+
+ dma_unmap_single(NULL, parport_ip32_dma.buf, parport_ip32_dma.len,
+ parport_ip32_dma.dir);
+}
+
+/**
+ * parport_ip32_dma_get_residue - get residue from last DMA transfer
+ *
+ * Returns the number of bytes remaining from last DMA transfer.
+ */
+static inline size_t parport_ip32_dma_get_residue(void)
+{
+ return parport_ip32_dma.left;
+}
+
+/**
+ * parport_ip32_dma_register - initialize DMA engine
+ *
+ * Returns zero for success.
+ */
+static int parport_ip32_dma_register(void)
+{
+ int err;
+
+ spin_lock_init(&parport_ip32_dma.lock);
+ parport_ip32_dma.irq_on = 1;
+
+ /* Reset DMA controller */
+ writeq(MACEPAR_CTLSTAT_RESET, &mace->perif.ctrl.parport.cntlstat);
+
+ /* Request IRQs */
+ err = request_irq(MACEISA_PAR_CTXA_IRQ, parport_ip32_dma_interrupt,
+ 0, "parport_ip32", NULL);
+ if (err)
+ goto fail_a;
+ err = request_irq(MACEISA_PAR_CTXB_IRQ, parport_ip32_dma_interrupt,
+ 0, "parport_ip32", NULL);
+ if (err)
+ goto fail_b;
+#if DEBUG_PARPORT_IP32
+ /* FIXME - what is this IRQ for? */
+ err = request_irq(MACEISA_PAR_MERR_IRQ, parport_ip32_merr_interrupt,
+ 0, "parport_ip32", NULL);
+ if (err)
+ goto fail_merr;
+#endif
+ return 0;
+
+#if DEBUG_PARPORT_IP32
+fail_merr:
+ free_irq(MACEISA_PAR_CTXB_IRQ, NULL);
+#endif
+fail_b:
+ free_irq(MACEISA_PAR_CTXA_IRQ, NULL);
+fail_a:
+ return err;
+}
+
+/**
+ * parport_ip32_dma_unregister - release and free resources for DMA engine
+ */
+static void parport_ip32_dma_unregister(void)
+{
+#if DEBUG_PARPORT_IP32
+ free_irq(MACEISA_PAR_MERR_IRQ, NULL);
+#endif
+ free_irq(MACEISA_PAR_CTXB_IRQ, NULL);
+ free_irq(MACEISA_PAR_CTXA_IRQ, NULL);
+}
+
+/*--- Interrupt handlers and associates --------------------------------*/
+
+/**
+ * parport_ip32_wakeup - wakes up code waiting for an interrupt
+ * @p: pointer to &struct parport
+ */
+static inline void parport_ip32_wakeup(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ complete(&priv->irq_complete);
+}
+
+/**
+ * parport_ip32_interrupt - interrupt handler
+ * @irq: interrupt number
+ * @dev_id: pointer to &struct parport
+ * @regs: pointer to &struct pt_regs
+ *
+ * Caught interrupts are forwarded to the upper parport layer if IRQ_mode is
+ * %PARPORT_IP32_IRQ_FWD.
+ */
+static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct parport * const p = dev_id;
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ enum parport_ip32_irq_mode irq_mode = priv->irq_mode;
+ switch (irq_mode) {
+ case PARPORT_IP32_IRQ_FWD:
+ parport_generic_irq(irq, p, regs);
+ break;
+ case PARPORT_IP32_IRQ_HERE:
+ parport_ip32_wakeup(p);
+ break;
+ }
+ return IRQ_HANDLED;
+}
+
+/*--- Some utility function to manipulate ECR register -----------------*/
+
+/**
+ * parport_ip32_read_econtrol - read contents of the ECR register
+ * @p: pointer to &struct parport
+ */
+static inline unsigned int parport_ip32_read_econtrol(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ return readb(priv->regs.ecr);
+}
+
+/**
+ * parport_ip32_write_econtrol - write new contents to the ECR register
+ * @p: pointer to &struct parport
+ * @c: new value to write
+ */
+static inline void parport_ip32_write_econtrol(struct parport *p,
+ unsigned int c)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ writeb(c, priv->regs.ecr);
+}
+
+/**
+ * parport_ip32_frob_econtrol - change bits from the ECR register
+ * @p: pointer to &struct parport
+ * @mask: bit mask of bits to change
+ * @val: new value for changed bits
+ *
+ * Read from the ECR, mask out the bits in @mask, exclusive-or with the bits
+ * in @val, and write the result to the ECR.
+ */
+static inline void parport_ip32_frob_econtrol(struct parport *p,
+ unsigned int mask,
+ unsigned int val)
+{
+ unsigned int c;
+ c = (parport_ip32_read_econtrol(p) & ~mask) ^ val;
+ parport_ip32_write_econtrol(p, c);
+}
+
+/**
+ * parport_ip32_set_mode - change mode of ECP port
+ * @p: pointer to &struct parport
+ * @mode: new mode to write in ECR
+ *
+ * ECR is reset in a sane state (interrupts and DMA disabled), and placed in
+ * mode @mode. Go through PS2 mode if needed.
+ */
+static void parport_ip32_set_mode(struct parport *p, unsigned int mode)
+{
+ unsigned int omode;
+
+ mode &= ECR_MODE_MASK;
+ omode = parport_ip32_read_econtrol(p) & ECR_MODE_MASK;
+
+ if (!(mode == ECR_MODE_SPP || mode == ECR_MODE_PS2
+ || omode == ECR_MODE_SPP || omode == ECR_MODE_PS2)) {
+ /* We have to go through PS2 mode */
+ unsigned int ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
+ parport_ip32_write_econtrol(p, ecr);
+ }
+ parport_ip32_write_econtrol(p, mode | ECR_nERRINTR | ECR_SERVINTR);
+}
+
+/*--- Basic functions needed for parport -------------------------------*/
+
+/**
+ * parport_ip32_read_data - return current contents of the DATA register
+ * @p: pointer to &struct parport
+ */
+static inline unsigned char parport_ip32_read_data(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ return readb(priv->regs.data);
+}
+
+/**
+ * parport_ip32_write_data - set new contents for the DATA register
+ * @p: pointer to &struct parport
+ * @d: new value to write
+ */
+static inline void parport_ip32_write_data(struct parport *p, unsigned char d)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ writeb(d, priv->regs.data);
+}
+
+/**
+ * parport_ip32_read_status - return current contents of the DSR register
+ * @p: pointer to &struct parport
+ */
+static inline unsigned char parport_ip32_read_status(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ return readb(priv->regs.dsr);
+}
+
+/**
+ * __parport_ip32_read_control - return cached contents of the DCR register
+ * @p: pointer to &struct parport
+ */
+static inline unsigned int __parport_ip32_read_control(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ return priv->dcr_cache; /* use soft copy */
+}
+
+/**
+ * __parport_ip32_write_control - set new contents for the DCR register
+ * @p: pointer to &struct parport
+ * @c: new value to write
+ */
+static inline void __parport_ip32_write_control(struct parport *p,
+ unsigned int c)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ CHECK_EXTRA_BITS(p, c, priv->dcr_writable);
+ c &= priv->dcr_writable; /* only writable bits */
+ writeb(c, priv->regs.dcr);
+ priv->dcr_cache = c; /* update soft copy */
+}
+
+/**
+ * __parport_ip32_frob_control - change bits from the DCR register
+ * @p: pointer to &struct parport
+ * @mask: bit mask of bits to change
+ * @val: new value for changed bits
+ *
+ * This is equivalent to read from the DCR, mask out the bits in @mask,
+ * exclusive-or with the bits in @val, and write the result to the DCR.
+ * Actually, the cached contents of the DCR is used.
+ */
+static inline void __parport_ip32_frob_control(struct parport *p,
+ unsigned int mask,
+ unsigned int val)
+{
+ unsigned int c;
+ c = (__parport_ip32_read_control(p) & ~mask) ^ val;
+ __parport_ip32_write_control(p, c);
+}
+
+/**
+ * parport_ip32_read_control - return cached contents of the DCR register
+ * @p: pointer to &struct parport
+ *
+ * The return value is masked so as to only return the value of %DCR_STROBE,
+ * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
+ */
+static inline unsigned char parport_ip32_read_control(struct parport *p)
+{
+ const unsigned int rm =
+ DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
+ return __parport_ip32_read_control(p) & rm;
+}
+
+/**
+ * parport_ip32_write_control - set new contents for the DCR register
+ * @p: pointer to &struct parport
+ * @c: new value to write
+ *
+ * The value is masked so as to only change the value of %DCR_STROBE,
+ * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
+ */
+static inline void parport_ip32_write_control(struct parport *p,
+ unsigned char c)
+{
+ const unsigned int wm =
+ DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
+ CHECK_EXTRA_BITS(p, c, wm);
+ __parport_ip32_frob_control(p, wm, c & wm);
+}
+
+/**
+ * parport_ip32_frob_control - change bits from the DCR register
+ * @p: pointer to &struct parport
+ * @mask: bit mask of bits to change
+ * @val: new value for changed bits
+ *
+ * This differs from __parport_ip32_frob_control() in that it only allows to
+ * change the value of %DCR_STROBE, %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
+ */
+static inline unsigned char parport_ip32_frob_control(struct parport *p,
+ unsigned char mask,
+ unsigned char val)
+{
+ const unsigned int wm =
+ DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
+ CHECK_EXTRA_BITS(p, mask, wm);
+ CHECK_EXTRA_BITS(p, val, wm);
+ __parport_ip32_frob_control(p, mask & wm, val & wm);
+ return parport_ip32_read_control(p);
+}
+
+/**
+ * parport_ip32_disable_irq - disable interrupts on the rising edge of nACK
+ * @p: pointer to &struct parport
+ */
+static inline void parport_ip32_disable_irq(struct parport *p)
+{
+ __parport_ip32_frob_control(p, DCR_IRQ, 0);
+}
+
+/**
+ * parport_ip32_enable_irq - enable interrupts on the rising edge of nACK
+ * @p: pointer to &struct parport
+ */
+static inline void parport_ip32_enable_irq(struct parport *p)
+{
+ __parport_ip32_frob_control(p, DCR_IRQ, DCR_IRQ);
+}
+
+/**
+ * parport_ip32_data_forward - enable host-to-peripheral communications
+ * @p: pointer to &struct parport
+ *
+ * Enable the data line drivers, for 8-bit host-to-peripheral communications.
+ */
+static inline void parport_ip32_data_forward(struct parport *p)
+{
+ __parport_ip32_frob_control(p, DCR_DIR, 0);
+}
+
+/**
+ * parport_ip32_data_reverse - enable peripheral-to-host communications
+ * @p: pointer to &struct parport
+ *
+ * Place the data bus in a high impedance state, if @p->modes has the
+ * PARPORT_MODE_TRISTATE bit set.
+ */
+static inline void parport_ip32_data_reverse(struct parport *p)
+{
+ __parport_ip32_frob_control(p, DCR_DIR, DCR_DIR);
+}
+
+/**
+ * parport_ip32_init_state - for core parport code
+ * @dev: pointer to &struct pardevice
+ * @s: pointer to &struct parport_state to initialize
+ */
+static void parport_ip32_init_state(struct pardevice *dev,
+ struct parport_state *s)
+{
+ s->u.ip32.dcr = DCR_SELECT | DCR_nINIT;
+ s->u.ip32.ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
+}
+
+/**
+ * parport_ip32_save_state - for core parport code
+ * @p: pointer to &struct parport
+ * @s: pointer to &struct parport_state to save state to
+ */
+static void parport_ip32_save_state(struct parport *p,
+ struct parport_state *s)
+{
+ s->u.ip32.dcr = __parport_ip32_read_control(p);
+ s->u.ip32.ecr = parport_ip32_read_econtrol(p);
+}
+
+/**
+ * parport_ip32_restore_state - for core parport code
+ * @p: pointer to &struct parport
+ * @s: pointer to &struct parport_state to restore state from
+ */
+static void parport_ip32_restore_state(struct parport *p,
+ struct parport_state *s)
+{
+ parport_ip32_set_mode(p, s->u.ip32.ecr & ECR_MODE_MASK);
+ parport_ip32_write_econtrol(p, s->u.ip32.ecr);
+ __parport_ip32_write_control(p, s->u.ip32.dcr);
+}
+
+/*--- EPP mode functions -----------------------------------------------*/
+
+/**
+ * parport_ip32_clear_epp_timeout - clear Timeout bit in EPP mode
+ * @p: pointer to &struct parport
+ *
+ * Returns 1 if the Timeout bit is clear, and 0 otherwise.
+ */
+static unsigned int parport_ip32_clear_epp_timeout(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ unsigned int cleared;
+
+ if (!(parport_ip32_read_status(p) & DSR_TIMEOUT))
+ cleared = 1;
+ else {
+ unsigned int r;
+ /* To clear timeout some chips require double read */
+ parport_ip32_read_status(p);
+ r = parport_ip32_read_status(p);
+ /* Some reset by writing 1 */
+ writeb(r | DSR_TIMEOUT, priv->regs.dsr);
+ /* Others by writing 0 */
+ writeb(r & ~DSR_TIMEOUT, priv->regs.dsr);
+
+ r = parport_ip32_read_status(p);
+ cleared = !(r & DSR_TIMEOUT);
+ }
+
+ pr_trace(p, "(): %s", cleared ? "cleared" : "failed");
+ return cleared;
+}
+
+/**
+ * parport_ip32_epp_read - generic EPP read function
+ * @eppreg: I/O register to read from
+ * @p: pointer to &struct parport
+ * @buf: buffer to store read data
+ * @len: length of buffer @buf
+ * @flags: may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_read(void __iomem *eppreg,
+ struct parport *p, void *buf,
+ size_t len, int flags)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ size_t got;
+ parport_ip32_set_mode(p, ECR_MODE_EPP);
+ parport_ip32_data_reverse(p);
+ parport_ip32_write_control(p, DCR_nINIT);
+ if ((flags & PARPORT_EPP_FAST) && (len > 1)) {
+ readsb(eppreg, buf, len);
+ if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
+ parport_ip32_clear_epp_timeout(p);
+ return -EIO;
+ }
+ got = len;
+ } else {
+ u8 *bufp = buf;
+ for (got = 0; got < len; got++) {
+ *bufp++ = readb(eppreg);
+ if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
+ parport_ip32_clear_epp_timeout(p);
+ break;
+ }
+ }
+ }
+ parport_ip32_data_forward(p);
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ return got;
+}
+
+/**
+ * parport_ip32_epp_write - generic EPP write function
+ * @eppreg: I/O register to write to
+ * @p: pointer to &struct parport
+ * @buf: buffer of data to write
+ * @len: length of buffer @buf
+ * @flags: may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_write(void __iomem *eppreg,
+ struct parport *p, const void *buf,
+ size_t len, int flags)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ size_t written;
+ parport_ip32_set_mode(p, ECR_MODE_EPP);
+ parport_ip32_data_forward(p);
+ parport_ip32_write_control(p, DCR_nINIT);
+ if ((flags & PARPORT_EPP_FAST) && (len > 1)) {
+ writesb(eppreg, buf, len);
+ if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
+ parport_ip32_clear_epp_timeout(p);
+ return -EIO;
+ }
+ written = len;
+ } else {
+ const u8 *bufp = buf;
+ for (written = 0; written < len; written++) {
+ writeb(*bufp++, eppreg);
+ if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
+ parport_ip32_clear_epp_timeout(p);
+ break;
+ }
+ }
+ }
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ return written;
+}
+
+/**
+ * parport_ip32_epp_read_data - read a block of data in EPP mode
+ * @p: pointer to &struct parport
+ * @buf: buffer to store read data
+ * @len: length of buffer @buf
+ * @flags: may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_read_data(struct parport *p, void *buf,
+ size_t len, int flags)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ return parport_ip32_epp_read(priv->regs.eppData0, p, buf, len, flags);
+}
+
+/**
+ * parport_ip32_epp_write_data - write a block of data in EPP mode
+ * @p: pointer to &struct parport
+ * @buf: buffer of data to write
+ * @len: length of buffer @buf
+ * @flags: may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_write_data(struct parport *p, const void *buf,
+ size_t len, int flags)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ return parport_ip32_epp_write(priv->regs.eppData0, p, buf, len, flags);
+}
+
+/**
+ * parport_ip32_epp_read_addr - read a block of addresses in EPP mode
+ * @p: pointer to &struct parport
+ * @buf: buffer to store read data
+ * @len: length of buffer @buf
+ * @flags: may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_read_addr(struct parport *p, void *buf,
+ size_t len, int flags)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ return parport_ip32_epp_read(priv->regs.eppAddr, p, buf, len, flags);
+}
+
+/**
+ * parport_ip32_epp_write_addr - write a block of addresses in EPP mode
+ * @p: pointer to &struct parport
+ * @buf: buffer of data to write
+ * @len: length of buffer @buf
+ * @flags: may be PARPORT_EPP_FAST
+ */
+static size_t parport_ip32_epp_write_addr(struct parport *p, const void *buf,
+ size_t len, int flags)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ return parport_ip32_epp_write(priv->regs.eppAddr, p, buf, len, flags);
+}
+
+/*--- ECP mode functions (FIFO) ----------------------------------------*/
+
+/**
+ * parport_ip32_fifo_wait_break - check if the waiting function should return
+ * @p: pointer to &struct parport
+ * @expire: timeout expiring date, in jiffies
+ *
+ * parport_ip32_fifo_wait_break() checks if the waiting function should return
+ * immediately or not. The break conditions are:
+ * - expired timeout;
+ * - a pending signal;
+ * - nFault asserted low.
+ * This function also calls cond_resched().
+ */
+static unsigned int parport_ip32_fifo_wait_break(struct parport *p,
+ unsigned long expire)
+{
+ cond_resched();
+ if (time_after(jiffies, expire)) {
+ pr_debug1(PPIP32 "%s: FIFO write timed out\n", p->name);
+ return 1;
+ }
+ if (signal_pending(current)) {
+ pr_debug1(PPIP32 "%s: Signal pending\n", p->name);
+ return 1;
+ }
+ if (!(parport_ip32_read_status(p) & DSR_nFAULT)) {
+ pr_debug1(PPIP32 "%s: nFault asserted low\n", p->name);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * parport_ip32_fwp_wait_polling - wait for FIFO to empty (polling)
+ * @p: pointer to &struct parport
+ *
+ * Returns the number of bytes that can safely be written in the FIFO. A
+ * return value of zero means that the calling function should terminate as
+ * fast as possible.
+ */
+static unsigned int parport_ip32_fwp_wait_polling(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ struct parport * const physport = p->physport;
+ unsigned long expire;
+ unsigned int count;
+ unsigned int ecr;
+
+ expire = jiffies + physport->cad->timeout;
+ count = 0;
+ while (1) {
+ if (parport_ip32_fifo_wait_break(p, expire))
+ break;
+
+ /* Check FIFO state. We do nothing when the FIFO is nor full,
+ * nor empty. It appears that the FIFO full bit is not always
+ * reliable, the FIFO state is sometimes wrongly reported, and
+ * the chip gets confused if we give it another byte. */
+ ecr = parport_ip32_read_econtrol(p);
+ if (ecr & ECR_F_EMPTY) {
+ /* FIFO is empty, fill it up */
+ count = priv->fifo_depth;
+ break;
+ }
+
+ /* Wait a moment... */
+ udelay(FIFO_POLLING_INTERVAL);
+ } /* while (1) */
+
+ return count;
+}
+
+/**
+ * parport_ip32_fwp_wait_interrupt - wait for FIFO to empty (interrupt-driven)
+ * @p: pointer to &struct parport
+ *
+ * Returns the number of bytes that can safely be written in the FIFO. A
+ * return value of zero means that the calling function should terminate as
+ * fast as possible.
+ */
+static unsigned int parport_ip32_fwp_wait_interrupt(struct parport *p)
+{
+ static unsigned int lost_interrupt = 0;
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ struct parport * const physport = p->physport;
+ unsigned long nfault_timeout;
+ unsigned long expire;
+ unsigned int count;
+ unsigned int ecr;
+
+ nfault_timeout = min((unsigned long)physport->cad->timeout,
+ msecs_to_jiffies(FIFO_NFAULT_TIMEOUT));
+ expire = jiffies + physport->cad->timeout;
+ count = 0;
+ while (1) {
+ if (parport_ip32_fifo_wait_break(p, expire))
+ break;
+
+ /* Initialize mutex used to take interrupts into account */
+ INIT_COMPLETION(priv->irq_complete);
+
+ /* Enable serviceIntr */
+ parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
+
+ /* Enabling serviceIntr while the FIFO is empty does not
+ * always generate an interrupt, so check for emptiness
+ * now. */
+ ecr = parport_ip32_read_econtrol(p);
+ if (!(ecr & ECR_F_EMPTY)) {
+ /* FIFO is not empty: wait for an interrupt or a
+ * timeout to occur */
+ wait_for_completion_interruptible_timeout(
+ &priv->irq_complete, nfault_timeout);
+ ecr = parport_ip32_read_econtrol(p);
+ if ((ecr & ECR_F_EMPTY) && !(ecr & ECR_SERVINTR)
+ && !lost_interrupt) {
+ printk(KERN_WARNING PPIP32
+ "%s: lost interrupt in %s\n",
+ p->name, __func__);
+ lost_interrupt = 1;
+ }
+ }
+
+ /* Disable serviceIntr */
+ parport_ip32_frob_econtrol(p, ECR_SERVINTR, ECR_SERVINTR);
+
+ /* Check FIFO state */
+ if (ecr & ECR_F_EMPTY) {
+ /* FIFO is empty, fill it up */
+ count = priv->fifo_depth;
+ break;
+ } else if (ecr & ECR_SERVINTR) {
+ /* FIFO is not empty, but we know that can safely push
+ * writeIntrThreshold bytes into it */
+ count = priv->writeIntrThreshold;
+ break;
+ }
+ /* FIFO is not empty, and we did not get any interrupt.
+ * Either it's time to check for nFault, or a signal is
+ * pending. This is verified in
+ * parport_ip32_fifo_wait_break(), so we continue the loop. */
+ } /* while (1) */
+
+ return count;
+}
+
+/**
+ * parport_ip32_fifo_write_block_pio - write a block of data (PIO mode)
+ * @p: pointer to &struct parport
+ * @buf: buffer of data to write
+ * @len: length of buffer @buf
+ *
+ * Uses PIO to write the contents of the buffer @buf into the parallel port
+ * FIFO. Returns the number of bytes that were actually written. It can work
+ * with or without the help of interrupts. The parallel port must be
+ * correctly initialized before calling parport_ip32_fifo_write_block_pio().
+ */
+static size_t parport_ip32_fifo_write_block_pio(struct parport *p,
+ const void *buf, size_t len)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ const u8 *bufp = buf;
+ size_t left = len;
+
+ priv->irq_mode = PARPORT_IP32_IRQ_HERE;
+
+ while (left > 0) {
+ unsigned int count;
+
+ count = (p->irq == PARPORT_IRQ_NONE) ?
+ parport_ip32_fwp_wait_polling(p) :
+ parport_ip32_fwp_wait_interrupt(p);
+ if (count == 0)
+ break; /* Transmission should be stopped */
+ if (count > left)
+ count = left;
+ if (count == 1) {
+ writeb(*bufp, priv->regs.fifo);
+ bufp++, left--;
+ } else {
+ writesb(priv->regs.fifo, bufp, count);
+ bufp += count, left -= count;
+ }
+ }
+
+ priv->irq_mode = PARPORT_IP32_IRQ_FWD;
+
+ return len - left;
+}
+
+/**
+ * parport_ip32_fifo_write_block_dma - write a block of data (DMA mode)
+ * @p: pointer to &struct parport
+ * @buf: buffer of data to write
+ * @len: length of buffer @buf
+ *
+ * Uses DMA to write the contents of the buffer @buf into the parallel port
+ * FIFO. Returns the number of bytes that were actually written. The
+ * parallel port must be correctly initialized before calling
+ * parport_ip32_fifo_write_block_dma().
+ */
+static size_t parport_ip32_fifo_write_block_dma(struct parport *p,
+ const void *buf, size_t len)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ struct parport * const physport = p->physport;
+ unsigned long nfault_timeout;
+ unsigned long expire;
+ size_t written;
+ unsigned int ecr;
+
+ priv->irq_mode = PARPORT_IP32_IRQ_HERE;
+
+ parport_ip32_dma_start(DMA_TO_DEVICE, (void *)buf, len);
+ INIT_COMPLETION(priv->irq_complete);
+ parport_ip32_frob_econtrol(p, ECR_DMAEN | ECR_SERVINTR, ECR_DMAEN);
+
+ nfault_timeout = min((unsigned long)physport->cad->timeout,
+ msecs_to_jiffies(FIFO_NFAULT_TIMEOUT));
+ expire = jiffies + physport->cad->timeout;
+ while (1) {
+ if (parport_ip32_fifo_wait_break(p, expire))
+ break;
+ wait_for_completion_interruptible_timeout(&priv->irq_complete,
+ nfault_timeout);
+ ecr = parport_ip32_read_econtrol(p);
+ if (ecr & ECR_SERVINTR)
+ break; /* DMA transfer just finished */
+ }
+ parport_ip32_dma_stop();
+ written = len - parport_ip32_dma_get_residue();
+
+ priv->irq_mode = PARPORT_IP32_IRQ_FWD;
+
+ return written;
+}
+
+/**
+ * parport_ip32_fifo_write_block - write a block of data
+ * @p: pointer to &struct parport
+ * @buf: buffer of data to write
+ * @len: length of buffer @buf
+ *
+ * Uses PIO or DMA to write the contents of the buffer @buf into the parallel
+ * p FIFO. Returns the number of bytes that were actually written.
+ */
+static size_t parport_ip32_fifo_write_block(struct parport *p,
+ const void *buf, size_t len)
+{
+ size_t written = 0;
+ if (len)
+ /* FIXME - Maybe some threshold value should be set for @len
+ * under which we revert to PIO mode? */
+ written = (p->modes & PARPORT_MODE_DMA) ?
+ parport_ip32_fifo_write_block_dma(p, buf, len) :
+ parport_ip32_fifo_write_block_pio(p, buf, len);
+ return written;
+}
+
+/**
+ * parport_ip32_drain_fifo - wait for FIFO to empty
+ * @p: pointer to &struct parport
+ * @timeout: timeout, in jiffies
+ *
+ * This function waits for FIFO to empty. It returns 1 when FIFO is empty, or
+ * 0 if the timeout @timeout is reached before, or if a signal is pending.
+ */
+static unsigned int parport_ip32_drain_fifo(struct parport *p,
+ unsigned long timeout)
+{
+ unsigned long expire = jiffies + timeout;
+ unsigned int polling_interval;
+ unsigned int counter;
+
+ /* Busy wait for approx. 200us */
+ for (counter = 0; counter < 40; counter++) {
+ if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY)
+ break;
+ if (time_after(jiffies, expire))
+ break;
+ if (signal_pending(current))
+ break;
+ udelay(5);
+ }
+ /* Poll slowly. Polling interval starts with 1 millisecond, and is
+ * increased exponentially until 128. */
+ polling_interval = 1; /* msecs */
+ while (!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY)) {
+ if (time_after_eq(jiffies, expire))
+ break;
+ msleep_interruptible(polling_interval);
+ if (signal_pending(current))
+ break;
+ if (polling_interval < 128)
+ polling_interval *= 2;
+ }
+
+ return !!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY);
+}
+
+/**
+ * parport_ip32_get_fifo_residue - reset FIFO
+ * @p: pointer to &struct parport
+ * @mode: current operation mode (ECR_MODE_PPF or ECR_MODE_ECP)
+ *
+ * This function resets FIFO, and returns the number of bytes remaining in it.
+ */
+static unsigned int parport_ip32_get_fifo_residue(struct parport *p,
+ unsigned int mode)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ unsigned int residue;
+ unsigned int cnfga;
+
+ /* FIXME - We are missing one byte if the printer is off-line. I
+ * don't know how to detect this. It looks that the full bit is not
+ * always reliable. For the moment, the problem is avoided in most
+ * cases by testing for BUSY in parport_ip32_compat_write_data().
+ */
+ if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY)
+ residue = 0;
+ else {
+ pr_debug1(PPIP32 "%s: FIFO is stuck\n", p->name);
+
+ /* Stop all transfers.
+ *
+ * Microsoft's document instructs to drive DCR_STROBE to 0,
+ * but it doesn't work (at least in Compatibility mode, not
+ * tested in ECP mode). Switching directly to Test mode (as
+ * in parport_pc) is not an option: it does confuse the port,
+ * ECP service interrupts are no more working after that. A
+ * hard reset is then needed to revert to a sane state.
+ *
+ * Let's hope that the FIFO is really stuck and that the
+ * peripheral doesn't wake up now.
+ */
+ parport_ip32_frob_control(p, DCR_STROBE, 0);
+
+ /* Fill up FIFO */
+ for (residue = priv->fifo_depth; residue > 0; residue--) {
+ if (parport_ip32_read_econtrol(p) & ECR_F_FULL)
+ break;
+ writeb(0x00, priv->regs.fifo);
+ }
+ }
+ if (residue)
+ pr_debug1(PPIP32 "%s: %d PWord%s left in FIFO\n",
+ p->name, residue,
+ (residue == 1) ? " was" : "s were");
+
+ /* Now reset the FIFO */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+
+ /* Host recovery for ECP mode */
+ if (mode == ECR_MODE_ECP) {
+ parport_ip32_data_reverse(p);
+ parport_ip32_frob_control(p, DCR_nINIT, 0);
+ if (parport_wait_peripheral(p, DSR_PERROR, 0))
+ pr_debug1(PPIP32 "%s: PEerror timeout 1 in %s\n",
+ p->name, __func__);
+ parport_ip32_frob_control(p, DCR_STROBE, DCR_STROBE);
+ parport_ip32_frob_control(p, DCR_nINIT, DCR_nINIT);
+ if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR))
+ pr_debug1(PPIP32 "%s: PEerror timeout 2 in %s\n",
+ p->name, __func__);
+ }
+
+ /* Adjust residue if needed */
+ parport_ip32_set_mode(p, ECR_MODE_CFG);
+ cnfga = readb(priv->regs.cnfgA);
+ if (!(cnfga & CNFGA_nBYTEINTRANS)) {
+ pr_debug1(PPIP32 "%s: cnfgA contains 0x%02x\n",
+ p->name, cnfga);
+ pr_debug1(PPIP32 "%s: Accounting for extra byte\n",
+ p->name);
+ residue++;
+ }
+
+ /* Don't care about partial PWords since we do not support
+ * PWord != 1 byte. */
+
+ /* Back to forward PS2 mode. */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ parport_ip32_data_forward(p);
+
+ return residue;
+}
+
+/**
+ * parport_ip32_compat_write_data - write a block of data in SPP mode
+ * @p: pointer to &struct parport
+ * @buf: buffer of data to write
+ * @len: length of buffer @buf
+ * @flags: ignored
+ */
+static size_t parport_ip32_compat_write_data(struct parport *p,
+ const void *buf, size_t len,
+ int flags)
+{
+ static unsigned int ready_before = 1;
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ struct parport * const physport = p->physport;
+ size_t written = 0;
+
+ /* Special case: a timeout of zero means we cannot call schedule().
+ * Also if O_NONBLOCK is set then use the default implementation. */
+ if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK)
+ return parport_ieee1284_write_compat(p, buf, len, flags);
+
+ /* Reset FIFO, go in forward mode, and disable ackIntEn */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
+ parport_ip32_data_forward(p);
+ parport_ip32_disable_irq(p);
+ parport_ip32_set_mode(p, ECR_MODE_PPF);
+ physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+
+ /* Wait for peripheral to become ready */
+ if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT,
+ DSR_nBUSY | DSR_nFAULT)) {
+ /* Avoid to flood the logs */
+ if (ready_before)
+ printk(KERN_INFO PPIP32 "%s: not ready in %s\n",
+ p->name, __func__);
+ ready_before = 0;
+ goto stop;
+ }
+ ready_before = 1;
+
+ written = parport_ip32_fifo_write_block(p, buf, len);
+
+ /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */
+ parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth);
+
+ /* Check for a potential residue */
+ written -= parport_ip32_get_fifo_residue(p, ECR_MODE_PPF);
+
+ /* Then, wait for BUSY to get low. */
+ if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY))
+ printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n",
+ p->name, __func__);
+
+stop:
+ /* Reset FIFO */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+ return written;
+}
+
+/*
+ * FIXME - Insert here parport_ip32_ecp_read_data().
+ */
+
+/**
+ * parport_ip32_ecp_write_data - write a block of data in ECP mode
+ * @p: pointer to &struct parport
+ * @buf: buffer of data to write
+ * @len: length of buffer @buf
+ * @flags: ignored
+ */
+static size_t parport_ip32_ecp_write_data(struct parport *p,
+ const void *buf, size_t len,
+ int flags)
+{
+ static unsigned int ready_before = 1;
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ struct parport * const physport = p->physport;
+ size_t written = 0;
+
+ /* Special case: a timeout of zero means we cannot call schedule().
+ * Also if O_NONBLOCK is set then use the default implementation. */
+ if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK)
+ return parport_ieee1284_ecp_write_data(p, buf, len, flags);
+
+ /* Negotiate to forward mode if necessary. */
+ if (physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) {
+ /* Event 47: Set nInit high. */
+ parport_ip32_frob_control(p, DCR_nINIT | DCR_AUTOFD,
+ DCR_nINIT | DCR_AUTOFD);
+
+ /* Event 49: PError goes high. */
+ if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) {
+ printk(KERN_DEBUG PPIP32 "%s: PError timeout in %s",
+ p->name, __func__);
+ physport->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN;
+ return 0;
+ }
+ }
+
+ /* Reset FIFO, go in forward mode, and disable ackIntEn */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
+ parport_ip32_data_forward(p);
+ parport_ip32_disable_irq(p);
+ parport_ip32_set_mode(p, ECR_MODE_ECP);
+ physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+
+ /* Wait for peripheral to become ready */
+ if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT,
+ DSR_nBUSY | DSR_nFAULT)) {
+ /* Avoid to flood the logs */
+ if (ready_before)
+ printk(KERN_INFO PPIP32 "%s: not ready in %s\n",
+ p->name, __func__);
+ ready_before = 0;
+ goto stop;
+ }
+ ready_before = 1;
+
+ written = parport_ip32_fifo_write_block(p, buf, len);
+
+ /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */
+ parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth);
+
+ /* Check for a potential residue */
+ written -= parport_ip32_get_fifo_residue(p, ECR_MODE_ECP);
+
+ /* Then, wait for BUSY to get low. */
+ if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY))
+ printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n",
+ p->name, __func__);
+
+stop:
+ /* Reset FIFO */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+ return written;
+}
+
+/*
+ * FIXME - Insert here parport_ip32_ecp_write_addr().
+ */
+
+/*--- Default parport operations ---------------------------------------*/
+
+static __initdata struct parport_operations parport_ip32_ops = {
+ .write_data = parport_ip32_write_data,
+ .read_data = parport_ip32_read_data,
+
+ .write_control = parport_ip32_write_control,
+ .read_control = parport_ip32_read_control,
+ .frob_control = parport_ip32_frob_control,
+
+ .read_status = parport_ip32_read_status,
+
+ .enable_irq = parport_ip32_enable_irq,
+ .disable_irq = parport_ip32_disable_irq,
+
+ .data_forward = parport_ip32_data_forward,
+ .data_reverse = parport_ip32_data_reverse,
+
+ .init_state = parport_ip32_init_state,
+ .save_state = parport_ip32_save_state,
+ .restore_state = parport_ip32_restore_state,
+
+ .epp_write_data = parport_ieee1284_epp_write_data,
+ .epp_read_data = parport_ieee1284_epp_read_data,
+ .epp_write_addr = parport_ieee1284_epp_write_addr,
+ .epp_read_addr = parport_ieee1284_epp_read_addr,
+
+ .ecp_write_data = parport_ieee1284_ecp_write_data,
+ .ecp_read_data = parport_ieee1284_ecp_read_data,
+ .ecp_write_addr = parport_ieee1284_ecp_write_addr,
+
+ .compat_write_data = parport_ieee1284_write_compat,
+ .nibble_read_data = parport_ieee1284_read_nibble,
+ .byte_read_data = parport_ieee1284_read_byte,
+
+ .owner = THIS_MODULE,
+};
+
+/*--- Device detection -------------------------------------------------*/
+
+/**
+ * parport_ip32_ecp_supported - check for an ECP port
+ * @p: pointer to the &parport structure
+ *
+ * Returns 1 if an ECP port is found, and 0 otherwise. This function actually
+ * checks if an Extended Control Register seems to be present. On successful
+ * return, the port is placed in SPP mode.
+ */
+static __init unsigned int parport_ip32_ecp_supported(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ unsigned int ecr;
+
+ ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
+ writeb(ecr, priv->regs.ecr);
+ if (readb(priv->regs.ecr) != (ecr | ECR_F_EMPTY))
+ goto fail;
+
+ pr_probe(p, "Found working ECR register\n");
+ parport_ip32_set_mode(p, ECR_MODE_SPP);
+ parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
+ return 1;
+
+fail:
+ pr_probe(p, "ECR register not found\n");
+ return 0;
+}
+
+/**
+ * parport_ip32_fifo_supported - check for FIFO parameters
+ * @p: pointer to the &parport structure
+ *
+ * Check for FIFO parameters of an Extended Capabilities Port. Returns 1 on
+ * success, and 0 otherwise. Adjust FIFO parameters in the parport structure.
+ * On return, the port is placed in SPP mode.
+ */
+static __init unsigned int parport_ip32_fifo_supported(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ unsigned int configa, configb;
+ unsigned int pword;
+ unsigned int i;
+
+ /* Configuration mode */
+ parport_ip32_set_mode(p, ECR_MODE_CFG);
+ configa = readb(priv->regs.cnfgA);
+ configb = readb(priv->regs.cnfgB);
+
+ /* Find out PWord size */
+ switch (configa & CNFGA_ID_MASK) {
+ case CNFGA_ID_8:
+ pword = 1;
+ break;
+ case CNFGA_ID_16:
+ pword = 2;
+ break;
+ case CNFGA_ID_32:
+ pword = 4;
+ break;
+ default:
+ pr_probe(p, "Unknown implementation ID: 0x%0x\n",
+ (configa & CNFGA_ID_MASK) >> CNFGA_ID_SHIFT);
+ goto fail;
+ break;
+ }
+ if (pword != 1) {
+ pr_probe(p, "Unsupported PWord size: %u\n", pword);
+ goto fail;
+ }
+ priv->pword = pword;
+ pr_probe(p, "PWord is %u bits\n", 8 * priv->pword);
+
+ /* Check for compression support */
+ writeb(configb | CNFGB_COMPRESS, priv->regs.cnfgB);
+ if (readb(priv->regs.cnfgB) & CNFGB_COMPRESS)
+ pr_probe(p, "Hardware compression detected (unsupported)\n");
+ writeb(configb & ~CNFGB_COMPRESS, priv->regs.cnfgB);
+
+ /* Reset FIFO and go in test mode (no interrupt, no DMA) */
+ parport_ip32_set_mode(p, ECR_MODE_TST);
+
+ /* FIFO must be empty now */
+ if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) {
+ pr_probe(p, "FIFO not reset\n");
+ goto fail;
+ }
+
+ /* Find out FIFO depth. */
+ priv->fifo_depth = 0;
+ for (i = 0; i < 1024; i++) {
+ if (readb(priv->regs.ecr) & ECR_F_FULL) {
+ /* FIFO full */
+ priv->fifo_depth = i;
+ break;
+ }
+ writeb((u8)i, priv->regs.fifo);
+ }
+ if (i >= 1024) {
+ pr_probe(p, "Can't fill FIFO\n");
+ goto fail;
+ }
+ if (!priv->fifo_depth) {
+ pr_probe(p, "Can't get FIFO depth\n");
+ goto fail;
+ }
+ pr_probe(p, "FIFO is %u PWords deep\n", priv->fifo_depth);
+
+ /* Enable interrupts */
+ parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
+
+ /* Find out writeIntrThreshold: number of PWords we know we can write
+ * if we get an interrupt. */
+ priv->writeIntrThreshold = 0;
+ for (i = 0; i < priv->fifo_depth; i++) {
+ if (readb(priv->regs.fifo) != (u8)i) {
+ pr_probe(p, "Invalid data in FIFO\n");
+ goto fail;
+ }
+ if (!priv->writeIntrThreshold
+ && readb(priv->regs.ecr) & ECR_SERVINTR)
+ /* writeIntrThreshold reached */
+ priv->writeIntrThreshold = i + 1;
+ if (i + 1 < priv->fifo_depth
+ && readb(priv->regs.ecr) & ECR_F_EMPTY) {
+ /* FIFO empty before the last byte? */
+ pr_probe(p, "Data lost in FIFO\n");
+ goto fail;
+ }
+ }
+ if (!priv->writeIntrThreshold) {
+ pr_probe(p, "Can't get writeIntrThreshold\n");
+ goto fail;
+ }
+ pr_probe(p, "writeIntrThreshold is %u\n", priv->writeIntrThreshold);
+
+ /* FIFO must be empty now */
+ if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) {
+ pr_probe(p, "Can't empty FIFO\n");
+ goto fail;
+ }
+
+ /* Reset FIFO */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ /* Set reverse direction (must be in PS2 mode) */
+ parport_ip32_data_reverse(p);
+ /* Test FIFO, no interrupt, no DMA */
+ parport_ip32_set_mode(p, ECR_MODE_TST);
+ /* Enable interrupts */
+ parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
+
+ /* Find out readIntrThreshold: number of PWords we can read if we get
+ * an interrupt. */
+ priv->readIntrThreshold = 0;
+ for (i = 0; i < priv->fifo_depth; i++) {
+ writeb(0xaa, priv->regs.fifo);
+ if (readb(priv->regs.ecr) & ECR_SERVINTR) {
+ /* readIntrThreshold reached */
+ priv->readIntrThreshold = i + 1;
+ break;
+ }
+ }
+ if (!priv->readIntrThreshold) {
+ pr_probe(p, "Can't get readIntrThreshold\n");
+ goto fail;
+ }
+ pr_probe(p, "readIntrThreshold is %u\n", priv->readIntrThreshold);
+
+ /* Reset ECR */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ parport_ip32_data_forward(p);
+ parport_ip32_set_mode(p, ECR_MODE_SPP);
+ return 1;
+
+fail:
+ priv->fifo_depth = 0;
+ parport_ip32_set_mode(p, ECR_MODE_SPP);
+ return 0;
+}
+
+/*--- Initialization code ----------------------------------------------*/
+
+/**
+ * parport_ip32_make_isa_registers - compute (ISA) register addresses
+ * @regs: pointer to &struct parport_ip32_regs to fill
+ * @base: base address of standard and EPP registers
+ * @base_hi: base address of ECP registers
+ * @regshift: how much to shift register offset by
+ *
+ * Compute register addresses, according to the ISA standard. The addresses
+ * of the standard and EPP registers are computed from address @base. The
+ * addresses of the ECP registers are computed from address @base_hi.
+ */
+static void __init
+parport_ip32_make_isa_registers(struct parport_ip32_regs *regs,
+ void __iomem *base, void __iomem *base_hi,
+ unsigned int regshift)
+{
+#define r_base(offset) ((u8 __iomem *)base + ((offset) << regshift))
+#define r_base_hi(offset) ((u8 __iomem *)base_hi + ((offset) << regshift))
+ *regs = (struct parport_ip32_regs){
+ .data = r_base(0),
+ .dsr = r_base(1),
+ .dcr = r_base(2),
+ .eppAddr = r_base(3),
+ .eppData0 = r_base(4),
+ .eppData1 = r_base(5),
+ .eppData2 = r_base(6),
+ .eppData3 = r_base(7),
+ .ecpAFifo = r_base(0),
+ .fifo = r_base_hi(0),
+ .cnfgA = r_base_hi(0),
+ .cnfgB = r_base_hi(1),
+ .ecr = r_base_hi(2)
+ };
+#undef r_base_hi
+#undef r_base
+}
+
+/**
+ * parport_ip32_probe_port - probe and register IP32 built-in parallel port
+ *
+ * Returns the new allocated &parport structure. On error, an error code is
+ * encoded in return value with the ERR_PTR function.
+ */
+static __init struct parport *parport_ip32_probe_port(void)
+{
+ struct parport_ip32_regs regs;
+ struct parport_ip32_private *priv = NULL;
+ struct parport_operations *ops = NULL;
+ struct parport *p = NULL;
+ int err;
+
+ parport_ip32_make_isa_registers(&regs, &mace->isa.parallel,
+ &mace->isa.ecp1284, 8 /* regshift */);
+
+ ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
+ priv = kmalloc(sizeof(struct parport_ip32_private), GFP_KERNEL);
+ p = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, ops);
+ if (ops == NULL || priv == NULL || p == NULL) {
+ err = -ENOMEM;
+ goto fail;
+ }
+ p->base = MACE_BASE + offsetof(struct sgi_mace, isa.parallel);
+ p->base_hi = MACE_BASE + offsetof(struct sgi_mace, isa.ecp1284);
+ p->private_data = priv;
+
+ *ops = parport_ip32_ops;
+ *priv = (struct parport_ip32_private){
+ .regs = regs,
+ .dcr_writable = DCR_DIR | DCR_SELECT | DCR_nINIT |
+ DCR_AUTOFD | DCR_STROBE,
+ .irq_mode = PARPORT_IP32_IRQ_FWD,
+ };
+ init_completion(&priv->irq_complete);
+
+ /* Probe port. */
+ if (!parport_ip32_ecp_supported(p)) {
+ err = -ENODEV;
+ goto fail;
+ }
+ parport_ip32_dump_state(p, "begin init", 0);
+
+ /* We found what looks like a working ECR register. Simply assume
+ * that all modes are correctly supported. Enable basic modes. */
+ p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
+ p->modes |= PARPORT_MODE_TRISTATE;
+
+ if (!parport_ip32_fifo_supported(p)) {
+ printk(KERN_WARNING PPIP32
+ "%s: error: FIFO disabled\n", p->name);
+ /* Disable hardware modes depending on a working FIFO. */
+ features &= ~PARPORT_IP32_ENABLE_SPP;
+ features &= ~PARPORT_IP32_ENABLE_ECP;
+ /* DMA is not needed if FIFO is not supported. */
+ features &= ~PARPORT_IP32_ENABLE_DMA;
+ }
+
+ /* Request IRQ */
+ if (features & PARPORT_IP32_ENABLE_IRQ) {
+ int irq = MACEISA_PARALLEL_IRQ;
+ if (request_irq(irq, parport_ip32_interrupt, 0, p->name, p)) {
+ printk(KERN_WARNING PPIP32
+ "%s: error: IRQ disabled\n", p->name);
+ /* DMA cannot work without interrupts. */
+ features &= ~PARPORT_IP32_ENABLE_DMA;
+ } else {
+ pr_probe(p, "Interrupt support enabled\n");
+ p->irq = irq;
+ priv->dcr_writable |= DCR_IRQ;
+ }
+ }
+
+ /* Allocate DMA resources */
+ if (features & PARPORT_IP32_ENABLE_DMA) {
+ if (parport_ip32_dma_register())
+ printk(KERN_WARNING PPIP32
+ "%s: error: DMA disabled\n", p->name);
+ else {
+ pr_probe(p, "DMA support enabled\n");
+ p->dma = 0; /* arbitrary value != PARPORT_DMA_NONE */
+ p->modes |= PARPORT_MODE_DMA;
+ }
+ }
+
+ if (features & PARPORT_IP32_ENABLE_SPP) {
+ /* Enable compatibility FIFO mode */
+ p->ops->compat_write_data = parport_ip32_compat_write_data;
+ p->modes |= PARPORT_MODE_COMPAT;
+ pr_probe(p, "Hardware support for SPP mode enabled\n");
+ }
+ if (features & PARPORT_IP32_ENABLE_EPP) {
+ /* Set up access functions to use EPP hardware. */
+ p->ops->epp_read_data = parport_ip32_epp_read_data;
+ p->ops->epp_write_data = parport_ip32_epp_write_data;
+ p->ops->epp_read_addr = parport_ip32_epp_read_addr;
+ p->ops->epp_write_addr = parport_ip32_epp_write_addr;
+ p->modes |= PARPORT_MODE_EPP;
+ pr_probe(p, "Hardware support for EPP mode enabled\n");
+ }
+ if (features & PARPORT_IP32_ENABLE_ECP) {
+ /* Enable ECP FIFO mode */
+ p->ops->ecp_write_data = parport_ip32_ecp_write_data;
+ /* FIXME - not implemented */
+/* p->ops->ecp_read_data = parport_ip32_ecp_read_data; */
+/* p->ops->ecp_write_addr = parport_ip32_ecp_write_addr; */
+ p->modes |= PARPORT_MODE_ECP;
+ pr_probe(p, "Hardware support for ECP mode enabled\n");
+ }
+
+ /* Initialize the port with sensible values */
+ parport_ip32_set_mode(p, ECR_MODE_PS2);
+ parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
+ parport_ip32_data_forward(p);
+ parport_ip32_disable_irq(p);
+ parport_ip32_write_data(p, 0x00);
+ parport_ip32_dump_state(p, "end init", 0);
+
+ /* Print out what we found */
+ printk(KERN_INFO "%s: SGI IP32 at 0x%lx (0x%lx)",
+ p->name, p->base, p->base_hi);
+ if (p->irq != PARPORT_IRQ_NONE)
+ printk(", irq %d", p->irq);
+ printk(" [");
+#define printmode(x) if (p->modes & PARPORT_MODE_##x) \
+ printk("%s%s", f++ ? "," : "", #x)
+ {
+ unsigned int f = 0;
+ printmode(PCSPP);
+ printmode(TRISTATE);
+ printmode(COMPAT);
+ printmode(EPP);
+ printmode(ECP);
+ printmode(DMA);
+ }
+#undef printmode
+ printk("]\n");
+
+ parport_announce_port(p);
+ return p;
+
+fail:
+ if (p)
+ parport_put_port(p);
+ kfree(priv);
+ kfree(ops);
+ return ERR_PTR(err);
+}
+
+/**
+ * parport_ip32_unregister_port - unregister a parallel port
+ * @p: pointer to the &struct parport
+ *
+ * Unregisters a parallel port and free previously allocated resources
+ * (memory, IRQ, ...).
+ */
+static __exit void parport_ip32_unregister_port(struct parport *p)
+{
+ struct parport_ip32_private * const priv = p->physport->private_data;
+ struct parport_operations *ops = p->ops;
+
+ parport_remove_port(p);
+ if (p->modes & PARPORT_MODE_DMA)
+ parport_ip32_dma_unregister();
+ if (p->irq != PARPORT_IRQ_NONE)
+ free_irq(p->irq, p);
+ parport_put_port(p);
+ kfree(priv);
+ kfree(ops);
+}
+
+/**
+ * parport_ip32_init - module initialization function
+ */
+static int __init parport_ip32_init(void)
+{
+ pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n");
+ pr_debug1(PPIP32 "Compiled on %s, %s\n", __DATE__, __TIME__);
+ this_port = parport_ip32_probe_port();
+ return IS_ERR(this_port) ? PTR_ERR(this_port) : 0;
+}
+
+/**
+ * parport_ip32_exit - module termination function
+ */
+static void __exit parport_ip32_exit(void)
+{
+ parport_ip32_unregister_port(this_port);
+}
+
+/*--- Module stuff -----------------------------------------------------*/
+
+MODULE_AUTHOR("Arnaud Giersch <arnaud.giersch@free.fr>");
+MODULE_DESCRIPTION("SGI IP32 built-in parallel port driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.6"); /* update in parport_ip32_init() too */
+
+module_init(parport_ip32_init);
+module_exit(parport_ip32_exit);
+
+module_param(verbose_probing, bool, S_IRUGO);
+MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialization");
+
+module_param(features, uint, S_IRUGO);
+MODULE_PARM_DESC(features,
+ "Bit mask of features to enable"
+ ", bit 0: IRQ support"
+ ", bit 1: DMA support"
+ ", bit 2: hardware SPP mode"
+ ", bit 3: hardware EPP mode"
+ ", bit 4: hardware ECP mode");
+
+/*--- Inform (X)Emacs about preferred coding style ---------------------*/
+/*
+ * Local Variables:
+ * mode: c
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * tab-width: 8
+ * fill-column: 78
+ * ispell-local-dictionary: "american"
+ * End:
+ */
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 76dd077e318..166de350778 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -329,9 +329,9 @@ static int __devinit parport_register (struct pci_dev *dev,
if (priv->num_par == ARRAY_SIZE (priv->port)) {
printk (KERN_WARNING
- "parport_serial: %s: only %u parallel ports "
+ "parport_serial: %s: only %zu parallel ports "
"supported (%d reported)\n", pci_name (dev),
- ARRAY_SIZE (priv->port), card->numports);
+ ARRAY_SIZE(priv->port), card->numports);
break;
}
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index b62aee8de3c..ea83b70e0de 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -199,7 +199,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer,
if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) {
if (belen != len) {
- printk (KERN_DEBUG "%s: Device ID was %d bytes"
+ printk (KERN_DEBUG "%s: Device ID was %zd bytes"
" while device told it would be %d"
" bytes\n",
port->name, len, belen);
@@ -214,7 +214,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer,
if (buffer[len-1] == ';') {
printk (KERN_DEBUG "%s: Device ID reading stopped"
" before device told data not available. "
- "Current idlen %d of %d, len bytes %02X %02X\n",
+ "Current idlen %u of %u, len bytes %02X %02X\n",
port->name, current_idlen, numidlens,
length[0], length[1]);
goto done;
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 2f1289eebb3..222a1cc4aa2 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -11,8 +11,7 @@ config HOTPLUG_PCI
---help---
Say Y here if you have a motherboard with a PCI Hotplug controller.
This allows you to add and remove PCI cards while the machine is
- powered up and running. The file system pcihpfs must be mounted
- in order to interact with any PCI Hotplug controllers.
+ powered up and running.
To compile this driver as a module, choose M here: the
module will be called pci_hotplug.
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 7e7f913ba7b..317457dd401 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -302,7 +302,7 @@ static int ibm_get_table_from_acpi(char **bufp)
}
package = (union acpi_object *) buffer.pointer;
- if(!(package) ||
+ if (!(package) ||
(package->type != ACPI_TYPE_PACKAGE) ||
!(package->package.elements)) {
err("%s: Invalid APCI object\n", __FUNCTION__);
@@ -405,7 +405,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
}
info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0';
- if(info.current_status && (info.valid & ACPI_VALID_HID) &&
+ if (info.current_status && (info.valid & ACPI_VALID_HID) &&
(!strcmp(info.hardware_id.value, IBM_HARDWARE_ID1) ||
!strcmp(info.hardware_id.value, IBM_HARDWARE_ID2))) {
dbg("found hardware: %s, handle: %p\n", info.hardware_id.value,
@@ -449,13 +449,11 @@ static int __init ibm_acpiphp_init(void)
}
ibm_note.device = device;
- status = acpi_install_notify_handler(
- ibm_acpi_handle,
- ACPI_DEVICE_NOTIFY,
- ibm_handle_events,
+ status = acpi_install_notify_handler(ibm_acpi_handle,
+ ACPI_DEVICE_NOTIFY, ibm_handle_events,
&ibm_note);
if (ACPI_FAILURE(status)) {
- err("%s: Failed to register notification handler\n",
+ err("%s: Failed to register notification handler\n",
__FUNCTION__);
retval = -EBUSY;
goto init_cleanup;
@@ -482,14 +480,13 @@ static void __exit ibm_acpiphp_exit(void)
if (acpiphp_unregister_attention(&ibm_attention_info))
err("%s: attention info deregistration failed", __FUNCTION__);
- status = acpi_remove_notify_handler(
+ status = acpi_remove_notify_handler(
ibm_acpi_handle,
ACPI_DEVICE_NOTIFY,
ibm_handle_events);
- if (ACPI_FAILURE(status))
- err("%s: Notification handler removal failed\n",
- __FUNCTION__);
- // remove the /sys entries
+ if (ACPI_FAILURE(status))
+ err("%s: Notification handler removal failed\n", __FUNCTION__);
+ /* remove the /sys entries */
if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr))
err("%s: removal of sysfs file apci_table failed\n",
__FUNCTION__);
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index aabf1e70b52..dc59da675c0 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -235,12 +235,12 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
{
int rc = 0;
struct slot *pslot;
- u8 cmd;
+ u8 cmd = 0x00; /* avoid compiler warning */
debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n",
(ulong) hotplug_slot, value);
ibmphp_lock_operations();
- cmd = 0x00; // avoid compiler warning
+
if (hotplug_slot) {
switch (value) {
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 7d93dbaf628..3eefe2cec72 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -103,13 +103,13 @@ static struct slot *find_slot(struct device_node *dn)
struct list_head *tmp, *n;
struct slot *slot;
- list_for_each_safe(tmp, n, &rpaphp_slot_head) {
- slot = list_entry(tmp, struct slot, rpaphp_slot_list);
- if (slot->dn == dn)
- return slot;
- }
+ list_for_each_safe(tmp, n, &rpaphp_slot_head) {
+ slot = list_entry(tmp, struct slot, rpaphp_slot_list);
+ if (slot->dn == dn)
+ return slot;
+ }
- return NULL;
+ return NULL;
}
static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
@@ -126,9 +126,9 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
return NULL;
}
-static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
+static void dlpar_pci_add_bus(struct device_node *dn)
{
- struct pci_dn *pdn = dn->data;
+ struct pci_dn *pdn = PCI_DN(dn);
struct pci_controller *phb = pdn->phb;
struct pci_dev *dev = NULL;
@@ -139,52 +139,52 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
if (!dev) {
printk(KERN_ERR "%s: failed to create pci dev for %s\n",
__FUNCTION__, dn->full_name);
- return NULL;
+ return;
}
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
of_scan_pci_bridge(dn, dev);
- rpaphp_init_new_devs(dev->subordinate);
+ pcibios_fixup_new_pci_devices(dev->subordinate,0);
/* Claim new bus resources */
pcibios_claim_one_bus(dev->bus);
/* ioremap() for child bus, which may or may not succeed */
- (void) remap_bus_range(dev->bus);
+ remap_bus_range(dev->subordinate);
/* Add new devices to global lists. Register in proc, sysfs. */
pci_bus_add_devices(phb->bus);
-
- /* Confirm new bridge dev was created */
- dev = dlpar_find_new_dev(phb->bus, dn);
- if (dev) {
- if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
- printk(KERN_ERR "%s: unexpected header type %d\n",
- __FUNCTION__, dev->hdr_type);
- return NULL;
- }
- }
-
- return dev;
}
static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
{
struct pci_dev *dev;
+ struct pci_controller *phb;
- if (rpaphp_find_pci_bus(dn))
+ if (pcibios_find_pci_bus(dn))
return -EINVAL;
/* Add pci bus */
- dev = dlpar_pci_add_bus(dn);
+ dlpar_pci_add_bus(dn);
+
+ /* Confirm new bridge dev was created */
+ phb = PCI_DN(dn)->phb;
+ dev = dlpar_find_new_dev(phb->bus, dn);
+
if (!dev) {
printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__,
drc_name);
return -EIO;
}
+ if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n",
+ __FUNCTION__, dev->hdr_type, drc_name);
+ return -EIO;
+ }
+
/* Add hotplug slot */
if (rpaphp_add_slot(dn)) {
printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
@@ -221,13 +221,13 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
struct pci_dn *pdn;
int rc = 0;
- if (!rpaphp_find_pci_bus(dn))
+ if (!pcibios_find_pci_bus(dn))
return -EINVAL;
slot = find_slot(dn);
if (slot) {
/* Remove hotplug slot */
- if (rpaphp_remove_slot(slot)) {
+ if (rpaphp_deregister_slot(slot)) {
printk(KERN_ERR
"%s: unable to remove hotplug slot %s\n",
__FUNCTION__, drc_name);
@@ -366,21 +366,25 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
struct pci_bus *bus;
struct slot *slot;
- bus = rpaphp_find_pci_bus(dn);
+ bus = pcibios_find_pci_bus(dn);
if (!bus)
return -EINVAL;
slot = find_slot(dn);
if (slot) {
/* Remove hotplug slot */
- if (rpaphp_remove_slot(slot)) {
+ if (rpaphp_deregister_slot(slot)) {
printk(KERN_ERR
"%s: unable to remove hotplug slot %s\n",
__FUNCTION__, drc_name);
return -EIO;
}
} else {
- rpaphp_unconfig_pci_adapter(bus);
+ struct pci_dev *dev, *tmp;
+ list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+ eeh_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
+ }
}
if (unmap_bus_range(bus)) {
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 57ea71a7bda..310b6186c0e 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -88,16 +88,10 @@ extern int num_slots;
/* function prototypes */
/* rpaphp_pci.c */
-extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn);
-extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
extern int rpaphp_enable_pci_slot(struct slot *slot);
-extern int register_pci_slot(struct slot *slot);
+extern int rpaphp_register_pci_slot(struct slot *slot);
extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
-extern void rpaphp_init_new_devs(struct pci_bus *bus);
-extern void rpaphp_eeh_init_nodes(struct device_node *dn);
-
-extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
-extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
+extern int rpaphp_get_sensor_state(struct slot *slot, int *state);
/* rpaphp_core.c */
extern int rpaphp_add_slot(struct device_node *dn);
@@ -108,8 +102,8 @@ extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
/* rpaphp_slot.c */
extern void dealloc_slot_struct(struct slot *slot);
extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
-extern int register_slot(struct slot *slot);
-extern int deregister_slot(struct slot *slot);
+extern int rpaphp_register_slot(struct slot *slot);
+extern int rpaphp_deregister_slot(struct slot *slot);
extern int rpaphp_get_power_status(struct slot *slot, u8 * value);
extern int rpaphp_set_attention_status(struct slot *slot, u8 status);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index cf075c34b57..6e79f5675b0 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -56,25 +56,6 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, 0644);
-static int enable_slot(struct hotplug_slot *slot);
-static int disable_slot(struct hotplug_slot *slot);
-static int set_attention_status(struct hotplug_slot *slot, u8 value);
-static int get_power_status(struct hotplug_slot *slot, u8 * value);
-static int get_attention_status(struct hotplug_slot *slot, u8 * value);
-static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
-static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
-
-struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
- .owner = THIS_MODULE,
- .enable_slot = enable_slot,
- .disable_slot = disable_slot,
- .set_attention_status = set_attention_status,
- .get_power_status = get_power_status,
- .get_attention_status = get_attention_status,
- .get_adapter_status = get_adapter_status,
- .get_max_bus_speed = get_max_bus_speed,
-};
-
static int rpaphp_get_attention_status(struct slot *slot)
{
return slot->hotplug_slot->info->attention_status;
@@ -196,11 +177,6 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
return 0;
}
-int rpaphp_remove_slot(struct slot *slot)
-{
- return deregister_slot(slot);
-}
-
static int get_children_props(struct device_node *dn, int **drc_indexes,
int **drc_names, int **drc_types, int **drc_power_domains)
{
@@ -307,13 +283,15 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names,
return 0;
}
-/****************************************************************
+/**
+ * rpaphp_add_slot -- add hotplug or dlpar slot
+ *
* rpaphp not only registers PCI hotplug slots(HOTPLUG),
* but also logical DR slots(EMBEDDED).
* HOTPLUG slot: An adapter can be physically added/removed.
* EMBEDDED slot: An adapter can be logically removed/added
* from/to a partition with the slot.
- ***************************************************************/
+ */
int rpaphp_add_slot(struct device_node *dn)
{
struct slot *slot;
@@ -344,7 +322,7 @@ int rpaphp_add_slot(struct device_node *dn)
dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
indexes[i + 1], name, type);
- retval = register_pci_slot(slot);
+ retval = rpaphp_register_pci_slot(slot);
}
}
exit:
@@ -393,53 +371,85 @@ static void __exit rpaphp_exit(void)
cleanup_slots();
}
-static int enable_slot(struct hotplug_slot *hotplug_slot)
+static int __enable_slot(struct slot *slot)
{
- int retval = 0;
- struct slot *slot = (struct slot *)hotplug_slot->private;
+ int state;
+ int retval;
- if (slot->state == CONFIGURED) {
- dbg("%s: %s is already enabled\n", __FUNCTION__, slot->name);
- goto exit;
+ if (slot->state == CONFIGURED)
+ return 0;
+
+ retval = rpaphp_get_sensor_state(slot, &state);
+ if (retval)
+ return retval;
+
+ if (state == PRESENT) {
+ pcibios_add_pci_devices(slot->bus);
+ slot->state = CONFIGURED;
+ } else if (state == EMPTY) {
+ slot->state = EMPTY;
+ } else {
+ err("%s: slot[%s] is in invalid state\n", __FUNCTION__, slot->name);
+ slot->state = NOT_VALID;
+ return -EINVAL;
}
+ return 0;
+}
+
+static int enable_slot(struct hotplug_slot *hotplug_slot)
+{
+ int retval;
+ struct slot *slot = (struct slot *)hotplug_slot->private;
- dbg("ENABLING SLOT %s\n", slot->name);
down(&rpaphp_sem);
- retval = rpaphp_enable_pci_slot(slot);
+ retval = __enable_slot(slot);
up(&rpaphp_sem);
-exit:
- dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
+
return retval;
}
-static int disable_slot(struct hotplug_slot *hotplug_slot)
+static int __disable_slot(struct slot *slot)
{
- int retval = -EINVAL;
- struct slot *slot = (struct slot *)hotplug_slot->private;
+ struct pci_dev *dev, *tmp;
- dbg("%s - Entry: slot[%s]\n", __FUNCTION__, slot->name);
+ if (slot->state == NOT_CONFIGURED)
+ return -EINVAL;
- if (slot->state == NOT_CONFIGURED) {
- dbg("%s: %s is already disabled\n", __FUNCTION__, slot->name);
- goto exit;
+ list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) {
+ eeh_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
}
- dbg("DISABLING SLOT %s\n", slot->name);
+ slot->state = NOT_CONFIGURED;
+ return 0;
+}
+
+static int disable_slot(struct hotplug_slot *hotplug_slot)
+{
+ struct slot *slot = (struct slot *)hotplug_slot->private;
+ int retval;
+
down(&rpaphp_sem);
- retval = rpaphp_unconfig_pci_adapter(slot->bus);
+ retval = __disable_slot (slot);
up(&rpaphp_sem);
- slot->state = NOT_CONFIGURED;
- info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
- slot->name);
-exit:
- dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
+
return retval;
}
+struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
+ .owner = THIS_MODULE,
+ .enable_slot = enable_slot,
+ .disable_slot = disable_slot,
+ .set_attention_status = set_attention_status,
+ .get_power_status = get_power_status,
+ .get_attention_status = get_attention_status,
+ .get_adapter_status = get_adapter_status,
+ .get_max_bus_speed = get_max_bus_speed,
+};
+
module_init(rpaphp_init);
module_exit(rpaphp_exit);
EXPORT_SYMBOL_GPL(rpaphp_add_slot);
-EXPORT_SYMBOL_GPL(rpaphp_remove_slot);
EXPORT_SYMBOL_GPL(rpaphp_slot_head);
EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 396b54b0c84..6f6cbede513 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -32,37 +32,7 @@
#include "../pci.h" /* for pci_add_new_bus */
#include "rpaphp.h"
-static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
- struct device_node *dn)
-{
- struct pci_bus *child = NULL;
- struct list_head *tmp;
- struct device_node *busdn;
-
- busdn = pci_bus_to_OF_node(bus);
- if (busdn == dn)
- return bus;
-
- list_for_each(tmp, &bus->children) {
- child = find_bus_among_children(pci_bus_b(tmp), dn);
- if (child)
- break;
- }
- return child;
-}
-
-struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
-{
- struct pci_dn *pdn = dn->data;
-
- if (!pdn || !pdn->phb || !pdn->phb->bus)
- return NULL;
-
- return find_bus_among_children(pdn->phb->bus, dn);
-}
-EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
-
-static int rpaphp_get_sensor_state(struct slot *slot, int *state)
+int rpaphp_get_sensor_state(struct slot *slot, int *state)
{
int rc;
int setlevel;
@@ -120,7 +90,7 @@ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
/* config/unconfig adapter */
*value = slot->state;
} else {
- bus = rpaphp_find_pci_bus(slot->dn);
+ bus = pcibios_find_pci_bus(slot->dn);
if (bus && !list_empty(&bus->devices))
*value = CONFIGURED;
else
@@ -131,140 +101,6 @@ exit:
return rc;
}
-/* Must be called before pci_bus_add_devices */
-void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
-{
- struct pci_dev *dev;
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- /*
- * Skip already-present devices (which are on the
- * global device list.)
- */
- if (list_empty(&dev->global_list)) {
- int i;
-
- /* Need to setup IOMMU tables */
- ppc_md.iommu_dev_setup(dev);
-
- if(fix_bus)
- pcibios_fixup_device_resources(dev, bus);
- pci_read_irq_line(dev);
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *r = &dev->resource[i];
-
- if (r->parent || !r->start || !r->flags)
- continue;
- pci_claim_resource(dev, i);
- }
- }
- }
-}
-
-static void rpaphp_eeh_add_bus_device(struct pci_bus *bus)
-{
- struct pci_dev *dev;
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- eeh_add_device_late(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- struct pci_bus *subbus = dev->subordinate;
- if (subbus)
- rpaphp_eeh_add_bus_device (subbus);
- }
- }
-}
-
-static int rpaphp_pci_config_bridge(struct pci_dev *dev)
-{
- u8 sec_busno;
- struct pci_bus *child_bus;
- struct pci_dev *child_dev;
-
- dbg("Enter %s: BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev));
-
- /* get busno of downstream bus */
- pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
-
- /* add to children of PCI bridge dev->bus */
- child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
- if (!child_bus) {
- err("%s: could not add second bus\n", __FUNCTION__);
- return -EIO;
- }
- sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
- /* do pci_scan_child_bus */
- pci_scan_child_bus(child_bus);
-
- list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
- eeh_add_device_late(child_dev);
- }
-
- /* fixup new pci devices without touching bus struct */
- rpaphp_fixup_new_pci_devices(child_bus, 0);
-
- /* Make the discovered devices available */
- pci_bus_add_devices(child_bus);
- return 0;
-}
-
-void rpaphp_init_new_devs(struct pci_bus *bus)
-{
- rpaphp_fixup_new_pci_devices(bus, 0);
- rpaphp_eeh_add_bus_device(bus);
-}
-EXPORT_SYMBOL_GPL(rpaphp_init_new_devs);
-
-/*****************************************************************************
- rpaphp_pci_config_slot() will configure all devices under the
- given slot->dn and return the the first pci_dev.
- *****************************************************************************/
-static struct pci_dev *
-rpaphp_pci_config_slot(struct pci_bus *bus)
-{
- struct device_node *dn = pci_bus_to_OF_node(bus);
- struct pci_dev *dev = NULL;
- int slotno;
- int num;
-
- dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
- if (!dn || !dn->child)
- return NULL;
-
- if (_machine == PLATFORM_PSERIES_LPAR) {
- of_scan_bus(dn, bus);
- if (list_empty(&bus->devices)) {
- err("%s: No new device found\n", __FUNCTION__);
- return NULL;
- }
-
- rpaphp_init_new_devs(bus);
- pci_bus_add_devices(bus);
- dev = list_entry(&bus->devices, struct pci_dev, bus_list);
- } else {
- slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
-
- /* pci_scan_slot should find all children */
- num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
- if (num) {
- rpaphp_fixup_new_pci_devices(bus, 1);
- pci_bus_add_devices(bus);
- }
- if (list_empty(&bus->devices)) {
- err("%s: No new device found\n", __FUNCTION__);
- return NULL;
- }
- list_for_each_entry(dev, &bus->devices, bus_list) {
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
- rpaphp_pci_config_bridge(dev);
-
- rpaphp_eeh_add_bus_device(bus);
- }
- }
-
- return dev;
-}
-
static void print_slot_pci_funcs(struct pci_bus *bus)
{
struct device_node *dn;
@@ -280,60 +116,6 @@ static void print_slot_pci_funcs(struct pci_bus *bus)
return;
}
-int rpaphp_config_pci_adapter(struct pci_bus *bus)
-{
- struct device_node *dn = pci_bus_to_OF_node(bus);
- struct pci_dev *dev;
- int rc = -ENODEV;
-
- dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
- if (!dn)
- goto exit;
-
- eeh_add_device_tree_early(dn);
- dev = rpaphp_pci_config_slot(bus);
- if (!dev) {
- err("%s: can't find any devices.\n", __FUNCTION__);
- goto exit;
- }
- print_slot_pci_funcs(bus);
- rc = 0;
-exit:
- dbg("Exit %s: rc=%d\n", __FUNCTION__, rc);
- return rc;
-}
-EXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter);
-
-static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
-{
- eeh_remove_device(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- struct pci_bus *bus = dev->subordinate;
- struct list_head *ln;
- if (!bus)
- return;
- for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
- struct pci_dev *pdev = pci_dev_b(ln);
- if (pdev)
- rpaphp_eeh_remove_bus_device(pdev);
- }
-
- }
- return;
-}
-
-int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
-{
- struct pci_dev *dev, *tmp;
-
- list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
- rpaphp_eeh_remove_bus_device(dev);
- pci_remove_bus_device(dev);
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
-
static int setup_pci_hotplug_slot_info(struct slot *slot)
{
struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
@@ -370,7 +152,7 @@ static int setup_pci_slot(struct slot *slot)
struct pci_bus *bus;
BUG_ON(!dn);
- bus = rpaphp_find_pci_bus(dn);
+ bus = pcibios_find_pci_bus(dn);
if (!bus) {
err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
goto exit_rc;
@@ -395,10 +177,7 @@ static int setup_pci_slot(struct slot *slot)
if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
dbg("%s CONFIGURING pci adapter in slot[%s]\n",
__FUNCTION__, slot->name);
- if (rpaphp_config_pci_adapter(slot->bus)) {
- err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
- goto exit_rc;
- }
+ pcibios_add_pci_devices(slot->bus);
} else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
@@ -420,7 +199,7 @@ exit_rc:
return -EINVAL;
}
-int register_pci_slot(struct slot *slot)
+int rpaphp_register_pci_slot(struct slot *slot)
{
int rc = -EINVAL;
@@ -428,42 +207,8 @@ int register_pci_slot(struct slot *slot)
goto exit_rc;
if (setup_pci_slot(slot))
goto exit_rc;
- rc = register_slot(slot);
+ rc = rpaphp_register_slot(slot);
exit_rc:
return rc;
}
-int rpaphp_enable_pci_slot(struct slot *slot)
-{
- int retval = 0, state;
-
- retval = rpaphp_get_sensor_state(slot, &state);
- if (retval)
- goto exit;
- dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
- /* if slot is not empty, enable the adapter */
- if (state == PRESENT) {
- dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
- retval = rpaphp_config_pci_adapter(slot->bus);
- if (!retval) {
- slot->state = CONFIGURED;
- info("%s: devices in slot[%s] configured\n",
- __FUNCTION__, slot->name);
- } else {
- slot->state = NOT_CONFIGURED;
- dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
- __FUNCTION__, slot->name);
- }
- } else if (state == EMPTY) {
- dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
- slot->state = EMPTY;
- } else {
- err("%s: slot[%s] is in invalid state\n", __FUNCTION__,
- slot->name);
- slot->state = NOT_VALID;
- retval = -EINVAL;
- }
-exit:
- dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
- return retval;
-}
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index daa89ae5712..78943e064b5 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -35,16 +35,16 @@
static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
{
- char *value;
- int retval = -ENOENT;
+ char *value;
+ int retval = -ENOENT;
struct slot *slot = (struct slot *)php_slot->private;
if (!slot)
return retval;
- value = slot->location;
- retval = sprintf (buf, "%s\n", value);
- return retval;
+ value = slot->location;
+ retval = sprintf (buf, "%s\n", value);
+ return retval;
}
static struct hotplug_slot_attribute hotplug_slot_attr_location = {
@@ -137,7 +137,7 @@ static int is_registered(struct slot *slot)
return 0;
}
-int deregister_slot(struct slot *slot)
+int rpaphp_deregister_slot(struct slot *slot)
{
int retval = 0;
struct hotplug_slot *php_slot = slot->hotplug_slot;
@@ -159,8 +159,9 @@ int deregister_slot(struct slot *slot)
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
return retval;
}
+EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
-int register_slot(struct slot *slot)
+int rpaphp_register_slot(struct slot *slot)
{
int retval;
@@ -169,7 +170,7 @@ int register_slot(struct slot *slot)
slot->power_domain, slot->type);
/* should not try to register the same slot twice */
if (is_registered(slot)) { /* should't be here */
- err("register_slot: slot[%s] is already registered\n", slot->name);
+ err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
rpaphp_release_slot(slot->hotplug_slot);
return -EAGAIN;
}
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index ce0e9b6ce83..7d6f521d02e 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -95,6 +95,7 @@ struct controller {
u8 function;
u8 slot_device_offset;
u8 add_support;
+ u32 pcix_misc2_reg; /* for amd pogo errata */
enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
@@ -113,6 +114,26 @@ struct hotplug_params {
/* Define AMD SHPC ID */
#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
+#define PCI_DEVICE_ID_AMD_POGO_7458 0x7458
+
+/* AMD PCIX bridge registers */
+
+#define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C
+#define PCIX_MISCII_OFFSET 0x48
+#define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80
+
+/* AMD PCIX_MISCII masks and offsets */
+#define PERRNONFATALENABLE_MASK 0x00040000
+#define PERRFATALENABLE_MASK 0x00080000
+#define PERRFLOODENABLE_MASK 0x00100000
+#define SERRNONFATALENABLE_MASK 0x00200000
+#define SERRFATALENABLE_MASK 0x00400000
+
+/* AMD PCIX_MISC_BRIDGE_ERRORS masks and offsets */
+#define PERR_OBSERVED_MASK 0x00000001
+
+/* AMD PCIX_MEM_BASE_LIMIT masks */
+#define RSE_MASK 0x40000000
#define INT_BUTTON_IGNORE 0
#define INT_PRESENCE_ON 1
@@ -333,6 +354,79 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
return retval;
}
+static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot)
+{
+ u32 pcix_misc2_temp;
+
+ /* save MiscII register */
+ pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp);
+
+ p_slot->ctrl->pcix_misc2_reg = pcix_misc2_temp;
+
+ /* clear SERR/PERR enable bits */
+ pcix_misc2_temp &= ~SERRFATALENABLE_MASK;
+ pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK;
+ pcix_misc2_temp &= ~PERRFLOODENABLE_MASK;
+ pcix_misc2_temp &= ~PERRFATALENABLE_MASK;
+ pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK;
+ pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
+}
+
+static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
+{
+ u32 pcix_misc2_temp;
+ u32 pcix_bridge_errors_reg;
+ u32 pcix_mem_base_reg;
+ u8 perr_set;
+ u8 rse_set;
+
+ /* write-one-to-clear Bridge_Errors[ PERR_OBSERVED ] */
+ pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg);
+ perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK;
+ if (perr_set) {
+ dbg ("%s W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__FUNCTION__ , perr_set);
+
+ pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set);
+ }
+
+ /* write-one-to-clear Memory_Base_Limit[ RSE ] */
+ pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg);
+ rse_set = pcix_mem_base_reg & RSE_MASK;
+ if (rse_set) {
+ dbg ("%s W1C: Memory_Base_Limit[ RSE ]\n",__FUNCTION__ );
+
+ pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);
+ }
+ /* restore MiscII register */
+ pci_read_config_dword( p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp );
+
+ if (p_slot->ctrl->pcix_misc2_reg & SERRFATALENABLE_MASK)
+ pcix_misc2_temp |= SERRFATALENABLE_MASK;
+ else
+ pcix_misc2_temp &= ~SERRFATALENABLE_MASK;
+
+ if (p_slot->ctrl->pcix_misc2_reg & SERRNONFATALENABLE_MASK)
+ pcix_misc2_temp |= SERRNONFATALENABLE_MASK;
+ else
+ pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK;
+
+ if (p_slot->ctrl->pcix_misc2_reg & PERRFLOODENABLE_MASK)
+ pcix_misc2_temp |= PERRFLOODENABLE_MASK;
+ else
+ pcix_misc2_temp &= ~PERRFLOODENABLE_MASK;
+
+ if (p_slot->ctrl->pcix_misc2_reg & PERRFATALENABLE_MASK)
+ pcix_misc2_temp |= PERRFATALENABLE_MASK;
+ else
+ pcix_misc2_temp &= ~PERRFATALENABLE_MASK;
+
+ if (p_slot->ctrl->pcix_misc2_reg & PERRNONFATALENABLE_MASK)
+ pcix_misc2_temp |= PERRNONFATALENABLE_MASK;
+ else
+ pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK;
+ pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
+}
+
#define SLOT_NAME_SIZE 10
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 25ccb0e4759..643252d9bf3 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -894,7 +894,17 @@ int shpchp_enable_slot (struct slot *p_slot)
dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- rc = board_added(p_slot);
+ if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) ||
+ (p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458))
+ && p_slot->ctrl->num_slots == 1) {
+ /* handle amd pogo errata; this must be done before enable */
+ amd_pogo_errata_save_misc_reg(p_slot);
+ rc = board_added(p_slot);
+ /* handle amd pogo errata; this must be done after enable */
+ amd_pogo_errata_restore_misc_reg(p_slot);
+ } else
+ rc = board_added(p_slot);
+
if (rc) {
p_slot->hpc_ops->get_adapter_status(p_slot,
&(p_slot->presence_save));
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 202b7507a35..48723d6fa60 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -137,6 +137,8 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
break;
}
}
+#else
+#define set_msi_affinity NULL
#endif /* CONFIG_SMP */
static void mask_MSI_irq(unsigned int vector)
@@ -214,7 +216,7 @@ static struct hw_interrupt_type msix_irq_type = {
.disable = mask_MSI_irq,
.ack = mask_MSI_irq,
.end = end_msi_irq_w_maskbit,
- .set_affinity = set_msi_irq_affinity
+ .set_affinity = set_msi_affinity
};
/*
@@ -230,7 +232,7 @@ static struct hw_interrupt_type msi_irq_w_maskbit_type = {
.disable = mask_MSI_irq,
.ack = mask_MSI_irq,
.end = end_msi_irq_w_maskbit,
- .set_affinity = set_msi_irq_affinity
+ .set_affinity = set_msi_affinity
};
/*
@@ -246,7 +248,7 @@ static struct hw_interrupt_type msi_irq_wo_maskbit_type = {
.disable = do_nothing,
.ack = do_nothing,
.end = end_msi_irq_wo_maskbit,
- .set_affinity = set_msi_irq_affinity
+ .set_affinity = set_msi_affinity
};
static void msi_data_init(struct msg_data *msi_data,
@@ -416,7 +418,9 @@ static void attach_msi_entry(struct msi_desc *entry, int vector)
static void irq_handler_init(int cap_id, int pos, int mask)
{
- spin_lock(&irq_desc[pos].lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&irq_desc[pos].lock, flags);
if (cap_id == PCI_CAP_ID_MSIX)
irq_desc[pos].handler = &msix_irq_type;
else {
@@ -425,7 +429,7 @@ static void irq_handler_init(int cap_id, int pos, int mask)
else
irq_desc[pos].handler = &msi_irq_w_maskbit_type;
}
- spin_unlock(&irq_desc[pos].lock);
+ spin_unlock_irqrestore(&irq_desc[pos].lock, flags);
}
static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 402136a5c9e..4ac52d441e4 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -22,12 +22,6 @@ extern int vector_irq[NR_VECTORS];
extern void (*interrupt[NR_IRQS])(void);
extern int pci_vector_resources(int last, int nr_released);
-#ifdef CONFIG_SMP
-#define set_msi_irq_affinity set_msi_affinity
-#else
-#define set_msi_irq_affinity NULL
-#endif
-
/*
* MSI-X Address Register
*/
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index d2a633efa10..d2d18791664 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -163,6 +163,7 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
}
+#if 0
/**
* pci_find_ext_capability - Find an extended capability
* @dev: PCI device to query
@@ -210,6 +211,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
return 0;
}
+#endif /* 0 */
/**
* pci_find_parent_resource - return resource region of parent bus of given region
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 605f0df0bfb..dda6099903c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1142,6 +1142,9 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
case 0x27c4:
ich = 7;
break;
+ case 0x2828: /* ICH8M */
+ ich = 8;
+ break;
default:
/* we do not handle this PCI device */
return;
@@ -1161,7 +1164,7 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
else
return; /* not in combined mode */
} else {
- WARN_ON((ich != 6) && (ich != 7));
+ WARN_ON((ich != 6) && (ich != 7) && (ich != 8));
tmp &= 0x3; /* interesting bits 1:0 */
if (tmp & (1 << 0))
comb = (1 << 2); /* PATA port 0, SATA port 1 */
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 50d6685dcbc..ea9277b7f89 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -112,6 +112,7 @@ pci_claim_resource(struct pci_dev *dev, int resource)
return err;
}
+EXPORT_SYMBOL_GPL(pci_claim_resource);
int pci_assign_resource(struct pci_dev *dev, int resno)
{
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 0ecbe4edbec..aaa568a3806 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -363,7 +363,7 @@ static int card_resume(struct pnp_dev *dev)
int pnp_register_card_driver(struct pnp_card_driver * drv)
{
- int count = 0;
+ int count;
struct list_head *pos, *temp;
drv->link.name = drv->name;
@@ -374,10 +374,15 @@ int pnp_register_card_driver(struct pnp_card_driver * drv)
drv->link.suspend = drv->suspend ? card_suspend : NULL;
drv->link.resume = drv->resume ? card_resume : NULL;
+ count = pnp_register_driver(&drv->link);
+ if (count < 0)
+ return count;
+
spin_lock(&pnp_lock);
list_add_tail(&drv->global_list, &pnp_card_drivers);
spin_unlock(&pnp_lock);
- pnp_register_driver(&drv->link);
+
+ count = 0;
list_for_each_safe(pos,temp,&pnp_cards){
struct pnp_card *card = list_entry(pos, struct pnp_card, global_list);
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 816479ad217..f104577f73e 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -27,12 +27,15 @@
static int num = 0;
+/* We need only to blacklist devices that have already an acpi driver that
+ * can't use pnp layer. We don't need to blacklist device that are directly
+ * used by the kernel (PCI root, ...), as it is harmless and there were
+ * already present in pnpbios. But there is an exception for devices that
+ * have irqs (PIC, Timer) because we call acpi_register_gsi.
+ * Finaly only devices that have a CRS method need to be in this list.
+ */
static char __initdata excluded_id_list[] =
- "PNP0C0A," /* Battery */
- "PNP0C0C,PNP0C0E,PNP0C0D," /* Button */
"PNP0C09," /* EC */
- "PNP0C0B," /* Fan */
- "PNP0A03," /* PCI root */
"PNP0C0F," /* Link device */
"PNP0000," /* PIC */
"PNP0100," /* Timer */
@@ -131,7 +134,8 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
struct pnp_id *dev_id;
struct pnp_dev *dev;
- if (!ispnpidacpi(acpi_device_hid(device)) ||
+ status = acpi_get_handle(device->handle, "_CRS", &temp);
+ if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
is_exclusive_device(device))
return 0;
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 416d30debe6..407b4eaddcb 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
* Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
- *
+ *
* 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
@@ -32,17 +32,17 @@
/*
* Allocated Resources
*/
-static int irq_flags(int edge_level, int active_high_low)
+static int irq_flags(int triggering, int polarity)
{
int flag;
- if (edge_level == ACPI_LEVEL_SENSITIVE) {
- if(active_high_low == ACPI_ACTIVE_LOW)
+ if (triggering == ACPI_LEVEL_SENSITIVE) {
+ if(polarity == ACPI_ACTIVE_LOW)
flag = IORESOURCE_IRQ_LOWLEVEL;
else
flag = IORESOURCE_IRQ_HIGHLEVEL;
}
else {
- if(active_high_low == ACPI_ACTIVE_LOW)
+ if(polarity == ACPI_ACTIVE_LOW)
flag = IORESOURCE_IRQ_LOWEDGE;
else
flag = IORESOURCE_IRQ_HIGHEDGE;
@@ -50,31 +50,31 @@ static int irq_flags(int edge_level, int active_high_low)
return flag;
}
-static void decode_irq_flags(int flag, int *edge_level, int *active_high_low)
+static void decode_irq_flags(int flag, int *triggering, int *polarity)
{
switch (flag) {
case IORESOURCE_IRQ_LOWLEVEL:
- *edge_level = ACPI_LEVEL_SENSITIVE;
- *active_high_low = ACPI_ACTIVE_LOW;
+ *triggering = ACPI_LEVEL_SENSITIVE;
+ *polarity = ACPI_ACTIVE_LOW;
break;
case IORESOURCE_IRQ_HIGHLEVEL:
- *edge_level = ACPI_LEVEL_SENSITIVE;
- *active_high_low = ACPI_ACTIVE_HIGH;
+ *triggering = ACPI_LEVEL_SENSITIVE;
+ *polarity = ACPI_ACTIVE_HIGH;
break;
case IORESOURCE_IRQ_LOWEDGE:
- *edge_level = ACPI_EDGE_SENSITIVE;
- *active_high_low = ACPI_ACTIVE_LOW;
+ *triggering = ACPI_EDGE_SENSITIVE;
+ *polarity = ACPI_ACTIVE_LOW;
break;
case IORESOURCE_IRQ_HIGHEDGE:
- *edge_level = ACPI_EDGE_SENSITIVE;
- *active_high_low = ACPI_ACTIVE_HIGH;
+ *triggering = ACPI_EDGE_SENSITIVE;
+ *polarity = ACPI_ACTIVE_HIGH;
break;
}
}
static void
pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
- int edge_level, int active_high_low)
+ int triggering, int polarity)
{
int i = 0;
int irq;
@@ -89,7 +89,7 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
return;
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
- irq = acpi_register_gsi(gsi, edge_level, active_high_low);
+ irq = acpi_register_gsi(gsi, triggering, polarity);
if (irq < 0) {
res->irq_resource[i].flags |= IORESOURCE_DISABLED;
return;
@@ -163,77 +163,96 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
int i;
- switch (res->id) {
- case ACPI_RSTYPE_IRQ:
+ switch (res->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
/*
* Per spec, only one interrupt per descriptor is allowed in
* _CRS, but some firmware violates this, so parse them all.
*/
- for (i = 0; i < res->data.irq.number_of_interrupts; i++) {
+ for (i = 0; i < res->data.irq.interrupt_count; i++) {
pnpacpi_parse_allocated_irqresource(res_table,
res->data.irq.interrupts[i],
- res->data.irq.edge_level,
- res->data.irq.active_high_low);
+ res->data.irq.triggering,
+ res->data.irq.polarity);
}
break;
- case ACPI_RSTYPE_EXT_IRQ:
- for (i = 0; i < res->data.extended_irq.number_of_interrupts; i++) {
- pnpacpi_parse_allocated_irqresource(res_table,
- res->data.extended_irq.interrupts[i],
- res->data.extended_irq.edge_level,
- res->data.extended_irq.active_high_low);
- }
- break;
- case ACPI_RSTYPE_DMA:
- if (res->data.dma.number_of_channels > 0)
- pnpacpi_parse_allocated_dmaresource(res_table,
+ case ACPI_RESOURCE_TYPE_DMA:
+ if (res->data.dma.channel_count > 0)
+ pnpacpi_parse_allocated_dmaresource(res_table,
res->data.dma.channels[0]);
break;
- case ACPI_RSTYPE_IO:
- pnpacpi_parse_allocated_ioresource(res_table,
- res->data.io.min_base_address,
- res->data.io.range_length);
+
+ case ACPI_RESOURCE_TYPE_IO:
+ pnpacpi_parse_allocated_ioresource(res_table,
+ res->data.io.minimum,
+ res->data.io.address_length);
break;
- case ACPI_RSTYPE_FIXED_IO:
- pnpacpi_parse_allocated_ioresource(res_table,
- res->data.fixed_io.base_address,
- res->data.fixed_io.range_length);
+
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_END_DEPENDENT:
break;
- case ACPI_RSTYPE_MEM24:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.memory24.min_base_address,
- res->data.memory24.range_length);
+
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+ pnpacpi_parse_allocated_ioresource(res_table,
+ res->data.fixed_io.address,
+ res->data.fixed_io.address_length);
+ break;
+
+ case ACPI_RESOURCE_TYPE_VENDOR:
break;
- case ACPI_RSTYPE_MEM32:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.memory32.min_base_address,
- res->data.memory32.range_length);
+
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ break;
+
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ pnpacpi_parse_allocated_memresource(res_table,
+ res->data.memory24.minimum,
+ res->data.memory24.address_length);
break;
- case ACPI_RSTYPE_FIXED_MEM32:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.fixed_memory32.range_base_address,
- res->data.fixed_memory32.range_length);
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+ pnpacpi_parse_allocated_memresource(res_table,
+ res->data.memory32.minimum,
+ res->data.memory32.address_length);
break;
- case ACPI_RSTYPE_ADDRESS16:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.address16.min_address_range,
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+ pnpacpi_parse_allocated_memresource(res_table,
+ res->data.fixed_memory32.address,
+ res->data.fixed_memory32.address_length);
+ break;
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ pnpacpi_parse_allocated_memresource(res_table,
+ res->data.address16.minimum,
res->data.address16.address_length);
break;
- case ACPI_RSTYPE_ADDRESS32:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.address32.min_address_range,
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ pnpacpi_parse_allocated_memresource(res_table,
+ res->data.address32.minimum,
res->data.address32.address_length);
break;
- case ACPI_RSTYPE_ADDRESS64:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.address64.min_address_range,
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ pnpacpi_parse_allocated_memresource(res_table,
+ res->data.address64.minimum,
res->data.address64.address_length);
break;
- case ACPI_RSTYPE_VENDOR:
+
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ break;
+
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
+ pnpacpi_parse_allocated_irqresource(res_table,
+ res->data.extended_irq.interrupts[i],
+ res->data.extended_irq.triggering,
+ res->data.extended_irq.polarity);
+ }
+ break;
+
+ case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
break;
+
default:
- pnp_warn("PnPACPI: unknown resource type %d", res->id);
+ pnp_warn("PnPACPI: unknown resource type %d", res->type);
return AE_ERROR;
}
@@ -253,13 +272,13 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso
int i;
struct pnp_dma * dma;
- if (p->number_of_channels == 0)
+ if (p->channel_count == 0)
return;
dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
- for(i = 0; i < p->number_of_channels; i++)
+ for(i = 0; i < p->channel_count; i++)
dma->map |= 1 << p->channels[i];
dma->flags = 0;
if (p->bus_master)
@@ -309,37 +328,37 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option,
int i;
struct pnp_irq * irq;
- if (p->number_of_interrupts == 0)
+ if (p->interrupt_count == 0)
return;
irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
- for(i = 0; i < p->number_of_interrupts; i++)
+ for(i = 0; i < p->interrupt_count; i++)
if (p->interrupts[i])
__set_bit(p->interrupts[i], irq->map);
- irq->flags = irq_flags(p->edge_level, p->active_high_low);
+ irq->flags = irq_flags(p->triggering, p->polarity);
pnp_register_irq_resource(option, irq);
return;
}
static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
- struct acpi_resource_ext_irq *p)
+ struct acpi_resource_extended_irq *p)
{
int i;
struct pnp_irq * irq;
- if (p->number_of_interrupts == 0)
+ if (p->interrupt_count == 0)
return;
irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
- for(i = 0; i < p->number_of_interrupts; i++)
+ for(i = 0; i < p->interrupt_count; i++)
if (p->interrupts[i])
__set_bit(p->interrupts[i], irq->map);
- irq->flags = irq_flags(p->edge_level, p->active_high_low);
+ irq->flags = irq_flags(p->triggering, p->polarity);
pnp_register_irq_resource(option, irq);
return;
@@ -351,16 +370,16 @@ pnpacpi_parse_port_option(struct pnp_option *option,
{
struct pnp_port * port;
- if (io->range_length == 0)
+ if (io->address_length == 0)
return;
port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
- port->min = io->min_base_address;
- port->max = io->max_base_address;
+ port->min = io->minimum;
+ port->max = io->maximum;
port->align = io->alignment;
- port->size = io->range_length;
- port->flags = ACPI_DECODE_16 == io->io_decode ?
+ port->size = io->address_length;
+ port->flags = ACPI_DECODE_16 == io->io_decode ?
PNP_PORT_FLAG_16BITADDR : 0;
pnp_register_port_resource(option,port);
return;
@@ -372,13 +391,13 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option,
{
struct pnp_port * port;
- if (io->range_length == 0)
+ if (io->address_length == 0)
return;
port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
- port->min = port->max = io->base_address;
- port->size = io->range_length;
+ port->min = port->max = io->address;
+ port->size = io->address_length;
port->align = 0;
port->flags = PNP_PORT_FLAG_FIXED;
pnp_register_port_resource(option,port);
@@ -387,21 +406,21 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option,
static void
pnpacpi_parse_mem24_option(struct pnp_option *option,
- struct acpi_resource_mem24 *p)
+ struct acpi_resource_memory24 *p)
{
struct pnp_mem * mem;
- if (p->range_length == 0)
+ if (p->address_length == 0)
return;
mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
- mem->min = p->min_base_address;
- mem->max = p->max_base_address;
+ mem->min = p->minimum;
+ mem->max = p->maximum;
mem->align = p->alignment;
- mem->size = p->range_length;
+ mem->size = p->address_length;
- mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
+ mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0;
pnp_register_mem_resource(option,mem);
@@ -410,21 +429,21 @@ pnpacpi_parse_mem24_option(struct pnp_option *option,
static void
pnpacpi_parse_mem32_option(struct pnp_option *option,
- struct acpi_resource_mem32 *p)
+ struct acpi_resource_memory32 *p)
{
struct pnp_mem * mem;
- if (p->range_length == 0)
+ if (p->address_length == 0)
return;
mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
- mem->min = p->min_base_address;
- mem->max = p->max_base_address;
+ mem->min = p->minimum;
+ mem->max = p->maximum;
mem->align = p->alignment;
- mem->size = p->range_length;
+ mem->size = p->address_length;
- mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
+ mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0;
pnp_register_mem_resource(option,mem);
@@ -433,33 +452,72 @@ pnpacpi_parse_mem32_option(struct pnp_option *option,
static void
pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
- struct acpi_resource_fixed_mem32 *p)
+ struct acpi_resource_fixed_memory32 *p)
{
struct pnp_mem * mem;
- if (p->range_length == 0)
+ if (p->address_length == 0)
return;
mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
- mem->min = mem->max = p->range_base_address;
- mem->size = p->range_length;
+ mem->min = mem->max = p->address;
+ mem->size = p->address_length;
mem->align = 0;
- mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
+ mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0;
pnp_register_mem_resource(option,mem);
return;
}
+static void
+pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r)
+{
+ struct acpi_resource_address64 addr, *p = &addr;
+ acpi_status status;
+ struct pnp_mem * mem;
+ struct pnp_port * port;
+
+ status = acpi_resource_to_address64(r, p);
+ if (!ACPI_SUCCESS(status)) {
+ pnp_warn("PnPACPI: failed to convert resource type %d", r->type);
+ return;
+ }
+
+ if (p->address_length == 0)
+ return;
+
+ if (p->resource_type == ACPI_MEMORY_RANGE) {
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ if (!mem)
+ return;
+ mem->min = mem->max = p->minimum;
+ mem->size = p->address_length;
+ mem->align = 0;
+ mem->flags = (p->info.mem.write_protect ==
+ ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0;
+ pnp_register_mem_resource(option,mem);
+ } else if (p->resource_type == ACPI_IO_RANGE) {
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ if (!port)
+ return;
+ port->min = port->max = p->minimum;
+ port->size = p->address_length;
+ port->align = 0;
+ port->flags = PNP_PORT_FLAG_FIXED;
+ pnp_register_port_resource(option,port);
+ }
+}
+
struct acpipnp_parse_option_s {
struct pnp_option *option;
struct pnp_option *option_independent;
struct pnp_dev *dev;
};
-static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
+static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
void *data)
{
int priority = 0;
@@ -467,35 +525,16 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
struct pnp_dev *dev = parse_data->dev;
struct pnp_option *option = parse_data->option;
- switch (res->id) {
- case ACPI_RSTYPE_IRQ:
+ switch (res->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
pnpacpi_parse_irq_option(option, &res->data.irq);
break;
- case ACPI_RSTYPE_EXT_IRQ:
- pnpacpi_parse_ext_irq_option(option,
- &res->data.extended_irq);
- break;
- case ACPI_RSTYPE_DMA:
+
+ case ACPI_RESOURCE_TYPE_DMA:
pnpacpi_parse_dma_option(option, &res->data.dma);
break;
- case ACPI_RSTYPE_IO:
- pnpacpi_parse_port_option(option, &res->data.io);
- break;
- case ACPI_RSTYPE_FIXED_IO:
- pnpacpi_parse_fixed_port_option(option,
- &res->data.fixed_io);
- break;
- case ACPI_RSTYPE_MEM24:
- pnpacpi_parse_mem24_option(option, &res->data.memory24);
- break;
- case ACPI_RSTYPE_MEM32:
- pnpacpi_parse_mem32_option(option, &res->data.memory32);
- break;
- case ACPI_RSTYPE_FIXED_MEM32:
- pnpacpi_parse_fixed_mem32_option(option,
- &res->data.fixed_memory32);
- break;
- case ACPI_RSTYPE_START_DPF:
+
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
switch (res->data.start_dpf.compatibility_priority) {
case ACPI_GOOD_CONFIGURATION:
priority = PNP_RES_PRIORITY_PREFERRED;
@@ -518,7 +557,8 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
return AE_ERROR;
parse_data->option = option;
break;
- case ACPI_RSTYPE_END_DPF:
+
+ case ACPI_RESOURCE_TYPE_END_DEPENDENT:
/*only one EndDependentFn is allowed*/
if (!parse_data->option_independent) {
pnp_warn("PnPACPI: more than one EndDependentFn");
@@ -527,15 +567,59 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
parse_data->option = parse_data->option_independent;
parse_data->option_independent = NULL;
break;
+
+ case ACPI_RESOURCE_TYPE_IO:
+ pnpacpi_parse_port_option(option, &res->data.io);
+ break;
+
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+ pnpacpi_parse_fixed_port_option(option,
+ &res->data.fixed_io);
+ break;
+
+ case ACPI_RESOURCE_TYPE_VENDOR:
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ break;
+
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ pnpacpi_parse_mem24_option(option, &res->data.memory24);
+ break;
+
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+ pnpacpi_parse_mem32_option(option, &res->data.memory32);
+ break;
+
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+ pnpacpi_parse_fixed_mem32_option(option,
+ &res->data.fixed_memory32);
+ break;
+
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ pnpacpi_parse_address_option(option, res);
+ break;
+
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ break;
+
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ pnpacpi_parse_ext_irq_option(option,
+ &res->data.extended_irq);
+ break;
+
+ case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
+ break;
+
default:
- pnp_warn("PnPACPI: unknown resource type %d", res->id);
+ pnp_warn("PnPACPI: unknown resource type %d", res->type);
return AE_ERROR;
}
return AE_OK;
}
-acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
+acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
struct pnp_dev *dev)
{
acpi_status status;
@@ -546,7 +630,7 @@ acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
return AE_ERROR;
parse_data.option_independent = parse_data.option;
parse_data.dev = dev;
- status = acpi_walk_resources(handle, METHOD_NAME__PRS,
+ status = acpi_walk_resources(handle, METHOD_NAME__PRS,
pnpacpi_option_resource, &parse_data);
return status;
@@ -559,21 +643,24 @@ static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
void *data)
{
int *res_cnt = (int *)data;
- switch (res->id) {
- case ACPI_RSTYPE_IRQ:
- case ACPI_RSTYPE_EXT_IRQ:
- case ACPI_RSTYPE_DMA:
- case ACPI_RSTYPE_IO:
- case ACPI_RSTYPE_FIXED_IO:
- case ACPI_RSTYPE_MEM24:
- case ACPI_RSTYPE_MEM32:
- case ACPI_RSTYPE_FIXED_MEM32:
-#if 0
- case ACPI_RSTYPE_ADDRESS16:
- case ACPI_RSTYPE_ADDRESS32:
- case ACPI_RSTYPE_ADDRESS64:
-#endif
+ switch (res->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
+ case ACPI_RESOURCE_TYPE_DMA:
+ case ACPI_RESOURCE_TYPE_IO:
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
(*res_cnt) ++;
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_VENDOR:
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
default:
return AE_OK;
}
@@ -584,22 +671,25 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res,
void *data)
{
struct acpi_resource **resource = (struct acpi_resource **)data;
- switch (res->id) {
- case ACPI_RSTYPE_IRQ:
- case ACPI_RSTYPE_EXT_IRQ:
- case ACPI_RSTYPE_DMA:
- case ACPI_RSTYPE_IO:
- case ACPI_RSTYPE_FIXED_IO:
- case ACPI_RSTYPE_MEM24:
- case ACPI_RSTYPE_MEM32:
- case ACPI_RSTYPE_FIXED_MEM32:
-#if 0
- case ACPI_RSTYPE_ADDRESS16:
- case ACPI_RSTYPE_ADDRESS32:
- case ACPI_RSTYPE_ADDRESS64:
-#endif
- (*resource)->id = res->id;
+ switch (res->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
+ case ACPI_RESOURCE_TYPE_DMA:
+ case ACPI_RESOURCE_TYPE_IO:
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ (*resource)->type = res->type;
(*resource)++;
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_VENDOR:
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
default:
return AE_OK;
}
@@ -607,14 +697,14 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res,
return AE_OK;
}
-int pnpacpi_build_resource_template(acpi_handle handle,
+int pnpacpi_build_resource_template(acpi_handle handle,
struct acpi_buffer *buffer)
{
struct acpi_resource *resource;
int res_cnt = 0;
acpi_status status;
- status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+ status = acpi_walk_resources(handle, METHOD_NAME__CRS,
pnpacpi_count_resources, &res_cnt);
if (ACPI_FAILURE(status)) {
pnp_err("Evaluate _CRS failed");
@@ -628,7 +718,7 @@ int pnpacpi_build_resource_template(acpi_handle handle,
return -ENOMEM;
pnp_dbg("Res cnt %d", res_cnt);
resource = (struct acpi_resource *)buffer->pointer;
- status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+ status = acpi_walk_resources(handle, METHOD_NAME__CRS,
pnpacpi_type_resources, &resource);
if (ACPI_FAILURE(status)) {
kfree(buffer->pointer);
@@ -636,54 +726,54 @@ int pnpacpi_build_resource_template(acpi_handle handle,
return -EINVAL;
}
/* resource will pointer the end resource now */
- resource->id = ACPI_RSTYPE_END_TAG;
+ resource->type = ACPI_RESOURCE_TYPE_END_TAG;
return 0;
}
-static void pnpacpi_encode_irq(struct acpi_resource *resource,
+static void pnpacpi_encode_irq(struct acpi_resource *resource,
struct resource *p)
{
- int edge_level, active_high_low;
+ int triggering, polarity;
- decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level,
- &active_high_low);
- resource->id = ACPI_RSTYPE_IRQ;
+ decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
+ &polarity);
+ resource->type = ACPI_RESOURCE_TYPE_IRQ;
resource->length = sizeof(struct acpi_resource);
- resource->data.irq.edge_level = edge_level;
- resource->data.irq.active_high_low = active_high_low;
- if (edge_level == ACPI_EDGE_SENSITIVE)
- resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+ resource->data.irq.triggering = triggering;
+ resource->data.irq.polarity = polarity;
+ if (triggering == ACPI_EDGE_SENSITIVE)
+ resource->data.irq.sharable = ACPI_EXCLUSIVE;
else
- resource->data.irq.shared_exclusive = ACPI_SHARED;
- resource->data.irq.number_of_interrupts = 1;
+ resource->data.irq.sharable = ACPI_SHARED;
+ resource->data.irq.interrupt_count = 1;
resource->data.irq.interrupts[0] = p->start;
}
static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
struct resource *p)
{
- int edge_level, active_high_low;
+ int triggering, polarity;
- decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level,
- &active_high_low);
- resource->id = ACPI_RSTYPE_EXT_IRQ;
+ decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
+ &polarity);
+ resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
resource->length = sizeof(struct acpi_resource);
resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
- resource->data.extended_irq.edge_level = edge_level;
- resource->data.extended_irq.active_high_low = active_high_low;
- if (edge_level == ACPI_EDGE_SENSITIVE)
- resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+ resource->data.extended_irq.triggering = triggering;
+ resource->data.extended_irq.polarity = polarity;
+ if (triggering == ACPI_EDGE_SENSITIVE)
+ resource->data.irq.sharable = ACPI_EXCLUSIVE;
else
- resource->data.irq.shared_exclusive = ACPI_SHARED;
- resource->data.extended_irq.number_of_interrupts = 1;
+ resource->data.irq.sharable = ACPI_SHARED;
+ resource->data.extended_irq.interrupt_count = 1;
resource->data.extended_irq.interrupts[0] = p->start;
}
static void pnpacpi_encode_dma(struct acpi_resource *resource,
struct resource *p)
{
- resource->id = ACPI_RSTYPE_DMA;
+ resource->type = ACPI_RESOURCE_TYPE_DMA;
resource->length = sizeof(struct acpi_resource);
/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
if (p->flags & IORESOURCE_DMA_COMPATIBLE)
@@ -701,75 +791,75 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource,
else if (p->flags & IORESOURCE_DMA_16BIT)
resource->data.dma.transfer = ACPI_TRANSFER_16;
resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER;
- resource->data.dma.number_of_channels = 1;
+ resource->data.dma.channel_count = 1;
resource->data.dma.channels[0] = p->start;
}
static void pnpacpi_encode_io(struct acpi_resource *resource,
struct resource *p)
{
- resource->id = ACPI_RSTYPE_IO;
+ resource->type = ACPI_RESOURCE_TYPE_IO;
resource->length = sizeof(struct acpi_resource);
/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)?
- ACPI_DECODE_16 : ACPI_DECODE_10;
- resource->data.io.min_base_address = p->start;
- resource->data.io.max_base_address = p->end;
+ ACPI_DECODE_16 : ACPI_DECODE_10;
+ resource->data.io.minimum = p->start;
+ resource->data.io.maximum = p->end;
resource->data.io.alignment = 0; /* Correct? */
- resource->data.io.range_length = p->end - p->start + 1;
+ resource->data.io.address_length = p->end - p->start + 1;
}
static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
struct resource *p)
{
- resource->id = ACPI_RSTYPE_FIXED_IO;
+ resource->type = ACPI_RESOURCE_TYPE_FIXED_IO;
resource->length = sizeof(struct acpi_resource);
- resource->data.fixed_io.base_address = p->start;
- resource->data.fixed_io.range_length = p->end - p->start + 1;
+ resource->data.fixed_io.address = p->start;
+ resource->data.fixed_io.address_length = p->end - p->start + 1;
}
static void pnpacpi_encode_mem24(struct acpi_resource *resource,
struct resource *p)
{
- resource->id = ACPI_RSTYPE_MEM24;
+ resource->type = ACPI_RESOURCE_TYPE_MEMORY24;
resource->length = sizeof(struct acpi_resource);
/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
- resource->data.memory24.read_write_attribute =
+ resource->data.memory24.write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
- resource->data.memory24.min_base_address = p->start;
- resource->data.memory24.max_base_address = p->end;
+ resource->data.memory24.minimum = p->start;
+ resource->data.memory24.maximum = p->end;
resource->data.memory24.alignment = 0;
- resource->data.memory24.range_length = p->end - p->start + 1;
+ resource->data.memory24.address_length = p->end - p->start + 1;
}
static void pnpacpi_encode_mem32(struct acpi_resource *resource,
struct resource *p)
{
- resource->id = ACPI_RSTYPE_MEM32;
+ resource->type = ACPI_RESOURCE_TYPE_MEMORY32;
resource->length = sizeof(struct acpi_resource);
- resource->data.memory32.read_write_attribute =
+ resource->data.memory32.write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
- resource->data.memory32.min_base_address = p->start;
- resource->data.memory32.max_base_address = p->end;
+ resource->data.memory32.minimum = p->start;
+ resource->data.memory32.maximum = p->end;
resource->data.memory32.alignment = 0;
- resource->data.memory32.range_length = p->end - p->start + 1;
+ resource->data.memory32.address_length = p->end - p->start + 1;
}
static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
struct resource *p)
{
- resource->id = ACPI_RSTYPE_FIXED_MEM32;
+ resource->type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32;
resource->length = sizeof(struct acpi_resource);
- resource->data.fixed_memory32.read_write_attribute =
+ resource->data.fixed_memory32.write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
- resource->data.fixed_memory32.range_base_address = p->start;
- resource->data.fixed_memory32.range_length = p->end - p->start + 1;
+ resource->data.fixed_memory32.address = p->start;
+ resource->data.fixed_memory32.address_length = p->end - p->start + 1;
}
-int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
+int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
struct acpi_buffer *buffer)
{
int i = 0;
@@ -780,58 +870,67 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
pnp_dbg("res cnt %d", res_cnt);
while (i < res_cnt) {
- switch(resource->id) {
- case ACPI_RSTYPE_IRQ:
+ switch(resource->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
pnp_dbg("Encode irq");
- pnpacpi_encode_irq(resource,
+ pnpacpi_encode_irq(resource,
&res_table->irq_resource[irq]);
irq++;
break;
- case ACPI_RSTYPE_EXT_IRQ:
- pnp_dbg("Encode ext irq");
- pnpacpi_encode_ext_irq(resource,
- &res_table->irq_resource[irq]);
- irq++;
- break;
- case ACPI_RSTYPE_DMA:
+ case ACPI_RESOURCE_TYPE_DMA:
pnp_dbg("Encode dma");
- pnpacpi_encode_dma(resource,
+ pnpacpi_encode_dma(resource,
&res_table->dma_resource[dma]);
dma ++;
break;
- case ACPI_RSTYPE_IO:
+ case ACPI_RESOURCE_TYPE_IO:
pnp_dbg("Encode io");
- pnpacpi_encode_io(resource,
+ pnpacpi_encode_io(resource,
&res_table->port_resource[port]);
port ++;
break;
- case ACPI_RSTYPE_FIXED_IO:
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
pnp_dbg("Encode fixed io");
pnpacpi_encode_fixed_io(resource,
&res_table->port_resource[port]);
port ++;
break;
- case ACPI_RSTYPE_MEM24:
+ case ACPI_RESOURCE_TYPE_MEMORY24:
pnp_dbg("Encode mem24");
pnpacpi_encode_mem24(resource,
&res_table->mem_resource[mem]);
mem ++;
break;
- case ACPI_RSTYPE_MEM32:
+ case ACPI_RESOURCE_TYPE_MEMORY32:
pnp_dbg("Encode mem32");
pnpacpi_encode_mem32(resource,
&res_table->mem_resource[mem]);
mem ++;
break;
- case ACPI_RSTYPE_FIXED_MEM32:
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
pnp_dbg("Encode fixed mem32");
pnpacpi_encode_fixed_mem32(resource,
&res_table->mem_resource[mem]);
mem ++;
break;
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ pnp_dbg("Encode ext irq");
+ pnpacpi_encode_ext_irq(resource,
+ &res_table->irq_resource[irq]);
+ irq++;
+ break;
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_VENDOR:
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
default: /* other type */
- pnp_warn("unknown resource type %d", resource->id);
+ pnp_warn("unknown resource type %d", resource->type);
return -EINVAL;
}
resource ++;
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig
index a86a650f3d6..721787cc5a1 100644
--- a/drivers/s390/Kconfig
+++ b/drivers/s390/Kconfig
@@ -51,6 +51,13 @@ config UNIX98_PTY_COUNT
When not in use, each additional set of 256 PTYs occupy
approximately 8 KB of kernel memory on 32-bit architectures.
+config HANGCHECK_TIMER
+ tristate "Hangcheck timer"
+ help
+ The hangcheck-timer module detects when the system has gone
+ out to lunch past a certain margin. It can reboot the system
+ or merely print a warning.
+
source "drivers/char/watchdog/Kconfig"
comment "S/390 character device drivers"
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index ef4c687e7c0..af1d5b404ce 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.172 $
*/
#include <linux/config.h>
@@ -153,7 +152,12 @@ static inline void
dasd_state_known_to_new(struct dasd_device * device)
{
/* Forget the discipline information. */
+ if (device->discipline)
+ module_put(device->discipline->owner);
device->discipline = NULL;
+ if (device->base_discipline)
+ module_put(device->base_discipline->owner);
+ device->base_discipline = NULL;
device->state = DASD_STATE_NEW;
dasd_free_queue(device);
@@ -675,11 +679,8 @@ dasd_term_IO(struct dasd_ccw_req * cqr)
rc = ccw_device_clear(device->cdev, (long) cqr);
switch (rc) {
case 0: /* termination successful */
- if (cqr->retries > 0) {
- cqr->retries--;
- cqr->status = DASD_CQR_CLEAR;
- } else
- cqr->status = DASD_CQR_FAILED;
+ cqr->retries--;
+ cqr->status = DASD_CQR_CLEAR;
cqr->stopclk = get_clock();
DBF_DEV_EVENT(DBF_DEBUG, device,
"terminate cqr %p successful",
@@ -1308,7 +1309,7 @@ dasd_tasklet(struct dasd_device * device)
/* Now call the callback function of requests with final status */
list_for_each_safe(l, n, &final_queue) {
cqr = list_entry(l, struct dasd_ccw_req, list);
- list_del(&cqr->list);
+ list_del_init(&cqr->list);
if (cqr->callback != NULL)
(cqr->callback)(cqr, cqr->callback_data);
}
@@ -1393,7 +1394,9 @@ _wait_for_wakeup(struct dasd_ccw_req *cqr)
device = cqr->device;
spin_lock_irq(get_ccwdev_lock(device->cdev));
- rc = cqr->status == DASD_CQR_DONE || cqr->status == DASD_CQR_FAILED;
+ rc = ((cqr->status == DASD_CQR_DONE ||
+ cqr->status == DASD_CQR_FAILED) &&
+ list_empty(&cqr->list));
spin_unlock_irq(get_ccwdev_lock(device->cdev));
return rc;
}
@@ -1457,15 +1460,37 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr)
while (!finished) {
rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr));
if (rc != -ERESTARTSYS) {
- /* Request status is either done or failed. */
- rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
+ /* Request is final (done or failed) */
+ rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
break;
}
spin_lock_irq(get_ccwdev_lock(device->cdev));
- if (cqr->status == DASD_CQR_IN_IO &&
- device->discipline->term_IO(cqr) == 0) {
- list_del(&cqr->list);
+ switch (cqr->status) {
+ case DASD_CQR_IN_IO:
+ /* terminate runnig cqr */
+ if (device->discipline->term_IO) {
+ cqr->retries = -1;
+ device->discipline->term_IO(cqr);
+ /*nished =
+ * wait (non-interruptible) for final status
+ * because signal ist still pending
+ */
+ spin_unlock_irq(get_ccwdev_lock(device->cdev));
+ wait_event(wait_q, _wait_for_wakeup(cqr));
+ spin_lock_irq(get_ccwdev_lock(device->cdev));
+ rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
+ finished = 1;
+ }
+ break;
+ case DASD_CQR_QUEUED:
+ /* request */
+ list_del_init(&cqr->list);
+ rc = -EIO;
finished = 1;
+ break;
+ default:
+ /* cqr with 'non-interruptable' status - just wait */
+ break;
}
spin_unlock_irq(get_ccwdev_lock(device->cdev));
}
@@ -1839,9 +1864,10 @@ dasd_generic_remove (struct ccw_device *cdev)
*/
int
dasd_generic_set_online (struct ccw_device *cdev,
- struct dasd_discipline *discipline)
+ struct dasd_discipline *base_discipline)
{
+ struct dasd_discipline *discipline;
struct dasd_device *device;
int rc;
@@ -1849,6 +1875,7 @@ dasd_generic_set_online (struct ccw_device *cdev,
if (IS_ERR(device))
return PTR_ERR(device);
+ discipline = base_discipline;
if (device->features & DASD_FEATURE_USEDIAG) {
if (!dasd_diag_discipline_pointer) {
printk (KERN_WARNING
@@ -1860,6 +1887,16 @@ dasd_generic_set_online (struct ccw_device *cdev,
}
discipline = dasd_diag_discipline_pointer;
}
+ if (!try_module_get(base_discipline->owner)) {
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+ if (!try_module_get(discipline->owner)) {
+ module_put(base_discipline->owner);
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+ device->base_discipline = base_discipline;
device->discipline = discipline;
rc = discipline->check_device(device);
@@ -1868,6 +1905,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
"dasd_generic couldn't online device %s "
"with discipline %s rc=%i\n",
cdev->dev.bus_id, discipline->name, rc);
+ module_put(discipline->owner);
+ module_put(base_discipline->owner);
dasd_delete_device(device);
return rc;
}
diff --git a/drivers/s390/block/dasd_3370_erp.c b/drivers/s390/block/dasd_3370_erp.c
index 84565c8f584..1d11c2a9525 100644
--- a/drivers/s390/block/dasd_3370_erp.c
+++ b/drivers/s390/block/dasd_3370_erp.c
@@ -4,7 +4,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
- * $Revision: 1.9 $
*/
#define PRINTK_HEADER "dasd_erp(3370)"
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index c143ecb53d9..4ee0f934e32 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -5,7 +5,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
*
- * $Revision: 1.36 $
*/
#include <linux/timer.h>
diff --git a/drivers/s390/block/dasd_9336_erp.c b/drivers/s390/block/dasd_9336_erp.c
index 01e87170a3a..dc861446d05 100644
--- a/drivers/s390/block/dasd_9336_erp.c
+++ b/drivers/s390/block/dasd_9336_erp.c
@@ -4,7 +4,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
- * $Revision: 1.8 $
*/
#define PRINTK_HEADER "dasd_erp(9336)"
diff --git a/drivers/s390/block/dasd_9343_erp.c b/drivers/s390/block/dasd_9343_erp.c
index 2a23b74faf3..4a5b79569aa 100644
--- a/drivers/s390/block/dasd_9343_erp.c
+++ b/drivers/s390/block/dasd_9343_erp.c
@@ -4,7 +4,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
- * $Revision: 1.13 $
*/
#define PRINTK_HEADER "dasd_erp(9343)"
diff --git a/drivers/s390/block/dasd_cmb.c b/drivers/s390/block/dasd_cmb.c
index 4f365bff275..e88f73ee72c 100644
--- a/drivers/s390/block/dasd_cmb.c
+++ b/drivers/s390/block/dasd_cmb.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.9 $)
- *
* Linux on zSeries Channel Measurement Facility support
* (dasd device driver interface)
*
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index caee16a3dc6..1629b27c48a 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -11,7 +11,6 @@
* functions may not be called from interrupt context. In particular
* dasd_get_device is a no-no from interrupt context.
*
- * $Revision: 1.43 $
*/
#include <linux/config.h>
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index ba80fdea7eb..3f9d704d265 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,7 +6,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.53 $
*/
#include <linux/config.h>
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index a4f80bd735f..38a4e55f895 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -6,7 +6,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.9 $
*/
#define MDSK_WRITE_REQ 0x01
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 96eb4825858..822e2a26557 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -7,7 +7,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.74 $
*/
#include <linux/config.h>
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index b6888c68b22..bc3823d3522 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -5,7 +5,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.10 $
*/
#ifndef DASD_ECKD_H
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 7cb98d25f34..8fd71ab02ef 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -7,7 +7,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.14 $
*/
#include <linux/config.h>
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 8ec75dc08e2..91145698f8e 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -4,7 +4,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.41 $
*/
#include <linux/config.h>
diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h
index 624f0402ee2..da1fa91fc01 100644
--- a/drivers/s390/block/dasd_fba.h
+++ b/drivers/s390/block/dasd_fba.h
@@ -4,7 +4,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.6 $
*/
#ifndef DASD_FBA_H
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index a601c9a3354..65dc844b975 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -9,7 +9,6 @@
*
* gendisk related functions for the dasd driver.
*
- * $Revision: 1.51 $
*/
#include <linux/config.h>
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index e4b401500b0..0592354cc60 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.68 $
*/
#ifndef DASD_INT_H
@@ -291,6 +290,7 @@ struct dasd_device {
/* Device discipline stuff. */
struct dasd_discipline *discipline;
+ struct dasd_discipline *base_discipline;
char *private;
/* Device state and target state. */
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 9396fcacb8f..fafeeae5267 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,8 +7,6 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.50 $
- *
* i/o controls for the dasd driver.
*/
#include <linux/config.h>
@@ -423,8 +421,15 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
dasd_info->cu_model = cdev->id.cu_model;
dasd_info->dev_type = cdev->id.dev_type;
dasd_info->dev_model = cdev->id.dev_model;
- dasd_info->open_count = atomic_read(&device->open_count);
dasd_info->status = device->state;
+ /*
+ * The open_count is increased for every opener, that includes
+ * the blkdev_get in dasd_scan_partitions.
+ * This must be hidden from user-space.
+ */
+ dasd_info->open_count = atomic_read(&device->open_count);
+ if (!device->bdev)
+ dasd_info->open_count++;
/*
* check if device is really formatted
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index fff9020d488..2d5da3c75ca 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,7 +9,6 @@
*
* /proc interface for the dasd driver.
*
- * $Revision: 1.33 $
*/
#include <linux/config.h>
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 1f060914cfa..606f6ad285a 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/interrupt.h>
+#include <linux/err.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
@@ -864,7 +865,7 @@ con3215_init(void)
}
cdev = ccw_device_probe_console();
- if (!cdev)
+ if (IS_ERR(cdev))
return -ENODEV;
raw3215[0] = raw = (struct raw3215_info *)
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index c570a9f6ce9..ef607a1de55 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/types.h>
+#include <linux/err.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
@@ -597,7 +598,7 @@ con3270_init(void)
}
cdev = ccw_device_probe_console();
- if (!cdev)
+ if (IS_ERR(cdev))
return -ENODEV;
rp = raw3270_setup_console(cdev);
if (IS_ERR(rp))
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 5bda2340a39..a317a123dab 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -440,7 +440,11 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
return -EPERM;
len = strnlen_user(u_kbs->kb_string,
sizeof(u_kbs->kb_string) - 1);
- p = kmalloc(len, GFP_KERNEL);
+ if (!len)
+ return -EFAULT;
+ if (len > sizeof(u_kbs->kb_string) - 1)
+ return -EINVAL;
+ p = kmalloc(len + 1, GFP_KERNEL);
if (!p)
return -ENOMEM;
if (copy_from_user(p, u_kbs->kb_string, len)) {
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index ceb0e474fde..4138564402b 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -85,11 +85,10 @@ static volatile enum sclp_mask_state_t {
/* Maximum retry counts */
#define SCLP_INIT_RETRY 3
#define SCLP_MASK_RETRY 3
-#define SCLP_REQUEST_RETRY 3
/* Timeout intervals in seconds.*/
-#define SCLP_BUSY_INTERVAL 2
-#define SCLP_RETRY_INTERVAL 5
+#define SCLP_BUSY_INTERVAL 10
+#define SCLP_RETRY_INTERVAL 15
static void sclp_process_queue(void);
static int sclp_init_mask(int calculate);
@@ -153,11 +152,9 @@ __sclp_start_request(struct sclp_req *req)
if (sclp_running_state != sclp_running_state_idle)
return 0;
del_timer(&sclp_request_timer);
- if (req->start_count <= SCLP_REQUEST_RETRY) {
- rc = service_call(req->command, req->sccb);
- req->start_count++;
- } else
- rc = -EIO;
+ rc = service_call(req->command, req->sccb);
+ req->start_count++;
+
if (rc == 0) {
/* Sucessfully started request */
req->status = SCLP_REQ_RUNNING;
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 20be88e91fa..682039cac15 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1357,7 +1357,7 @@ tape_34xx_init (void)
debug_set_level(TAPE_DBF_AREA, 6);
#endif
- DBF_EVENT(3, "34xx init: $Revision: 1.23 $\n");
+ DBF_EVENT(3, "34xx init\n");
/* Register driver for 3480/3490 tapes. */
rc = ccw_driver_register(&tape_34xx_driver);
if (rc)
@@ -1377,8 +1377,7 @@ tape_34xx_exit(void)
MODULE_DEVICE_TABLE(ccw, tape_34xx_ids);
MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH");
-MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape "
- "device driver ($Revision: 1.23 $)");
+MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape device driver");
MODULE_LICENSE("GPL");
module_init(tape_34xx_init);
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index fcaee447d6f..b3569c82bb1 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -1,6 +1,6 @@
/*
* (C) Copyright IBM Corp. 2004
- * tape_class.c ($Revision: 1.8 $)
+ * tape_class.c
*
* Tape class device support
*
@@ -12,7 +12,7 @@
MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
MODULE_DESCRIPTION(
"(C) Copyright IBM Corp. 2004 All Rights Reserved.\n"
- "tape_class.c ($Revision: 1.8 $)"
+ "tape_class.c"
);
MODULE_LICENSE("GPL");
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index 33133ad00ba..3d0ca054cde 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -1,6 +1,6 @@
/*
* (C) Copyright IBM Corp. 2004 All Rights Reserved.
- * tape_class.h ($Revision: 1.4 $)
+ * tape_class.h
*
* Tape class device support
*
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 8f486e1a850..4ea438c749c 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -1239,7 +1239,7 @@ tape_init (void)
#ifdef DBF_LIKE_HELL
debug_set_level(TAPE_DBF_AREA, 6);
#endif
- DBF_EVENT(3, "tape init: ($Revision: 1.54 $)\n");
+ DBF_EVENT(3, "tape init\n");
tape_proc_init();
tapechar_init ();
tapeblock_init ();
@@ -1263,8 +1263,7 @@ tape_exit(void)
MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and "
"Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)");
-MODULE_DESCRIPTION("Linux on zSeries channel attached "
- "tape device driver ($Revision: 1.54 $)");
+MODULE_DESCRIPTION("Linux on zSeries channel attached tape device driver");
MODULE_LICENSE("GPL");
module_init(tape_init);
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index cd2cc28e16a..5287631fbfc 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -2,8 +2,6 @@
* drivers/s390/cio/airq.c
* S/390 common I/O routines -- support for adapter interruptions
*
- * $Revision: 1.15 $
- *
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 72f27c151c0..cb8e2e672b6 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,6 @@
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
- * $Revision: 1.42 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 6c077ad71ed..8013c8eb76f 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,7 +1,6 @@
/*
* drivers/s390/cio/ccwgroup.c
* bus driver for ccwgroup
- * $Revision: 1.35 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 2cbb724791a..8cf9905d484 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,7 +1,6 @@
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
- * $Revision: 1.128 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -233,7 +232,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
return 0;
mask = 0x80 >> j;
- spin_lock(&sch->lock);
+ spin_lock_irq(&sch->lock);
stsch(sch->schid, &schib);
if (!schib.pmcw.dnv)
@@ -282,10 +281,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
out_unlock:
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
out_unreg:
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
sch->lpm = 0;
if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
@@ -653,7 +652,7 @@ __chp_add(struct subchannel_id schid, void *data)
if (!sch)
/* Check if the subchannel is now available. */
return __chp_add_new_sch(schid);
- spin_lock(&sch->lock);
+ spin_lock_irq(&sch->lock);
for (i=0; i<8; i++)
if (sch->schib.pmcw.chpid[i] == chp->id) {
if (stsch(sch->schid, &sch->schib) != 0) {
@@ -675,7 +674,7 @@ __chp_add(struct subchannel_id schid, void *data)
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
put_device(&sch->dev);
return 0;
}
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 44e4b4bb1c5..3e75095f35d 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -68,6 +68,6 @@ extern void *chsc_get_chp_desc(struct subchannel*, int);
extern int chsc_enable_facility(int);
-#define to_channelpath(dev) container_of(dev, struct channel_path, dev)
+#define to_channelpath(device) container_of(device, struct channel_path, dev)
#endif
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 6223b06d27d..cbb86fa5f29 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,6 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.140 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 0b03714e696..07ef3f640f4 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.19 $)
+ * linux/drivers/s390/cio/cmf.c
*
* Linux on zSeries Channel Measurement Facility support
*
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 516108779f6..1bbf231f8aa 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,7 +1,6 @@
/*
* drivers/s390/cio/css.c
* driver for channel subsystem
- * $Revision: 1.96 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index a67e7e60e33..afc4e88551a 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,7 +1,6 @@
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
- * $Revision: 1.140 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -255,7 +254,7 @@ modalias_show (struct device *dev, struct device_attribute *attr, char *buf)
struct ccw_device_id *id = &(cdev->id);
int ret;
- ret = sprintf(buf, "ccw:t%04Xm%02x",
+ ret = sprintf(buf, "ccw:t%04Xm%02X",
id->cu_type, id->cu_model);
if (id->dev_type != 0)
ret += sprintf(buf + ret, "dt%04Xdm%02X\n",
@@ -360,7 +359,7 @@ ccw_device_set_online(struct ccw_device *cdev)
else
pr_debug("ccw_device_offline returned %d, device %s\n",
ret, cdev->dev.bus_id);
- return (ret = 0) ? -ENODEV : ret;
+ return (ret == 0) ? -ENODEV : ret;
}
static ssize_t
@@ -1013,7 +1012,7 @@ ccw_device_probe_console(void)
int ret;
if (xchg(&console_cdev_in_use, 1) != 0)
- return NULL;
+ return ERR_PTR(-EBUSY);
sch = cio_probe_console();
if (IS_ERR(sch)) {
console_cdev_in_use = 0;
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 8b0218949b6..3a50b190328 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,8 +1,6 @@
/*
* drivers/s390/cio/device_ops.c
*
- * $Revision: 1.61 $
- *
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index d2a5b04d7cb..85b1020a1fc 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -405,7 +405,7 @@ __ccw_device_disband_start(struct ccw_device *cdev)
cdev->private->iretry = 5;
cdev->private->imask >>= 1;
}
- ccw_device_verify_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV);
+ ccw_device_disband_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV);
}
/*
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index dad4dd9887c..6c762b43f92 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -317,7 +317,6 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
/*
* We have ending status but no sense information. Do a basic sense.
*/
- sch = to_subchannel(cdev->dev.parent);
sch->sense_ccw.cmd_code = CCW_CMD_BASIC_SENSE;
sch->sense_ccw.cda = (__u32) __pa(cdev->private->irb.ecw);
sch->sense_ccw.count = SENSE_MAX_COUNT;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 77be2c39bfe..9ed37dc9a1b 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,8 +56,6 @@
#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.117 $"
-
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
MODULE_DESCRIPTION("QDIO base support version 2, " \
@@ -66,8 +64,7 @@ MODULE_LICENSE("GPL");
/******************** HERE WE GO ***********************************/
-static const char version[] = "QDIO base support version 2 ("
- VERSION_QDIO_C "/" VERSION_QDIO_H "/" VERSION_CIO_QDIO_H ")";
+static const char version[] = "QDIO base support version 2";
#ifdef QDIO_PERFORMANCE_STATS
static int proc_perf_file_registration;
@@ -168,8 +165,13 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
q_no = q->q_no;
if(!q->is_input_q)
q_no += irq->no_input_qs;
+again:
ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if (rc == 1) {
+ QDIO_DBF_TEXT5(1,trace,"eqAGAIN");
+ goto again;
+ }
if (rc < 0) {
QDIO_DBF_TEXT2(1,trace,"eqberr");
sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no);
@@ -198,8 +200,13 @@ qdio_do_sqbs(struct qdio_q *q, unsigned char state,
q_no = q->q_no;
if(!q->is_input_q)
q_no += irq->no_input_qs;
+again:
ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if (rc == 1) {
+ QDIO_DBF_TEXT5(1,trace,"sqAGAIN");
+ goto again;
+ }
if (rc < 0) {
QDIO_DBF_TEXT3(1,trace,"sqberr");
sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
@@ -1190,8 +1197,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
if (!no_used)
return 1;
-
- if (!q->siga_sync)
+ if (!q->siga_sync && !irq->is_qebsm)
/* we'll check for more primed buffers in qeth_stop_polling */
return 0;
if (irq->is_qebsm) {
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index fa385e761fe..ceb3ab31ee0 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -5,8 +5,6 @@
#include "schid.h"
-#define VERSION_CIO_QDIO_H "$Revision: 1.40 $"
-
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_VERBOSE_LEVEL 9
#else /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h
index f87c785f203..dbbcda3c846 100644
--- a/drivers/s390/crypto/z90common.h
+++ b/drivers/s390/crypto/z90common.h
@@ -27,8 +27,6 @@
#ifndef _Z90COMMON_H_
#define _Z90COMMON_H_
-#define VERSION_Z90COMMON_H "$Revision: 1.17 $"
-
#define RESPBUFFSIZE 256
#define PCI_FUNC_KEY_DECRYPT 0x5044
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 3a18443fdfa..5e6b1f535f6 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -29,8 +29,6 @@
#include <linux/ioctl.h>
-#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $"
-
#define z90crypt_VERSION 1
#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards
#define z90crypt_VARIANT 3 // 3 = CEX2A support
diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c
index d7f7494a0cb..4141919da80 100644
--- a/drivers/s390/crypto/z90hardware.c
+++ b/drivers/s390/crypto/z90hardware.c
@@ -32,12 +32,6 @@
#include "z90crypt.h"
#include "z90common.h"
-#define VERSION_Z90HARDWARE_C "$Revision: 1.34 $"
-
-char z90hardware_version[] __initdata =
- "z90hardware.o (" VERSION_Z90HARDWARE_C "/"
- VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")";
-
struct cca_token_hdr {
unsigned char token_identifier;
unsigned char version;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 2f54d033d7c..7d6f19030ef 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -38,14 +38,6 @@
#include "z90crypt.h"
#include "z90common.h"
-#define VERSION_Z90MAIN_C "$Revision: 1.62 $"
-
-static char z90main_version[] __initdata =
- "z90main.o (" VERSION_Z90MAIN_C "/"
- VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")";
-
-extern char z90hardware_version[];
-
/**
* Defaults that may be modified.
*/
@@ -594,8 +586,6 @@ z90crypt_init_module(void)
PRINTKN("Version %d.%d.%d loaded, built on %s %s\n",
z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT,
__DATE__, __TIME__);
- PRINTKN("%s\n", z90main_version);
- PRINTKN("%s\n", z90hardware_version);
PDEBUG("create_z90crypt (domain index %d) successful.\n",
domain);
} else
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index e70af7f3994..a86436a7a60 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -2,8 +2,6 @@
* drivers/s390/net/claw.c
* ESCON CLAW network driver
*
- * $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $
- *
* Linux for zSeries version
* Copyright (C) 2002,2005 IBM Corporation
* Author(s) Original code written by:
@@ -4391,14 +4389,7 @@ static int __init
claw_init(void)
{
int ret = 0;
- printk(KERN_INFO "claw: starting driver "
-#ifdef MODULE
- "module "
-#else
- "compiled into kernel "
-#endif
- " $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ \n");
-
+ printk(KERN_INFO "claw: starting driver\n");
#ifdef FUNCTRACE
printk(KERN_INFO "claw: %s() enter \n",__FUNCTION__);
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h
index 3df71970f60..969be465309 100644
--- a/drivers/s390/net/claw.h
+++ b/drivers/s390/net/claw.h
@@ -2,7 +2,7 @@
* Define constants *
* *
********************************************************/
-#define VERSION_CLAW_H "$Revision: 1.6 $"
+
/*-----------------------------------------------------*
* CCW command codes for CLAW protocol *
*------------------------------------------------------*/
diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
index 0e2a8bb9303..e6e72deb36b 100644
--- a/drivers/s390/net/ctcdbug.c
+++ b/drivers/s390/net/ctcdbug.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.6 $)
+ * linux/drivers/s390/net/ctcdbug.c
*
* CTC / ESCON network driver - s390 dbf exploit.
*
@@ -9,8 +9,6 @@
* Author(s): Original Code written by
* Peter Tiedemann (ptiedem@de.ibm.com)
*
- * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $
- *
* 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)
@@ -80,4 +78,3 @@ ctc_register_dbf_views(void)
return 0;
}
-
diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
index 7d6afa1627c..413925ee23d 100644
--- a/drivers/s390/net/ctcdbug.h
+++ b/drivers/s390/net/ctcdbug.h
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.6 $)
+ * linux/drivers/s390/net/ctcdbug.h
*
* CTC / ESCON network driver - s390 dbf exploit.
*
@@ -9,8 +9,6 @@
* Author(s): Original Code written by
* Peter Tiedemann (ptiedem@de.ibm.com)
*
- * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $
- *
* 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)
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 1901feef07d..af9f212314b 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,6 +1,4 @@
/*
- * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $
- *
* CTC / ESCON network driver
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -37,8 +35,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $
- *
*/
#undef DEBUG
#include <linux/module.h>
@@ -248,22 +244,11 @@ static void
print_banner(void)
{
static int printed = 0;
- char vbuf[] = "$Revision: 1.79 $";
- char *version = vbuf;
if (printed)
return;
- if ((version = strchr(version, ':'))) {
- char *p = strchr(version + 1, '$');
- if (p)
- *p = '\0';
- } else
- version = " ??? ";
- printk(KERN_INFO "CTC driver Version%s"
-#ifdef DEBUG
- " (DEBUG-VERSION, " __DATE__ __TIME__ ")"
-#endif
- " initialized\n", version);
+
+ printk(KERN_INFO "CTC driver initialized\n");
printed = 1;
}
diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h
index ba3605f1633..d2e835c0c13 100644
--- a/drivers/s390/net/ctcmain.h
+++ b/drivers/s390/net/ctcmain.h
@@ -1,6 +1,4 @@
/*
- * $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $
- *
* CTC / ESCON network driver
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -29,8 +27,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $
- *
*/
#ifndef _CTCMAIN_H_
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 93d1725eb79..5cdcdbf9296 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -1,6 +1,4 @@
/*
- * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $
- *
* CTC / ESCON network driver, tty interface.
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
diff --git a/drivers/s390/net/ctctty.h b/drivers/s390/net/ctctty.h
index 84b2f8f23ab..7254dc00631 100644
--- a/drivers/s390/net/ctctty.h
+++ b/drivers/s390/net/ctctty.h
@@ -1,6 +1,4 @@
/*
- * $Id: ctctty.h,v 1.4 2003/09/18 08:01:10 mschwide Exp $
- *
* CTC / ESCON network driver, tty interface.
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 2014fb7a488..b12533104c1 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,6 +1,4 @@
/*
- * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $
- *
* CTC / LCS ccw_device driver
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
index 24029bd9c7d..6caf5fa6a3b 100644
--- a/drivers/s390/net/fsm.c
+++ b/drivers/s390/net/fsm.c
@@ -1,6 +1,4 @@
/**
- * $Id: fsm.c,v 1.6 2003/10/15 11:37:29 mschwide Exp $
- *
* A generic FSM based on fsm used in isdn4linux
*
*/
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index 5b98253be7a..af679c10f1b 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -1,5 +1,3 @@
-/* $Id: fsm.h,v 1.1.1.1 2002/03/13 19:33:09 mschwide Exp $
- */
#ifndef _FSM_H_
#define _FSM_H_
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index ea817739256..760e77ec5a1 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,6 +1,4 @@
/*
- * $Id: iucv.c,v 1.47 2005/11/21 11:35:22 mschwide Exp $
- *
* IUCV network driver
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -29,8 +27,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.47 $
- *
*/
/* #define DEBUG */
@@ -355,17 +351,7 @@ do { \
static void
iucv_banner(void)
{
- char vbuf[] = "$Revision: 1.47 $";
- char *version = vbuf;
-
- if ((version = strchr(version, ':'))) {
- char *p = strchr(version + 1, '$');
- if (p)
- *p = '\0';
- } else
- version = " ??? ";
- printk(KERN_INFO
- "IUCV lowlevel driver Version%s initialized\n", version);
+ printk(KERN_INFO "IUCV lowlevel driver initialized\n");
}
/**
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index da8c515743e..9cf88d7201d 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -11,8 +11,6 @@
* Frank Pavlic (fpavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*
- * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $
- *
* 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)
@@ -59,9 +57,8 @@
/**
* initialization string for output
*/
-#define VERSION_LCS_C "$Revision: 1.99 $"
-static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
+static char version[] __initdata = "LCS driver";
static char debug_buffer[255];
/**
@@ -101,9 +98,9 @@ lcs_register_debug_facility(void)
return -ENOMEM;
}
debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view);
- debug_set_level(lcs_dbf_setup, 4);
+ debug_set_level(lcs_dbf_setup, 2);
debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view);
- debug_set_level(lcs_dbf_trace, 4);
+ debug_set_level(lcs_dbf_trace, 2);
return 0;
}
@@ -1295,9 +1292,8 @@ lcs_set_multicast_list(struct net_device *dev)
LCS_DBF_TEXT(4, trace, "setmulti");
card = (struct lcs_card *) dev->priv;
- if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) {
+ if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD))
schedule_work(&card->kernel_thread_starter);
- }
}
#endif /* CONFIG_IP_MULTICAST */
@@ -1462,6 +1458,8 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer)
lcs_release_buffer(channel, buffer);
card = (struct lcs_card *)
((char *) channel - offsetof(struct lcs_card, write));
+ if (netif_queue_stopped(card->dev))
+ netif_wake_queue(card->dev);
spin_lock(&card->lock);
card->tx_emitted--;
if (card->tx_emitted <= 0 && card->tx_buffer != NULL)
@@ -1481,6 +1479,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
struct net_device *dev)
{
struct lcs_header *header;
+ int rc = 0;
LCS_DBF_TEXT(5, trace, "hardxmit");
if (skb == NULL) {
@@ -1495,10 +1494,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
card->stats.tx_carrier_errors++;
return 0;
}
- if (netif_queue_stopped(dev) ) {
- card->stats.tx_dropped++;
- return -EBUSY;
- }
+ netif_stop_queue(card->dev);
+ spin_lock(&card->lock);
if (card->tx_buffer != NULL &&
card->tx_buffer->count + sizeof(struct lcs_header) +
skb->len + sizeof(u16) > LCS_IOBUFFERSIZE)
@@ -1509,7 +1506,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
card->tx_buffer = lcs_get_buffer(&card->write);
if (card->tx_buffer == NULL) {
card->stats.tx_dropped++;
- return -EBUSY;
+ rc = -EBUSY;
+ goto out;
}
card->tx_buffer->callback = lcs_txbuffer_cb;
card->tx_buffer->count = 0;
@@ -1521,13 +1519,18 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
header->type = card->lan_type;
header->slot = card->portno;
memcpy(header + 1, skb->data, skb->len);
+ spin_unlock(&card->lock);
card->stats.tx_bytes += skb->len;
card->stats.tx_packets++;
dev_kfree_skb(skb);
- if (card->tx_emitted <= 0)
+ netif_wake_queue(card->dev);
+ spin_lock(&card->lock);
+ if (card->tx_emitted <= 0 && card->tx_buffer != NULL)
/* If this is the first tx buffer emit it immediately. */
__lcs_emit_txbuffer(card);
- return 0;
+out:
+ spin_unlock(&card->lock);
+ return rc;
}
static int
@@ -1538,9 +1541,7 @@ lcs_start_xmit(struct sk_buff *skb, struct net_device *dev)
LCS_DBF_TEXT(5, trace, "pktxmit");
card = (struct lcs_card *) dev->priv;
- spin_lock(&card->lock);
rc = __lcs_start_xmit(card, skb, dev);
- spin_unlock(&card->lock);
return rc;
}
@@ -2322,7 +2323,6 @@ __init lcs_init_module(void)
PRINT_ERR("Initialization failed\n");
return rc;
}
-
return 0;
}
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index a7f348ef1b0..2fad5e40c2e 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -6,8 +6,6 @@
#include <linux/workqueue.h>
#include <asm/ccwdev.h>
-#define VERSION_LCS_H "$Revision: 1.19 $"
-
#define LCS_DBF_TEXT(level, name, text) \
do { \
debug_text_event(lcs_dbf_##name, level, text); \
@@ -97,7 +95,7 @@ do { \
*/
#define LCS_ILLEGAL_OFFSET 0xffff
#define LCS_IOBUFFERSIZE 0x5000
-#define LCS_NUM_BUFFS 8 /* needs to be power of 2 */
+#define LCS_NUM_BUFFS 32 /* needs to be power of 2 */
#define LCS_MAC_LENGTH 6
#define LCS_INVALID_PORT_NO -1
#define LCS_LANCMD_TIMEOUT_DEFAULT 5
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index ac4c4b83fe1..71d3853e868 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,6 +1,4 @@
/*
- * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $
- *
* IUCV network driver
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -31,8 +29,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV network driver $Revision: 1.69 $
- *
*/
#undef DEBUG
@@ -2077,16 +2073,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write);
static void
netiucv_banner(void)
{
- char vbuf[] = "$Revision: 1.69 $";
- char *version = vbuf;
-
- if ((version = strchr(version, ':'))) {
- char *p = strchr(version + 1, '$');
- if (p)
- *p = '\0';
- } else
- version = " ??? ";
- PRINT_INFO("NETIUCV driver Version%s initialized\n", version);
+ PRINT_INFO("NETIUCV driver initialized\n");
}
static void __exit
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index d238c7ed103..4df0fcd7b10 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -25,8 +25,6 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.152 $"
-
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
#else
@@ -1078,16 +1076,6 @@ qeth_get_qdio_q_format(struct qeth_card *card)
}
static inline int
-qeth_isdigit(char * buf)
-{
- while (*buf) {
- if (!isdigit(*buf++))
- return 0;
- }
- return 1;
-}
-
-static inline int
qeth_isxdigit(char * buf)
{
while (*buf) {
@@ -1106,33 +1094,17 @@ qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
static inline int
qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
{
- const char *start, *end;
- char abuf[4];
- char *tmp;
- int len;
- int i;
-
- start = buf;
- for (i = 0; i < 4; i++) {
- if (i == 3) {
- end = strchr(start,0xa);
- if (end)
- len = end - start;
- else
- len = strlen(start);
- }
- else {
- end = strchr(start, '.');
- len = end - start;
- }
- if ((len <= 0) || (len > 3))
- return -EINVAL;
- memset(abuf, 0, 4);
- strncpy(abuf, start, len);
- if (!qeth_isdigit(abuf))
+ int count = 0, rc = 0;
+ int in[4];
+
+ rc = sscanf(buf, "%d.%d.%d.%d%n",
+ &in[0], &in[1], &in[2], &in[3], &count);
+ if (rc != 4 || count)
+ return -EINVAL;
+ for (count = 0; count < 4; count++) {
+ if (in[count] > 255)
return -EINVAL;
- addr[i] = simple_strtoul(abuf, &tmp, 10);
- start = end + 1;
+ addr[count] = in[count];
}
return 0;
}
@@ -1151,36 +1123,44 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf)
static inline int
qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
{
- const char *start, *end;
- u16 *tmp_addr;
- char abuf[5];
- char *tmp;
- int len;
- int i;
-
- tmp_addr = (u16 *)addr;
- start = buf;
- for (i = 0; i < 8; i++) {
- if (i == 7) {
- end = strchr(start,0xa);
- if (end)
- len = end - start;
- else
- len = strlen(start);
- }
- else {
- end = strchr(start, ':');
- len = end - start;
+ char *end, *start;
+ __u16 *in;
+ char num[5];
+ int num2, cnt, out, found, save_cnt;
+ unsigned short in_tmp[8] = {0, };
+
+ cnt = out = found = save_cnt = num2 = 0;
+ end = start = (char *) buf;
+ in = (__u16 *) addr;
+ memset(in, 0, 16);
+ while (end) {
+ end = strchr(end,':');
+ if (end == NULL) {
+ end = (char *)buf + (strlen(buf));
+ out = 1;
+ }
+ if ((end - start)) {
+ memset(num, 0, 5);
+ memcpy(num, start, end - start);
+ if (!qeth_isxdigit(num))
+ return -EINVAL;
+ sscanf(start, "%x", &num2);
+ if (found)
+ in_tmp[save_cnt++] = num2;
+ else
+ in[cnt++] = num2;
+ if (out)
+ break;
+ } else {
+ if (found)
+ return -EINVAL;
+ found = 1;
}
- if ((len <= 0) || (len > 4))
- return -EINVAL;
- memset(abuf, 0, 5);
- strncpy(abuf, start, len);
- if (!qeth_isxdigit(abuf))
- return -EINVAL;
- tmp_addr[i] = simple_strtoul(abuf, &tmp, 16);
- start = end + 1;
- }
+ start = ++end;
+ }
+ cnt = 7;
+ while (save_cnt)
+ in[cnt--] = in_tmp[--save_cnt];
return 0;
}
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index f94f1f25eec..82cb4af2f0e 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -1,6 +1,5 @@
/*
- *
- * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $)
+ * linux/drivers/s390/net/qeth_eddp.c
*
* Enhanced Device Driver Packing (EDDP) support for the qeth driver.
*
@@ -8,8 +7,6 @@
*
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $
- *
*/
#include <linux/config.h>
#include <linux/errno.h>
@@ -62,8 +59,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx)
for (i = 0; i < ctx->num_pages; ++i)
free_page((unsigned long)ctx->pages[i]);
kfree(ctx->pages);
- if (ctx->elements != NULL)
- kfree(ctx->elements);
+ kfree(ctx->elements);
kfree(ctx);
}
@@ -416,6 +412,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
QETH_DBF_TEXT(trace, 5, "eddpftcp");
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
+ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+ eddp->skb_offset += sizeof(struct ethhdr);
+#ifdef CONFIG_QETH_VLAN
+ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+ eddp->skb_offset += VLAN_HLEN;
+#endif /* CONFIG_QETH_VLAN */
+ }
tcph = eddp->skb->h.th;
while (eddp->skb_offset < eddp->skb->len) {
data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
@@ -486,6 +489,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
return -ENOMEM;
}
if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+ skb->mac.raw = (skb->data) + sizeof(struct qeth_hdr);
memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
#ifdef CONFIG_QETH_VLAN
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h
index e1b51860bc5..cae9ba26505 100644
--- a/drivers/s390/net/qeth_eddp.h
+++ b/drivers/s390/net/qeth_eddp.h
@@ -1,14 +1,12 @@
/*
- * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.5 $)
+ * linux/drivers/s390/net/qeth_eddp.h
*
- * Header file for qeth enhanced device driver pakcing.
+ * Header file for qeth enhanced device driver packing.
*
* Copyright 2004 IBM Corporation
*
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.5 $ $Date: 2005/03/24 09:04:18 $
- *
*/
#ifndef __QETH_EDDP_H__
#define __QETH_EDDP_H__
diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
index c0b4c8d82c4..e422b41c656 100644
--- a/drivers/s390/net/qeth_fs.h
+++ b/drivers/s390/net/qeth_fs.h
@@ -12,11 +12,6 @@
#ifndef __QETH_FS_H__
#define __QETH_FS_H__
-#define VERSION_QETH_FS_H "$Revision: 1.10 $"
-
-extern const char *VERSION_QETH_PROC_C;
-extern const char *VERSION_QETH_SYS_C;
-
#ifdef CONFIG_PROC_FS
extern int
qeth_create_procfs_entries(void);
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 97f927c01a8..dba7f7f02e7 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,5 @@
/*
- *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.251 $)
+ * linux/drivers/s390/net/qeth_main.c
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,8 +11,6 @@
* Frank Pavlic (fpavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.251 $ $Date: 2005/05/04 20:19:18 $
- *
* 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)
@@ -73,7 +70,6 @@
#include "qeth_eddp.h"
#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.251 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -520,7 +516,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
QETH_DBF_TEXT(setup, 3, "setoffl");
QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
- netif_carrier_off(card->dev);
+ if (card->dev && netif_carrier_ok(card->dev))
+ netif_carrier_off(card->dev);
recover_flag = card->state;
if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
PRINT_WARN("Stopping card %s interrupted by user!\n",
@@ -1683,6 +1680,7 @@ qeth_cmd_timeout(unsigned long data)
spin_unlock_irqrestore(&reply->card->lock, flags);
}
+
static struct qeth_ipa_cmd *
qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
{
@@ -1703,7 +1701,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
QETH_CARD_IFNAME(card),
card->info.chpid);
card->lan_online = 0;
- netif_carrier_off(card->dev);
+ if (card->dev && netif_carrier_ok(card->dev))
+ netif_carrier_off(card->dev);
return NULL;
case IPA_CMD_STARTLAN:
PRINT_INFO("Link reestablished on %s "
@@ -5566,7 +5565,7 @@ qeth_set_multicast_list(struct net_device *dev)
if (card->info.type == QETH_CARD_TYPE_OSN)
return ;
- QETH_DBF_TEXT(trace,3,"setmulti");
+ QETH_DBF_TEXT(trace, 3, "setmulti");
qeth_delete_mc_addresses(card);
if (card->options.layer2) {
qeth_layer2_add_multicast(card);
@@ -5583,7 +5582,6 @@ out:
return;
if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
schedule_work(&card->kernel_thread_starter);
-
}
static int
@@ -7456,6 +7454,7 @@ qeth_softsetup_card(struct qeth_card *card)
card->lan_online = 1;
if (card->info.type==QETH_CARD_TYPE_OSN)
goto out;
+ qeth_set_large_send(card, card->options.large_send);
if (card->options.layer2) {
card->dev->features |=
NETIF_F_HW_VLAN_FILTER |
@@ -7472,12 +7471,6 @@ qeth_softsetup_card(struct qeth_card *card)
#endif
goto out;
}
- if ((card->options.large_send == QETH_LARGE_SEND_EDDP) ||
- (card->options.large_send == QETH_LARGE_SEND_TSO))
- card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
- else
- card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
-
if ((rc = qeth_setadapter_parms(card)))
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
if ((rc = qeth_start_ipassists(card)))
@@ -8626,12 +8619,7 @@ qeth_init(void)
{
int rc=0;
- PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n",
- version, VERSION_QETH_C, VERSION_QETH_H,
- VERSION_QETH_MPC_H, VERSION_QETH_MPC_C,
- VERSION_QETH_FS_H, VERSION_QETH_PROC_C,
- VERSION_QETH_SYS_C, QETH_VERSION_IPV6,
- QETH_VERSION_VLAN);
+ PRINT_INFO("loading %s\n", version);
INIT_LIST_HEAD(&qeth_card_list.list);
INIT_LIST_HEAD(&qeth_notify_list);
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
index 5f8754addc1..77c83209d70 100644
--- a/drivers/s390/net/qeth_mpc.c
+++ b/drivers/s390/net/qeth_mpc.c
@@ -11,8 +11,6 @@
#include <asm/cio.h>
#include "qeth_mpc.h"
-const char *VERSION_QETH_MPC_C = "$Revision: 1.13 $";
-
unsigned char IDX_ACTIVATE_READ[]={
0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 864cec5f6c6..011c4104102 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -14,10 +14,6 @@
#include <asm/qeth.h>
-#define VERSION_QETH_MPC_H "$Revision: 1.46 $"
-
-extern const char *VERSION_QETH_MPC_C;
-
#define IPA_PDU_HEADER_SIZE 0x40
#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e)
#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26)
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 7bf35098831..3c6339df879 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.16 $)
+ * linux/drivers/s390/net/qeth_fs.c
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to procfs.
@@ -21,8 +21,6 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_PROC_C = "$Revision: 1.16 $";
-
/***** /proc/qeth *****/
#define QETH_PROCFILE_NAME "qeth"
static struct proc_dir_entry *qeth_procfile;
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 0ea185f70f7..c1831f57258 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.60 $)
+ * linux/drivers/s390/net/qeth_sys.c
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,8 +20,6 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.60 $";
-
/*****************************************************************************/
/* */
/* /sys-fs stuff UNDER DEVELOPMENT !!! */
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index 3c50b6f24f5..1286ddea450 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.8 $)
+ * linux/drivers/s390/net/qeth_tso.h
*
* Header file for qeth TCP Segmentation Offload support.
*
@@ -7,8 +7,6 @@
*
* Author(s): Frank Pavlic <fpavlic@de.ibm.com>
*
- * $Revision: 1.8 $ $Date: 2005/05/04 20:19:18 $
- *
*/
#ifndef __QETH_TSO_H__
#define __QETH_TSO_H__
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
index 206518c7d33..e3f64716982 100644
--- a/drivers/s390/s390_rdev.c
+++ b/drivers/s390/s390_rdev.c
@@ -1,7 +1,6 @@
/*
* drivers/s390/s390_rdev.c
* s390 root device
- * $Revision: 1.4 $
*
* Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index d9ea7ed2e46..7abb42a09ae 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -90,15 +90,16 @@ struct crw {
static inline int stcrw(struct crw *pcrw )
{
- int ccode;
+ int ccode;
- __asm__ __volatile__(
- "STCRW 0(%1)\n\t"
- "IPM %0\n\t"
- "SRL %0,28\n\t"
- : "=d" (ccode) : "a" (pcrw)
- : "cc", "1" );
- return ccode;
+ __asm__ __volatile__(
+ "stcrw 0(%2)\n\t"
+ "ipm %0\n\t"
+ "srl %0,28\n\t"
+ : "=d" (ccode), "=m" (*pcrw)
+ : "a" (pcrw)
+ : "cc" );
+ return ccode;
}
#endif /* __s390mach */
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 167fef39d8a..95b92f317b6 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -29,8 +29,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_AUX_REVISION "$Revision: 1.145 $"
-
#include "zfcp_ext.h"
/* accumulated log level (module parameter) */
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 0fc46381fc2..241136d0c6e 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -27,8 +27,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_CCW_C_REVISION "$Revision: 1.58 $"
-
#include "zfcp_ext.h"
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 95599719f8a..a5f2ba9a8fd 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -23,8 +23,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_DBF_REVISION "$Revision$"
-
#include <asm/debug.h>
#include <linux/ctype.h>
#include "zfcp_ext.h"
@@ -712,10 +710,9 @@ static inline void
_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *new_fsf_req)
+ struct zfcp_fsf_req *fsf_req,
+ struct zfcp_fsf_req *old_fsf_req)
{
- struct zfcp_fsf_req *fsf_req =
- (struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
unsigned long flags;
@@ -729,19 +726,20 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
if (offset == 0) {
strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
- if (scsi_cmnd->device) {
- rec->scsi_id = scsi_cmnd->device->id;
- rec->scsi_lun = scsi_cmnd->device->lun;
+ if (scsi_cmnd != NULL) {
+ if (scsi_cmnd->device) {
+ rec->scsi_id = scsi_cmnd->device->id;
+ rec->scsi_lun = scsi_cmnd->device->lun;
+ }
+ rec->scsi_result = scsi_cmnd->result;
+ rec->scsi_cmnd = (unsigned long)scsi_cmnd;
+ rec->scsi_serial = scsi_cmnd->serial_number;
+ memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+ min((int)scsi_cmnd->cmd_len,
+ ZFCP_DBF_SCSI_OPCODE));
+ rec->scsi_retries = scsi_cmnd->retries;
+ rec->scsi_allowed = scsi_cmnd->allowed;
}
- rec->scsi_result = scsi_cmnd->result;
- rec->scsi_cmnd = (unsigned long)scsi_cmnd;
- rec->scsi_serial = scsi_cmnd->serial_number;
- memcpy(rec->scsi_opcode,
- &scsi_cmnd->cmnd,
- min((int)scsi_cmnd->cmd_len,
- ZFCP_DBF_SCSI_OPCODE));
- rec->scsi_retries = scsi_cmnd->retries;
- rec->scsi_allowed = scsi_cmnd->allowed;
if (fsf_req != NULL) {
fcp_rsp = (struct fcp_rsp_iu *)
&(fsf_req->qtcb->bottom.io.fcp_rsp);
@@ -774,15 +772,8 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
rec->fsf_seqno = fsf_req->seq_no;
rec->fsf_issued = fsf_req->issued;
}
- if (new_fsf_req != NULL) {
- rec->type.new_fsf_req.fsf_reqid =
- (unsigned long)
- new_fsf_req;
- rec->type.new_fsf_req.fsf_seqno =
- new_fsf_req->seq_no;
- rec->type.new_fsf_req.fsf_issued =
- new_fsf_req->issued;
- }
+ rec->type.old_fsf_reqid =
+ (unsigned long) old_fsf_req;
} else {
strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
dump->total_size = buflen;
@@ -803,19 +794,21 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
inline void
zfcp_scsi_dbf_event_result(const char *tag, int level,
struct zfcp_adapter *adapter,
- struct scsi_cmnd *scsi_cmnd)
+ struct scsi_cmnd *scsi_cmnd,
+ struct zfcp_fsf_req *fsf_req)
{
- _zfcp_scsi_dbf_event_common("rslt",
- tag, level, adapter, scsi_cmnd, NULL);
+ _zfcp_scsi_dbf_event_common("rslt", tag, level,
+ adapter, scsi_cmnd, fsf_req, NULL);
}
inline void
zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *new_fsf_req)
+ struct zfcp_fsf_req *new_fsf_req,
+ struct zfcp_fsf_req *old_fsf_req)
{
- _zfcp_scsi_dbf_event_common("abrt",
- tag, 1, adapter, scsi_cmnd, new_fsf_req);
+ _zfcp_scsi_dbf_event_common("abrt", tag, 1,
+ adapter, scsi_cmnd, new_fsf_req, old_fsf_req);
}
inline void
@@ -825,7 +818,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
struct zfcp_adapter *adapter = unit->port->adapter;
_zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
- tag, 1, adapter, scsi_cmnd, NULL);
+ tag, 1, adapter, scsi_cmnd, NULL, NULL);
}
static int
@@ -858,6 +851,10 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
rec->scsi_retries);
len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
rec->scsi_allowed);
+ if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
+ len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx",
+ rec->type.old_fsf_reqid);
+ }
len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
rec->fsf_reqid);
len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
@@ -885,21 +882,6 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
min((int)rec->type.fcp.sns_info_len,
ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
rec->type.fcp.sns_info_len);
- } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
- len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
- rec->type.new_fsf_req.fsf_reqid);
- len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
- rec->type.new_fsf_req.fsf_seqno);
- len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
- rec->type.new_fsf_req.fsf_issued);
- } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
- (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
- len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
- rec->type.new_fsf_req.fsf_reqid);
- len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
- rec->type.new_fsf_req.fsf_seqno);
- len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
- rec->type.new_fsf_req.fsf_issued);
}
len += sprintf(out_buf + len, "\n");
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 9bb511083a2..7f551d66f47 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -34,8 +34,6 @@
#ifndef ZFCP_DEF_H
#define ZFCP_DEF_H
-#define ZFCP_DEF_REVISION "$Revision: 1.111 $"
-
/*************************** INCLUDES *****************************************/
#include <linux/init.h>
@@ -154,11 +152,6 @@ typedef u32 scsi_lun_t;
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
-/* Retry 5 times every 2 second, then every minute */
-#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5
-#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200
-#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000
-
/* timeout value for "default timer" for fsf requests */
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
@@ -431,11 +424,7 @@ struct zfcp_scsi_dbf_record {
u32 fsf_seqno;
u64 fsf_issued;
union {
- struct {
- u64 fsf_reqid;
- u32 fsf_seqno;
- u64 fsf_issued;
- } new_fsf_req;
+ u64 old_fsf_reqid;
struct {
u8 rsp_validity;
u8 rsp_scsi_status;
@@ -917,8 +906,6 @@ struct zfcp_adapter {
wwn_t peer_wwnn; /* P2P peer WWNN */
wwn_t peer_wwpn; /* P2P peer WWPN */
u32 peer_d_id; /* P2P peer D_ID */
- wwn_t physical_wwpn; /* WWPN of physical port */
- u32 physical_s_id; /* local FC port ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
u8 fc_service_class;
u32 hydra_version; /* Hydra version */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index c065cb836c9..e3c4bdd29a6 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -31,8 +31,6 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP
-#define ZFCP_ERP_REVISION "$Revision: 1.86 $"
-
#include "zfcp_ext.h"
static int zfcp_erp_adisc(struct zfcp_port *);
@@ -2248,15 +2246,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
{
int retval;
- if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &erp_action->adapter->status)) &&
- (erp_action->adapter->adapter_features &
- FSF_FEATURE_HBAAPI_MANAGEMENT)) {
- zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
- atomic_set(&erp_action->adapter->erp_counter, 0);
- return ZFCP_ERP_FAILED;
- }
-
retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
if (retval == ZFCP_ERP_FAILED)
return ZFCP_ERP_FAILED;
@@ -2268,13 +2257,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
{
@@ -2352,48 +2334,40 @@ static int
zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
{
int ret;
- int retries;
- int sleep;
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_adapter *adapter;
+ adapter = erp_action->adapter;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
- retries = 0;
- do {
- write_lock(&adapter->erp_lock);
- zfcp_erp_action_to_running(erp_action);
- write_unlock(&adapter->erp_lock);
- zfcp_erp_timeout_init(erp_action);
- ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
- if (ret == -EOPNOTSUPP) {
- debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
- return ZFCP_ERP_SUCCEEDED;
- } else if (ret) {
- debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
- return ZFCP_ERP_FAILED;
- }
- debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
+ write_lock(&adapter->erp_lock);
+ zfcp_erp_action_to_running(erp_action);
+ write_unlock(&adapter->erp_lock);
- down(&adapter->erp_ready_sem);
- if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
- ZFCP_LOG_INFO("error: exchange of port data "
- "for adapter %s timed out\n",
- zfcp_get_busid_by_adapter(adapter));
- break;
- }
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status))
- break;
+ zfcp_erp_timeout_init(erp_action);
+ ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
+ if (ret == -EOPNOTSUPP) {
+ debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
+ return ZFCP_ERP_SUCCEEDED;
+ } else if (ret) {
+ debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
+ return ZFCP_ERP_FAILED;
+ }
+ debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
- if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
- sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
- retries++;
- } else
- sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
- schedule_timeout(sleep);
- } while (1);
+ ret = ZFCP_ERP_SUCCEEDED;
+ down(&adapter->erp_ready_sem);
+ if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+ ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
+ "%s)\n", zfcp_get_busid_by_adapter(adapter));
+ ret = ZFCP_ERP_FAILED;
+ }
+ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) {
+ ZFCP_LOG_INFO("error: exchange port data failed (adapter "
+ "%s\n", zfcp_get_busid_by_adapter(adapter));
+ ret = ZFCP_ERP_FAILED;
+ }
- return ZFCP_ERP_SUCCEEDED;
+ return ret;
}
/*
@@ -3441,6 +3415,8 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
"(adapter %s, wwpn=0x%016Lx)\n",
zfcp_get_busid_by_port(port),
port->wwpn);
+ else
+ scsi_flush_work(adapter->scsi_host);
}
zfcp_port_put(port);
break;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index c3782261cb5..700f5402a97 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -32,8 +32,6 @@
#ifndef ZFCP_EXT_H
#define ZFCP_EXT_H
-#define ZFCP_EXT_REVISION "$Revision: 1.62 $"
-
#include "zfcp_def.h"
extern struct zfcp_data zfcp_data;
@@ -196,9 +194,10 @@ extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
- struct scsi_cmnd *);
+ struct scsi_cmnd *,
+ struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
- struct scsi_cmnd *,
+ struct scsi_cmnd *, struct zfcp_fsf_req *,
struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
struct scsi_cmnd *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index cbfab09899c..662ec571d73 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -30,8 +30,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_FSF_C_REVISION "$Revision: 1.92 $"
-
#include "zfcp_ext.h"
static int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *);
@@ -390,6 +388,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
case FSF_PROT_LINK_DOWN:
zfcp_fsf_link_down_info_eval(adapter,
&prot_status_qual->link_down_info);
+ zfcp_erp_adapter_reopen(adapter, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -560,10 +559,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
- if (link_down == NULL) {
- zfcp_erp_adapter_reopen(adapter, 0);
- return;
- }
+ if (link_down == NULL)
+ goto out;
switch (link_down->error_code) {
case FSF_PSQ_LINK_NO_LIGHT:
@@ -645,16 +642,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
link_down->explanation_code,
link_down->vendor_specific_code);
- switch (link_down->error_code) {
- case FSF_PSQ_LINK_NO_LIGHT:
- case FSF_PSQ_LINK_WRAP_PLUG:
- case FSF_PSQ_LINK_NO_FCP:
- case FSF_PSQ_LINK_FIRMWARE_UPDATE:
- zfcp_erp_adapter_reopen(adapter, 0);
- break;
- default:
- zfcp_erp_adapter_failed(adapter);
- }
+ out:
+ zfcp_erp_adapter_failed(adapter);
}
/*
@@ -2306,6 +2295,35 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
return retval;
}
+/**
+ * zfcp_fsf_exchange_port_evaluate
+ * @fsf_req: fsf_req which belongs to xchg port data request
+ * @xchg_ok: specifies if xchg port data was incomplete or complete (0/1)
+ */
+static void
+zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
+{
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb *qtcb;
+ struct fsf_qtcb_bottom_port *bottom, *data;
+ struct Scsi_Host *shost;
+
+ adapter = fsf_req->adapter;
+ qtcb = fsf_req->qtcb;
+ bottom = &qtcb->bottom.port;
+ shost = adapter->scsi_host;
+
+ data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
+ if (data)
+ memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
+
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ fc_host_permanent_port_name(shost) = bottom->wwpn;
+ else
+ fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
+ fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+ fc_host_supported_speeds(shost) = bottom->supported_speed;
+}
/**
* zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
@@ -2314,38 +2332,26 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
static void
zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
{
- struct zfcp_adapter *adapter = fsf_req->adapter;
- struct Scsi_Host *shost = adapter->scsi_host;
- struct fsf_qtcb *qtcb = fsf_req->qtcb;
- struct fsf_qtcb_bottom_port *bottom, *data;
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb *qtcb;
+
+ adapter = fsf_req->adapter;
+ qtcb = fsf_req->qtcb;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
switch (qtcb->header.fsf_status) {
case FSF_GOOD:
+ zfcp_fsf_exchange_port_evaluate(fsf_req, 1);
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-
- bottom = &qtcb->bottom.port;
- data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
- if (data)
- memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
- if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
- fc_host_permanent_port_name(shost) = bottom->wwpn;
- else
- fc_host_permanent_port_name(shost) =
- fc_host_port_name(shost);
- fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
- fc_host_supported_speeds(shost) = bottom->supported_speed;
break;
-
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+ zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-
zfcp_fsf_link_down_info_eval(adapter,
&qtcb->header.fsf_status_qual.link_down_info);
break;
-
default:
debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
debug_event(adapter->erp_dbf, 0,
@@ -4205,11 +4211,11 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
if (scpnt->result != 0)
- zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req);
else if (scpnt->retries > 0)
- zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req);
else
- zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req);
/* cleanup pointer (need this especially for abort) */
scpnt->host_scribble = NULL;
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index d719f66a29a..1c3275163c9 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -29,8 +29,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_QDIO_C_REVISION "$Revision: 1.20 $"
-
#include "zfcp_ext.h"
static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 3c2cbcccbf5..9f6b4d7a46f 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -31,8 +31,6 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
-#define ZFCP_SCSI_REVISION "$Revision: 1.74 $"
-
#include "zfcp_ext.h"
static void zfcp_scsi_slave_destroy(struct scsi_device *sdp);
@@ -244,7 +242,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
zfcp_scsi_dbf_event_result("fail", 4,
(struct zfcp_adapter*) scpnt->device->host->hostdata[0],
- scpnt);
+ scpnt, NULL);
/* return directly */
scpnt->scsi_done(scpnt);
}
@@ -448,7 +446,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
if (!old_fsf_req) {
write_unlock_irqrestore(&adapter->abort_lock, flags);
- zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL);
retval = SUCCESS;
goto out;
}
@@ -462,6 +460,8 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
adapter, unit, 0);
if (!new_fsf_req) {
ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
+ zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
+ old_fsf_req);
retval = FAILED;
goto out;
}
@@ -472,13 +472,16 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
/* status should be valid since signals were not permitted */
if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
- zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
+ NULL);
retval = SUCCESS;
} else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
- zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req,
+ NULL);
retval = SUCCESS;
} else {
- zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req,
+ NULL);
retval = FAILED;
}
zfcp_fsf_req_free(new_fsf_req);
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index 9f262250043..b29ac25e07f 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -27,8 +27,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.38 $"
-
#include "zfcp_ext.h"
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
@@ -57,8 +55,6 @@ ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
-ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
-ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
@@ -243,8 +239,6 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_peer_wwnn.attr,
&dev_attr_peer_wwpn.attr,
&dev_attr_peer_d_id.attr,
- &dev_attr_physical_wwpn.attr,
- &dev_attr_physical_s_id.attr,
&dev_attr_card_version.attr,
&dev_attr_lic_version.attr,
&dev_attr_status.attr,
diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c
index 77a5e2dcc0f..6622d55e0a4 100644
--- a/drivers/s390/scsi/zfcp_sysfs_driver.c
+++ b/drivers/s390/scsi/zfcp_sysfs_driver.c
@@ -27,8 +27,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.17 $"
-
#include "zfcp_ext.h"
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index 3924eb38805..f401d42db21 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -28,8 +28,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.47 $"
-
#include "zfcp_ext.h"
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 2f50815f65c..ad5dfb889be 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -28,8 +28,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.30 $"
-
#include "zfcp_ext.h"
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 31c49754227..d9152d02088 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -61,6 +61,7 @@
Add support for embedded firmware error strings.
2.26.02.003 - Correctly handle single sgl's with use_sg=1.
2.26.02.004 - Add support for 9550SX controllers.
+ 2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
*/
#include <linux/module.h>
@@ -84,7 +85,7 @@
#include "3w-9xxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "2.26.02.004"
+#define TW_DRIVER_VERSION "2.26.02.005"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -1408,7 +1409,7 @@ static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int requ
dma_addr_t mapping;
struct scsi_cmnd *cmd = tw_dev->srb[request_id];
struct pci_dev *pdev = tw_dev->tw_pci_dev;
- int retval = 0;
+ dma_addr_t retval = 0;
if (cmd->request_bufflen == 0) {
retval = 0;
@@ -1798,7 +1799,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
int i, sg_count;
struct scsi_cmnd *srb = NULL;
struct scatterlist *sglist = NULL;
- u32 buffaddr = 0x0;
+ dma_addr_t buffaddr = 0x0;
int retval = 1;
if (tw_dev->srb[request_id]) {
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 7139659dd95..a16f8ded8f1 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -173,10 +173,10 @@ int aac_get_config_status(struct aac_dev *dev)
int status = 0;
struct fib * fibptr;
- if (!(fibptr = fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
{
struct aac_get_config_status *dinfo;
dinfo = (struct aac_get_config_status *) fib_data(fibptr);
@@ -186,7 +186,7 @@ int aac_get_config_status(struct aac_dev *dev)
dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data));
}
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_get_config_status),
FsaNormal,
@@ -209,30 +209,30 @@ int aac_get_config_status(struct aac_dev *dev)
status = -EINVAL;
}
}
- fib_complete(fibptr);
+ aac_fib_complete(fibptr);
/* Send a CT_COMMIT_CONFIG to enable discovery of devices */
if (status >= 0) {
if (commit == 1) {
struct aac_commit_config * dinfo;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
dinfo = (struct aac_commit_config *) fib_data(fibptr);
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_commit_config),
FsaNormal,
1, 1,
NULL, NULL);
- fib_complete(fibptr);
+ aac_fib_complete(fibptr);
} else if (commit == 0) {
printk(KERN_WARNING
"aac_get_config_status: Foreign device configurations are being ignored\n");
}
}
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return status;
}
@@ -255,15 +255,15 @@ int aac_get_containers(struct aac_dev *dev)
instance = dev->scsi_host_ptr->unique_id;
- if (!(fibptr = fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
dinfo = (struct aac_get_container_count *) fib_data(fibptr);
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_get_container_count),
FsaNormal,
@@ -272,7 +272,7 @@ int aac_get_containers(struct aac_dev *dev)
if (status >= 0) {
dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
- fib_complete(fibptr);
+ aac_fib_complete(fibptr);
}
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
@@ -280,7 +280,7 @@ int aac_get_containers(struct aac_dev *dev)
fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(
sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
if (!fsa_dev_ptr) {
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return -ENOMEM;
}
memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
@@ -294,14 +294,14 @@ int aac_get_containers(struct aac_dev *dev)
fsa_dev_ptr[index].devname[0] = '\0';
- fib_init(fibptr);
+ aac_fib_init(fibptr);
dinfo = (struct aac_query_mount *) fib_data(fibptr);
dinfo->command = cpu_to_le32(VM_NameServe);
dinfo->count = cpu_to_le32(index);
dinfo->type = cpu_to_le32(FT_FILESYS);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_query_mount),
FsaNormal,
@@ -319,7 +319,7 @@ int aac_get_containers(struct aac_dev *dev)
dinfo->count = cpu_to_le32(index);
dinfo->type = cpu_to_le32(FT_FILESYS);
- if (fib_send(ContainerCommand,
+ if (aac_fib_send(ContainerCommand,
fibptr,
sizeof(struct aac_query_mount),
FsaNormal,
@@ -347,7 +347,7 @@ int aac_get_containers(struct aac_dev *dev)
if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
fsa_dev_ptr[index].ro = 1;
}
- fib_complete(fibptr);
+ aac_fib_complete(fibptr);
/*
* If there are no more containers, then stop asking.
*/
@@ -355,7 +355,7 @@ int aac_get_containers(struct aac_dev *dev)
break;
}
}
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return status;
}
@@ -413,8 +413,8 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@@ -430,10 +430,10 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- if (!(cmd_fibcontext = fib_alloc(dev)))
+ if (!(cmd_fibcontext = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);
dinfo->command = cpu_to_le32(VM_ContainerConfig);
@@ -441,7 +441,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
dinfo->cid = cpu_to_le32(cid);
dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
sizeof (struct aac_get_name),
FsaNormal,
@@ -455,14 +455,14 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
if (status == -EINPROGRESS)
return 0;
- printk(KERN_WARNING "aac_get_container_name: fib_send failed with status: %d.\n", status);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return -1;
}
/**
- * probe_container - query a logical volume
+ * aac_probe_container - query a logical volume
* @dev: device to query
* @cid: container identifier
*
@@ -470,7 +470,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
* is updated in the struct fsa_dev_info structure rather than returned.
*/
-int probe_container(struct aac_dev *dev, int cid)
+int aac_probe_container(struct aac_dev *dev, int cid)
{
struct fsa_dev_info *fsa_dev_ptr;
int status;
@@ -482,10 +482,10 @@ int probe_container(struct aac_dev *dev, int cid)
fsa_dev_ptr = dev->fsa_dev;
instance = dev->scsi_host_ptr->unique_id;
- if (!(fibptr = fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
dinfo = (struct aac_query_mount *)fib_data(fibptr);
@@ -493,14 +493,14 @@ int probe_container(struct aac_dev *dev, int cid)
dinfo->count = cpu_to_le32(cid);
dinfo->type = cpu_to_le32(FT_FILESYS);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof(struct aac_query_mount),
FsaNormal,
1, 1,
NULL, NULL);
if (status < 0) {
- printk(KERN_WARNING "aacraid: probe_container query failed.\n");
+ printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n");
goto error;
}
@@ -512,7 +512,7 @@ int probe_container(struct aac_dev *dev, int cid)
dinfo->count = cpu_to_le32(cid);
dinfo->type = cpu_to_le32(FT_FILESYS);
- if (fib_send(ContainerCommand,
+ if (aac_fib_send(ContainerCommand,
fibptr,
sizeof(struct aac_query_mount),
FsaNormal,
@@ -535,8 +535,8 @@ int probe_container(struct aac_dev *dev, int cid)
}
error:
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
return status;
}
@@ -700,14 +700,14 @@ int aac_get_adapter_info(struct aac_dev* dev)
struct aac_bus_info *command;
struct aac_bus_info_response *bus_info;
- if (!(fibptr = fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
info = (struct aac_adapter_info *) fib_data(fibptr);
memset(info,0,sizeof(*info));
- rcode = fib_send(RequestAdapterInfo,
+ rcode = aac_fib_send(RequestAdapterInfo,
fibptr,
sizeof(*info),
FsaNormal,
@@ -716,8 +716,8 @@ int aac_get_adapter_info(struct aac_dev* dev)
NULL);
if (rcode < 0) {
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
return rcode;
}
memcpy(&dev->adapter_info, info, sizeof(*info));
@@ -725,13 +725,13 @@ int aac_get_adapter_info(struct aac_dev* dev)
if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
struct aac_supplement_adapter_info * info;
- fib_init(fibptr);
+ aac_fib_init(fibptr);
info = (struct aac_supplement_adapter_info *) fib_data(fibptr);
memset(info,0,sizeof(*info));
- rcode = fib_send(RequestSupplementAdapterInfo,
+ rcode = aac_fib_send(RequestSupplementAdapterInfo,
fibptr,
sizeof(*info),
FsaNormal,
@@ -748,7 +748,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
* GetBusInfo
*/
- fib_init(fibptr);
+ aac_fib_init(fibptr);
bus_info = (struct aac_bus_info_response *) fib_data(fibptr);
@@ -761,7 +761,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
command->MethodId = cpu_to_le32(1);
command->CtlCmd = cpu_to_le32(GetBusInfo);
- rcode = fib_send(ContainerCommand,
+ rcode = aac_fib_send(ContainerCommand,
fibptr,
sizeof (*bus_info),
FsaNormal,
@@ -891,8 +891,8 @@ int aac_get_adapter_info(struct aac_dev* dev)
}
}
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
return rcode;
}
@@ -976,8 +976,8 @@ static void io_callback(void *context, struct fib * fibptr)
? sizeof(scsicmd->sense_buffer)
: sizeof(dev->fsa_dev[cid].sense_data));
}
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@@ -1062,11 +1062,11 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Alocate and initialize a Fib
*/
- if (!(cmd_fibcontext = fib_alloc(dev))) {
+ if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
return -1;
}
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
if (dev->raw_io_interface) {
struct aac_raw_io *readcmd;
@@ -1086,7 +1086,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerRawIo,
+ status = aac_fib_send(ContainerRawIo,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1112,7 +1112,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand64,
+ status = aac_fib_send(ContainerCommand64,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1136,7 +1136,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1153,14 +1153,14 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
if (status == -EINPROGRESS)
return 0;
- printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status);
+ printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
/*
* For some reason, the Fib didn't queue, return QUEUE_FULL
*/
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
scsicmd->scsi_done(scsicmd);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return 0;
}
@@ -1228,12 +1228,12 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
- if (!(cmd_fibcontext = fib_alloc(dev))) {
+ if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
scsicmd->result = DID_ERROR << 16;
scsicmd->scsi_done(scsicmd);
return 0;
}
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
if (dev->raw_io_interface) {
struct aac_raw_io *writecmd;
@@ -1253,7 +1253,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerRawIo,
+ status = aac_fib_send(ContainerRawIo,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1279,7 +1279,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand64,
+ status = aac_fib_send(ContainerCommand64,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1305,7 +1305,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
fibsize,
FsaNormal,
@@ -1322,15 +1322,15 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
return 0;
}
- printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status);
+ printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status);
/*
* For some reason, the Fib didn't queue, return QUEUE_FULL
*/
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
scsicmd->scsi_done(scsicmd);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return 0;
}
@@ -1369,8 +1369,8 @@ static void synchronize_callback(void *context, struct fib *fibptr)
sizeof(cmd->sense_buffer)));
}
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
cmd->scsi_done(cmd);
}
@@ -1407,10 +1407,10 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
* Allocate and initialize a Fib
*/
if (!(cmd_fibcontext =
- fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
+ aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
return SCSI_MLQUEUE_HOST_BUSY;
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
synchronizecmd = fib_data(cmd_fibcontext);
synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
@@ -1422,7 +1422,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
sizeof(struct aac_synchronize),
FsaNormal,
@@ -1437,9 +1437,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
return 0;
printk(KERN_WARNING
- "aac_synchronize: fib_send failed with status: %d.\n", status);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ "aac_synchronize: aac_fib_send failed with status: %d.\n", status);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return SCSI_MLQUEUE_HOST_BUSY;
}
@@ -1465,7 +1465,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
* itself.
*/
if (scmd_id(scsicmd) != host->this_id) {
- if ((scsicmd->device->channel == 0) ){
+ if ((scsicmd->device->channel == CONTAINER_CHANNEL)) {
if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){
scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd);
@@ -1488,7 +1488,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case READ_CAPACITY:
case TEST_UNIT_READY:
spin_unlock_irq(host->host_lock);
- probe_container(dev, cid);
+ aac_probe_container(dev, cid);
if ((fsa_dev_ptr[cid].valid & 1) == 0)
fsa_dev_ptr[cid].valid = 0;
spin_lock_irq(host->host_lock);
@@ -1935,33 +1935,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
case SRB_STATUS_ERROR_RECOVERY:
case SRB_STATUS_PENDING:
case SRB_STATUS_SUCCESS:
- if(scsicmd->cmnd[0] == INQUIRY ){
- u8 b;
- u8 b1;
- /* We can't expose disk devices because we can't tell whether they
- * are the raw container drives or stand alone drives. If they have
- * the removable bit set then we should expose them though.
- */
- b = (*(u8*)scsicmd->buffer)&0x1f;
- b1 = ((u8*)scsicmd->buffer)[1];
- if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER
- || (b==TYPE_DISK && (b1&0x80)) ){
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
- /*
- * We will allow disk devices if in RAID/SCSI mode and
- * the channel is 2
- */
- } else if ((dev->raid_scsi_mode) &&
- (scmd_channel(scsicmd) == 2)) {
- scsicmd->result = DID_OK << 16 |
- COMMAND_COMPLETE << 8;
- } else {
- scsicmd->result = DID_NO_CONNECT << 16 |
- COMMAND_COMPLETE << 8;
- }
- } else {
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
- }
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
break;
case SRB_STATUS_DATA_OVERRUN:
switch(scsicmd->cmnd[0]){
@@ -1981,28 +1955,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
break;
case INQUIRY: {
- u8 b;
- u8 b1;
- /* We can't expose disk devices because we can't tell whether they
- * are the raw container drives or stand alone drives
- */
- b = (*(u8*)scsicmd->buffer)&0x0f;
- b1 = ((u8*)scsicmd->buffer)[1];
- if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER
- || (b==TYPE_DISK && (b1&0x80)) ){
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
- /*
- * We will allow disk devices if in RAID/SCSI mode and
- * the channel is 2
- */
- } else if ((dev->raid_scsi_mode) &&
- (scmd_channel(scsicmd) == 2)) {
- scsicmd->result = DID_OK << 16 |
- COMMAND_COMPLETE << 8;
- } else {
- scsicmd->result = DID_NO_CONNECT << 16 |
- COMMAND_COMPLETE << 8;
- }
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
break;
}
default:
@@ -2089,8 +2042,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
*/
scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
- fib_complete(fibptr);
- fib_free(fibptr);
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@@ -2142,10 +2095,10 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
- if (!(cmd_fibcontext = fib_alloc(dev))) {
+ if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
return -1;
}
- fib_init(cmd_fibcontext);
+ aac_fib_init(cmd_fibcontext);
srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
@@ -2179,7 +2132,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ScsiPortCommand64, cmd_fibcontext,
+ status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext,
fibsize, FsaNormal, 0, 1,
(fib_callback) aac_srb_callback,
(void *) scsicmd);
@@ -2201,7 +2154,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
+ status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
(fib_callback) aac_srb_callback, (void *) scsicmd);
}
/*
@@ -2211,9 +2164,9 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
return 0;
}
- printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status);
- fib_complete(cmd_fibcontext);
- fib_free(cmd_fibcontext);
+ printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
+ aac_fib_complete(cmd_fibcontext);
+ aac_fib_free(cmd_fibcontext);
return -1;
}
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 66dbb6d2c50..2d430b7e8cf 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1774,16 +1774,16 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor)
struct scsi_cmnd;
const char *aac_driverinfo(struct Scsi_Host *);
-struct fib *fib_alloc(struct aac_dev *dev);
-int fib_setup(struct aac_dev *dev);
-void fib_map_free(struct aac_dev *dev);
-void fib_free(struct fib * context);
-void fib_init(struct fib * context);
+struct fib *aac_fib_alloc(struct aac_dev *dev);
+int aac_fib_setup(struct aac_dev *dev);
+void aac_fib_map_free(struct aac_dev *dev);
+void aac_fib_free(struct fib * context);
+void aac_fib_init(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val);
-int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
+int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
-int fib_complete(struct fib * context);
+int aac_fib_complete(struct fib * context);
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
struct aac_dev *aac_init_adapter(struct aac_dev *dev);
int aac_get_config_status(struct aac_dev *dev);
@@ -1799,11 +1799,11 @@ unsigned int aac_command_normal(struct aac_queue * q);
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
int aac_command_thread(struct aac_dev * dev);
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
-int fib_adapter_complete(struct fib * fibptr, unsigned short size);
+int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
-int probe_container(struct aac_dev *dev, int cid);
+int aac_probe_container(struct aac_dev *dev, int cid);
extern int numacb;
extern int acbsize;
extern char aac_driver_version[];
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 4fe79cd7c95..47fefca7269 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
unsigned size;
int retval;
- fibptr = fib_alloc(dev);
+ fibptr = aac_fib_alloc(dev);
if(fibptr == NULL) {
return -ENOMEM;
}
@@ -73,7 +73,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* First copy in the header so that we can check the size field.
*/
if (copy_from_user((void *)kfib, arg, sizeof(struct aac_fibhdr))) {
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return -EFAULT;
}
/*
@@ -110,13 +110,13 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
*/
kfib->header.XferState = 0;
} else {
- retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
+ retval = aac_fib_send(le16_to_cpu(kfib->header.Command), fibptr,
le16_to_cpu(kfib->header.Size) , FsaNormal,
1, 1, NULL, NULL);
if (retval) {
goto cleanup;
}
- if (fib_complete(fibptr) != 0) {
+ if (aac_fib_complete(fibptr) != 0) {
retval = -EINVAL;
goto cleanup;
}
@@ -138,7 +138,7 @@ cleanup:
fibptr->hw_fib_pa = hw_fib_pa;
fibptr->hw_fib = hw_fib;
}
- fib_free(fibptr);
+ aac_fib_free(fibptr);
return retval;
}
@@ -464,10 +464,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
- if (!(srbfib = fib_alloc(dev))) {
+ if (!(srbfib = aac_fib_alloc(dev))) {
return -ENOMEM;
}
- fib_init(srbfib);
+ aac_fib_init(srbfib);
srbcmd = (struct aac_srb*) fib_data(srbfib);
@@ -601,7 +601,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
srbcmd->count = cpu_to_le32(byte_count);
psg->count = cpu_to_le32(sg_indx+1);
- status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
+ status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
} else {
struct user_sgmap* upsg = &user_srbcmd->sg;
struct sgmap* psg = &srbcmd->sg;
@@ -649,7 +649,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
srbcmd->count = cpu_to_le32(byte_count);
psg->count = cpu_to_le32(sg_indx+1);
- status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
+ status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
}
if (status != 0){
@@ -684,8 +684,8 @@ cleanup:
for(i=0; i <= sg_indx; i++){
kfree(sg_list[i]);
}
- fib_complete(srbfib);
- fib_free(srbfib);
+ aac_fib_complete(srbfib);
+ aac_fib_free(srbfib);
return rcode;
}
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 82821d331c0..1628d094943 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -185,17 +185,17 @@ int aac_send_shutdown(struct aac_dev * dev)
struct aac_close *cmd;
int status;
- fibctx = fib_alloc(dev);
+ fibctx = aac_fib_alloc(dev);
if (!fibctx)
return -ENOMEM;
- fib_init(fibctx);
+ aac_fib_init(fibctx);
cmd = (struct aac_close *) fib_data(fibctx);
cmd->command = cpu_to_le32(VM_CloseAll);
cmd->cid = cpu_to_le32(0xffffffff);
- status = fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibctx,
sizeof(struct aac_close),
FsaNormal,
@@ -203,8 +203,8 @@ int aac_send_shutdown(struct aac_dev * dev)
NULL, NULL);
if (status == 0)
- fib_complete(fibctx);
- fib_free(fibctx);
+ aac_fib_complete(fibctx);
+ aac_fib_free(fibctx);
return status;
}
@@ -427,7 +427,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
/*
* Initialize the list of fibs
*/
- if(fib_setup(dev)<0){
+ if (aac_fib_setup(dev) < 0) {
kfree(dev->queues);
return NULL;
}
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 38d6d00fb0f..609fd19b184 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -38,10 +38,10 @@
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/blkdev.h>
+#include <linux/delay.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <asm/semaphore.h>
-#include <asm/delay.h>
#include "aacraid.h"
@@ -67,27 +67,27 @@ static int fib_map_alloc(struct aac_dev *dev)
}
/**
- * fib_map_free - free the fib objects
+ * aac_fib_map_free - free the fib objects
* @dev: Adapter to free
*
* Free the PCI mappings and the memory allocated for FIB blocks
* on this adapter.
*/
-void fib_map_free(struct aac_dev *dev)
+void aac_fib_map_free(struct aac_dev *dev)
{
pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa);
}
/**
- * fib_setup - setup the fibs
+ * aac_fib_setup - setup the fibs
* @dev: Adapter to set up
*
* Allocate the PCI space for the fibs, map it and then intialise the
* fib area, the unmapped fib data and also the free list
*/
-int fib_setup(struct aac_dev * dev)
+int aac_fib_setup(struct aac_dev * dev)
{
struct fib *fibptr;
struct hw_fib *hw_fib_va;
@@ -134,14 +134,14 @@ int fib_setup(struct aac_dev * dev)
}
/**
- * fib_alloc - allocate a fib
+ * aac_fib_alloc - allocate a fib
* @dev: Adapter to allocate the fib for
*
* Allocate a fib from the adapter fib pool. If the pool is empty we
* return NULL.
*/
-struct fib * fib_alloc(struct aac_dev *dev)
+struct fib *aac_fib_alloc(struct aac_dev *dev)
{
struct fib * fibptr;
unsigned long flags;
@@ -170,14 +170,14 @@ struct fib * fib_alloc(struct aac_dev *dev)
}
/**
- * fib_free - free a fib
+ * aac_fib_free - free a fib
* @fibptr: fib to free up
*
* Frees up a fib and places it on the appropriate queue
* (either free or timed out)
*/
-void fib_free(struct fib * fibptr)
+void aac_fib_free(struct fib *fibptr)
{
unsigned long flags;
@@ -188,7 +188,7 @@ void fib_free(struct fib * fibptr)
fibptr->dev->timeout_fib = fibptr;
} else {
if (fibptr->hw_fib->header.XferState != 0) {
- printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
+ printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
(void*)fibptr,
le32_to_cpu(fibptr->hw_fib->header.XferState));
}
@@ -199,13 +199,13 @@ void fib_free(struct fib * fibptr)
}
/**
- * fib_init - initialise a fib
+ * aac_fib_init - initialise a fib
* @fibptr: The fib to initialize
*
* Set up the generic fib fields ready for use
*/
-void fib_init(struct fib *fibptr)
+void aac_fib_init(struct fib *fibptr)
{
struct hw_fib *hw_fib = fibptr->hw_fib;
@@ -362,7 +362,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
*/
/**
- * fib_send - send a fib to the adapter
+ * aac_fib_send - send a fib to the adapter
* @command: Command to send
* @fibptr: The fib
* @size: Size of fib data area
@@ -378,7 +378,9 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
* response FIB is received from the adapter.
*/
-int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data)
+int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
+ int priority, int wait, int reply, fib_callback callback,
+ void *callback_data)
{
struct aac_dev * dev = fibptr->dev;
struct hw_fib * hw_fib = fibptr->hw_fib;
@@ -493,7 +495,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
q->numpending++;
*(q->headers.producer) = cpu_to_le32(index + 1);
spin_unlock_irqrestore(q->lock, qflags);
- dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
+ dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index));
if (!(nointr & aac_config.irq_mod))
aac_adapter_notify(dev, AdapNormCmdQueue);
}
@@ -520,7 +522,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
list_del(&fibptr->queue);
spin_unlock_irqrestore(q->lock, qflags);
if (wait == -1) {
- printk(KERN_ERR "aacraid: fib_send: first asynchronous command timed out.\n"
+ printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n"
"Usually a result of a PCI interrupt routing problem;\n"
"update mother board BIOS or consider utilizing one of\n"
"the SAFE mode kernel options (acpi, apic etc)\n");
@@ -624,7 +626,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
}
/**
- * fib_adapter_complete - complete adapter issued fib
+ * aac_fib_adapter_complete - complete adapter issued fib
* @fibptr: fib to complete
* @size: size of fib
*
@@ -632,7 +634,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
* the adapter.
*/
-int fib_adapter_complete(struct fib * fibptr, unsigned short size)
+int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_dev * dev = fibptr->dev;
@@ -683,20 +685,20 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
}
else
{
- printk(KERN_WARNING "fib_adapter_complete: Unknown xferstate detected.\n");
+ printk(KERN_WARNING "aac_fib_adapter_complete: Unknown xferstate detected.\n");
BUG();
}
return 0;
}
/**
- * fib_complete - fib completion handler
+ * aac_fib_complete - fib completion handler
* @fib: FIB to complete
*
* Will do all necessary work to complete a FIB.
*/
-int fib_complete(struct fib * fibptr)
+int aac_fib_complete(struct fib *fibptr)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
@@ -995,14 +997,14 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (!dev || !dev->scsi_host_ptr)
return;
/*
- * force reload of disk info via probe_container
+ * force reload of disk info via aac_probe_container
*/
if ((device_config_needed == CHANGE)
&& (dev->fsa_dev[container].valid == 1))
dev->fsa_dev[container].valid = 2;
if ((device_config_needed == CHANGE) ||
(device_config_needed == ADD))
- probe_container(dev, container);
+ aac_probe_container(dev, container);
device = scsi_device_lookup(dev->scsi_host_ptr,
CONTAINER_TO_CHANNEL(container),
CONTAINER_TO_ID(container),
@@ -1104,7 +1106,7 @@ int aac_command_thread(struct aac_dev * dev)
/* Handle Driver Notify Events */
aac_handle_aif(dev, fib);
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fib, (u16)sizeof(u32));
+ aac_fib_adapter_complete(fib, (u16)sizeof(u32));
} else {
struct list_head *entry;
/* The u32 here is important and intended. We are using
@@ -1241,7 +1243,7 @@ int aac_command_thread(struct aac_dev * dev)
* Set the status of this FIB
*/
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fib, sizeof(u32));
+ aac_fib_adapter_complete(fib, sizeof(u32));
spin_unlock_irqrestore(&dev->fib_lock, flagv);
/* Free up the remaining resources */
hw_fib_p = hw_fib_pool;
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index 439948ef825..f6bcb9486f8 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -206,7 +206,7 @@ unsigned int aac_command_normal(struct aac_queue *q)
* Set the status of this FIB
*/
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fib, sizeof(u32));
+ aac_fib_adapter_complete(fib, sizeof(u32));
spin_lock_irqsave(q->lock, flags);
}
}
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 0bf5f9a943e..27161789056 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -385,17 +385,45 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
static int aac_slave_configure(struct scsi_device *sdev)
{
- struct Scsi_Host *host = sdev->host;
+ if (sdev_channel(sdev) == CONTAINER_CHANNEL) {
+ sdev->skip_ms_page_8 = 1;
+ sdev->skip_ms_page_3f = 1;
+ }
+ if ((sdev->type == TYPE_DISK) &&
+ (sdev_channel(sdev) != CONTAINER_CHANNEL)) {
+ struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
+ if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
+ sdev->no_uld_attach = 1;
+ }
+ if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
+ (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
+ struct scsi_device * dev;
+ struct Scsi_Host *host = sdev->host;
+ unsigned num_lsu = 0;
+ unsigned num_one = 0;
+ unsigned depth;
- if (sdev->tagged_supported)
- scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128);
- else
+ __shost_for_each_device(dev, host) {
+ if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
+ (sdev_channel(dev) == CONTAINER_CHANNEL))
+ ++num_lsu;
+ else
+ ++num_one;
+ }
+ if (num_lsu == 0)
+ ++num_lsu;
+ depth = (host->can_queue - num_one) / num_lsu;
+ if (depth > 256)
+ depth = 256;
+ else if (depth < 2)
+ depth = 2;
+ scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
+ if (!(((struct aac_dev *)host->hostdata)->adapter_info.options &
+ AAC_OPT_NEW_COMM))
+ blk_queue_max_segment_size(sdev->request_queue, 65536);
+ } else
scsi_adjust_queue_depth(sdev, 0, 1);
- if (!(((struct aac_dev *)host->hostdata)->adapter_info.options
- & AAC_OPT_NEW_COMM))
- blk_queue_max_segment_size(sdev->request_queue, 65536);
-
return 0;
}
@@ -870,7 +898,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
/*
* max channel will be the physical channels plus 1 virtual channel
- * all containers are on the virtual channel 0
+ * all containers are on the virtual channel 0 (CONTAINER_CHANNEL)
* physical channels are address by their actual physical number+1
*/
if (aac->nondasd_support == 1)
@@ -913,7 +941,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac_adapter_disable_int(aac);
free_irq(pdev->irq, aac);
out_unmap:
- fib_map_free(aac);
+ aac_fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
kfree(aac->queues);
iounmap(aac->regs.sa);
@@ -947,7 +975,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
aac_send_shutdown(aac);
aac_adapter_disable_int(aac);
- fib_map_free(aac);
+ aac_fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
aac->comm_phys);
kfree(aac->queues);
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index d113290b5fc..a800fb51168 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -276,6 +276,20 @@ static const struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* ESB2 */
{ PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH7-M DH */
+ { PCI_VENDOR_ID_INTEL, 0x2821, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2822, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2824, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2829, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8M */
+ { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8M */
+ { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* JMicron JMB360 */
+ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* JMicron JMB363 */
{ } /* terminate list */
};
@@ -792,7 +806,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
void __iomem *mmio = probe_ent->mmio_base;
u32 tmp, cap_save;
- u16 tmp16;
unsigned int i, j, using_dac;
int rc;
void __iomem *port_mmio;
@@ -826,9 +839,13 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
writel(0xf, mmio + HOST_PORTS_IMPL);
(void) readl(mmio + HOST_PORTS_IMPL); /* flush */
- pci_read_config_word(pdev, 0x92, &tmp16);
- tmp16 |= 0xf;
- pci_write_config_word(pdev, 0x92, tmp16);
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+ u16 tmp16;
+
+ pci_read_config_word(pdev, 0x92, &tmp16);
+ tmp16 |= 0xf;
+ pci_write_config_word(pdev, 0x92, tmp16);
+ }
hpriv->cap = readl(mmio + HOST_CAP);
hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
@@ -1072,6 +1089,10 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (have_msi)
hpriv->flags |= AHCI_FLAG_MSI;
+ /* JMicron-specific fixup: make sure we're in AHCI mode */
+ if (pdev->vendor == 0x197b)
+ pci_write_config_byte(pdev, 0x41, 0xa1);
+
/* initialize adapter */
rc = ahci_host_init(probe_ent);
if (rc)
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index 69ed77fcb71..7955ebe8e1e 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -37,13 +37,13 @@ config AIC79XX_CMDS_PER_DEVICE
config AIC79XX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
depends on SCSI_AIC79XX
- default "15000"
+ default "5000"
---help---
The number of milliseconds to delay after an initial bus reset.
The bus settle delay following all error recovery actions is
dictated by the SCSI layer and is not affected by this value.
- Default: 15000 (15 seconds)
+ Default: 5000 (5 seconds)
config AIC79XX_BUILD_FIRMWARE
bool "Build Adapter Firmware with Kernel Build"
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 2cfdbef447d..1d11f7e7756 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#109 $
*
* $FreeBSD$
*/
@@ -222,6 +222,7 @@ typedef enum {
typedef enum {
AHD_FENONE = 0x00000,
AHD_WIDE = 0x00001,/* Wide Channel */
+ AHD_AIC79XXB_SLOWCRC = 0x00002,/* SLOWCRC bit should be set */
AHD_MULTI_FUNC = 0x00100,/* Multi-Function/Channel Device */
AHD_TARGETMODE = 0x01000,/* Has tested target mode support */
AHD_MULTIROLE = 0x02000,/* Space for two roles at a time */
diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
index 3a3204703b1..be14e2ecb8f 100644
--- a/drivers/scsi/aic7xxx/aic79xx.reg
+++ b/drivers/scsi/aic7xxx/aic79xx.reg
@@ -1,7 +1,7 @@
/*
* Aic79xx register and scratch ram definitions.
*
- * Copyright (c) 1994-2001 Justin T. Gibbs.
+ * Copyright (c) 1994-2001, 2004 Justin T. Gibbs.
* Copyright (c) 2000-2002 Adaptec Inc.
* All rights reserved.
*
@@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@@ -3715,8 +3715,9 @@ scratch_ram {
SEQ_FLAGS2 {
size 1
- field TARGET_MSG_PENDING 0x02
- field SELECTOUT_QFROZEN 0x04
+ field PENDING_MK_MESSAGE 0x01
+ field TARGET_MSG_PENDING 0x02
+ field SELECTOUT_QFROZEN 0x04
}
ALLOCFIFO_SCBPTR {
@@ -3777,6 +3778,26 @@ scratch_ram {
CMDSIZE_TABLE {
size 8
}
+ /*
+ * When an SCB with the MK_MESSAGE flag is
+ * queued to the controller, it cannot enter
+ * the waiting for selection list until the
+ * selections for any previously queued
+ * commands to that target complete. During
+ * the wait, the MK_MESSAGE SCB is queued
+ * here.
+ */
+ MK_MESSAGE_SCB {
+ size 2
+ }
+ /*
+ * Saved SCSIID of MK_MESSAGE_SCB to avoid
+ * an extra SCBPTR operation when deciding
+ * if the MK_MESSAGE_SCB can be run.
+ */
+ MK_MESSAGE_SCSIID {
+ size 1
+ }
}
/************************* Hardware SCB Definition ****************************/
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq
index bef1f9d369b..58bc17591b5 100644
--- a/drivers/scsi/aic7xxx/aic79xx.seq
+++ b/drivers/scsi/aic7xxx/aic79xx.seq
@@ -1,7 +1,7 @@
/*
* Adaptec U320 device driver firmware for Linux and FreeBSD.
*
- * Copyright (c) 1994-2001 Justin T. Gibbs.
+ * Copyright (c) 1994-2001, 2004 Justin T. Gibbs.
* Copyright (c) 2000-2002 Adaptec Inc.
* All rights reserved.
*
@@ -40,7 +40,7 @@
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $"
PATCH_ARG_LIST = "struct ahd_softc *ahd"
PREFIX = "ahd_"
@@ -110,10 +110,8 @@ check_waiting_list:
* one last time.
*/
test SSTAT0, SELDO jnz select_out;
-END_CRITICAL;
call start_selection;
idle_loop_checkbus:
-BEGIN_CRITICAL;
test SSTAT0, SELDO jnz select_out;
END_CRITICAL;
test SSTAT0, SELDI jnz select_in;
@@ -294,7 +292,6 @@ fetch_new_scb_inprog:
test CCSCBCTL, ARRDONE jz return;
fetch_new_scb_done:
and CCSCBCTL, ~(CCARREN|CCSCBEN);
- bmov REG0, SCBPTR, 2;
clr A;
add CMDS_PENDING, 1;
adc CMDS_PENDING[1], A;
@@ -316,43 +313,117 @@ fetch_new_scb_done:
clr SCB_FIFO_USE_COUNT;
/* Update the next SCB address to download. */
bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4;
+ /*
+ * NULL out the SCB links since these fields
+ * occupy the same location as SCB_NEXT_SCB_BUSADDR.
+ */
mvi SCB_NEXT[1], SCB_LIST_NULL;
mvi SCB_NEXT2[1], SCB_LIST_NULL;
/* Increment our position in the QINFIFO. */
mov NONE, SNSCB_QOFF;
+
/*
- * SCBs that want to send messages are always
- * queued independently. This ensures that they
- * are at the head of the SCB list to select out
- * to a target and we will see the MK_MESSAGE flag.
+ * Save SCBID of this SCB in REG0 since
+ * SCBPTR will be clobbered during target
+ * list updates. We also record the SCB's
+ * flags so that we can refer to them even
+ * after SCBPTR has been changed.
+ */
+ bmov REG0, SCBPTR, 2;
+ mov A, SCB_CONTROL;
+
+ /*
+ * Find the tail SCB of the execution queue
+ * for this target.
*/
- test SCB_CONTROL, MK_MESSAGE jnz first_new_target_scb;
shr SINDEX, 3, SCB_SCSIID;
and SINDEX, ~0x1;
mvi SINDEX[1], (WAITING_SCB_TAILS >> 8);
bmov DINDEX, SINDEX, 2;
bmov SCBPTR, SINDIR, 2;
+
+ /*
+ * Update the tail to point to the new SCB.
+ */
bmov DINDIR, REG0, 2;
+
+ /*
+ * If the queue was empty, queue this SCB as
+ * the first for this target.
+ */
cmp SCBPTR[1], SCB_LIST_NULL je first_new_target_scb;
+
+ /*
+ * SCBs that want to send messages must always be
+ * at the head of their per-target queue so that
+ * ATN can be asserted even if the current
+ * negotiation agreement is packetized. If the
+ * target queue is empty, the SCB can be queued
+ * immediately. If the queue is not empty, we must
+ * wait for it to empty before entering this SCB
+ * into the waiting for selection queue. Otherwise
+ * our batching and round-robin selection scheme
+ * could allow commands to be queued out of order.
+ * To simplify the implementation, we stop pulling
+ * new commands from the host until the MK_MESSAGE
+ * SCB can be queued to the waiting for selection
+ * list.
+ */
+ test A, MK_MESSAGE jz batch_scb;
+
+ /*
+ * If the last SCB is also a MK_MESSAGE SCB, then
+ * order is preserved even if we batch.
+ */
+ test SCB_CONTROL, MK_MESSAGE jz batch_scb;
+
+ /*
+ * Defer this SCB and stop fetching new SCBs until
+ * it can be queued. Since the SCB_SCSIID of the
+ * tail SCB must be the same as that of the newly
+ * queued SCB, there is no need to restore the SCBID
+ * here.
+ */
+ or SEQ_FLAGS2, PENDING_MK_MESSAGE;
+ bmov MK_MESSAGE_SCB, REG0, 2;
+ mov MK_MESSAGE_SCSIID, SCB_SCSIID ret;
+
+batch_scb:
+ /*
+ * Otherwise just update the previous tail SCB to
+ * point to the new tail.
+ */
bmov SCB_NEXT, REG0, 2 ret;
+
first_new_target_scb:
+ /*
+ * Append SCB to the tail of the waiting for
+ * selection list.
+ */
cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb;
bmov SCBPTR, WAITING_TID_TAIL, 2;
bmov SCB_NEXT2, REG0, 2;
bmov WAITING_TID_TAIL, REG0, 2 ret;
first_new_scb:
+ /*
+ * Whole list is empty, so the head of
+ * the list must be initialized too.
+ */
bmov WAITING_TID_HEAD, REG0, 2;
bmov WAITING_TID_TAIL, REG0, 2 ret;
END_CRITICAL;
scbdma_idle:
/*
- * Give precedence to downloading new SCBs to execute
- * unless select-outs are currently frozen.
+ * Don't bother downloading new SCBs to execute
+ * if select-outs are currently frozen or we have
+ * a MK_MESSAGE SCB waiting to enter the queue.
*/
- test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz . + 2;
+ test SEQ_FLAGS2, SELECTOUT_QFROZEN|PENDING_MK_MESSAGE
+ jnz scbdma_no_new_scbs;
BEGIN_CRITICAL;
test QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb;
+scbdma_no_new_scbs:
cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb;
cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return;
/* FALLTHROUGH */
@@ -671,27 +742,41 @@ curscb_ww_done:
}
/*
- * Requeue any SCBs not sent, to the tail of the waiting Q.
+ * The whole list made it. Clear our tail pointer to indicate
+ * that the per-target selection queue is now empty.
*/
- cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done;
+ cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_clear_tail;
/*
+ * Requeue any SCBs not sent, to the tail of the waiting Q.
* We know that neither the per-TID list nor the list of
- * TIDs is empty. Use this knowledge to our advantage.
+ * TIDs is empty. Use this knowledge to our advantage and
+ * queue the remainder to the tail of the global execution
+ * queue.
*/
bmov REG0, SCB_NEXT, 2;
+select_out_queue_remainder:
bmov SCBPTR, WAITING_TID_TAIL, 2;
bmov SCB_NEXT2, REG0, 2;
bmov WAITING_TID_TAIL, REG0, 2;
jmp select_out_inc_tid_q;
-select_out_list_done:
+select_out_clear_tail:
+ /*
+ * Queue any pending MK_MESSAGE SCB for this target now
+ * that the queue is empty.
+ */
+ test SEQ_FLAGS2, PENDING_MK_MESSAGE jz select_out_no_mk_message_scb;
+ mov A, MK_MESSAGE_SCSIID;
+ cmp SCB_SCSIID, A jne select_out_no_mk_message_scb;
+ and SEQ_FLAGS2, ~PENDING_MK_MESSAGE;
+ bmov REG0, MK_MESSAGE_SCB, 2;
+ jmp select_out_queue_remainder;
+
+select_out_no_mk_message_scb:
/*
- * The whole list made it. Just clear our TID's tail pointer
- * unless we were queued independently due to our need to
- * send a message.
+ * Clear this target's execution tail and increment the queue.
*/
- test SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q;
shr DINDEX, 3, SCB_SCSIID;
or DINDEX, 1; /* Want only the second byte */
mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8);
@@ -703,8 +788,8 @@ select_out_inc_tid_q:
mvi WAITING_TID_TAIL[1], SCB_LIST_NULL;
bmov SCBPTR, CURRSCB, 2;
mvi CLRSINT0, CLRSELDO;
- test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase;
- test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase;
+ test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_mode_cleared;
+ test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_mode_cleared;
/*
* If this is a packetized connection, return to our
@@ -2127,6 +2212,18 @@ SET_DST_MODE M_DFF0;
mvi DFFSXFRCTL, CLRCHN;
unexpected_nonpkt_mode_cleared:
mvi CLRSINT2, CLRNONPACKREQ;
+ if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
+ /*
+ * Test to ensure that the bus has not
+ * already gone free prior to clearing
+ * any stale busfree status. This avoids
+ * a window whereby a busfree just after
+ * a selection could be missed.
+ */
+ test SCSISIGI, BSYI jz . + 2;
+ mvi CLRSINT1,CLRBUSFREE;
+ or SIMODE1, ENBUSFREE;
+ }
test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase;
SET_SEQINTCODE(ENTERING_NONPACK)
jmp ITloop;
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index db8f5ce99ee..342f77966a5 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#250 $
*/
#ifdef __linux__
@@ -197,7 +197,8 @@ static int ahd_search_scb_list(struct ahd_softc *ahd, int target,
char channel, int lun, u_int tag,
role_t role, uint32_t status,
ahd_search_action action,
- u_int *list_head, u_int tid);
+ u_int *list_head, u_int *list_tail,
+ u_int tid);
static void ahd_stitch_tid_list(struct ahd_softc *ahd,
u_int tid_prev, u_int tid_cur,
u_int tid_next);
@@ -1660,7 +1661,8 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
* so just clear the error.
*/
ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ);
- } else if ((status & BUSFREE) != 0) {
+ } else if ((status & BUSFREE) != 0
+ || (lqistat1 & LQOBUSFREE) != 0) {
u_int lqostat1;
int restart;
int clear_fifo;
@@ -2025,10 +2027,6 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
u_int waiting_t;
u_int next;
- if ((busfreetime & BUSFREE_LQO) == 0)
- printf("%s: Warning, BUSFREE time is 0x%x. "
- "Expected BUSFREE_LQO.\n",
- ahd_name(ahd), busfreetime);
/*
* The LQO manager detected an unexpected busfree
* either:
@@ -2251,8 +2249,14 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
struct ahd_tmode_tstate *tstate;
/*
- * PPR Rejected. Try non-ppr negotiation
- * and retry command.
+ * PPR Rejected.
+ *
+ * If the previous negotiation was packetized,
+ * this could be because the device has been
+ * reset without our knowledge. Force our
+ * current negotiation to async and retry the
+ * negotiation. Otherwise retry the command
+ * with non-ppr negotiation.
*/
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
@@ -2261,11 +2265,34 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
devinfo.our_scsiid,
devinfo.target, &tstate);
- tinfo->curr.transport_version = 2;
- tinfo->goal.transport_version = 2;
- tinfo->goal.ppr_options = 0;
- ahd_qinfifo_requeue_tail(ahd, scb);
- printerror = 0;
+ if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) {
+ ahd_set_width(ahd, &devinfo,
+ MSG_EXT_WDTR_BUS_8_BIT,
+ AHD_TRANS_CUR,
+ /*paused*/TRUE);
+ ahd_set_syncrate(ahd, &devinfo,
+ /*period*/0, /*offset*/0,
+ /*ppr_options*/0,
+ AHD_TRANS_CUR,
+ /*paused*/TRUE);
+ /*
+ * The expect PPR busfree handler below
+ * will effect the retry and necessary
+ * abort.
+ */
+ } else {
+ tinfo->curr.transport_version = 2;
+ tinfo->goal.transport_version = 2;
+ tinfo->goal.ppr_options = 0;
+ /*
+ * Remove any SCBs in the waiting for selection
+ * queue that may also be for this target so
+ * that command ordering is preserved.
+ */
+ ahd_freeze_devq(ahd, scb);
+ ahd_qinfifo_requeue_tail(ahd, scb);
+ printerror = 0;
+ }
} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
&& ppr_busfree == 0) {
/*
@@ -2280,6 +2307,12 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
MSG_EXT_WDTR_BUS_8_BIT,
AHD_TRANS_CUR|AHD_TRANS_GOAL,
/*paused*/TRUE);
+ /*
+ * Remove any SCBs in the waiting for selection
+ * queue that may also be for this target so that
+ * command ordering is preserved.
+ */
+ ahd_freeze_devq(ahd, scb);
ahd_qinfifo_requeue_tail(ahd, scb);
printerror = 0;
} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
@@ -2297,6 +2330,12 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
/*ppr_options*/0,
AHD_TRANS_CUR|AHD_TRANS_GOAL,
/*paused*/TRUE);
+ /*
+ * Remove any SCBs in the waiting for selection
+ * queue that may also be for this target so that
+ * command ordering is preserved.
+ */
+ ahd_freeze_devq(ahd, scb);
ahd_qinfifo_requeue_tail(ahd, scb);
printerror = 0;
} else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0
@@ -2369,14 +2408,14 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
*/
printf("%s: ", ahd_name(ahd));
}
- if (lastphase != P_BUSFREE)
- ahd_force_renegotiation(ahd, &devinfo);
printf("Unexpected busfree %s, %d SCBs aborted, "
"PRGMCNT == 0x%x\n",
ahd_lookup_phase_entry(lastphase)->phasemsg,
aborted,
ahd_inw(ahd, PRGMCNT));
ahd_dump_card_state(ahd);
+ if (lastphase != P_BUSFREE)
+ ahd_force_renegotiation(ahd, &devinfo);
}
/* Always restart the sequencer. */
return (1);
@@ -3293,6 +3332,15 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
con_opts |= WIDEXFER;
/*
+ * Slow down our CRC interval to be
+ * compatible with packetized U320 devices
+ * that can't handle a CRC at full speed
+ */
+ if (ahd->features & AHD_AIC79XXB_SLOWCRC) {
+ con_opts |= ENSLOWCRC;
+ }
+
+ /*
* During packetized transfers, the target will
* give us the oportunity to send command packets
* without us asserting attention.
@@ -3315,7 +3363,6 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
{
struct scb *pending_scb;
int pending_scb_count;
- u_int scb_tag;
int paused;
u_int saved_scbptr;
ahd_mode_state saved_modes;
@@ -3333,7 +3380,6 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
pending_scb_count = 0;
LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
struct ahd_devinfo devinfo;
- struct hardware_scb *pending_hscb;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
@@ -3341,11 +3387,10 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
devinfo.our_scsiid,
devinfo.target, &tstate);
- pending_hscb = pending_scb->hscb;
if ((tstate->auto_negotiate & devinfo.target_mask) == 0
&& (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
- pending_hscb->control &= ~MK_MESSAGE;
+ pending_scb->hscb->control &= ~MK_MESSAGE;
}
ahd_sync_scb(ahd, pending_scb,
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
@@ -3377,18 +3422,15 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
saved_scbptr = ahd_get_scbptr(ahd);
/* Ensure that the hscbs down on the card match the new information */
- for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {
- struct hardware_scb *pending_hscb;
+ LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
+ u_int scb_tag;
u_int control;
- pending_scb = ahd_lookup_scb(ahd, scb_tag);
- if (pending_scb == NULL)
- continue;
+ scb_tag = SCB_GET_TAG(pending_scb);
ahd_set_scbptr(ahd, scb_tag);
- pending_hscb = pending_scb->hscb;
control = ahd_inb_scbram(ahd, SCB_CONTROL);
control &= ~MK_MESSAGE;
- control |= pending_hscb->control & MK_MESSAGE;
+ control |= pending_scb->hscb->control & MK_MESSAGE;
ahd_outb(ahd, SCB_CONTROL, control);
}
ahd_set_scbptr(ahd, saved_scbptr);
@@ -6500,13 +6542,14 @@ ahd_chip_init(struct ahd_softc *ahd)
| ENLQIOVERI_LQ|ENLQIOVERI_NLQ);
ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC);
/*
- * An interrupt from LQOBUSFREE is made redundant by the
- * BUSFREE interrupt. We choose to have the sequencer catch
- * LQOPHCHGINPKT errors manually for the command phase at the
- * start of a packetized selection case.
- ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE|ENLQOPHACHGINPKT);
+ * We choose to have the sequencer catch LQOPHCHGINPKT errors
+ * manually for the command phase at the start of a packetized
+ * selection case. ENLQOBUSFREE should be made redundant by
+ * the BUSFREE interrupt, but it seems that some LQOBUSFREE
+ * events fail to assert the BUSFREE interrupt so we must
+ * also enable LQOBUSFREE interrupts.
*/
- ahd_outb(ahd, LQOMODE1, 0);
+ ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE);
/*
* Setup sequencer interrupt handlers.
@@ -6617,6 +6660,8 @@ ahd_chip_init(struct ahd_softc *ahd)
/* We don't have any waiting selections */
ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL);
ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL);
+ ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL);
+ ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF);
for (i = 0; i < AHD_NUM_TARGETS; i++)
ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL);
@@ -6704,6 +6749,18 @@ ahd_chip_init(struct ahd_softc *ahd)
ahd_loadseq(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+
+ if (ahd->features & AHD_AIC79XXB_SLOWCRC) {
+ u_int negodat3 = ahd_inb(ahd, NEGCONOPTS);
+
+ negodat3 |= ENSLOWCRC;
+ ahd_outb(ahd, NEGCONOPTS, negodat3);
+ negodat3 = ahd_inb(ahd, NEGCONOPTS);
+ if (!(negodat3 & ENSLOWCRC))
+ printf("aic79xx: failed to set the SLOWCRC bit\n");
+ else
+ printf("aic79xx: SLOWCRC bit set\n");
+ }
}
/*
@@ -7260,12 +7317,28 @@ ahd_reset_cmds_pending(struct ahd_softc *ahd)
ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
}
+void
+ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
+{
+ cam_status ostat;
+ cam_status cstat;
+
+ ostat = ahd_get_transaction_status(scb);
+ if (ostat == CAM_REQ_INPROG)
+ ahd_set_transaction_status(scb, status);
+ cstat = ahd_get_transaction_status(scb);
+ if (cstat != CAM_REQ_CMP)
+ ahd_freeze_scb(scb);
+ ahd_done(ahd, scb);
+}
+
int
ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
int lun, u_int tag, role_t role, uint32_t status,
ahd_search_action action)
{
struct scb *scb;
+ struct scb *mk_msg_scb;
struct scb *prev_scb;
ahd_mode_state saved_modes;
u_int qinstart;
@@ -7274,6 +7347,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
u_int tid_next;
u_int tid_prev;
u_int scbid;
+ u_int seq_flags2;
u_int savedscbptr;
uint32_t busaddr;
int found;
@@ -7329,23 +7403,10 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
found++;
switch (action) {
case SEARCH_COMPLETE:
- {
- cam_status ostat;
- cam_status cstat;
-
- ostat = ahd_get_transaction_status(scb);
- if (ostat == CAM_REQ_INPROG)
- ahd_set_transaction_status(scb,
- status);
- cstat = ahd_get_transaction_status(scb);
- if (cstat != CAM_REQ_CMP)
- ahd_freeze_scb(scb);
if ((scb->flags & SCB_ACTIVE) == 0)
printf("Inactive SCB in qinfifo\n");
- ahd_done(ahd, scb);
-
+ ahd_done_with_status(ahd, scb, status);
/* FALLTHROUGH */
- }
case SEARCH_REMOVE:
break;
case SEARCH_PRINT:
@@ -7375,21 +7436,24 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
* looking for matches.
*/
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+ seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2);
+ if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) {
+ scbid = ahd_inw(ahd, MK_MESSAGE_SCB);
+ mk_msg_scb = ahd_lookup_scb(ahd, scbid);
+ } else
+ mk_msg_scb = NULL;
savedscbptr = ahd_get_scbptr(ahd);
tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
tid_prev = SCB_LIST_NULL;
targets = 0;
for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) {
u_int tid_head;
+ u_int tid_tail;
- /*
- * We limit based on the number of SCBs since
- * MK_MESSAGE SCBs are not in the per-tid lists.
- */
targets++;
- if (targets > AHD_SCB_MAX) {
+ if (targets > AHD_NUM_TARGETS)
panic("TID LIST LOOP");
- }
+
if (scbid >= ahd->scb_data.numscbs) {
printf("%s: Waiting TID List inconsistency. "
"SCB index == 0x%x, yet numscbs == 0x%x.",
@@ -7419,8 +7483,71 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
tid_head = scbid;
found += ahd_search_scb_list(ahd, target, channel,
lun, tag, role, status,
- action, &tid_head,
+ action, &tid_head, &tid_tail,
SCB_GET_TARGET(ahd, scb));
+ /*
+ * Check any MK_MESSAGE SCB that is still waiting to
+ * enter this target's waiting for selection queue.
+ */
+ if (mk_msg_scb != NULL
+ && ahd_match_scb(ahd, mk_msg_scb, target, channel,
+ lun, tag, role)) {
+
+ /*
+ * We found an scb that needs to be acted on.
+ */
+ found++;
+ switch (action) {
+ case SEARCH_COMPLETE:
+ if ((mk_msg_scb->flags & SCB_ACTIVE) == 0)
+ printf("Inactive SCB pending MK_MSG\n");
+ ahd_done_with_status(ahd, mk_msg_scb, status);
+ /* FALLTHROUGH */
+ case SEARCH_REMOVE:
+ {
+ u_int tail_offset;
+
+ printf("Removing MK_MSG scb\n");
+
+ /*
+ * Reset our tail to the tail of the
+ * main per-target list.
+ */
+ tail_offset = WAITING_SCB_TAILS
+ + (2 * SCB_GET_TARGET(ahd, mk_msg_scb));
+ ahd_outw(ahd, tail_offset, tid_tail);
+
+ seq_flags2 &= ~PENDING_MK_MESSAGE;
+ ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
+ ahd_outw(ahd, CMDS_PENDING,
+ ahd_inw(ahd, CMDS_PENDING)-1);
+ mk_msg_scb = NULL;
+ break;
+ }
+ case SEARCH_PRINT:
+ printf(" 0x%x", SCB_GET_TAG(scb));
+ /* FALLTHROUGH */
+ case SEARCH_COUNT:
+ break;
+ }
+ }
+
+ if (mk_msg_scb != NULL
+ && SCBID_IS_NULL(tid_head)
+ && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
+ SCB_LIST_NULL, ROLE_UNKNOWN)) {
+
+ /*
+ * When removing the last SCB for a target
+ * queue with a pending MK_MESSAGE scb, we
+ * must queue the MK_MESSAGE scb.
+ */
+ printf("Queueing mk_msg_scb\n");
+ tid_head = ahd_inw(ahd, MK_MESSAGE_SCB);
+ seq_flags2 &= ~PENDING_MK_MESSAGE;
+ ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
+ mk_msg_scb = NULL;
+ }
if (tid_head != scbid)
ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next);
if (!SCBID_IS_NULL(tid_head))
@@ -7428,6 +7555,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
if (action == SEARCH_PRINT)
printf(")\n");
}
+
+ /* Restore saved state. */
ahd_set_scbptr(ahd, savedscbptr);
ahd_restore_modes(ahd, saved_modes);
return (found);
@@ -7436,7 +7565,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
static int
ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
int lun, u_int tag, role_t role, uint32_t status,
- ahd_search_action action, u_int *list_head, u_int tid)
+ ahd_search_action action, u_int *list_head,
+ u_int *list_tail, u_int tid)
{
struct scb *scb;
u_int scbid;
@@ -7448,6 +7578,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
found = 0;
prev = SCB_LIST_NULL;
next = *list_head;
+ *list_tail = SCB_LIST_NULL;
for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) {
if (scbid >= ahd->scb_data.numscbs) {
printf("%s:SCB List inconsistency. "
@@ -7463,6 +7594,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
panic("Waiting List traversal\n");
}
ahd_set_scbptr(ahd, scbid);
+ *list_tail = scbid;
next = ahd_inw_scbram(ahd, SCB_NEXT);
if (ahd_match_scb(ahd, scb, target, channel,
lun, SCB_LIST_NULL, role) == 0) {
@@ -7472,24 +7604,14 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
found++;
switch (action) {
case SEARCH_COMPLETE:
- {
- cam_status ostat;
- cam_status cstat;
-
- ostat = ahd_get_transaction_status(scb);
- if (ostat == CAM_REQ_INPROG)
- ahd_set_transaction_status(scb, status);
- cstat = ahd_get_transaction_status(scb);
- if (cstat != CAM_REQ_CMP)
- ahd_freeze_scb(scb);
if ((scb->flags & SCB_ACTIVE) == 0)
printf("Inactive SCB in Waiting List\n");
- ahd_done(ahd, scb);
+ ahd_done_with_status(ahd, scb, status);
/* FALLTHROUGH */
- }
case SEARCH_REMOVE:
ahd_rem_wscb(ahd, scbid, prev, next, tid);
- if (prev == SCB_LIST_NULL)
+ *list_tail = prev;
+ if (SCBID_IS_NULL(prev))
*list_head = next;
break;
case SEARCH_PRINT:
@@ -7558,14 +7680,17 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
}
/*
- * SCBs that had MK_MESSAGE set in them will not
- * be queued to the per-target lists, so don't
- * blindly clear the tail pointer.
+ * SCBs that have MK_MESSAGE set in them may
+ * cause the tail pointer to be updated without
+ * setting the next pointer of the previous tail.
+ * Only clear the tail if the removed SCB was
+ * the tail.
*/
tail_offset = WAITING_SCB_TAILS + (2 * tid);
if (SCBID_IS_NULL(next)
&& ahd_inw(ahd, tail_offset) == scbid)
ahd_outw(ahd, tail_offset, prev);
+
ahd_add_scb_to_free_list(ahd, scbid);
return (next);
}
@@ -8148,11 +8273,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
ahd_setup_data_scb(ahd, scb);
scb->flags |= SCB_SENSE;
ahd_queue_scb(ahd, scb);
- /*
- * Ensure we have enough time to actually
- * retrieve the sense.
- */
- ahd_scb_timer_reset(scb, 5 * 1000000);
break;
}
case SCSI_STATUS_OK:
@@ -8793,6 +8913,9 @@ ahd_dump_card_state(struct ahd_softc *ahd)
* Mode independent registers.
*/
cur_col = 0;
+ ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50);
+ ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50);
+ ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50);
ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50);
ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50);
ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50);
@@ -8808,6 +8931,12 @@ ahd_dump_card_state(struct ahd_softc *ahd)
ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50);
ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50);
ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50);
+ ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50);
+ ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT),
+ &cur_col, 50);
+ ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50);
+ ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID),
+ &cur_col, 50);
ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50);
ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50);
ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50);
@@ -8915,7 +9044,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
fifo_scbptr = ahd_get_scbptr(ahd);
- printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
+ printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
ahd_name(ahd), i,
(dffstat & (FIFO0FREE << i)) ? "Free" : "Active",
ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);
@@ -8970,6 +9099,9 @@ ahd_dump_card_state(struct ahd_softc *ahd)
printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n",
ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT),
ahd_inb(ahd, MAXCMDCNT));
+ printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n",
+ ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID),
+ ahd_inb(ahd, SAVED_LUN));
ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50);
printf("\n");
ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
index 91c4f7f484b..8ad3ce945b9 100644
--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
+++ b/drivers/scsi/aic7xxx/aic79xx_inline.h
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#59 $
*
* $FreeBSD$
*/
@@ -804,9 +804,10 @@ ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
uint64_t host_dataptr;
host_dataptr = ahd_le64toh(scb->hscb->dataptr);
- printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
+ printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
ahd_name(ahd),
- SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr),
+ SCB_GET_TAG(scb), scb->hscb->scsiid,
+ ahd_le32toh(scb->hscb->hscb_busaddr),
(u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
(u_int)(host_dataptr & 0xFFFFFFFF),
ahd_le32toh(scb->hscb->datacnt));
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 2567e29960b..7254ea535a1 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -314,6 +314,21 @@ static uint32_t aic79xx_seltime;
*/
uint32_t aic79xx_periodic_otag;
+/* Some storage boxes are using an LSI chip which has a bug making it
+ * impossible to use aic79xx Rev B chip in 320 speeds. The following
+ * storage boxes have been reported to be buggy:
+ * EonStor 3U 16-Bay: U16U-G3A3
+ * EonStor 2U 12-Bay: U12U-G3A3
+ * SentinelRAID: 2500F R5 / R6
+ * SentinelRAID: 2500F R1
+ * SentinelRAID: 2500F/1500F
+ * SentinelRAID: 150F
+ *
+ * To get around this LSI bug, you can set your board to 160 mode
+ * or you can enable the SLOWCRC bit.
+ */
+uint32_t aic79xx_slowcrc;
+
/*
* Module information and settable options.
*/
@@ -343,6 +358,7 @@ MODULE_PARM_DESC(aic79xx,
" amplitude:<int> Set the signal amplitude (0-7).\n"
" seltime:<int> Selection Timeout:\n"
" (0/256ms,1/128ms,2/64ms,3/32ms)\n"
+" slowcrc Turn on the SLOWCRC bit (Rev B only)\n"
"\n"
" Sample /etc/modprobe.conf line:\n"
" Enable verbose logging\n"
@@ -1003,6 +1019,7 @@ aic79xx_setup(char *s)
{ "slewrate", NULL },
{ "precomp", NULL },
{ "amplitude", NULL },
+ { "slowcrc", &aic79xx_slowcrc },
};
end = strchr(s, '\0');
@@ -1072,7 +1089,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
return (ENOMEM);
*((struct ahd_softc **)host->hostdata) = ahd;
- ahd_lock(ahd, &s);
ahd->platform_data->host = host;
host->can_queue = AHD_MAX_QUEUE;
host->cmd_per_lun = 2;
@@ -1083,7 +1099,9 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
host->max_lun = AHD_NUM_LUNS;
host->max_channel = 0;
host->sg_tablesize = AHD_NSEG;
+ ahd_lock(ahd, &s);
ahd_set_unit(ahd, ahd_linux_unit++);
+ ahd_unlock(ahd, &s);
sprintf(buf, "scsi%d", host->host_no);
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
if (new_name != NULL) {
@@ -1093,7 +1111,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
host->unique_id = ahd->unit;
ahd_linux_initialize_scsi_bus(ahd);
ahd_intr_enable(ahd, TRUE);
- ahd_unlock(ahd, &s);
host->transportt = ahd_linux_transport_template;
@@ -1127,6 +1144,7 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
{
u_int target_id;
u_int numtarg;
+ unsigned long s;
target_id = 0;
numtarg = 0;
@@ -1139,6 +1157,8 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
else
numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
+ ahd_lock(ahd, &s);
+
/*
* Force negotiation to async for all targets that
* will not see an initial bus reset.
@@ -1155,16 +1175,12 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
ahd_update_neg_request(ahd, &devinfo, tstate,
tinfo, AHD_NEG_ALWAYS);
}
+ ahd_unlock(ahd, &s);
/* Give the bus some time to recover */
if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
ahd_freeze_simq(ahd);
- init_timer(&ahd->platform_data->reset_timer);
- ahd->platform_data->reset_timer.data = (u_long)ahd;
- ahd->platform_data->reset_timer.expires =
- jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
- ahd->platform_data->reset_timer.function =
- (ahd_linux_callback_t *)ahd_release_simq;
- add_timer(&ahd->platform_data->reset_timer);
+ msleep(AIC79XX_RESET_DELAY);
+ ahd_release_simq(ahd);
}
}
@@ -2033,6 +2049,9 @@ ahd_linux_sem_timeout(u_long arg)
void
ahd_freeze_simq(struct ahd_softc *ahd)
{
+ unsigned long s;
+
+ ahd_lock(ahd, &s);
ahd->platform_data->qfrozen++;
if (ahd->platform_data->qfrozen == 1) {
scsi_block_requests(ahd->platform_data->host);
@@ -2040,6 +2059,7 @@ ahd_freeze_simq(struct ahd_softc *ahd)
CAM_LUN_WILDCARD, SCB_LIST_NULL,
ROLE_INITIATOR, CAM_REQUEUE_REQ);
}
+ ahd_unlock(ahd, &s);
}
void
@@ -2344,8 +2364,9 @@ done:
ahd_name(ahd), dev->active);
retval = FAILED;
}
- }
- ahd_unlock(ahd, &flags);
+ } else
+ ahd_unlock(ahd, &flags);
+
return (retval);
}
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index cb74fccc810..9cb10134510 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#137 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#166 $
*
*/
#ifndef _AIC79XX_LINUX_H_
@@ -228,7 +228,6 @@ typedef struct timer_list ahd_timer_t;
typedef void ahd_linux_callback_t (u_long);
static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
ahd_callback_t *func, void *arg);
-static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
static __inline void
ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
@@ -243,12 +242,6 @@ ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
add_timer(timer);
}
-static __inline void
-ahd_scb_timer_reset(struct scb *scb, u_int usec)
-{
- mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
-}
-
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
@@ -389,7 +382,6 @@ struct ahd_platform_data {
spinlock_t spin_lock;
u_int qfrozen;
- struct timer_list reset_timer;
struct semaphore eh_sem;
struct Scsi_Host *host; /* pointer to scsi host */
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index bf360ae021a..ebbf7e4ff4c 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -220,10 +220,10 @@ ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
*base2 = pci_resource_start(ahd->dev_softc, 3);
if (*base == 0 || *base2 == 0)
return (ENOMEM);
- if (request_region(*base, 256, "aic79xx") == 0)
+ if (!request_region(*base, 256, "aic79xx"))
return (ENOMEM);
- if (request_region(*base2, 256, "aic79xx") == 0) {
- release_region(*base2, 256);
+ if (!request_region(*base2, 256, "aic79xx")) {
+ release_region(*base, 256);
return (ENOMEM);
}
return (0);
@@ -237,7 +237,7 @@ ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
u_long start;
u_long base_page;
u_long base_offset;
- int error;
+ int error = 0;
if (aic79xx_allow_memio == 0)
return (ENOMEM);
@@ -245,16 +245,15 @@ ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) != 0)
return (ENOMEM);
- error = 0;
start = pci_resource_start(ahd->dev_softc, 1);
base_page = start & PAGE_MASK;
base_offset = start - base_page;
if (start != 0) {
*bus_addr = start;
- if (request_mem_region(start, 0x1000, "aic79xx") == 0)
+ if (!request_mem_region(start, 0x1000, "aic79xx"))
error = ENOMEM;
- if (error == 0) {
- *maddr = ioremap_nocache(base_page, base_offset + 256);
+ if (!error) {
+ *maddr = ioremap_nocache(base_page, base_offset + 512);
if (*maddr == NULL) {
error = ENOMEM;
release_mem_region(start, 0x1000);
@@ -344,7 +343,7 @@ ahd_pci_map_int(struct ahd_softc *ahd)
error = request_irq(ahd->dev_softc->irq, ahd_linux_isr,
SA_SHIRQ, "aic79xx", ahd);
- if (error == 0)
+ if (!error)
ahd->platform_data->irq = ahd->dev_softc->irq;
return (-error);
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 196a6344b03..757242e522c 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#92 $
*/
#ifdef __linux__
@@ -950,12 +950,19 @@ ahd_aic790X_setup(struct ahd_softc *ahd)
if ((ahd->flags & AHD_HP_BOARD) == 0)
AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);
} else {
+ /* This is revision B and newer. */
+ extern uint32_t aic79xx_slowcrc;
u_int devconfig1;
ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
- | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY;
+ | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY
+ | AHD_BUSFREEREV_BUG;
ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;
+ /* If the user requested the the SLOWCRC bit to be set. */
+ if (aic79xx_slowcrc)
+ ahd->features |= AHD_AIC79XXB_SLOWCRC;
+
/*
* Some issues have been resolved in the 7901B.
*/
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
index 8763b158856..2068e00d2c7 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
*/
typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahd_reg_parse_entry {
@@ -2204,6 +2204,20 @@ ahd_reg_print_t ahd_cmdsize_table_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_mk_message_scb_print;
+#else
+#define ahd_mk_message_scb_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "MK_MESSAGE_SCB", 0x160, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_mk_message_scsiid_print;
+#else
+#define ahd_mk_message_scsiid_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "MK_MESSAGE_SCSIID", 0x162, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_base_print;
#else
#define ahd_scb_base_print(regvalue, cur_col, wrap) \
@@ -3638,6 +3652,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SEQ_FLAGS2 0x14d
#define SELECTOUT_QFROZEN 0x04
#define TARGET_MSG_PENDING 0x02
+#define PENDING_MK_MESSAGE 0x01
#define ALLOCFIFO_SCBPTR 0x14e
@@ -3655,6 +3670,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CMDSIZE_TABLE 0x158
+#define MK_MESSAGE_SCB 0x160
+
+#define MK_MESSAGE_SCSIID 0x162
+
#define SCB_BASE 0x180
#define SCB_RESIDUAL_DATACNT 0x180
@@ -3800,5 +3819,5 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
/* Exported Labels */
-#define LABEL_seq_isr 0x285
-#define LABEL_timer_isr 0x281
+#define LABEL_seq_isr 0x28f
+#define LABEL_timer_isr 0x28b
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
index a4137c98537..db38a61a8cb 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
*/
#include "aic79xx_osm.h"
@@ -3382,6 +3382,7 @@ ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
+ { "PENDING_MK_MESSAGE", 0x01, 0x01 },
{ "TARGET_MSG_PENDING", 0x02, 0x02 },
{ "SELECTOUT_QFROZEN", 0x04, 0x04 }
};
@@ -3389,7 +3390,7 @@ static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
int
ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2",
+ return (ahd_print_register(SEQ_FLAGS2_parse_table, 3, "SEQ_FLAGS2",
0x14d, regvalue, cur_col, wrap));
}
@@ -3450,6 +3451,20 @@ ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
+ahd_mk_message_scb_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCB",
+ 0x160, regvalue, cur_col, wrap));
+}
+
+int
+ahd_mk_message_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCSIID",
+ 0x162, regvalue, cur_col, wrap));
+}
+
+int
ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_BASE",
diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
index b1e5365be23..11bed07e90b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
@@ -2,17 +2,17 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
*/
static uint8_t seqprog[] = {
0xff, 0x02, 0x06, 0x78,
- 0x00, 0xea, 0x64, 0x59,
+ 0x00, 0xea, 0x6e, 0x59,
0x01, 0xea, 0x04, 0x30,
0xff, 0x04, 0x0c, 0x78,
- 0x19, 0xea, 0x64, 0x59,
+ 0x19, 0xea, 0x6e, 0x59,
0x19, 0xea, 0x04, 0x00,
- 0x33, 0xea, 0x5e, 0x59,
+ 0x33, 0xea, 0x68, 0x59,
0x33, 0xea, 0x00, 0x00,
0x60, 0x3a, 0x3a, 0x68,
0x04, 0x4d, 0x35, 0x78,
@@ -33,15 +33,15 @@ static uint8_t seqprog[] = {
0xff, 0xea, 0x62, 0x02,
0x00, 0xe2, 0x3a, 0x40,
0xff, 0x21, 0x3b, 0x70,
- 0x40, 0x4b, 0xaa, 0x69,
- 0x00, 0xe2, 0x68, 0x59,
- 0x40, 0x4b, 0xaa, 0x69,
- 0x20, 0x4b, 0x96, 0x69,
+ 0x40, 0x4b, 0xb4, 0x69,
+ 0x00, 0xe2, 0x72, 0x59,
+ 0x40, 0x4b, 0xb4, 0x69,
+ 0x20, 0x4b, 0xa0, 0x69,
0xfc, 0x42, 0x44, 0x78,
0x10, 0x40, 0x44, 0x78,
- 0x00, 0xe2, 0xfc, 0x5d,
+ 0x00, 0xe2, 0x10, 0x5e,
0x20, 0x4d, 0x48, 0x78,
- 0x00, 0xe2, 0xfc, 0x5d,
+ 0x00, 0xe2, 0x10, 0x5e,
0x30, 0x3f, 0xc0, 0x09,
0x30, 0xe0, 0x50, 0x60,
0x7f, 0x4a, 0x94, 0x08,
@@ -51,7 +51,7 @@ static uint8_t seqprog[] = {
0x00, 0xe2, 0x76, 0x58,
0x00, 0xe2, 0x86, 0x58,
0x00, 0xe2, 0x06, 0x40,
- 0x33, 0xea, 0x5e, 0x59,
+ 0x33, 0xea, 0x68, 0x59,
0x33, 0xea, 0x00, 0x00,
0x01, 0x52, 0x84, 0x78,
0x02, 0x58, 0x50, 0x31,
@@ -59,26 +59,26 @@ static uint8_t seqprog[] = {
0xff, 0x97, 0x6f, 0x78,
0x50, 0x4b, 0x6a, 0x68,
0xbf, 0x3a, 0x74, 0x08,
- 0x14, 0xea, 0x64, 0x59,
+ 0x14, 0xea, 0x6e, 0x59,
0x14, 0xea, 0x04, 0x00,
0x08, 0x92, 0x25, 0x03,
0xff, 0x90, 0x5f, 0x68,
- 0x00, 0xe2, 0x76, 0x5b,
+ 0x00, 0xe2, 0x8a, 0x5b,
0x00, 0xe2, 0x5e, 0x40,
- 0x00, 0xea, 0x5e, 0x59,
+ 0x00, 0xea, 0x68, 0x59,
0x01, 0xea, 0x00, 0x30,
0x80, 0xf9, 0x7e, 0x68,
- 0x00, 0xe2, 0x5c, 0x59,
- 0x11, 0xea, 0x5e, 0x59,
+ 0x00, 0xe2, 0x66, 0x59,
+ 0x11, 0xea, 0x68, 0x59,
0x11, 0xea, 0x00, 0x00,
- 0x80, 0xf9, 0x5c, 0x79,
+ 0x80, 0xf9, 0x66, 0x79,
0xff, 0xea, 0xd4, 0x0d,
- 0x22, 0xea, 0x5e, 0x59,
+ 0x22, 0xea, 0x68, 0x59,
0x22, 0xea, 0x00, 0x00,
0x10, 0x16, 0x90, 0x78,
0x10, 0x16, 0x2c, 0x00,
0x01, 0x0b, 0xae, 0x32,
- 0x18, 0xad, 0x12, 0x79,
+ 0x18, 0xad, 0x1c, 0x79,
0x04, 0xad, 0xdc, 0x68,
0x80, 0xad, 0x84, 0x78,
0x10, 0xad, 0xaa, 0x78,
@@ -118,7 +118,6 @@ static uint8_t seqprog[] = {
0x80, 0x18, 0x30, 0x04,
0x40, 0xad, 0x84, 0x78,
0xe7, 0xad, 0x5a, 0x09,
- 0x02, 0xa8, 0x40, 0x31,
0xff, 0xea, 0xc0, 0x09,
0x01, 0x54, 0xa9, 0x1a,
0x00, 0x55, 0xab, 0x22,
@@ -128,24 +127,30 @@ static uint8_t seqprog[] = {
0xff, 0xea, 0x5a, 0x03,
0xff, 0xea, 0x5e, 0x03,
0x01, 0x10, 0xd4, 0x31,
- 0x10, 0x92, 0x07, 0x69,
+ 0x02, 0xa8, 0x40, 0x31,
+ 0x01, 0x92, 0xc1, 0x31,
0x3d, 0x93, 0xc5, 0x29,
0xfe, 0xe2, 0xc4, 0x09,
0x01, 0xea, 0xc6, 0x01,
0x02, 0xe2, 0xc8, 0x31,
0x02, 0xec, 0x50, 0x31,
0x02, 0xa0, 0xda, 0x31,
- 0xff, 0xa9, 0x06, 0x71,
+ 0xff, 0xa9, 0x10, 0x71,
+ 0x10, 0xe0, 0x0e, 0x79,
+ 0x10, 0x92, 0x0f, 0x79,
+ 0x01, 0x4d, 0x9b, 0x02,
+ 0x02, 0xa0, 0xc0, 0x32,
+ 0x01, 0x93, 0xc5, 0x36,
0x02, 0xa0, 0x58, 0x37,
- 0xff, 0x21, 0x0f, 0x71,
+ 0xff, 0x21, 0x19, 0x71,
0x02, 0x22, 0x51, 0x31,
0x02, 0xa0, 0x5c, 0x33,
0x02, 0xa0, 0x44, 0x36,
0x02, 0xa0, 0x40, 0x32,
0x02, 0xa0, 0x44, 0x36,
- 0x04, 0x4d, 0x17, 0x69,
- 0x40, 0x16, 0x48, 0x69,
- 0xff, 0x2d, 0x4d, 0x61,
+ 0x05, 0x4d, 0x21, 0x69,
+ 0x40, 0x16, 0x52, 0x69,
+ 0xff, 0x2d, 0x57, 0x61,
0xff, 0x29, 0x85, 0x70,
0x02, 0x28, 0x55, 0x32,
0x01, 0xea, 0x5a, 0x01,
@@ -159,22 +164,22 @@ static uint8_t seqprog[] = {
0x01, 0x56, 0xad, 0x1a,
0xff, 0x54, 0xa9, 0x1a,
0xff, 0x55, 0xab, 0x22,
- 0xff, 0x8d, 0x41, 0x71,
- 0x80, 0xac, 0x40, 0x71,
- 0x20, 0x16, 0x40, 0x69,
+ 0xff, 0x8d, 0x4b, 0x71,
+ 0x80, 0xac, 0x4a, 0x71,
+ 0x20, 0x16, 0x4a, 0x69,
0x00, 0xac, 0xc4, 0x19,
- 0x07, 0xe2, 0x40, 0xf9,
+ 0x07, 0xe2, 0x4a, 0xf9,
0x02, 0x8c, 0x51, 0x31,
- 0x00, 0xe2, 0x24, 0x41,
+ 0x00, 0xe2, 0x2e, 0x41,
0x01, 0xac, 0x08, 0x31,
0x09, 0xea, 0x5a, 0x01,
0x02, 0x8c, 0x51, 0x32,
0xff, 0xea, 0x1a, 0x07,
0x04, 0x24, 0xf9, 0x30,
- 0x1d, 0xea, 0x52, 0x41,
+ 0x1d, 0xea, 0x5c, 0x41,
0x02, 0x2c, 0x51, 0x31,
0x04, 0xa8, 0xf9, 0x30,
- 0x19, 0xea, 0x52, 0x41,
+ 0x19, 0xea, 0x5c, 0x41,
0x06, 0xea, 0x08, 0x81,
0x01, 0xe2, 0x5a, 0x35,
0x02, 0xf2, 0xf0, 0x31,
@@ -190,27 +195,27 @@ static uint8_t seqprog[] = {
0x02, 0x20, 0xb9, 0x30,
0x02, 0x20, 0x51, 0x31,
0x4c, 0x93, 0xd7, 0x28,
- 0x10, 0x92, 0x77, 0x79,
+ 0x10, 0x92, 0x81, 0x79,
0x01, 0x6b, 0xc0, 0x30,
0x02, 0x64, 0xc8, 0x00,
0x40, 0x3a, 0x74, 0x04,
0x00, 0xe2, 0x76, 0x58,
- 0x33, 0xea, 0x5e, 0x59,
+ 0x33, 0xea, 0x68, 0x59,
0x33, 0xea, 0x00, 0x00,
0x30, 0x3f, 0xc0, 0x09,
- 0x30, 0xe0, 0x78, 0x61,
- 0x20, 0x3f, 0x8e, 0x69,
- 0x10, 0x3f, 0x78, 0x79,
+ 0x30, 0xe0, 0x82, 0x61,
+ 0x20, 0x3f, 0x98, 0x69,
+ 0x10, 0x3f, 0x82, 0x79,
0x02, 0xea, 0x7e, 0x00,
- 0x00, 0xea, 0x5e, 0x59,
+ 0x00, 0xea, 0x68, 0x59,
0x01, 0xea, 0x00, 0x30,
0x02, 0x4e, 0x51, 0x35,
0x01, 0xea, 0x7e, 0x00,
- 0x11, 0xea, 0x5e, 0x59,
+ 0x11, 0xea, 0x68, 0x59,
0x11, 0xea, 0x00, 0x00,
0x02, 0x4e, 0x51, 0x35,
0xc0, 0x4a, 0x94, 0x00,
- 0x04, 0x41, 0x9c, 0x79,
+ 0x04, 0x41, 0xa6, 0x79,
0x08, 0xea, 0x98, 0x00,
0x08, 0x57, 0xae, 0x00,
0x08, 0x3c, 0x78, 0x00,
@@ -218,12 +223,12 @@ static uint8_t seqprog[] = {
0x0f, 0x67, 0xc0, 0x09,
0x00, 0x3a, 0x75, 0x02,
0x20, 0xea, 0x96, 0x00,
- 0x00, 0xe2, 0x14, 0x42,
+ 0x00, 0xe2, 0x28, 0x42,
0xc0, 0x4a, 0x94, 0x00,
- 0x40, 0x3a, 0xc8, 0x69,
+ 0x40, 0x3a, 0xd2, 0x69,
0x02, 0x55, 0x06, 0x68,
- 0x02, 0x56, 0xc8, 0x69,
- 0xff, 0x5b, 0xc8, 0x61,
+ 0x02, 0x56, 0xd2, 0x69,
+ 0xff, 0x5b, 0xd2, 0x61,
0x02, 0x20, 0x51, 0x31,
0x80, 0xea, 0xb2, 0x01,
0x44, 0xea, 0x00, 0x00,
@@ -231,40 +236,45 @@ static uint8_t seqprog[] = {
0x33, 0xea, 0x00, 0x00,
0xff, 0xea, 0xb2, 0x09,
0xff, 0xe0, 0xc0, 0x19,
- 0xff, 0xe0, 0xca, 0x79,
+ 0xff, 0xe0, 0xd4, 0x79,
0x02, 0xac, 0x51, 0x31,
- 0x00, 0xe2, 0xc0, 0x41,
+ 0x00, 0xe2, 0xca, 0x41,
0x02, 0x5e, 0x50, 0x31,
0x02, 0xa8, 0xb8, 0x30,
0x02, 0x5c, 0x50, 0x31,
- 0xff, 0xad, 0xdb, 0x71,
+ 0xff, 0xad, 0xe5, 0x71,
0x02, 0xac, 0x41, 0x31,
0x02, 0x22, 0x51, 0x31,
0x02, 0xa0, 0x5c, 0x33,
0x02, 0xa0, 0x44, 0x32,
- 0x00, 0xe2, 0xe4, 0x41,
- 0x10, 0x92, 0xe5, 0x69,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x01, 0x4d, 0xf1, 0x79,
+ 0x01, 0x62, 0xc1, 0x31,
+ 0x00, 0x93, 0xf1, 0x61,
+ 0xfe, 0x4d, 0x9b, 0x0a,
+ 0x02, 0x60, 0x41, 0x31,
+ 0x00, 0xe2, 0xdc, 0x41,
0x3d, 0x93, 0xc9, 0x29,
0x01, 0xe4, 0xc8, 0x01,
0x01, 0xea, 0xca, 0x01,
0xff, 0xea, 0xda, 0x01,
0x02, 0x20, 0x51, 0x31,
0x02, 0xae, 0x41, 0x32,
- 0xff, 0x21, 0xed, 0x61,
+ 0xff, 0x21, 0x01, 0x62,
0xff, 0xea, 0x46, 0x02,
0x02, 0x5c, 0x50, 0x31,
0x40, 0xea, 0x96, 0x00,
- 0x02, 0x56, 0x04, 0x6e,
- 0x01, 0x55, 0x04, 0x6e,
- 0x10, 0x92, 0xf9, 0x79,
- 0x10, 0x40, 0x02, 0x6a,
- 0x01, 0x56, 0x02, 0x7a,
+ 0x02, 0x56, 0x20, 0x6e,
+ 0x01, 0x55, 0x20, 0x6e,
+ 0x10, 0x92, 0x0d, 0x7a,
+ 0x10, 0x40, 0x16, 0x6a,
+ 0x01, 0x56, 0x16, 0x7a,
0xff, 0x97, 0x07, 0x78,
- 0x13, 0xea, 0x64, 0x59,
+ 0x13, 0xea, 0x6e, 0x59,
0x13, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x06, 0x40,
0xbf, 0x3a, 0x74, 0x08,
- 0x04, 0x41, 0x08, 0x7a,
+ 0x04, 0x41, 0x1c, 0x7a,
0x08, 0xea, 0x98, 0x00,
0x08, 0x57, 0xae, 0x00,
0x01, 0x93, 0x75, 0x32,
@@ -272,108 +282,108 @@ static uint8_t seqprog[] = {
0x40, 0xea, 0x72, 0x02,
0x08, 0x3c, 0x78, 0x00,
0x80, 0xea, 0x6e, 0x02,
- 0x00, 0xe2, 0xe2, 0x5b,
+ 0x00, 0xe2, 0xf6, 0x5b,
0x01, 0x3c, 0xc1, 0x31,
- 0x9f, 0xe0, 0x84, 0x7c,
- 0x80, 0xe0, 0x28, 0x72,
- 0xa0, 0xe0, 0x64, 0x72,
- 0xc0, 0xe0, 0x5a, 0x72,
- 0xe0, 0xe0, 0x94, 0x72,
- 0x01, 0xea, 0x64, 0x59,
+ 0x9f, 0xe0, 0x98, 0x7c,
+ 0x80, 0xe0, 0x3c, 0x72,
+ 0xa0, 0xe0, 0x78, 0x72,
+ 0xc0, 0xe0, 0x6e, 0x72,
+ 0xe0, 0xe0, 0xa8, 0x72,
+ 0x01, 0xea, 0x6e, 0x59,
0x01, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x14, 0x42,
- 0x80, 0x39, 0x2f, 0x7a,
- 0x03, 0xea, 0x64, 0x59,
+ 0x00, 0xe2, 0x28, 0x42,
+ 0x80, 0x39, 0x43, 0x7a,
+ 0x03, 0xea, 0x6e, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0xee, 0x00, 0x36, 0x6a,
+ 0xee, 0x00, 0x4a, 0x6a,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x5e, 0x59,
+ 0x33, 0xea, 0x68, 0x59,
0x33, 0xea, 0x00, 0x00,
0x02, 0xa8, 0x9c, 0x32,
- 0x00, 0xe2, 0x7e, 0x59,
+ 0x00, 0xe2, 0x88, 0x59,
0xef, 0x96, 0xd5, 0x19,
- 0x00, 0xe2, 0x46, 0x52,
+ 0x00, 0xe2, 0x5a, 0x52,
0x09, 0x80, 0xe1, 0x30,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0x4c, 0x42,
+ 0x00, 0xe2, 0x60, 0x42,
0x01, 0x96, 0xd1, 0x30,
0x10, 0x80, 0x89, 0x31,
0x20, 0xea, 0x32, 0x00,
0xbf, 0x39, 0x73, 0x0a,
- 0x10, 0x4c, 0x56, 0x6a,
- 0x20, 0x19, 0x4e, 0x6a,
- 0x20, 0x19, 0x52, 0x6a,
- 0x02, 0x4d, 0x14, 0x6a,
+ 0x10, 0x4c, 0x6a, 0x6a,
+ 0x20, 0x19, 0x62, 0x6a,
+ 0x20, 0x19, 0x66, 0x6a,
+ 0x02, 0x4d, 0x28, 0x6a,
0x40, 0x39, 0x73, 0x02,
- 0x00, 0xe2, 0x14, 0x42,
- 0x80, 0x39, 0xd5, 0x6a,
+ 0x00, 0xe2, 0x28, 0x42,
+ 0x80, 0x39, 0xe9, 0x6a,
0x01, 0x44, 0x10, 0x33,
0x08, 0x92, 0x25, 0x03,
- 0x00, 0xe2, 0x14, 0x42,
+ 0x00, 0xe2, 0x28, 0x42,
0x10, 0xea, 0x80, 0x00,
0x01, 0x37, 0xc5, 0x31,
- 0x80, 0xe2, 0x80, 0x62,
- 0x10, 0x92, 0xa5, 0x6a,
+ 0x80, 0xe2, 0x94, 0x62,
+ 0x10, 0x92, 0xb9, 0x6a,
0xc0, 0x94, 0xc5, 0x01,
- 0x40, 0x92, 0x71, 0x6a,
+ 0x40, 0x92, 0x85, 0x6a,
0xbf, 0xe2, 0xc4, 0x09,
- 0x20, 0x92, 0x85, 0x7a,
+ 0x20, 0x92, 0x99, 0x7a,
0x01, 0xe2, 0x88, 0x30,
- 0x00, 0xe2, 0xe2, 0x5b,
- 0xa0, 0x3c, 0x8d, 0x62,
+ 0x00, 0xe2, 0xf6, 0x5b,
+ 0xa0, 0x3c, 0xa1, 0x62,
0x23, 0x92, 0x89, 0x08,
- 0x00, 0xe2, 0xe2, 0x5b,
- 0xa0, 0x3c, 0x8d, 0x62,
- 0x00, 0xa8, 0x84, 0x42,
- 0xff, 0xe2, 0x84, 0x62,
- 0x00, 0xe2, 0xa4, 0x42,
+ 0x00, 0xe2, 0xf6, 0x5b,
+ 0xa0, 0x3c, 0xa1, 0x62,
+ 0x00, 0xa8, 0x98, 0x42,
+ 0xff, 0xe2, 0x98, 0x62,
+ 0x00, 0xe2, 0xb8, 0x42,
0x40, 0xea, 0x98, 0x00,
0x01, 0xe2, 0x88, 0x30,
- 0x00, 0xe2, 0xe2, 0x5b,
- 0xa0, 0x3c, 0x63, 0x72,
+ 0x00, 0xe2, 0xf6, 0x5b,
+ 0xa0, 0x3c, 0x77, 0x72,
0x40, 0xea, 0x98, 0x00,
0x01, 0x37, 0x95, 0x32,
0x08, 0xea, 0x6e, 0x02,
- 0x00, 0xe2, 0x14, 0x42,
- 0xe0, 0xea, 0xfe, 0x5b,
- 0x80, 0xe0, 0xe0, 0x6a,
- 0x04, 0xe0, 0x92, 0x73,
- 0x02, 0xe0, 0xc4, 0x73,
- 0x00, 0xea, 0x3e, 0x73,
- 0x03, 0xe0, 0xd4, 0x73,
- 0x23, 0xe0, 0xb6, 0x72,
- 0x08, 0xe0, 0xdc, 0x72,
- 0x00, 0xe2, 0xe2, 0x5b,
- 0x07, 0xea, 0x64, 0x59,
+ 0x00, 0xe2, 0x28, 0x42,
+ 0xe0, 0xea, 0x12, 0x5c,
+ 0x80, 0xe0, 0xf4, 0x6a,
+ 0x04, 0xe0, 0xa6, 0x73,
+ 0x02, 0xe0, 0xd8, 0x73,
+ 0x00, 0xea, 0x52, 0x73,
+ 0x03, 0xe0, 0xe8, 0x73,
+ 0x23, 0xe0, 0xca, 0x72,
+ 0x08, 0xe0, 0xf0, 0x72,
+ 0x00, 0xe2, 0xf6, 0x5b,
+ 0x07, 0xea, 0x6e, 0x59,
0x07, 0xea, 0x04, 0x00,
- 0x08, 0x48, 0x15, 0x72,
- 0x04, 0x48, 0xb3, 0x62,
+ 0x08, 0x48, 0x29, 0x72,
+ 0x04, 0x48, 0xc7, 0x62,
0x01, 0x49, 0x89, 0x30,
- 0x00, 0xe2, 0xa4, 0x42,
+ 0x00, 0xe2, 0xb8, 0x42,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0xa4, 0x42,
+ 0x00, 0xe2, 0xb8, 0x42,
0x01, 0x00, 0x6c, 0x32,
- 0x33, 0xea, 0x5e, 0x59,
+ 0x33, 0xea, 0x68, 0x59,
0x33, 0xea, 0x00, 0x00,
0x4c, 0x3a, 0xc1, 0x28,
0x01, 0x64, 0xc0, 0x31,
- 0x00, 0x36, 0x5f, 0x59,
+ 0x00, 0x36, 0x69, 0x59,
0x01, 0x36, 0x01, 0x30,
- 0x01, 0xe0, 0xda, 0x7a,
- 0xa0, 0xea, 0xf4, 0x5b,
- 0x01, 0xa0, 0xda, 0x62,
- 0x01, 0x84, 0xcf, 0x7a,
- 0x01, 0x95, 0xdd, 0x6a,
- 0x05, 0xea, 0x64, 0x59,
+ 0x01, 0xe0, 0xee, 0x7a,
+ 0xa0, 0xea, 0x08, 0x5c,
+ 0x01, 0xa0, 0xee, 0x62,
+ 0x01, 0x84, 0xe3, 0x7a,
+ 0x01, 0x95, 0xf1, 0x6a,
+ 0x05, 0xea, 0x6e, 0x59,
0x05, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xdc, 0x42,
- 0x03, 0xea, 0x64, 0x59,
+ 0x00, 0xe2, 0xf0, 0x42,
+ 0x03, 0xea, 0x6e, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xdc, 0x42,
- 0x07, 0xea, 0x06, 0x5c,
+ 0x00, 0xe2, 0xf0, 0x42,
+ 0x07, 0xea, 0x1a, 0x5c,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0x14, 0x42,
+ 0x00, 0xe2, 0x28, 0x42,
0x3f, 0xe0, 0x76, 0x0a,
0xc0, 0x3a, 0xc1, 0x09,
0x00, 0x3b, 0x51, 0x01,
@@ -384,54 +394,54 @@ static uint8_t seqprog[] = {
0x01, 0xea, 0xc6, 0x01,
0x02, 0xe2, 0xc8, 0x31,
0x02, 0xec, 0x40, 0x31,
- 0xff, 0xa1, 0xfc, 0x72,
+ 0xff, 0xa1, 0x10, 0x73,
0x02, 0xe8, 0xda, 0x31,
0x02, 0xa0, 0x50, 0x31,
- 0x00, 0xe2, 0x1e, 0x43,
+ 0x00, 0xe2, 0x32, 0x43,
0x80, 0x39, 0x73, 0x02,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0xe2, 0x5b,
+ 0x00, 0xe2, 0xf6, 0x5b,
0x01, 0x39, 0x73, 0x02,
- 0xe0, 0x3c, 0x39, 0x63,
+ 0xe0, 0x3c, 0x4d, 0x63,
0x02, 0x39, 0x73, 0x02,
- 0x20, 0x46, 0x32, 0x63,
+ 0x20, 0x46, 0x46, 0x63,
0xff, 0xea, 0x52, 0x09,
- 0xa8, 0xea, 0xf4, 0x5b,
- 0x04, 0x92, 0x19, 0x7b,
+ 0xa8, 0xea, 0x08, 0x5c,
+ 0x04, 0x92, 0x2d, 0x7b,
0x01, 0x3a, 0xc1, 0x31,
- 0x00, 0x93, 0x19, 0x63,
+ 0x00, 0x93, 0x2d, 0x63,
0x01, 0x3b, 0xc1, 0x31,
- 0x00, 0x94, 0x23, 0x73,
+ 0x00, 0x94, 0x37, 0x73,
0x01, 0xa9, 0x52, 0x11,
- 0xff, 0xa9, 0x0e, 0x6b,
- 0x00, 0xe2, 0x32, 0x43,
+ 0xff, 0xa9, 0x22, 0x6b,
+ 0x00, 0xe2, 0x46, 0x43,
0x10, 0x39, 0x73, 0x02,
- 0x04, 0x92, 0x33, 0x7b,
+ 0x04, 0x92, 0x47, 0x7b,
0xfb, 0x92, 0x25, 0x0b,
0xff, 0xea, 0x72, 0x0a,
- 0x01, 0xa4, 0x2d, 0x6b,
+ 0x01, 0xa4, 0x41, 0x6b,
0x02, 0xa8, 0x9c, 0x32,
- 0x00, 0xe2, 0x7e, 0x59,
- 0x10, 0x92, 0xdd, 0x7a,
- 0xff, 0xea, 0x06, 0x5c,
- 0x00, 0xe2, 0xdc, 0x42,
- 0x04, 0xea, 0x64, 0x59,
+ 0x00, 0xe2, 0x88, 0x59,
+ 0x10, 0x92, 0xf1, 0x7a,
+ 0xff, 0xea, 0x1a, 0x5c,
+ 0x00, 0xe2, 0xf0, 0x42,
+ 0x04, 0xea, 0x6e, 0x59,
0x04, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xdc, 0x42,
- 0x04, 0xea, 0x64, 0x59,
+ 0x00, 0xe2, 0xf0, 0x42,
+ 0x04, 0xea, 0x6e, 0x59,
0x04, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x14, 0x42,
- 0x08, 0x92, 0xd5, 0x7a,
- 0xc0, 0x39, 0x49, 0x7b,
- 0x80, 0x39, 0xd5, 0x6a,
- 0xff, 0x88, 0x49, 0x6b,
- 0x40, 0x39, 0xd5, 0x6a,
- 0x10, 0x92, 0x4f, 0x7b,
- 0x0a, 0xea, 0x64, 0x59,
+ 0x00, 0xe2, 0x28, 0x42,
+ 0x08, 0x92, 0xe9, 0x7a,
+ 0xc0, 0x39, 0x5d, 0x7b,
+ 0x80, 0x39, 0xe9, 0x6a,
+ 0xff, 0x88, 0x5d, 0x6b,
+ 0x40, 0x39, 0xe9, 0x6a,
+ 0x10, 0x92, 0x63, 0x7b,
+ 0x0a, 0xea, 0x6e, 0x59,
0x0a, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x6e, 0x5b,
- 0x00, 0xe2, 0xae, 0x43,
- 0x50, 0x4b, 0x56, 0x6b,
+ 0x00, 0xe2, 0x82, 0x5b,
+ 0x00, 0xe2, 0xc2, 0x43,
+ 0x50, 0x4b, 0x6a, 0x6b,
0xbf, 0x3a, 0x74, 0x08,
0x01, 0xe0, 0xf4, 0x31,
0xff, 0xea, 0xc0, 0x09,
@@ -441,31 +451,31 @@ static uint8_t seqprog[] = {
0x01, 0xfa, 0xc0, 0x35,
0x02, 0xa8, 0x90, 0x32,
0x02, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x5e, 0x59,
+ 0x33, 0xea, 0x68, 0x59,
0x33, 0xea, 0x00, 0x00,
0x02, 0x48, 0x51, 0x31,
0xff, 0x90, 0x85, 0x68,
- 0xff, 0x88, 0x7b, 0x6b,
- 0x01, 0xa4, 0x77, 0x6b,
- 0x02, 0xa4, 0x7f, 0x6b,
- 0x01, 0x84, 0x7f, 0x7b,
+ 0xff, 0x88, 0x8f, 0x6b,
+ 0x01, 0xa4, 0x8b, 0x6b,
+ 0x02, 0xa4, 0x93, 0x6b,
+ 0x01, 0x84, 0x93, 0x7b,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
- 0xff, 0x88, 0x7f, 0x73,
- 0x00, 0xe2, 0x52, 0x5b,
+ 0xff, 0x88, 0x93, 0x73,
+ 0x00, 0xe2, 0x66, 0x5b,
0x02, 0xa8, 0x20, 0x33,
0x04, 0xa4, 0x49, 0x03,
0xff, 0xea, 0x1a, 0x03,
- 0xff, 0x2d, 0x8b, 0x63,
+ 0xff, 0x2d, 0x9f, 0x63,
0x02, 0xa8, 0x58, 0x32,
0x02, 0xa8, 0x5c, 0x36,
0x02, 0xa8, 0x40, 0x31,
0x02, 0x2e, 0x51, 0x31,
0x02, 0xa0, 0x18, 0x33,
0x02, 0xa0, 0x5c, 0x36,
- 0xc0, 0x39, 0xd5, 0x6a,
+ 0xc0, 0x39, 0xe9, 0x6a,
0x04, 0x92, 0x25, 0x03,
- 0x20, 0x92, 0xaf, 0x6b,
+ 0x20, 0x92, 0xc3, 0x6b,
0x02, 0xa8, 0x40, 0x31,
0xc0, 0x3a, 0xc1, 0x09,
0x00, 0x3b, 0x51, 0x01,
@@ -480,60 +490,60 @@ static uint8_t seqprog[] = {
0xf7, 0x57, 0xae, 0x08,
0x08, 0xea, 0x98, 0x00,
0x01, 0x44, 0xd4, 0x31,
- 0xee, 0x00, 0xb8, 0x6b,
+ 0xee, 0x00, 0xcc, 0x6b,
0x02, 0xea, 0xb4, 0x00,
0xc0, 0xea, 0x72, 0x02,
- 0x09, 0x4c, 0xba, 0x7b,
+ 0x09, 0x4c, 0xce, 0x7b,
0x01, 0xea, 0x78, 0x02,
0x08, 0x4c, 0x06, 0x68,
- 0x0b, 0xea, 0x64, 0x59,
+ 0x0b, 0xea, 0x6e, 0x59,
0x0b, 0xea, 0x04, 0x00,
0x01, 0x44, 0xd4, 0x31,
- 0x20, 0x39, 0x15, 0x7a,
- 0x00, 0xe2, 0xcc, 0x5b,
- 0x00, 0xe2, 0x14, 0x42,
- 0x01, 0x84, 0xd1, 0x7b,
+ 0x20, 0x39, 0x29, 0x7a,
+ 0x00, 0xe2, 0xe0, 0x5b,
+ 0x00, 0xe2, 0x28, 0x42,
+ 0x01, 0x84, 0xe5, 0x7b,
0x01, 0xa4, 0x49, 0x07,
0x08, 0x60, 0x30, 0x33,
0x08, 0x80, 0x41, 0x37,
0xdf, 0x39, 0x73, 0x0a,
- 0xee, 0x00, 0xde, 0x6b,
+ 0xee, 0x00, 0xf2, 0x6b,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x5e, 0x59,
+ 0x33, 0xea, 0x68, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x00, 0xe2, 0x7e, 0x59,
- 0x00, 0xe2, 0xdc, 0x42,
- 0xff, 0x42, 0xee, 0x6b,
- 0x01, 0x41, 0xe2, 0x6b,
- 0x02, 0x41, 0xe2, 0x7b,
- 0xff, 0x42, 0xee, 0x6b,
- 0x01, 0x41, 0xe2, 0x6b,
- 0x02, 0x41, 0xe2, 0x7b,
- 0xff, 0x42, 0xee, 0x7b,
- 0x04, 0x4c, 0xe2, 0x6b,
+ 0x00, 0xe2, 0x88, 0x59,
+ 0x00, 0xe2, 0xf0, 0x42,
+ 0xff, 0x42, 0x02, 0x6c,
+ 0x01, 0x41, 0xf6, 0x6b,
+ 0x02, 0x41, 0xf6, 0x7b,
+ 0xff, 0x42, 0x02, 0x6c,
+ 0x01, 0x41, 0xf6, 0x6b,
+ 0x02, 0x41, 0xf6, 0x7b,
+ 0xff, 0x42, 0x02, 0x7c,
+ 0x04, 0x4c, 0xf6, 0x6b,
0xe0, 0x41, 0x78, 0x0e,
0x01, 0x44, 0xd4, 0x31,
- 0xff, 0x42, 0xf6, 0x7b,
- 0x04, 0x4c, 0xf6, 0x6b,
+ 0xff, 0x42, 0x0a, 0x7c,
+ 0x04, 0x4c, 0x0a, 0x6c,
0xe0, 0x41, 0x78, 0x0a,
- 0xe0, 0x3c, 0x15, 0x62,
+ 0xe0, 0x3c, 0x29, 0x62,
0xff, 0xea, 0xca, 0x09,
0x01, 0xe2, 0xc8, 0x31,
0x01, 0x46, 0xda, 0x35,
0x01, 0x44, 0xd4, 0x35,
0x10, 0xea, 0x80, 0x00,
0x01, 0xe2, 0x6e, 0x36,
- 0x04, 0xa6, 0x0e, 0x7c,
+ 0x04, 0xa6, 0x22, 0x7c,
0xff, 0xea, 0x5a, 0x09,
0xff, 0xea, 0x4c, 0x0d,
- 0x01, 0xa6, 0x3a, 0x6c,
+ 0x01, 0xa6, 0x4e, 0x6c,
0x10, 0xad, 0x84, 0x78,
- 0x80, 0xad, 0x32, 0x6c,
+ 0x80, 0xad, 0x46, 0x6c,
0x08, 0xad, 0x84, 0x68,
- 0x20, 0x19, 0x26, 0x7c,
+ 0x20, 0x19, 0x3a, 0x7c,
0x80, 0xea, 0xb2, 0x01,
0x11, 0x00, 0x00, 0x10,
- 0x02, 0xa6, 0x22, 0x7c,
+ 0x02, 0xa6, 0x36, 0x7c,
0xff, 0xea, 0xb2, 0x0d,
0x11, 0x00, 0x00, 0x10,
0xff, 0xea, 0xb2, 0x09,
@@ -561,7 +571,7 @@ static uint8_t seqprog[] = {
0x00, 0x86, 0x0d, 0x23,
0x00, 0x87, 0x0f, 0x23,
0x01, 0x84, 0xc5, 0x31,
- 0x80, 0x83, 0x5d, 0x7c,
+ 0x80, 0x83, 0x71, 0x7c,
0x02, 0xe2, 0xc4, 0x01,
0xff, 0xea, 0x4c, 0x09,
0x01, 0xe2, 0x36, 0x30,
@@ -572,75 +582,75 @@ static uint8_t seqprog[] = {
0xfe, 0xa6, 0x4c, 0x0d,
0x0b, 0x98, 0xe1, 0x30,
0xfd, 0xa4, 0x49, 0x09,
- 0x80, 0xa3, 0x71, 0x7c,
+ 0x80, 0xa3, 0x85, 0x7c,
0x02, 0xa4, 0x48, 0x01,
0x01, 0xa4, 0x36, 0x30,
0xa8, 0xea, 0x32, 0x00,
0xfd, 0xa4, 0x49, 0x0b,
0x05, 0xa3, 0x07, 0x33,
- 0x80, 0x83, 0x7d, 0x6c,
+ 0x80, 0x83, 0x91, 0x6c,
0x02, 0xea, 0x4c, 0x05,
0xff, 0xea, 0x4c, 0x0d,
- 0x00, 0xe2, 0x56, 0x59,
- 0x02, 0xa6, 0x10, 0x6c,
+ 0x00, 0xe2, 0x60, 0x59,
+ 0x02, 0xa6, 0x24, 0x6c,
0x80, 0xf9, 0xf2, 0x05,
- 0xc0, 0x39, 0x8b, 0x7c,
- 0x03, 0xea, 0x64, 0x59,
+ 0xc0, 0x39, 0x9f, 0x7c,
+ 0x03, 0xea, 0x6e, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0x20, 0x39, 0xaf, 0x7c,
- 0x01, 0x84, 0x95, 0x6c,
- 0x06, 0xea, 0x64, 0x59,
+ 0x20, 0x39, 0xc3, 0x7c,
+ 0x01, 0x84, 0xa9, 0x6c,
+ 0x06, 0xea, 0x6e, 0x59,
0x06, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xb2, 0x44,
+ 0x00, 0xe2, 0xc6, 0x44,
0x01, 0x00, 0x6c, 0x32,
- 0xee, 0x00, 0x9e, 0x6c,
+ 0xee, 0x00, 0xb2, 0x6c,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x5e, 0x59,
+ 0x33, 0xea, 0x68, 0x59,
0x33, 0xea, 0x00, 0x00,
0x80, 0x3d, 0x7a, 0x00,
- 0xfc, 0x42, 0xa0, 0x7c,
+ 0xfc, 0x42, 0xb4, 0x7c,
0x7f, 0x3d, 0x7a, 0x08,
- 0x00, 0x36, 0x5f, 0x59,
+ 0x00, 0x36, 0x69, 0x59,
0x01, 0x36, 0x01, 0x30,
- 0x09, 0xea, 0x64, 0x59,
+ 0x09, 0xea, 0x6e, 0x59,
0x09, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x14, 0x42,
- 0x01, 0xa4, 0x95, 0x6c,
- 0x00, 0xe2, 0x68, 0x5c,
+ 0x00, 0xe2, 0x28, 0x42,
+ 0x01, 0xa4, 0xa9, 0x6c,
+ 0x00, 0xe2, 0x7c, 0x5c,
0x20, 0x39, 0x73, 0x02,
0x01, 0x00, 0x6c, 0x32,
- 0x02, 0xa6, 0xba, 0x7c,
- 0x00, 0xe2, 0x7e, 0x5c,
+ 0x02, 0xa6, 0xce, 0x7c,
+ 0x00, 0xe2, 0x92, 0x5c,
0x00, 0xe2, 0x76, 0x58,
0x00, 0xe2, 0x86, 0x58,
0x00, 0xe2, 0x5a, 0x58,
- 0x00, 0x36, 0x5f, 0x59,
+ 0x00, 0x36, 0x69, 0x59,
0x01, 0x36, 0x01, 0x30,
- 0x20, 0x19, 0xba, 0x6c,
- 0x00, 0xe2, 0xea, 0x5c,
- 0x04, 0x19, 0xd4, 0x6c,
+ 0x20, 0x19, 0xce, 0x6c,
+ 0x00, 0xe2, 0xfe, 0x5c,
+ 0x04, 0x19, 0xe8, 0x6c,
0x02, 0x19, 0x32, 0x00,
- 0x01, 0x84, 0xd5, 0x7c,
- 0x01, 0x1b, 0xce, 0x7c,
- 0x01, 0x1a, 0xd4, 0x6c,
- 0x00, 0xe2, 0x84, 0x44,
- 0x80, 0x4b, 0xda, 0x6c,
- 0x01, 0x4c, 0xd6, 0x7c,
- 0x03, 0x42, 0x84, 0x6c,
- 0x00, 0xe2, 0x0a, 0x5c,
+ 0x01, 0x84, 0xe9, 0x7c,
+ 0x01, 0x1b, 0xe2, 0x7c,
+ 0x01, 0x1a, 0xe8, 0x6c,
+ 0x00, 0xe2, 0x98, 0x44,
+ 0x80, 0x4b, 0xee, 0x6c,
+ 0x01, 0x4c, 0xea, 0x7c,
+ 0x03, 0x42, 0x98, 0x6c,
+ 0x00, 0xe2, 0x1e, 0x5c,
0x80, 0xf9, 0xf2, 0x01,
- 0x04, 0x39, 0x15, 0x7a,
- 0x00, 0xe2, 0x14, 0x42,
- 0x08, 0x5d, 0xf2, 0x6c,
+ 0x04, 0x39, 0x29, 0x7a,
+ 0x00, 0xe2, 0x28, 0x42,
+ 0x08, 0x5d, 0x06, 0x6d,
0x00, 0xe2, 0x76, 0x58,
- 0x00, 0x36, 0x5f, 0x59,
+ 0x00, 0x36, 0x69, 0x59,
0x01, 0x36, 0x01, 0x30,
- 0x02, 0x1b, 0xe2, 0x7c,
- 0x08, 0x5d, 0xf0, 0x7c,
+ 0x02, 0x1b, 0xf6, 0x7c,
+ 0x08, 0x5d, 0x04, 0x7d,
0x03, 0x68, 0x00, 0x37,
0x01, 0x84, 0x09, 0x07,
- 0x80, 0x1b, 0xfc, 0x7c,
- 0x80, 0x84, 0xfd, 0x6c,
+ 0x80, 0x1b, 0x10, 0x7d,
+ 0x80, 0x84, 0x11, 0x6d,
0xff, 0x85, 0x0b, 0x1b,
0xff, 0x86, 0x0d, 0x23,
0xff, 0x87, 0x0f, 0x23,
@@ -652,161 +662,164 @@ static uint8_t seqprog[] = {
0xf9, 0xd9, 0xb2, 0x0d,
0x01, 0xd9, 0xb2, 0x05,
0x01, 0x52, 0x48, 0x31,
- 0x20, 0xa4, 0x26, 0x7d,
- 0x20, 0x5b, 0x26, 0x7d,
- 0x80, 0xf9, 0x34, 0x7d,
+ 0x20, 0xa4, 0x3a, 0x7d,
+ 0x20, 0x5b, 0x3a, 0x7d,
+ 0x80, 0xf9, 0x48, 0x7d,
0x02, 0xea, 0xb4, 0x00,
0x11, 0x00, 0x00, 0x10,
- 0x04, 0x19, 0x40, 0x7d,
+ 0x04, 0x19, 0x54, 0x7d,
0xdf, 0x19, 0x32, 0x08,
- 0x60, 0x5b, 0x40, 0x6d,
- 0x01, 0x4c, 0x1a, 0x7d,
+ 0x60, 0x5b, 0x54, 0x6d,
+ 0x01, 0x4c, 0x2e, 0x7d,
0x20, 0x19, 0x32, 0x00,
0x01, 0xd9, 0xb2, 0x05,
0x02, 0xea, 0xb4, 0x00,
0x01, 0xd9, 0xb2, 0x05,
- 0x10, 0x5b, 0x38, 0x6d,
- 0x08, 0x5b, 0x42, 0x6d,
- 0x20, 0x5b, 0x32, 0x6d,
- 0x02, 0x5b, 0x62, 0x6d,
- 0x0e, 0xea, 0x64, 0x59,
+ 0x10, 0x5b, 0x4c, 0x6d,
+ 0x08, 0x5b, 0x56, 0x6d,
+ 0x20, 0x5b, 0x46, 0x6d,
+ 0x02, 0x5b, 0x76, 0x6d,
+ 0x0e, 0xea, 0x6e, 0x59,
0x0e, 0xea, 0x04, 0x00,
- 0x80, 0xf9, 0x22, 0x6d,
+ 0x80, 0xf9, 0x36, 0x6d,
0xdf, 0x5c, 0xb8, 0x08,
0x01, 0xd9, 0xb2, 0x05,
- 0x01, 0xa4, 0x1d, 0x6e,
- 0x00, 0xe2, 0x68, 0x5c,
- 0x00, 0xe2, 0x6c, 0x5d,
+ 0x01, 0xa4, 0x37, 0x6e,
+ 0x00, 0xe2, 0x7c, 0x5c,
+ 0x00, 0xe2, 0x80, 0x5d,
0x01, 0x90, 0x21, 0x1b,
0x01, 0xd9, 0xb2, 0x05,
- 0x00, 0xe2, 0x52, 0x5b,
+ 0x00, 0xe2, 0x66, 0x5b,
0xf3, 0x96, 0xd5, 0x19,
- 0x00, 0xe2, 0x50, 0x55,
- 0x80, 0x96, 0x51, 0x6d,
- 0x0f, 0xea, 0x64, 0x59,
+ 0x00, 0xe2, 0x64, 0x55,
+ 0x80, 0x96, 0x65, 0x6d,
+ 0x0f, 0xea, 0x6e, 0x59,
0x0f, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x58, 0x45,
+ 0x00, 0xe2, 0x6c, 0x45,
0x04, 0x8c, 0xe1, 0x30,
0x01, 0xea, 0xf2, 0x00,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0xff, 0x97, 0x5f, 0x7d,
- 0x14, 0xea, 0x64, 0x59,
+ 0xff, 0x97, 0x73, 0x7d,
+ 0x14, 0xea, 0x6e, 0x59,
0x14, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xce, 0x5d,
+ 0x00, 0xe2, 0xe2, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
0x09, 0x80, 0xe1, 0x30,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0xc6, 0x5d,
+ 0x00, 0xe2, 0xda, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
- 0x02, 0xa6, 0x7c, 0x7d,
- 0x00, 0xe2, 0x56, 0x59,
- 0x20, 0x5b, 0x8a, 0x6d,
- 0xfc, 0x42, 0x76, 0x7d,
- 0x10, 0x40, 0x78, 0x6d,
- 0x20, 0x4d, 0x7a, 0x7d,
- 0x08, 0x5d, 0x8a, 0x6d,
- 0x02, 0xa6, 0x10, 0x6c,
- 0x00, 0xe2, 0x56, 0x59,
- 0x20, 0x5b, 0x8a, 0x6d,
- 0x01, 0x1b, 0xaa, 0x6d,
- 0xfc, 0x42, 0x86, 0x7d,
- 0x10, 0x40, 0x88, 0x6d,
+ 0x02, 0xa6, 0x90, 0x7d,
+ 0x00, 0xe2, 0x60, 0x59,
+ 0x20, 0x5b, 0x9e, 0x6d,
+ 0xfc, 0x42, 0x8a, 0x7d,
+ 0x10, 0x40, 0x8c, 0x6d,
+ 0x20, 0x4d, 0x8e, 0x7d,
+ 0x08, 0x5d, 0x9e, 0x6d,
+ 0x02, 0xa6, 0x24, 0x6c,
+ 0x00, 0xe2, 0x60, 0x59,
+ 0x20, 0x5b, 0x9e, 0x6d,
+ 0x01, 0x1b, 0xbe, 0x6d,
+ 0xfc, 0x42, 0x9a, 0x7d,
+ 0x10, 0x40, 0x9c, 0x6d,
0x20, 0x4d, 0x84, 0x78,
0x08, 0x5d, 0x84, 0x78,
0x02, 0x19, 0x32, 0x00,
0x01, 0x5b, 0x40, 0x31,
- 0x00, 0xe2, 0xea, 0x5c,
- 0x00, 0xe2, 0xcc, 0x5b,
+ 0x00, 0xe2, 0xfe, 0x5c,
+ 0x00, 0xe2, 0xe0, 0x5b,
0x20, 0xea, 0xb6, 0x00,
- 0x00, 0xe2, 0x0a, 0x5c,
+ 0x00, 0xe2, 0x1e, 0x5c,
0x20, 0x5c, 0xb8, 0x00,
- 0x04, 0x19, 0xa0, 0x6d,
- 0x01, 0x1a, 0xa0, 0x6d,
- 0x00, 0xe2, 0x56, 0x59,
+ 0x04, 0x19, 0xb4, 0x6d,
+ 0x01, 0x1a, 0xb4, 0x6d,
+ 0x00, 0xe2, 0x60, 0x59,
0x01, 0x1a, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
- 0x20, 0xa0, 0x04, 0x7e,
+ 0x20, 0xa0, 0x18, 0x7e,
0xff, 0x90, 0x21, 0x1b,
- 0x08, 0x92, 0x63, 0x6b,
+ 0x08, 0x92, 0x77, 0x6b,
0x02, 0xea, 0xb4, 0x04,
0x01, 0xa4, 0x49, 0x03,
- 0x40, 0x5b, 0xba, 0x6d,
- 0x00, 0xe2, 0x56, 0x59,
- 0x40, 0x5b, 0xba, 0x6d,
- 0x04, 0x5d, 0x1e, 0x7e,
- 0x01, 0x1a, 0x1e, 0x7e,
+ 0x40, 0x5b, 0xce, 0x6d,
+ 0x00, 0xe2, 0x60, 0x59,
+ 0x40, 0x5b, 0xce, 0x6d,
+ 0x04, 0x5d, 0x38, 0x7e,
+ 0x01, 0x1a, 0x38, 0x7e,
0x20, 0x4d, 0x84, 0x78,
- 0x40, 0x5b, 0x04, 0x7e,
- 0x04, 0x5d, 0x1e, 0x7e,
- 0x01, 0x1a, 0x1e, 0x7e,
+ 0x40, 0x5b, 0x18, 0x7e,
+ 0x04, 0x5d, 0x38, 0x7e,
+ 0x01, 0x1a, 0x38, 0x7e,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0x90, 0x21, 0x1b,
- 0x08, 0x92, 0x63, 0x6b,
+ 0x08, 0x92, 0x77, 0x6b,
0x02, 0xea, 0xb4, 0x04,
- 0x00, 0xe2, 0x56, 0x59,
+ 0x00, 0xe2, 0x60, 0x59,
0x01, 0x1b, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0x02, 0xea, 0xb4, 0x04,
- 0x00, 0xe2, 0x56, 0x59,
- 0x01, 0x1b, 0xe2, 0x6d,
- 0x40, 0x5b, 0xf0, 0x7d,
- 0x01, 0x1b, 0xe2, 0x6d,
+ 0x00, 0xe2, 0x60, 0x59,
+ 0x01, 0x1b, 0xf6, 0x6d,
+ 0x40, 0x5b, 0x04, 0x7e,
+ 0x01, 0x1b, 0xf6, 0x6d,
0x02, 0x19, 0x32, 0x00,
0x01, 0x1a, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0xea, 0x10, 0x03,
0x08, 0x92, 0x25, 0x03,
- 0x00, 0xe2, 0x62, 0x43,
- 0x01, 0x1a, 0xec, 0x7d,
- 0x40, 0x5b, 0xe8, 0x7d,
- 0x01, 0x1a, 0xd6, 0x6d,
+ 0x00, 0xe2, 0x76, 0x43,
+ 0x01, 0x1a, 0x00, 0x7e,
+ 0x40, 0x5b, 0xfc, 0x7d,
+ 0x01, 0x1a, 0xea, 0x6d,
0xfc, 0x42, 0x84, 0x78,
- 0x01, 0x1a, 0xf0, 0x6d,
- 0x10, 0xea, 0x64, 0x59,
+ 0x01, 0x1a, 0x04, 0x6e,
+ 0x10, 0xea, 0x6e, 0x59,
0x10, 0xea, 0x04, 0x00,
0xfc, 0x42, 0x84, 0x78,
- 0x10, 0x40, 0xf6, 0x6d,
+ 0x10, 0x40, 0x0a, 0x6e,
0x20, 0x4d, 0x84, 0x78,
- 0x40, 0x5b, 0xd6, 0x6d,
+ 0x40, 0x5b, 0xea, 0x6d,
0x01, 0x1a, 0x84, 0x78,
0x01, 0x90, 0x21, 0x1b,
0x30, 0x3f, 0xc0, 0x09,
0x30, 0xe0, 0x84, 0x60,
0x40, 0x4b, 0x84, 0x68,
0xff, 0xea, 0x52, 0x01,
- 0xee, 0x00, 0x0c, 0x6e,
+ 0xee, 0x00, 0x20, 0x6e,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0x90, 0x21, 0x1b,
0x02, 0xea, 0xb4, 0x00,
0x20, 0xea, 0x9a, 0x00,
- 0xf3, 0x42, 0x16, 0x6e,
- 0x12, 0xea, 0x64, 0x59,
+ 0x04, 0x41, 0x26, 0x7e,
+ 0x08, 0xea, 0x98, 0x00,
+ 0x08, 0x57, 0xae, 0x00,
+ 0xf3, 0x42, 0x30, 0x6e,
+ 0x12, 0xea, 0x6e, 0x59,
0x12, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x14, 0x42,
- 0x0d, 0xea, 0x64, 0x59,
+ 0x00, 0xe2, 0x28, 0x42,
+ 0x0d, 0xea, 0x6e, 0x59,
0x0d, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x14, 0x42,
+ 0x00, 0xe2, 0x28, 0x42,
0x01, 0x90, 0x21, 0x1b,
- 0x11, 0xea, 0x64, 0x59,
+ 0x11, 0xea, 0x6e, 0x59,
0x11, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x52, 0x5b,
+ 0x00, 0xe2, 0x66, 0x5b,
0x08, 0x5a, 0xb4, 0x00,
- 0x00, 0xe2, 0x44, 0x5e,
+ 0x00, 0xe2, 0x5e, 0x5e,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0x56, 0x59,
- 0x80, 0x1a, 0x32, 0x7e,
- 0x00, 0xe2, 0x44, 0x5e,
+ 0x00, 0xe2, 0x60, 0x59,
+ 0x80, 0x1a, 0x4c, 0x7e,
+ 0x00, 0xe2, 0x5e, 0x5e,
0x80, 0x19, 0x32, 0x00,
- 0x40, 0x5b, 0x38, 0x6e,
- 0x08, 0x5a, 0x38, 0x7e,
+ 0x40, 0x5b, 0x52, 0x6e,
+ 0x08, 0x5a, 0x52, 0x7e,
0x20, 0x4d, 0x84, 0x78,
0x02, 0x84, 0x09, 0x03,
- 0x40, 0x5b, 0x04, 0x7e,
+ 0x40, 0x5b, 0x18, 0x7e,
0xff, 0x90, 0x21, 0x1b,
0x80, 0xf9, 0xf2, 0x01,
- 0x08, 0x92, 0x63, 0x6b,
+ 0x08, 0x92, 0x77, 0x6b,
0x02, 0xea, 0xb4, 0x04,
0x01, 0x40, 0xe1, 0x30,
0x05, 0x41, 0xe3, 0x98,
@@ -1039,138 +1052,138 @@ static struct patch {
{ ahd_patch0_func, 64, 1, 1 },
{ ahd_patch2_func, 67, 1, 2 },
{ ahd_patch0_func, 68, 1, 1 },
- { ahd_patch4_func, 116, 1, 1 },
- { ahd_patch2_func, 175, 3, 1 },
- { ahd_patch1_func, 178, 2, 1 },
- { ahd_patch5_func, 180, 1, 1 },
- { ahd_patch2_func, 189, 1, 2 },
- { ahd_patch0_func, 190, 1, 1 },
- { ahd_patch6_func, 191, 2, 2 },
- { ahd_patch0_func, 193, 6, 3 },
- { ahd_patch2_func, 196, 1, 2 },
- { ahd_patch0_func, 197, 1, 1 },
- { ahd_patch2_func, 200, 1, 2 },
- { ahd_patch0_func, 201, 1, 1 },
- { ahd_patch3_func, 203, 1, 1 },
- { ahd_patch7_func, 204, 3, 1 },
- { ahd_patch3_func, 213, 1, 1 },
- { ahd_patch5_func, 214, 16, 2 },
- { ahd_patch0_func, 230, 1, 1 },
- { ahd_patch8_func, 250, 2, 1 },
- { ahd_patch1_func, 254, 1, 2 },
- { ahd_patch0_func, 255, 1, 1 },
- { ahd_patch7_func, 258, 3, 1 },
- { ahd_patch1_func, 273, 1, 2 },
- { ahd_patch0_func, 274, 1, 1 },
- { ahd_patch1_func, 277, 1, 2 },
- { ahd_patch0_func, 278, 1, 1 },
- { ahd_patch2_func, 281, 1, 2 },
- { ahd_patch0_func, 282, 1, 1 },
- { ahd_patch9_func, 295, 2, 2 },
- { ahd_patch0_func, 297, 1, 1 },
- { ahd_patch1_func, 339, 1, 2 },
- { ahd_patch0_func, 340, 1, 1 },
- { ahd_patch2_func, 348, 1, 2 },
- { ahd_patch0_func, 349, 1, 1 },
- { ahd_patch2_func, 352, 1, 2 },
- { ahd_patch0_func, 353, 1, 1 },
- { ahd_patch1_func, 359, 1, 2 },
- { ahd_patch0_func, 360, 1, 1 },
- { ahd_patch1_func, 362, 1, 2 },
+ { ahd_patch4_func, 115, 1, 1 },
+ { ahd_patch2_func, 180, 3, 1 },
+ { ahd_patch1_func, 183, 2, 1 },
+ { ahd_patch5_func, 185, 1, 1 },
+ { ahd_patch2_func, 194, 1, 2 },
+ { ahd_patch0_func, 195, 1, 1 },
+ { ahd_patch6_func, 196, 2, 2 },
+ { ahd_patch0_func, 198, 6, 3 },
+ { ahd_patch2_func, 201, 1, 2 },
+ { ahd_patch0_func, 202, 1, 1 },
+ { ahd_patch2_func, 205, 1, 2 },
+ { ahd_patch0_func, 206, 1, 1 },
+ { ahd_patch3_func, 208, 1, 1 },
+ { ahd_patch7_func, 209, 3, 1 },
+ { ahd_patch3_func, 218, 1, 1 },
+ { ahd_patch5_func, 219, 16, 2 },
+ { ahd_patch0_func, 235, 1, 1 },
+ { ahd_patch8_func, 260, 2, 1 },
+ { ahd_patch1_func, 264, 1, 2 },
+ { ahd_patch0_func, 265, 1, 1 },
+ { ahd_patch7_func, 268, 3, 1 },
+ { ahd_patch1_func, 283, 1, 2 },
+ { ahd_patch0_func, 284, 1, 1 },
+ { ahd_patch1_func, 287, 1, 2 },
+ { ahd_patch0_func, 288, 1, 1 },
+ { ahd_patch2_func, 291, 1, 2 },
+ { ahd_patch0_func, 292, 1, 1 },
+ { ahd_patch9_func, 305, 2, 2 },
+ { ahd_patch0_func, 307, 1, 1 },
+ { ahd_patch1_func, 349, 1, 2 },
+ { ahd_patch0_func, 350, 1, 1 },
+ { ahd_patch2_func, 358, 1, 2 },
+ { ahd_patch0_func, 359, 1, 1 },
+ { ahd_patch2_func, 362, 1, 2 },
{ ahd_patch0_func, 363, 1, 1 },
- { ahd_patch10_func, 382, 1, 1 },
- { ahd_patch10_func, 385, 1, 1 },
- { ahd_patch10_func, 387, 1, 1 },
- { ahd_patch10_func, 399, 1, 1 },
- { ahd_patch1_func, 409, 1, 2 },
- { ahd_patch0_func, 410, 1, 1 },
- { ahd_patch1_func, 412, 1, 2 },
- { ahd_patch0_func, 413, 1, 1 },
- { ahd_patch1_func, 421, 1, 2 },
- { ahd_patch0_func, 422, 1, 1 },
- { ahd_patch2_func, 435, 1, 2 },
- { ahd_patch0_func, 436, 1, 1 },
- { ahd_patch11_func, 472, 1, 1 },
- { ahd_patch1_func, 480, 1, 2 },
- { ahd_patch0_func, 481, 1, 1 },
- { ahd_patch2_func, 493, 1, 2 },
- { ahd_patch0_func, 494, 1, 1 },
- { ahd_patch12_func, 497, 6, 2 },
- { ahd_patch0_func, 503, 1, 1 },
- { ahd_patch13_func, 524, 7, 1 },
- { ahd_patch14_func, 533, 1, 1 },
- { ahd_patch15_func, 542, 1, 1 },
- { ahd_patch16_func, 543, 1, 2 },
- { ahd_patch0_func, 544, 1, 1 },
- { ahd_patch17_func, 547, 1, 1 },
- { ahd_patch16_func, 548, 1, 1 },
- { ahd_patch18_func, 559, 1, 2 },
- { ahd_patch0_func, 560, 1, 1 },
- { ahd_patch1_func, 579, 1, 2 },
- { ahd_patch0_func, 580, 1, 1 },
- { ahd_patch1_func, 583, 1, 2 },
- { ahd_patch0_func, 584, 1, 1 },
- { ahd_patch2_func, 589, 1, 2 },
+ { ahd_patch1_func, 369, 1, 2 },
+ { ahd_patch0_func, 370, 1, 1 },
+ { ahd_patch1_func, 372, 1, 2 },
+ { ahd_patch0_func, 373, 1, 1 },
+ { ahd_patch10_func, 392, 1, 1 },
+ { ahd_patch10_func, 395, 1, 1 },
+ { ahd_patch10_func, 397, 1, 1 },
+ { ahd_patch10_func, 409, 1, 1 },
+ { ahd_patch1_func, 419, 1, 2 },
+ { ahd_patch0_func, 420, 1, 1 },
+ { ahd_patch1_func, 422, 1, 2 },
+ { ahd_patch0_func, 423, 1, 1 },
+ { ahd_patch1_func, 431, 1, 2 },
+ { ahd_patch0_func, 432, 1, 1 },
+ { ahd_patch2_func, 445, 1, 2 },
+ { ahd_patch0_func, 446, 1, 1 },
+ { ahd_patch11_func, 482, 1, 1 },
+ { ahd_patch1_func, 490, 1, 2 },
+ { ahd_patch0_func, 491, 1, 1 },
+ { ahd_patch2_func, 503, 1, 2 },
+ { ahd_patch0_func, 504, 1, 1 },
+ { ahd_patch12_func, 507, 6, 2 },
+ { ahd_patch0_func, 513, 1, 1 },
+ { ahd_patch13_func, 534, 7, 1 },
+ { ahd_patch14_func, 543, 1, 1 },
+ { ahd_patch15_func, 552, 1, 1 },
+ { ahd_patch16_func, 553, 1, 2 },
+ { ahd_patch0_func, 554, 1, 1 },
+ { ahd_patch17_func, 557, 1, 1 },
+ { ahd_patch16_func, 558, 1, 1 },
+ { ahd_patch18_func, 569, 1, 2 },
+ { ahd_patch0_func, 570, 1, 1 },
+ { ahd_patch1_func, 589, 1, 2 },
{ ahd_patch0_func, 590, 1, 1 },
- { ahd_patch2_func, 594, 1, 2 },
- { ahd_patch0_func, 595, 1, 1 },
- { ahd_patch1_func, 596, 1, 2 },
- { ahd_patch0_func, 597, 1, 1 },
- { ahd_patch2_func, 608, 1, 2 },
- { ahd_patch0_func, 609, 1, 1 },
- { ahd_patch19_func, 613, 1, 1 },
- { ahd_patch20_func, 618, 1, 1 },
- { ahd_patch21_func, 619, 2, 1 },
- { ahd_patch20_func, 623, 1, 2 },
- { ahd_patch0_func, 624, 1, 1 },
- { ahd_patch2_func, 627, 1, 2 },
- { ahd_patch0_func, 628, 1, 1 },
- { ahd_patch2_func, 643, 1, 2 },
- { ahd_patch0_func, 644, 1, 1 },
- { ahd_patch13_func, 645, 14, 1 },
- { ahd_patch1_func, 663, 1, 2 },
- { ahd_patch0_func, 664, 1, 1 },
- { ahd_patch13_func, 665, 1, 1 },
- { ahd_patch1_func, 677, 1, 2 },
- { ahd_patch0_func, 678, 1, 1 },
- { ahd_patch1_func, 685, 1, 2 },
- { ahd_patch0_func, 686, 1, 1 },
- { ahd_patch19_func, 709, 1, 1 },
- { ahd_patch19_func, 747, 1, 1 },
- { ahd_patch1_func, 758, 1, 2 },
- { ahd_patch0_func, 759, 1, 1 },
- { ahd_patch1_func, 776, 1, 2 },
- { ahd_patch0_func, 777, 1, 1 },
- { ahd_patch1_func, 779, 1, 2 },
- { ahd_patch0_func, 780, 1, 1 },
- { ahd_patch1_func, 783, 1, 2 },
- { ahd_patch0_func, 784, 1, 1 },
- { ahd_patch22_func, 786, 1, 2 },
- { ahd_patch0_func, 787, 2, 1 },
- { ahd_patch23_func, 790, 4, 2 },
- { ahd_patch0_func, 794, 1, 1 },
- { ahd_patch23_func, 802, 11, 1 }
+ { ahd_patch1_func, 593, 1, 2 },
+ { ahd_patch0_func, 594, 1, 1 },
+ { ahd_patch2_func, 599, 1, 2 },
+ { ahd_patch0_func, 600, 1, 1 },
+ { ahd_patch2_func, 604, 1, 2 },
+ { ahd_patch0_func, 605, 1, 1 },
+ { ahd_patch1_func, 606, 1, 2 },
+ { ahd_patch0_func, 607, 1, 1 },
+ { ahd_patch2_func, 618, 1, 2 },
+ { ahd_patch0_func, 619, 1, 1 },
+ { ahd_patch19_func, 623, 1, 1 },
+ { ahd_patch20_func, 628, 1, 1 },
+ { ahd_patch21_func, 629, 2, 1 },
+ { ahd_patch20_func, 633, 1, 2 },
+ { ahd_patch0_func, 634, 1, 1 },
+ { ahd_patch2_func, 637, 1, 2 },
+ { ahd_patch0_func, 638, 1, 1 },
+ { ahd_patch2_func, 653, 1, 2 },
+ { ahd_patch0_func, 654, 1, 1 },
+ { ahd_patch13_func, 655, 14, 1 },
+ { ahd_patch1_func, 673, 1, 2 },
+ { ahd_patch0_func, 674, 1, 1 },
+ { ahd_patch13_func, 675, 1, 1 },
+ { ahd_patch1_func, 687, 1, 2 },
+ { ahd_patch0_func, 688, 1, 1 },
+ { ahd_patch1_func, 695, 1, 2 },
+ { ahd_patch0_func, 696, 1, 1 },
+ { ahd_patch19_func, 719, 1, 1 },
+ { ahd_patch19_func, 757, 1, 1 },
+ { ahd_patch1_func, 768, 1, 2 },
+ { ahd_patch0_func, 769, 1, 1 },
+ { ahd_patch7_func, 785, 3, 1 },
+ { ahd_patch1_func, 789, 1, 2 },
+ { ahd_patch0_func, 790, 1, 1 },
+ { ahd_patch1_func, 792, 1, 2 },
+ { ahd_patch0_func, 793, 1, 1 },
+ { ahd_patch1_func, 796, 1, 2 },
+ { ahd_patch0_func, 797, 1, 1 },
+ { ahd_patch22_func, 799, 1, 2 },
+ { ahd_patch0_func, 800, 2, 1 },
+ { ahd_patch23_func, 803, 4, 2 },
+ { ahd_patch0_func, 807, 1, 1 },
+ { ahd_patch23_func, 815, 11, 1 }
};
static struct cs {
uint16_t begin;
uint16_t end;
} critical_sections[] = {
- { 17, 28 },
- { 29, 30 },
+ { 17, 30 },
{ 47, 58 },
{ 61, 63 },
{ 65, 66 },
{ 72, 92 },
- { 110, 137 },
- { 138, 175 },
- { 180, 188 },
- { 213, 264 },
- { 425, 433 },
- { 443, 445 },
- { 448, 457 },
- { 709, 739 },
- { 749, 753 }
+ { 110, 142 },
+ { 143, 180 },
+ { 185, 193 },
+ { 218, 274 },
+ { 435, 443 },
+ { 453, 455 },
+ { 458, 467 },
+ { 719, 749 },
+ { 759, 763 }
};
static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c
index f936b691232..924102720b1 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm.c
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#22 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $
*
* $FreeBSD$
*/
@@ -609,10 +609,10 @@ output_listing(char *ifilename)
while (line < cur_instr->srcline) {
fgets(buf, sizeof(buf), ifile);
- fprintf(listfile, "\t\t%s", buf);
+ fprintf(listfile, " \t%s", buf);
line++;
}
- fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
+ fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
#ifdef __LITTLE_ENDIAN
cur_instr->format.bytes[0],
cur_instr->format.bytes[1],
@@ -624,14 +624,23 @@ output_listing(char *ifilename)
cur_instr->format.bytes[1],
cur_instr->format.bytes[0]);
#endif
- fgets(buf, sizeof(buf), ifile);
- fprintf(listfile, "\t%s", buf);
- line++;
+ /*
+ * Macro expansions can cause several instructions
+ * to be output for a single source line. Only
+ * advance the line once in these cases.
+ */
+ if (line == cur_instr->srcline) {
+ fgets(buf, sizeof(buf), ifile);
+ fprintf(listfile, "\t%s", buf);
+ line++;
+ } else {
+ fprintf(listfile, "\n");
+ }
instrptr++;
}
/* Dump the remainder of the file */
while(fgets(buf, sizeof(buf), ifile) != NULL)
- fprintf(listfile, "\t\t%s", buf);
+ fprintf(listfile, " %s", buf);
fclose(ifile);
}
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
index 67e046d9662..c328596def3 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#30 $
*
* $FreeBSD$
*/
@@ -157,6 +157,8 @@ static int is_download_const(expression_t *immed);
%token T_END_CS
+%token T_PAD_PAGE
+
%token T_FIELD
%token T_ENUM
@@ -189,6 +191,10 @@ static int is_download_const(expression_t *immed);
%token <value> T_OR
+/* 16 bit extensions */
+%token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
+%token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
+
%token T_RET
%token T_NOP
@@ -207,7 +213,7 @@ static int is_download_const(expression_t *immed);
%type <expression> expression immediate immediate_or_a
-%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
+%type <value> export ret f1_opcode f2_opcode f4_opcode jmp_jc_jnc_call jz_jnz je_jne
%type <value> mode_value mode_list macro_arglist
@@ -1304,6 +1310,15 @@ f2_opcode:
| T_ROR { $$ = AIC_OP_ROR; }
;
+f4_opcode:
+ T_OR16 { $$ = AIC_OP_OR16; }
+| T_AND16 { $$ = AIC_OP_AND16; }
+| T_XOR16 { $$ = AIC_OP_XOR16; }
+| T_ADD16 { $$ = AIC_OP_ADD16; }
+| T_ADC16 { $$ = AIC_OP_ADC16; }
+| T_MVI16 { $$ = AIC_OP_MVI16; }
+;
+
code:
f2_opcode destination ',' expression opt_source ret ';'
{
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
index e64f802bbaa..9df9e2ce353 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
@@ -37,13 +37,14 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#11 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#12 $
*
* $FreeBSD$
*/
#include <asm/byteorder.h>
+/* 8bit ALU logic operations */
struct ins_format1 {
#ifdef __LITTLE_ENDIAN
uint32_t immediate : 8,
@@ -62,6 +63,7 @@ struct ins_format1 {
#endif
};
+/* 8bit ALU shift/rotate operations */
struct ins_format2 {
#ifdef __LITTLE_ENDIAN
uint32_t shift_control : 8,
@@ -80,6 +82,7 @@ struct ins_format2 {
#endif
};
+/* 8bit branch control operations */
struct ins_format3 {
#ifdef __LITTLE_ENDIAN
uint32_t immediate : 8,
@@ -96,10 +99,68 @@ struct ins_format3 {
#endif
};
+/* 16bit ALU logic operations */
+struct ins_format4 {
+#ifdef __LITTLE_ENDIAN
+ uint32_t opcode_ext : 8,
+ source : 9,
+ destination : 9,
+ ret : 1,
+ opcode : 4,
+ parity : 1;
+#else
+ uint32_t parity : 1,
+ opcode : 4,
+ ret : 1,
+ destination : 9,
+ source : 9,
+ opcode_ext : 8;
+#endif
+};
+
+/* 16bit branch control operations */
+struct ins_format5 {
+#ifdef __LITTLE_ENDIAN
+ uint32_t opcode_ext : 8,
+ source : 9,
+ address : 10,
+ opcode : 4,
+ parity : 1;
+#else
+ uint32_t parity : 1,
+ opcode : 4,
+ address : 10,
+ source : 9,
+ opcode_ext : 8;
+#endif
+};
+
+/* Far branch operations */
+struct ins_format6 {
+#ifdef __LITTLE_ENDIAN
+ uint32_t page : 3,
+ opcode_ext : 5,
+ source : 9,
+ address : 10,
+ opcode : 4,
+ parity : 1;
+#else
+ uint32_t parity : 1,
+ opcode : 4,
+ address : 10,
+ source : 9,
+ opcode_ext : 5,
+ page : 3;
+#endif
+};
+
union ins_formats {
struct ins_format1 format1;
struct ins_format2 format2;
struct ins_format3 format3;
+ struct ins_format4 format4;
+ struct ins_format5 format5;
+ struct ins_format6 format6;
uint8_t bytes[4];
uint32_t integer;
};
@@ -118,6 +179,8 @@ struct instruction {
#define AIC_OP_ROL 0x5
#define AIC_OP_BMOV 0x6
+#define AIC_OP_MVI16 0x7
+
#define AIC_OP_JMP 0x8
#define AIC_OP_JC 0x9
#define AIC_OP_JNC 0xa
@@ -131,3 +194,26 @@ struct instruction {
#define AIC_OP_SHL 0x10
#define AIC_OP_SHR 0x20
#define AIC_OP_ROR 0x30
+
+/* 16bit Ops. Low byte main opcode. High byte extended opcode. */
+#define AIC_OP_OR16 0x8005
+#define AIC_OP_AND16 0x8105
+#define AIC_OP_XOR16 0x8205
+#define AIC_OP_ADD16 0x8305
+#define AIC_OP_ADC16 0x8405
+#define AIC_OP_JNE16 0x8805
+#define AIC_OP_JNZ16 0x8905
+#define AIC_OP_JE16 0x8C05
+#define AIC_OP_JZ16 0x8B05
+#define AIC_OP_JMP16 0x9005
+#define AIC_OP_JC16 0x9105
+#define AIC_OP_JNC16 0x9205
+#define AIC_OP_CALL16 0x9305
+#define AIC_OP_CALL16 0x9305
+
+/* Page extension is low three bits of second opcode byte. */
+#define AIC_OP_JMPF 0xA005
+#define AIC_OP_CALLF 0xB005
+#define AIC_OP_JCF 0xC005
+#define AIC_OP_JNCF 0xD005
+#define AIC_OP_CMPXCHG 0xE005
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
index 45c0b233d0b..7c3983f868a 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $
*
* $FreeBSD$
*/
@@ -132,7 +132,7 @@ if[ \t]*\( {
*string_buf_ptr++ = *yptr++;
}
}
-
+else { return T_ELSE; }
VERSION { return T_VERSION; }
PREFIX { return T_PREFIX; }
PATCH_ARG_LIST { return T_PATCH_ARG_LIST; }
@@ -173,10 +173,6 @@ RW|RO|WO {
yylval.value = WO;
return T_MODE;
}
-BEGIN_CRITICAL { return T_BEGIN_CS; }
-END_CRITICAL { return T_END_CS; }
-SET_SRC_MODE { return T_SET_SRC_MODE; }
-SET_DST_MODE { return T_SET_DST_MODE; }
field { return T_FIELD; }
enum { return T_ENUM; }
mask { return T_MASK; }
@@ -192,6 +188,13 @@ none { return T_NONE; }
sindex { return T_SINDEX; }
A { return T_A; }
+ /* Instruction Formatting */
+PAD_PAGE { return T_PAD_PAGE; }
+BEGIN_CRITICAL { return T_BEGIN_CS; }
+END_CRITICAL { return T_END_CS; }
+SET_SRC_MODE { return T_SET_SRC_MODE; }
+SET_DST_MODE { return T_SET_DST_MODE; }
+
/* Opcodes */
shl { return T_SHL; }
shr { return T_SHR; }
@@ -223,7 +226,17 @@ and { return T_AND; }
or { return T_OR; }
ret { return T_RET; }
nop { return T_NOP; }
-else { return T_ELSE; }
+
+ /* ARP2 16bit extensions */
+or16 { return T_OR16; }
+and16 { return T_AND16; }
+xor16 { return T_XOR16; }
+add16 { return T_ADD16; }
+adc16 { return T_ADC16; }
+mvi16 { return T_MVI16; }
+test16 { return T_TEST16; }
+cmp16 { return T_CMP16; }
+cmpxchg { return T_CMPXCHG; }
/* Allowed Symbols */
\<\< { return T_EXPR_LSHIFT; }
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 557788ec4ee..fc3ca051cee 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -157,6 +157,9 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ } /* terminate list */
};
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index c8a32cf47d7..cbf825263f3 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -246,6 +246,7 @@ struct ScsiReqBlk {
* total_xfer_length in xferred. These values are restored in
* pci_unmap_srb_sense. This is the only place xferred is used.
*/
+ unsigned char *virt_addr_req; /* Saved virtual address of the request buffer */
u32 xferred; /* Saved copy of total_xfer_length */
u16 state;
@@ -2017,7 +2018,7 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
sg_verify_length(srb);
/* we need the corresponding virtual address */
- if (!segment) {
+ if (!segment || (srb->flag & AUTO_REQSENSE)) {
srb->virt_addr += xferred;
return;
}
@@ -3318,6 +3319,7 @@ static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb,
srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address;
srb->segment_x[0].length =
srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length;
+ srb->virt_addr = srb->virt_addr_req;
}
@@ -3711,6 +3713,8 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
srb->xferred = srb->total_xfer_length;
/* srb->segment_x : a one entry of S/G list table */
srb->total_xfer_length = sizeof(cmd->sense_buffer);
+ srb->virt_addr_req = srb->virt_addr;
+ srb->virt_addr = cmd->sense_buffer;
srb->segment_x[0].length = sizeof(cmd->sense_buffer);
/* Map sense buffer */
srb->segment_x[0].address =
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index bd3ffdf6c80..62e3cda859a 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -2816,7 +2816,7 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
}
#endif
- } else {
+ } else if (scp->request_bufflen) {
scp->SCp.Status = GDTH_MAP_SINGLE;
scp->SCp.Message = (read_write == 1 ?
PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 822b9fa706f..eaefeddb2b4 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -87,7 +87,7 @@ static int max_channel = 3;
static int init_timeout = 5;
static int max_requests = 50;
-#define IBMVSCSI_VERSION "1.5.7"
+#define IBMVSCSI_VERSION "1.5.8"
MODULE_DESCRIPTION("IBM Virtual SCSI");
MODULE_AUTHOR("Dave Boutcher");
@@ -534,7 +534,6 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
struct ibmvscsi_host_data *hostdata)
{
- struct scsi_cmnd *cmnd;
u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
int rc;
@@ -544,19 +543,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
* can handle more requests (can_queue) when we actually can't
*/
if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
- (atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
- /* See if the adapter is disabled */
- if (atomic_read(&hostdata->request_limit) < 0)
- goto send_error;
-
- printk(KERN_WARNING
- "ibmvscsi: Warning, request_limit exceeded\n");
- unmap_cmd_data(&evt_struct->iu.srp.cmd,
- evt_struct,
- hostdata->dev);
- free_event_struct(&hostdata->pool, evt_struct);
- return SCSI_MLQUEUE_HOST_BUSY;
- }
+ (atomic_dec_if_positive(&hostdata->request_limit) < 0))
+ goto send_error;
/* Copy the IU into the transfer area */
*evt_struct->xfer_iu = evt_struct->iu;
@@ -572,7 +560,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
list_del(&evt_struct->list);
- printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
+ printk(KERN_ERR "ibmvscsi: send error %d\n",
rc);
goto send_error;
}
@@ -582,14 +570,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
send_error:
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
- if ((cmnd = evt_struct->cmnd) != NULL) {
- cmnd->result = DID_ERROR << 16;
- evt_struct->cmnd_done(cmnd);
- } else if (evt_struct->done)
- evt_struct->done(evt_struct);
-
free_event_struct(&hostdata->pool, evt_struct);
- return 0;
+ return SCSI_MLQUEUE_HOST_BUSY;
}
/**
@@ -802,7 +784,8 @@ static void login_rsp(struct srp_event_struct *evt_struct)
case SRP_LOGIN_RSP_TYPE: /* it worked! */
break;
case SRP_LOGIN_REJ_TYPE: /* refused! */
- printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REQ rejected\n");
+ printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
+ evt_struct->xfer_iu->srp.login_rej.reason);
/* Login failed. */
atomic_set(&hostdata->request_limit, -1);
return;
@@ -834,6 +817,9 @@ static void login_rsp(struct srp_event_struct *evt_struct)
return;
}
+ /* If we had any pending I/Os, kick them */
+ scsi_unblock_requests(hostdata->host);
+
send_mad_adapter_info(hostdata);
return;
}
@@ -862,6 +848,7 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
init_timeout * HZ);
login = &evt_struct->iu.srp.login_req;
+ memset(login, 0x00, sizeof(struct srp_login_req));
login->type = SRP_LOGIN_REQ_TYPE;
login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
login->required_buffer_formats = 0x0006;
@@ -1122,7 +1109,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
* purge_requests: Our virtual adapter just shut down. purge any sent requests
* @hostdata: the adapter
*/
-static void purge_requests(struct ibmvscsi_host_data *hostdata)
+static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
{
struct srp_event_struct *tmp_evt, *pos;
unsigned long flags;
@@ -1131,7 +1118,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata)
list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
list_del(&tmp_evt->list);
if (tmp_evt->cmnd) {
- tmp_evt->cmnd->result = (DID_ERROR << 16);
+ tmp_evt->cmnd->result = (error_code << 16);
unmap_cmd_data(&tmp_evt->iu.srp.cmd,
tmp_evt,
tmp_evt->hostdata->dev);
@@ -1186,12 +1173,30 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
}
return;
- case 0xFF: /* Hypervisor telling us the connection is closed */
- printk(KERN_INFO "ibmvscsi: Virtual adapter failed!\n");
+ case 0xFF: /* Hypervisor telling us the connection is closed */
+ scsi_block_requests(hostdata->host);
+ if (crq->format == 0x06) {
+ /* We need to re-setup the interpartition connection */
+ printk(KERN_INFO
+ "ibmvscsi: Re-enabling adapter!\n");
+ purge_requests(hostdata, DID_REQUEUE);
+ if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
+ hostdata) == 0)
+ if (ibmvscsi_send_crq(hostdata,
+ 0xC001000000000000LL, 0))
+ printk(KERN_ERR
+ "ibmvscsi: transmit error after"
+ " enable\n");
+ } else {
+ printk(KERN_INFO
+ "ibmvscsi: Virtual adapter failed rc %d!\n",
+ crq->format);
- atomic_set(&hostdata->request_limit, -1);
- purge_requests(hostdata);
- ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+ atomic_set(&hostdata->request_limit, -1);
+ purge_requests(hostdata, DID_ERROR);
+ ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+ }
+ scsi_unblock_requests(hostdata->host);
return;
case 0x80: /* real payload */
break;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 5b0edd1f192..4550d71e474 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -103,6 +103,9 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata);
+int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
+ struct ibmvscsi_host_data *hostdata);
+
void ibmvscsi_handle_crq(struct viosrp_crq *crq,
struct ibmvscsi_host_data *hostdata);
int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
index ce15d9e3962..7eed0b09817 100644
--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
@@ -124,6 +124,19 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
}
/**
+ * reenable_crq_queue: - reenables a crq after a failure
+ * @queue: crq_queue to initialize and register
+ * @hostdata: ibmvscsi_host_data of host
+ *
+ * no-op for iSeries
+ */
+int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
+ struct ibmvscsi_host_data *hostdata)
+{
+ return 0;
+}
+
+/**
* ibmvscsi_send_crq: - Send a CRQ
* @hostdata: the adapter
* @word1: the first 64 bits of the data
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 75db2f5c545..f47dd87c05e 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -281,6 +281,28 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
}
/**
+ * reenable_crq_queue: - reenables a crq after
+ * @queue: crq_queue to initialize and register
+ * @hostdata: ibmvscsi_host_data of host
+ *
+ */
+int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
+ struct ibmvscsi_host_data *hostdata)
+{
+ int rc;
+ struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+ /* Re-enable the CRQ */
+ do {
+ rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
+ } while ((rc == H_InProgress) || (rc == H_Busy) || (H_isLongBusy(rc)));
+
+ if (rc)
+ printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
+ return rc;
+}
+
+/**
* reset_crq_queue: - resets a crq after a failure
* @queue: crq_queue to initialize and register
* @hostdata: ibmvscsi_host_data of host
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 3c688ef5466..0cf0e4c7ac0 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -751,9 +751,8 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
idescsi_add_settings(drive);
}
-static int ide_scsi_remove(struct device *dev)
+static void ide_scsi_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct Scsi_Host *scsihost = drive->driver_data;
struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
struct gendisk *g = scsi->disk;
@@ -768,11 +767,9 @@ static int ide_scsi_remove(struct device *dev)
scsi_remove_host(scsihost);
ide_scsi_put(scsi);
-
- return 0;
}
-static int ide_scsi_probe(struct device *);
+static int ide_scsi_probe(ide_drive_t *);
#ifdef CONFIG_PROC_FS
static ide_proc_entry_t idescsi_proc[] = {
@@ -788,9 +785,9 @@ static ide_driver_t idescsi_driver = {
.owner = THIS_MODULE,
.name = "ide-scsi",
.bus = &ide_bus_type,
- .probe = ide_scsi_probe,
- .remove = ide_scsi_remove,
},
+ .probe = ide_scsi_probe,
+ .remove = ide_scsi_remove,
.version = IDESCSI_VERSION,
.media = ide_scsi,
.supports_dsc_overlap = 0,
@@ -1119,9 +1116,8 @@ static struct scsi_host_template idescsi_template = {
.proc_name = "ide-scsi",
};
-static int ide_scsi_probe(struct device *dev)
+static int ide_scsi_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idescsi_scsi_t *idescsi;
struct Scsi_Host *host;
struct gendisk *g;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 27acf78cf8d..2bba5e55d7b 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -4236,35 +4236,6 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
}
/**
- * ipr_save_ioafp_mode_select - Save adapters mode select data
- * @ioa_cfg: ioa config struct
- * @scsi_cmd: scsi command struct
- *
- * This function saves mode select data for the adapter to
- * use following an adapter reset.
- *
- * Return value:
- * 0 on success / SCSI_MLQUEUE_HOST_BUSY on failure
- **/
-static int ipr_save_ioafp_mode_select(struct ipr_ioa_cfg *ioa_cfg,
- struct scsi_cmnd *scsi_cmd)
-{
- if (!ioa_cfg->saved_mode_pages) {
- ioa_cfg->saved_mode_pages = kmalloc(sizeof(struct ipr_mode_pages),
- GFP_ATOMIC);
- if (!ioa_cfg->saved_mode_pages) {
- dev_err(&ioa_cfg->pdev->dev,
- "IOA mode select buffer allocation failed\n");
- return SCSI_MLQUEUE_HOST_BUSY;
- }
- }
-
- memcpy(ioa_cfg->saved_mode_pages, scsi_cmd->buffer, scsi_cmd->cmnd[4]);
- ioa_cfg->saved_mode_page_len = scsi_cmd->cmnd[4];
- return 0;
-}
-
-/**
* ipr_queuecommand - Queue a mid-layer request
* @scsi_cmd: scsi command struct
* @done: done function
@@ -4338,9 +4309,6 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
(!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE))
ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
- if (ipr_is_ioa_resource(res) && scsi_cmd->cmnd[0] == MODE_SELECT)
- rc = ipr_save_ioafp_mode_select(ioa_cfg, scsi_cmd);
-
if (likely(rc == 0))
rc = ipr_build_ioadl(ioa_cfg, ipr_cmd);
@@ -4829,17 +4797,11 @@ static int ipr_ioafp_mode_select_page28(struct ipr_cmnd *ipr_cmd)
int length;
ENTER;
- if (ioa_cfg->saved_mode_pages) {
- memcpy(mode_pages, ioa_cfg->saved_mode_pages,
- ioa_cfg->saved_mode_page_len);
- length = ioa_cfg->saved_mode_page_len;
- } else {
- ipr_scsi_bus_speed_limit(ioa_cfg);
- ipr_check_term_power(ioa_cfg, mode_pages);
- ipr_modify_ioafp_mode_page_28(ioa_cfg, mode_pages);
- length = mode_pages->hdr.length + 1;
- mode_pages->hdr.length = 0;
- }
+ ipr_scsi_bus_speed_limit(ioa_cfg);
+ ipr_check_term_power(ioa_cfg, mode_pages);
+ ipr_modify_ioafp_mode_page_28(ioa_cfg, mode_pages);
+ length = mode_pages->hdr.length + 1;
+ mode_pages->hdr.length = 0;
ipr_build_mode_select(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), 0x11,
ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, mode_pages),
@@ -5969,7 +5931,6 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
}
ipr_free_dump(ioa_cfg);
- kfree(ioa_cfg->saved_mode_pages);
kfree(ioa_cfg->trace);
}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index b639332131f..fd360bfe56d 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.1.1"
-#define IPR_DRIVER_DATE "(November 15, 2005)"
+#define IPR_DRIVER_VERSION "2.1.2"
+#define IPR_DRIVER_DATE "(February 8, 2006)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -1000,7 +1000,6 @@ struct ipr_ioa_cfg {
struct Scsi_Host *host;
struct pci_dev *pdev;
struct ipr_sglist *ucode_sglist;
- struct ipr_mode_pages *saved_mode_pages;
u8 saved_mode_page_len;
struct work_struct work_q;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index e5e1ca44e1e..86c546164da 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -3499,6 +3499,7 @@ ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp)
int device_error;
uint32_t transfer_len;
IPS_DCDB_TABLE_TAPE *tapeDCDB;
+ IPS_SCSI_INQ_DATA inquiryData;
METHOD_TRACE("ips_map_status", 1);
@@ -3557,13 +3558,13 @@ ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp)
errcode = DID_OK;
/* Restrict access to physical DASD */
- if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
- ((((char *) scb->scsi_cmd->
- buffer)[0] & 0x1f) == TYPE_DISK)) {
- /* underflow -- no error */
- /* restrict access to physical DASD */
- errcode = DID_TIME_OUT;
- break;
+ if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
+ ips_scmd_buf_read(scb->scsi_cmd,
+ &inquiryData, sizeof (inquiryData));
+ if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) {
+ errcode = DID_TIME_OUT;
+ break;
+ }
}
} else
errcode = DID_ERROR;
@@ -4135,6 +4136,7 @@ ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus)
uint8_t basic_status;
uint8_t ext_status;
int errcode;
+ IPS_SCSI_INQ_DATA inquiryData;
METHOD_TRACE("ips_chkstatus", 1);
@@ -4255,11 +4257,11 @@ ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus)
scb->scsi_cmd->result = errcode << 16;
} else { /* bus == 0 */
/* restrict access to physical drives */
- if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
- ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) ==
- TYPE_DISK)) {
-
- scb->scsi_cmd->result = DID_TIME_OUT << 16;
+ if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
+ ips_scmd_buf_read(scb->scsi_cmd,
+ &inquiryData, sizeof (inquiryData));
+ if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK)
+ scb->scsi_cmd->result = DID_TIME_OUT << 16;
}
} /* else */
} else { /* recovered error / success */
@@ -5012,7 +5014,7 @@ ips_init_copperhead(ips_ha_t * ha)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (j >= 45)
@@ -5038,7 +5040,7 @@ ips_init_copperhead(ips_ha_t * ha)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (j >= 240)
@@ -5056,7 +5058,7 @@ ips_init_copperhead(ips_ha_t * ha)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (i >= 240)
@@ -5106,7 +5108,7 @@ ips_init_copperhead_memio(ips_ha_t * ha)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (j >= 45)
@@ -5132,7 +5134,7 @@ ips_init_copperhead_memio(ips_ha_t * ha)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (j >= 240)
@@ -5150,7 +5152,7 @@ ips_init_copperhead_memio(ips_ha_t * ha)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (i >= 240)
@@ -5202,7 +5204,7 @@ ips_init_morpheus(ips_ha_t * ha)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (i >= 45) {
@@ -5228,7 +5230,7 @@ ips_init_morpheus(ips_ha_t * ha)
if (Post != 0x4F00)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (i >= 120) {
@@ -5258,7 +5260,7 @@ ips_init_morpheus(ips_ha_t * ha)
break;
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
}
if (i >= 240) {
@@ -5318,12 +5320,12 @@ ips_reset_copperhead(ips_ha_t * ha)
outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR);
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
outb(0, ha->io_addr + IPS_REG_SCPR);
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
if ((*ha->func.init) (ha))
break;
@@ -5363,12 +5365,12 @@ ips_reset_copperhead_memio(ips_ha_t * ha)
writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR);
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
writeb(0, ha->mem_ptr + IPS_REG_SCPR);
/* Delay for 1 Second */
- MDELAY(IPS_ONE_SEC);
+ msleep(IPS_ONE_SEC);
if ((*ha->func.init) (ha))
break;
@@ -5409,7 +5411,7 @@ ips_reset_morpheus(ips_ha_t * ha)
writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR);
/* Delay for 5 Seconds */
- MDELAY(5 * IPS_ONE_SEC);
+ msleep(5 * IPS_ONE_SEC);
/* Do a PCI config read to wait for adapter */
pci_read_config_byte(ha->pcidev, 4, &junk);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 780bfcc6709..ff79e68b347 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -146,7 +146,7 @@ iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
spin_unlock_irqrestore(&session->lock, flags);
set_bit(SUSPEND_BIT, &conn->suspend_tx);
set_bit(SUSPEND_BIT, &conn->suspend_rx);
- iscsi_conn_error(iscsi_handle(conn), err);
+ iscsi_conn_error(conn->cls_conn, err);
}
static inline int
@@ -244,12 +244,10 @@ iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
if (sc->sc_data_direction == DMA_TO_DEVICE) {
struct iscsi_data_task *dtask, *n;
/* WRITE: cleanup Data-Out's if any */
- spin_lock(&conn->lock);
list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) {
list_del(&dtask->item);
mempool_free(dtask, ctask->datapool);
}
- spin_unlock(&conn->lock);
}
ctask->xmstate = XMSTATE_IDLE;
ctask->r2t = NULL;
@@ -689,7 +687,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
break;
if (!conn->in.datalen) {
- rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
+ rc = iscsi_recv_pdu(conn->cls_conn, hdr,
NULL, 0);
if (conn->login_mtask != mtask) {
spin_lock(&session->lock);
@@ -737,7 +735,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
if (!conn->in.datalen) {
struct iscsi_mgmt_task *mtask;
- rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
+ rc = iscsi_recv_pdu(conn->cls_conn, hdr,
NULL, 0);
mtask = (struct iscsi_mgmt_task *)
session->mgmt_cmds[conn->in.itt -
@@ -761,7 +759,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
rc = iscsi_check_assign_cmdsn(session,
(struct iscsi_nopin*)hdr);
if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
- rc = iscsi_recv_pdu(iscsi_handle(conn),
+ rc = iscsi_recv_pdu(conn->cls_conn,
hdr, NULL, 0);
} else
rc = ISCSI_ERR_PROTO;
@@ -1044,7 +1042,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
goto exit;
}
- rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
+ rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr,
conn->data, conn->in.datalen);
if (!rc && conn->datadgst_en &&
@@ -2428,19 +2426,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
}
static struct iscsi_cls_conn *
-iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
+iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
{
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
struct iscsi_conn *conn;
struct iscsi_cls_conn *cls_conn;
- cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
- conn_idx);
+ cls_conn = iscsi_create_conn(cls_session, conn_idx);
if (!cls_conn)
return NULL;
conn = cls_conn->dd_data;
+ memset(conn, 0, sizeof(*conn));
- memset(conn, 0, sizeof(struct iscsi_conn));
+ conn->cls_conn = cls_conn;
conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
conn->in_progress = IN_PROGRESS_WAIT_HEADER;
conn->id = conn_idx;
@@ -2452,8 +2451,6 @@ iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
- spin_lock_init(&conn->lock);
-
/* initialize general xmit PDU commands queue */
conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
GFP_KERNEL, NULL);
@@ -2625,11 +2622,13 @@ iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
}
static int
-iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
- uint32_t transport_fd, int is_leading)
+iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
+ int is_leading)
{
- struct iscsi_session *session = iscsi_ptr(sessionh);
- struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = iscsi_ptr(connh);
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
struct sock *sk;
struct socket *sock;
int err;
@@ -2703,9 +2702,9 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
}
static int
-iscsi_conn_start(iscsi_connh_t connh)
+iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
struct sock *sk;
@@ -2754,9 +2753,9 @@ iscsi_conn_start(iscsi_connh_t connh)
}
static void
-iscsi_conn_stop(iscsi_connh_t connh, int flag)
+iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
struct sock *sk;
unsigned long flags;
@@ -3253,9 +3252,9 @@ static struct scsi_host_template iscsi_sht = {
static struct iscsi_transport iscsi_tcp_transport;
-static struct Scsi_Host *
+static struct iscsi_cls_session *
iscsi_session_create(struct scsi_transport_template *scsit,
- uint32_t initial_cmdsn)
+ uint32_t initial_cmdsn, uint32_t *sid)
{
struct Scsi_Host *shost;
struct iscsi_session *session;
@@ -3268,13 +3267,14 @@ iscsi_session_create(struct scsi_transport_template *scsit,
session = iscsi_hostdata(shost->hostdata);
memset(session, 0, sizeof(struct iscsi_session));
session->host = shost;
- session->state = ISCSI_STATE_LOGGED_IN;
+ session->state = ISCSI_STATE_FREE;
session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
session->cmds_max = ISCSI_XMIT_CMDS_MAX;
session->cmdsn = initial_cmdsn;
session->exp_cmdsn = initial_cmdsn + 1;
session->max_cmdsn = initial_cmdsn + 1;
session->max_r2t = 1;
+ *sid = shost->host_no;
/* initialize SCSI PDU commands pool */
if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
@@ -3311,22 +3311,24 @@ iscsi_session_create(struct scsi_transport_template *scsit,
if (iscsi_r2tpool_alloc(session))
goto r2tpool_alloc_fail;
- return shost;
+ return hostdata_session(shost->hostdata);
r2tpool_alloc_fail:
for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
kfree(session->mgmt_cmds[cmd_i]->data);
- iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
immdata_alloc_fail:
+ iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
mgmtpool_alloc_fail:
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
cmdpool_alloc_fail:
+ iscsi_transport_destroy_session(shost);
return NULL;
}
static void
-iscsi_session_destroy(struct Scsi_Host *shost)
+iscsi_session_destroy(struct iscsi_cls_session *cls_session)
{
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
int cmd_i;
struct iscsi_data_task *dtask, *n;
@@ -3350,10 +3352,10 @@ iscsi_session_destroy(struct Scsi_Host *shost)
}
static int
-iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
+iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
uint32_t value)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
spin_lock_bh(&session->lock);
@@ -3495,9 +3497,10 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
}
static int
-iscsi_session_get_param(struct Scsi_Host *shost,
+iscsi_session_get_param(struct iscsi_cls_session *cls_session,
enum iscsi_param param, uint32_t *value)
{
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
switch(param) {
@@ -3539,9 +3542,10 @@ iscsi_session_get_param(struct Scsi_Host *shost,
}
static int
-iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
+iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ enum iscsi_param param, uint32_t *value)
{
- struct iscsi_conn *conn = data;
+ struct iscsi_conn *conn = cls_conn->dd_data;
switch(param) {
case ISCSI_PARAM_MAX_RECV_DLENGTH:
@@ -3564,9 +3568,9 @@ iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
}
static void
-iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
+iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
stats->txdata_octets = conn->txdata_octets;
stats->rxdata_octets = conn->rxdata_octets;
@@ -3587,10 +3591,10 @@ iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
}
static int
-iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data,
- uint32_t data_size)
+iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+ char *data, uint32_t data_size)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
int rc;
mutex_lock(&conn->xmitmutex);
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index f95e61b76f7..ba26741ac15 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -113,7 +113,10 @@ struct iscsi_tcp_recv {
int datadgst;
};
+struct iscsi_cls_conn;
+
struct iscsi_conn {
+ struct iscsi_cls_conn *cls_conn; /* ptr to class connection */
struct iscsi_hdr hdr; /* header placeholder */
char hdrext[4*sizeof(__u16) +
sizeof(__u32)];
@@ -143,7 +146,6 @@ struct iscsi_conn {
struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */
struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */
struct iscsi_cmd_task *ctask; /* xmit ctask in progress */
- spinlock_t lock; /* FIXME: to be removed */
/* old values for socket callbacks */
void (*old_data_ready)(struct sock *, int);
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 99bae8369ab..7ddd5a69352 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -611,6 +611,10 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
if (dev->flags & ATA_DFLAG_PIO) {
tf->protocol = ATA_PROT_PIO;
index = dev->multi_count ? 0 : 8;
+ } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
+ /* Unable to use DMA due to host limitation */
+ tf->protocol = ATA_PROT_PIO;
+ index = dev->multi_count ? 0 : 8;
} else {
tf->protocol = ATA_PROT_DMA;
index = 16;
@@ -1051,18 +1055,22 @@ 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)) {
+ /* Usual case. Word 53 indicates word 64 is valid */
+ if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) {
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 ;
+ /* If word 64 isn't valid then Word 51 high byte 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] >> 8) & 0xFF)) - 1 ;
return modes;
+ /* But wait.. there's more. Design your standards by committee and
+ you too can get a free iordy field to process. However its the
+ speeds not the modes that are supported... Note drivers using the
+ timing API will get this right anyway */
}
struct ata_exec_internal_arg {
@@ -1165,6 +1173,39 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
}
/**
+ * ata_pio_need_iordy - check if iordy needed
+ * @adev: ATA device
+ *
+ * Check if the current speed of the device requires IORDY. Used
+ * by various controllers for chip configuration.
+ */
+
+unsigned int ata_pio_need_iordy(const struct ata_device *adev)
+{
+ int pio;
+ int speed = adev->pio_mode - XFER_PIO_0;
+
+ if (speed < 2)
+ return 0;
+ if (speed > 2)
+ return 1;
+
+ /* If we have no drive specific rule, then PIO 2 is non IORDY */
+
+ if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE */
+ pio = adev->id[ATA_ID_EIDE_PIO];
+ /* Is the speed faster than the drive allows non IORDY ? */
+ if (pio) {
+ /* This is cycle times not frequency - watch the logic! */
+ if (pio > 240) /* PIO2 is 240nS per cycle */
+ return 1;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/**
* ata_dev_identify - obtain IDENTIFY x DEVICE page
* @ap: port on which device we wish to probe resides
* @device: device bus address, starting at zero
@@ -1415,7 +1456,7 @@ void ata_dev_config(struct ata_port *ap, unsigned int i)
ap->udma_mask &= ATA_UDMA5;
ap->host->max_sectors = ATA_MAX_SECTORS;
ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
- ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+ ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS;
}
if (ap->ops->dev_config)
@@ -3056,10 +3097,21 @@ static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int do_write)
{
- if (ap->flags & ATA_FLAG_MMIO)
- ata_mmio_data_xfer(ap, buf, buflen, do_write);
- else
- ata_pio_data_xfer(ap, buf, buflen, do_write);
+ /* Make the crap hardware pay the costs not the good stuff */
+ if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) {
+ unsigned long flags;
+ local_irq_save(flags);
+ if (ap->flags & ATA_FLAG_MMIO)
+ ata_mmio_data_xfer(ap, buf, buflen, do_write);
+ else
+ ata_pio_data_xfer(ap, buf, buflen, do_write);
+ local_irq_restore(flags);
+ } else {
+ if (ap->flags & ATA_FLAG_MMIO)
+ ata_mmio_data_xfer(ap, buf, buflen, do_write);
+ else
+ ata_pio_data_xfer(ap, buf, buflen, do_write);
+ }
}
/**
@@ -3305,11 +3357,12 @@ static void ata_pio_error(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
- printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
-
qc = ata_qc_from_tag(ap, ap->active_tag);
assert(qc != NULL);
+ if (qc->tf.command != ATA_CMD_PACKET)
+ printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
+
/* make sure qc->err_mask is available to
* know what's wrong and recover
*/
@@ -5122,6 +5175,7 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
EXPORT_SYMBOL_GPL(ata_dev_config);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
EXPORT_SYMBOL_GPL(ata_timing_compute);
EXPORT_SYMBOL_GPL(ata_timing_merge);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index cfbceb50471..07b1e7cc61d 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1700,6 +1700,31 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
return sizeof(def_rw_recovery_mpage);
}
+/*
+ * We can turn this into a real blacklist if it's needed, for now just
+ * blacklist any Maxtor BANC1G10 revision firmware
+ */
+static int ata_dev_supports_fua(u16 *id)
+{
+ unsigned char model[41], fw[9];
+
+ if (!ata_id_has_fua(id))
+ return 0;
+
+ model[40] = '\0';
+ fw[8] = '\0';
+
+ ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1);
+ ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1);
+
+ if (strncmp(model, "Maxtor", 6))
+ return 1;
+ if (strncmp(fw, "BANC1G10", 8))
+ return 1;
+
+ return 0; /* blacklisted */
+}
+
/**
* ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
* @args: device IDENTIFY data / SCSI command of interest.
@@ -1797,7 +1822,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
return 0;
dpofua = 0;
- if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
+ if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
(!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
dpofua = 1 << 4;
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 311a4122bd7..93edaa8696c 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -537,9 +537,9 @@ static int mac53c94_remove(struct macio_dev *mdev)
free_irq(fp->intr, fp);
if (fp->regs)
- iounmap((void *) fp->regs);
+ iounmap(fp->regs);
if (fp->dma)
- iounmap((void *) fp->dma);
+ iounmap(fp->dma);
kfree(fp->dma_cmd_space);
scsi_host_put(host);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index d101a8a6f4e..7144674bc8e 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -5049,7 +5049,7 @@ static struct pci_device_id megaraid_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, megaraid_pci_tbl);
static struct pci_driver megaraid_pci_driver = {
- .name = "megaraid",
+ .name = "megaraid_legacy",
.id_table = megaraid_pci_tbl,
.probe = megaraid_probe_one,
.remove = __devexit_p(megaraid_remove_one),
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 4b3e0d6e5af..4b75fe619d9 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -5,7 +5,7 @@
#include <linux/mutex.h>
#define MEGARAID_VERSION \
- "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"
+ "v2.00.4 (Release Date: Thu Feb 9 08:51:30 EST 2006)\n"
/*
* Driver features - change the values to enable or disable features in the
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 511ed52a580..7de267e1445 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_sas.c
- * Version : v00.00.02.00-rc4
+ * Version : v00.00.02.04
*
* Authors:
* Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
@@ -55,13 +55,19 @@ static struct pci_device_id megasas_pci_table[] = {
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_LSI_SAS1064R,
+ PCI_DEVICE_ID_LSI_SAS1064R, // xscale IOP
PCI_ANY_ID,
PCI_ANY_ID,
},
{
+ PCI_VENDOR_ID_LSI_LOGIC,
+ PCI_DEVICE_ID_LSI_SAS1078R, // ppc IOP
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ },
+ {
PCI_VENDOR_ID_DELL,
- PCI_DEVICE_ID_DELL_PERC5,
+ PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
PCI_ANY_ID,
PCI_ANY_ID,
},
@@ -119,12 +125,18 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
}
+
/**
- * megasas_enable_intr - Enables interrupts
+* The following functions are defined for xscale
+* (deviceid : 1064R, PERC5) controllers
+*/
+
+/**
+ * megasas_enable_intr_xscale - Enables interrupts
* @regs: MFI register set
*/
static inline void
-megasas_enable_intr(struct megasas_register_set __iomem * regs)
+megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
{
writel(1, &(regs)->outbound_intr_mask);
@@ -133,13 +145,153 @@ megasas_enable_intr(struct megasas_register_set __iomem * regs)
}
/**
+ * megasas_read_fw_status_reg_xscale - returns the current FW status value
+ * @regs: MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs)
+{
+ return readl(&(regs)->outbound_msg_0);
+}
+/**
+ * megasas_clear_interrupt_xscale - Check & clear interrupt
+ * @regs: MFI register set
+ */
+static int
+megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
+{
+ u32 status;
+ /*
+ * Check if it is our interrupt
+ */
+ status = readl(&regs->outbound_intr_status);
+
+ if (!(status & MFI_OB_INTR_STATUS_MASK)) {
+ return 1;
+ }
+
+ /*
+ * Clear the interrupt by writing back the same value
+ */
+ writel(status, &regs->outbound_intr_status);
+
+ return 0;
+}
+
+/**
+ * megasas_fire_cmd_xscale - Sends command to the FW
+ * @frame_phys_addr : Physical address of cmd
+ * @frame_count : Number of frames for the command
+ * @regs : MFI register set
+ */
+static inline void
+megasas_fire_cmd_xscale(dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs)
+{
+ writel((frame_phys_addr >> 3)|(frame_count),
+ &(regs)->inbound_queue_port);
+}
+
+static struct megasas_instance_template megasas_instance_template_xscale = {
+
+ .fire_cmd = megasas_fire_cmd_xscale,
+ .enable_intr = megasas_enable_intr_xscale,
+ .clear_intr = megasas_clear_intr_xscale,
+ .read_fw_status_reg = megasas_read_fw_status_reg_xscale,
+};
+
+/**
+* This is the end of set of functions & definitions specific
+* to xscale (deviceid : 1064R, PERC5) controllers
+*/
+
+/**
+* The following functions are defined for ppc (deviceid : 0x60)
+* controllers
+*/
+
+/**
+ * megasas_enable_intr_ppc - Enables interrupts
+ * @regs: MFI register set
+ */
+static inline void
+megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+ writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
+
+ writel(~0x80000004, &(regs)->outbound_intr_mask);
+
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_ppc - returns the current FW status value
+ * @regs: MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
+{
+ return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_ppc - Check & clear interrupt
+ * @regs: MFI register set
+ */
+static int
+megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+ u32 status;
+ /*
+ * Check if it is our interrupt
+ */
+ status = readl(&regs->outbound_intr_status);
+
+ if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
+ return 1;
+ }
+
+ /*
+ * Clear the interrupt by writing back the same value
+ */
+ writel(status, &regs->outbound_doorbell_clear);
+
+ return 0;
+}
+/**
+ * megasas_fire_cmd_ppc - Sends command to the FW
+ * @frame_phys_addr : Physical address of cmd
+ * @frame_count : Number of frames for the command
+ * @regs : MFI register set
+ */
+static inline void
+megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs)
+{
+ writel((frame_phys_addr | (frame_count<<1))|1,
+ &(regs)->inbound_queue_port);
+}
+
+static struct megasas_instance_template megasas_instance_template_ppc = {
+
+ .fire_cmd = megasas_fire_cmd_ppc,
+ .enable_intr = megasas_enable_intr_ppc,
+ .clear_intr = megasas_clear_intr_ppc,
+ .read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+};
+
+/**
+* This is the end of set of functions & definitions
+* specific to ppc (deviceid : 0x60) controllers
+*/
+
+/**
* megasas_disable_intr - Disables interrupts
* @regs: MFI register set
*/
static inline void
megasas_disable_intr(struct megasas_register_set __iomem * regs)
{
- u32 mask = readl(&regs->outbound_intr_mask) & (~0x00000001);
+ u32 mask = 0x1f;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
@@ -167,8 +319,7 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
/*
* Issue the frame using inbound queue port
*/
- writel(cmd->frame_phys_addr >> 3,
- &instance->reg_set->inbound_queue_port);
+ instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
/*
* Wait for cmd_status to change
@@ -198,8 +349,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance,
{
cmd->cmd_status = ENODATA;
- writel(cmd->frame_phys_addr >> 3,
- &instance->reg_set->inbound_queue_port);
+ instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA));
@@ -242,8 +392,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
cmd->sync_cmd = 1;
cmd->cmd_status = 0xFF;
- writel(cmd->frame_phys_addr >> 3,
- &instance->reg_set->inbound_queue_port);
+ instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
/*
* Wait for this cmd to complete
@@ -558,112 +707,29 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
}
/**
- * megasas_build_cmd - Prepares a command packet
- * @instance: Adapter soft state
- * @scp: SCSI command
- * @frame_count: [OUT] Number of frames used to prepare this command
+ * megasas_is_ldio - Checks if the cmd is for logical drive
+ * @scmd: SCSI command
+ *
+ * Called by megasas_queue_command to find out if the command to be queued
+ * is a logical drive command
*/
-static struct megasas_cmd *megasas_build_cmd(struct megasas_instance
- *instance,
- struct scsi_cmnd *scp,
- int *frame_count)
+static inline int megasas_is_ldio(struct scsi_cmnd *cmd)
{
- u32 logical_cmd;
- struct megasas_cmd *cmd;
-
- /*
- * Find out if this is logical or physical drive command.
- */
- logical_cmd = MEGASAS_IS_LOGICAL(scp);
-
- /*
- * Logical drive command
- */
- if (logical_cmd) {
-
- if (scp->device->id >= MEGASAS_MAX_LD) {
- scp->result = DID_BAD_TARGET << 16;
- return NULL;
- }
-
- switch (scp->cmnd[0]) {
-
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- case READ_6:
- case WRITE_6:
- case READ_16:
- case WRITE_16:
- /*
- * Fail for LUN > 0
- */
- if (scp->device->lun) {
- scp->result = DID_BAD_TARGET << 16;
- return NULL;
- }
-
- cmd = megasas_get_cmd(instance);
-
- if (!cmd) {
- scp->result = DID_IMM_RETRY << 16;
- return NULL;
- }
-
- *frame_count = megasas_build_ldio(instance, scp, cmd);
-
- if (!(*frame_count)) {
- megasas_return_cmd(instance, cmd);
- return NULL;
- }
-
- return cmd;
-
- default:
- /*
- * Fail for LUN > 0
- */
- if (scp->device->lun) {
- scp->result = DID_BAD_TARGET << 16;
- return NULL;
- }
-
- cmd = megasas_get_cmd(instance);
-
- if (!cmd) {
- scp->result = DID_IMM_RETRY << 16;
- return NULL;
- }
-
- *frame_count = megasas_build_dcdb(instance, scp, cmd);
-
- if (!(*frame_count)) {
- megasas_return_cmd(instance, cmd);
- return NULL;
- }
-
- return cmd;
- }
- } else {
- cmd = megasas_get_cmd(instance);
-
- if (!cmd) {
- scp->result = DID_IMM_RETRY << 16;
- return NULL;
- }
-
- *frame_count = megasas_build_dcdb(instance, scp, cmd);
-
- if (!(*frame_count)) {
- megasas_return_cmd(instance, cmd);
- return NULL;
- }
-
- return cmd;
+ if (!MEGASAS_IS_LOGICAL(cmd))
+ return 0;
+ switch (cmd->cmnd[0]) {
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:
+ case READ_6:
+ case WRITE_6:
+ case READ_16:
+ case WRITE_16:
+ return 1;
+ default:
+ return 0;
}
-
- return NULL;
}
/**
@@ -684,13 +750,27 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
scmd->scsi_done = done;
scmd->result = 0;
- cmd = megasas_build_cmd(instance, scmd, &frame_count);
-
- if (!cmd) {
- done(scmd);
- return 0;
+ if (MEGASAS_IS_LOGICAL(scmd) &&
+ (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
+ scmd->result = DID_BAD_TARGET << 16;
+ goto out_done;
}
+ cmd = megasas_get_cmd(instance);
+ if (!cmd)
+ return SCSI_MLQUEUE_HOST_BUSY;
+
+ /*
+ * Logical drive command
+ */
+ if (megasas_is_ldio(scmd))
+ frame_count = megasas_build_ldio(instance, scmd, cmd);
+ else
+ frame_count = megasas_build_dcdb(instance, scmd, cmd);
+
+ if (!frame_count)
+ goto out_return_cmd;
+
cmd->scmd = scmd;
scmd->SCp.ptr = (char *)cmd;
scmd->SCp.sent_command = jiffies;
@@ -702,10 +782,15 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
instance->fw_outstanding++;
spin_unlock_irqrestore(&instance->instance_lock, flags);
- writel(((cmd->frame_phys_addr >> 3) | (cmd->frame_count - 1)),
- &instance->reg_set->inbound_queue_port);
+ instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
return 0;
+
+ out_return_cmd:
+ megasas_return_cmd(instance, cmd);
+ out_done:
+ done(scmd);
+ return 0;
}
/**
@@ -1108,7 +1193,6 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
static int
megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
{
- u32 status;
u32 producer;
u32 consumer;
u32 context;
@@ -1116,17 +1200,10 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
/*
* Check if it is our interrupt
+ * Clear the interrupt
*/
- status = readl(&instance->reg_set->outbound_intr_status);
-
- if (!(status & MFI_OB_INTR_STATUS_MASK)) {
+ if(instance->instancet->clear_intr(instance->reg_set))
return IRQ_NONE;
- }
-
- /*
- * Clear the interrupt by writing back the same value
- */
- writel(status, &instance->reg_set->outbound_intr_status);
producer = *instance->producer;
consumer = *instance->consumer;
@@ -1160,7 +1237,7 @@ static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs)
/**
* megasas_transition_to_ready - Move the FW to READY state
- * @reg_set: MFI register set
+ * @instance: Adapter soft state
*
* During the initialization, FW passes can potentially be in any one of
* several possible states. If the FW in operational, waiting-for-handshake
@@ -1168,14 +1245,14 @@ static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs)
* has to wait for the ready state.
*/
static int
-megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set)
+megasas_transition_to_ready(struct megasas_instance* instance)
{
int i;
u8 max_wait;
u32 fw_state;
u32 cur_state;
- fw_state = readl(&reg_set->outbound_msg_0) & MFI_STATE_MASK;
+ fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
while (fw_state != MFI_STATE_READY) {
@@ -1193,7 +1270,7 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set)
* Set the CLR bit in inbound doorbell
*/
writel(MFI_INIT_CLEAR_HANDSHAKE,
- &reg_set->inbound_doorbell);
+ &instance->reg_set->inbound_doorbell);
max_wait = 2;
cur_state = MFI_STATE_WAIT_HANDSHAKE;
@@ -1203,8 +1280,8 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set)
/*
* Bring it to READY state; assuming max wait 2 secs
*/
- megasas_disable_intr(reg_set);
- writel(MFI_INIT_READY, &reg_set->inbound_doorbell);
+ megasas_disable_intr(instance->reg_set);
+ writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell);
max_wait = 10;
cur_state = MFI_STATE_OPERATIONAL;
@@ -1253,8 +1330,8 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set)
* The cur_state should not last for more than max_wait secs
*/
for (i = 0; i < (max_wait * 1000); i++) {
- fw_state = MFI_STATE_MASK &
- readl(&reg_set->outbound_msg_0);
+ fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &
+ MFI_STATE_MASK ;
if (fw_state == cur_state) {
msleep(1);
@@ -1616,18 +1693,30 @@ static int megasas_init_mfi(struct megasas_instance *instance)
reg_set = instance->reg_set;
+ switch(instance->pdev->device)
+ {
+ case PCI_DEVICE_ID_LSI_SAS1078R:
+ instance->instancet = &megasas_instance_template_ppc;
+ break;
+ case PCI_DEVICE_ID_LSI_SAS1064R:
+ case PCI_DEVICE_ID_DELL_PERC5:
+ default:
+ instance->instancet = &megasas_instance_template_xscale;
+ break;
+ }
+
/*
* We expect the FW state to be READY
*/
- if (megasas_transition_to_ready(instance->reg_set))
+ if (megasas_transition_to_ready(instance))
goto fail_ready_state;
/*
* Get various operational parameters from status register
*/
- instance->max_fw_cmds = readl(&reg_set->outbound_msg_0) & 0x00FFFF;
- instance->max_num_sge = (readl(&reg_set->outbound_msg_0) & 0xFF0000) >>
- 0x10;
+ instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
+ instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >>
+ 0x10;
/*
* Create a pool of commands
*/
@@ -1936,8 +2025,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
/*
* Issue the aen registration frame
*/
- writel(cmd->frame_phys_addr >> 3,
- &instance->reg_set->inbound_queue_port);
+ instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
return 0;
}
@@ -1991,6 +2079,7 @@ static int megasas_io_attach(struct megasas_instance *instance)
host->max_channel = MEGASAS_MAX_CHANNELS - 1;
host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
host->max_lun = MEGASAS_MAX_LUN;
+ host->max_cmd_len = 16;
/*
* Notify the mid-layer about the new controller
@@ -2126,7 +2215,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto fail_irq;
}
- megasas_enable_intr(instance->reg_set);
+ instance->instancet->enable_intr(instance->reg_set);
/*
* Store instance in PCI softstate
@@ -2681,9 +2770,8 @@ megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
switch (cmd) {
- case MEGASAS_IOC_FIRMWARE:{
- return megasas_mgmt_compat_ioctl_fw(file, arg);
- }
+ case MEGASAS_IOC_FIRMWARE32:
+ return megasas_mgmt_compat_ioctl_fw(file, arg);
case MEGASAS_IOC_GET_AEN:
return megasas_mgmt_ioctl_aen(file, arg);
}
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index eaec9d53142..89639f0c38e 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -18,10 +18,9 @@
/**
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.02.00-rc4"
-#define MEGASAS_RELDATE "Sep 16, 2005"
-#define MEGASAS_EXT_VERSION "Fri Sep 16 12:37:08 EDT 2005"
-
+#define MEGASAS_VERSION "00.00.02.04"
+#define MEGASAS_RELDATE "Feb 03, 2006"
+#define MEGASAS_EXT_VERSION "Fri Feb 03 14:31:44 PST 2006"
/*
* =====================================
* MegaRAID SAS MFI firmware definitions
@@ -554,31 +553,46 @@ struct megasas_ctrl_info {
#define MFI_OB_INTR_STATUS_MASK 0x00000002
#define MFI_POLL_TIMEOUT_SECS 10
+#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
+#define PCI_DEVICE_ID_LSI_SAS1078R 0x00000060
+
struct megasas_register_set {
+ u32 reserved_0[4]; /*0000h*/
+
+ u32 inbound_msg_0; /*0010h*/
+ u32 inbound_msg_1; /*0014h*/
+ u32 outbound_msg_0; /*0018h*/
+ u32 outbound_msg_1; /*001Ch*/
+
+ u32 inbound_doorbell; /*0020h*/
+ u32 inbound_intr_status; /*0024h*/
+ u32 inbound_intr_mask; /*0028h*/
+
+ u32 outbound_doorbell; /*002Ch*/
+ u32 outbound_intr_status; /*0030h*/
+ u32 outbound_intr_mask; /*0034h*/
- u32 reserved_0[4]; /*0000h */
+ u32 reserved_1[2]; /*0038h*/
- u32 inbound_msg_0; /*0010h */
- u32 inbound_msg_1; /*0014h */
- u32 outbound_msg_0; /*0018h */
- u32 outbound_msg_1; /*001Ch */
+ u32 inbound_queue_port; /*0040h*/
+ u32 outbound_queue_port; /*0044h*/
- u32 inbound_doorbell; /*0020h */
- u32 inbound_intr_status; /*0024h */
- u32 inbound_intr_mask; /*0028h */
+ u32 reserved_2[22]; /*0048h*/
- u32 outbound_doorbell; /*002Ch */
- u32 outbound_intr_status; /*0030h */
- u32 outbound_intr_mask; /*0034h */
+ u32 outbound_doorbell_clear; /*00A0h*/
- u32 reserved_1[2]; /*0038h */
+ u32 reserved_3[3]; /*00A4h*/
- u32 inbound_queue_port; /*0040h */
- u32 outbound_queue_port; /*0044h */
+ u32 outbound_scratch_pad ; /*00B0h*/
- u32 reserved_2; /*004Ch */
+ u32 reserved_4[3]; /*00B4h*/
- u32 index_registers[1004]; /*0050h */
+ u32 inbound_low_queue_port ; /*00C0h*/
+
+ u32 inbound_high_queue_port ; /*00C4h*/
+
+ u32 reserved_5; /*00C8h*/
+ u32 index_registers[820]; /*00CCh*/
} __attribute__ ((packed));
@@ -1013,6 +1027,16 @@ struct megasas_evt_detail {
} __attribute__ ((packed));
+ struct megasas_instance_template {
+ void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
+
+ void (*enable_intr)(struct megasas_register_set __iomem *) ;
+
+ int (*clear_intr)(struct megasas_register_set __iomem *);
+
+ u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
+ };
+
struct megasas_instance {
u32 *producer;
@@ -1056,6 +1080,8 @@ struct megasas_instance {
u32 fw_outstanding;
u32 hw_crit_error;
spinlock_t instance_lock;
+
+ struct megasas_instance_template *instancet;
};
#define MEGASAS_IS_LOGICAL(scp) \
@@ -1125,11 +1151,10 @@ struct compat_megasas_iocpacket {
struct compat_iovec sgl[MAX_IOCTL_SGE];
} __attribute__ ((packed));
-#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct compat_megasas_iocpacket)
-#else
-#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket)
#endif
+#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket)
+#define MEGASAS_IOC_FIRMWARE32 _IOWR('M', 1, struct compat_megasas_iocpacket)
#define MEGASAS_IOC_GET_AEN _IOW('M', 3, struct megasas_aen)
struct megasas_mgmt_info {
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 0878f95b544..e0230249fa0 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -17,9 +17,11 @@
* General Public License for more details.
*
******************************************************************************/
-#define QLA1280_VERSION "3.25"
+#define QLA1280_VERSION "3.26"
/*****************************************************************************
Revision History:
+ Rev 3.26, January 16, 2006 Jes Sorensen
+ - Ditch all < 2.6 support
Rev 3.25.1, February 10, 2005 Christoph Hellwig
- use pci_map_single to map non-S/G requests
- remove qla1280_proc_info
@@ -356,25 +358,18 @@
#include <asm/types.h>
#include <asm/system.h>
-#if LINUX_VERSION_CODE >= 0x020545
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-#else
-#include <linux/blk.h>
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "sd.h"
-#endif
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
#include <asm/sn/io.h>
#endif
-#if LINUX_VERSION_CODE < 0x020407
-#error "Kernels older than 2.4.7 are no longer supported"
+#if LINUX_VERSION_CODE < 0x020600
+#error "Kernels older than 2.6.0 are no longer supported"
#endif
@@ -441,52 +436,6 @@
#define NVRAM_DELAY() udelay(500) /* 2 microseconds */
-#if LINUX_VERSION_CODE < 0x020500
-#define HOST_LOCK &io_request_lock
-#define irqreturn_t void
-#define IRQ_RETVAL(foo)
-#define MSG_ORDERED_TAG 1
-
-#define DMA_BIDIRECTIONAL SCSI_DATA_UNKNOWN
-#define DMA_TO_DEVICE SCSI_DATA_WRITE
-#define DMA_FROM_DEVICE SCSI_DATA_READ
-#define DMA_NONE SCSI_DATA_NONE
-
-#ifndef HAVE_SECTOR_T
-typedef unsigned int sector_t;
-#endif
-
-static inline void
-scsi_adjust_queue_depth(struct scsi_device *device, int tag, int depth)
-{
- if (tag) {
- device->tagged_queue = tag;
- device->current_tag = 0;
- }
- device->queue_depth = depth;
-}
-static inline struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *t, size_t s)
-{
- return scsi_register(t, s);
-}
-static inline void scsi_host_put(struct Scsi_Host *h)
-{
- scsi_unregister(h);
-}
-#else
-#define HOST_LOCK ha->host->host_lock
-#endif
-#if LINUX_VERSION_CODE < 0x020600
-#define DEV_SIMPLE_TAGS(device) device->tagged_queue
-/*
- * Hack around that qla1280_remove_one is called from
- * qla1280_release in 2.4
- */
-#undef __devexit
-#define __devexit
-#else
-#define DEV_SIMPLE_TAGS(device) device->simple_tags
-#endif
#if defined(__ia64__) && !defined(ia64_platform_is)
#define ia64_platform_is(foo) (!strcmp(x, platform_name))
#endif
@@ -506,9 +455,6 @@ static void qla1280_remove_one(struct pci_dev *);
* QLogic Driver Support Function Prototypes.
*/
static void qla1280_done(struct scsi_qla_host *);
-#if LINUX_VERSION_CODE < 0x020545
-static void qla1280_get_target_options(struct scsi_cmnd *, struct scsi_qla_host *);
-#endif
static int qla1280_get_token(char *);
static int qla1280_setup(char *s) __init;
@@ -610,11 +556,7 @@ __setup("qla1280=", qla1280_setup);
#define CMD_SNSLEN(Cmnd) sizeof(Cmnd->sense_buffer)
#define CMD_RESULT(Cmnd) Cmnd->result
#define CMD_HANDLE(Cmnd) Cmnd->host_scribble
-#if LINUX_VERSION_CODE < 0x020545
-#define CMD_REQUEST(Cmnd) Cmnd->request.cmd
-#else
#define CMD_REQUEST(Cmnd) Cmnd->request->cmd
-#endif
#define CMD_HOST(Cmnd) Cmnd->device->host
#define SCSI_BUS_32(Cmnd) Cmnd->device->channel
@@ -1064,10 +1006,10 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
add_timer(&timer);
/* wait for the action to complete (or the timer to expire) */
- spin_unlock_irq(HOST_LOCK);
+ spin_unlock_irq(ha->host->host_lock);
wait_for_completion(&wait);
del_timer_sync(&timer);
- spin_lock_irq(HOST_LOCK);
+ spin_lock_irq(ha->host->host_lock);
sp->wait = NULL;
/* the only action we might get a fail for is abort */
@@ -1173,96 +1115,6 @@ qla1280_biosparam(struct scsi_device *sdev, struct block_device *bdev,
return 0;
}
-#if LINUX_VERSION_CODE < 0x020600
-static int
-qla1280_detect(struct scsi_host_template *template)
-{
- struct pci_device_id *id = &qla1280_pci_tbl[0];
- struct pci_dev *pdev = NULL;
- int num_hosts = 0;
-
- if (sizeof(struct srb) > sizeof(Scsi_Pointer)) {
- printk(KERN_WARNING
- "qla1280: struct srb too big, aborting\n");
- return 0;
- }
-
- if ((DMA_BIDIRECTIONAL != PCI_DMA_BIDIRECTIONAL) ||
- (DMA_TO_DEVICE != PCI_DMA_TODEVICE) ||
- (DMA_FROM_DEVICE != PCI_DMA_FROMDEVICE) ||
- (DMA_NONE != PCI_DMA_NONE)) {
- printk(KERN_WARNING
- "qla1280: dma direction bits don't match\n");
- return 0;
- }
-
-#ifdef MODULE
- /*
- * If we are called as a module, the qla1280 pointer may not be null
- * and it would point to our bootup string, just like on the lilo
- * command line. IF not NULL, then process this config string with
- * qla1280_setup
- *
- * Boot time Options
- * To add options at boot time add a line to your lilo.conf file like:
- * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}"
- * which will result in the first four devices on the first two
- * controllers being set to a tagged queue depth of 32.
- */
- if (qla1280)
- qla1280_setup(qla1280);
-#endif
-
- /* First Initialize QLA12160 on PCI Bus 1 Dev 2 */
- while ((pdev = pci_find_device(id->vendor, id->device, pdev))) {
- if (pdev->bus->number == 1 && PCI_SLOT(pdev->devfn) == 2) {
- if (!qla1280_probe_one(pdev, id))
- num_hosts++;
- }
- }
-
- pdev = NULL;
- /* Try and find each different type of adapter we support */
- for (id = &qla1280_pci_tbl[0]; id->device; id++) {
- while ((pdev = pci_find_device(id->vendor, id->device, pdev))) {
- /*
- * skip QLA12160 already initialized on
- * PCI Bus 1 Dev 2 since we already initialized
- * and presented it
- */
- if (id->device == PCI_DEVICE_ID_QLOGIC_ISP12160 &&
- pdev->bus->number == 1 &&
- PCI_SLOT(pdev->devfn) == 2)
- continue;
-
- if (!qla1280_probe_one(pdev, id))
- num_hosts++;
- }
- }
-
- return num_hosts;
-}
-
-/*
- * This looks a bit ugly as we could just pass down host to
- * qla1280_remove_one, but I want to keep qla1280_release purely a wrapper
- * around pci_driver::remove as used from 2.6 onwards.
- */
-static int
-qla1280_release(struct Scsi_Host *host)
-{
- struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
-
- qla1280_remove_one(ha->pdev);
- return 0;
-}
-
-static int
-qla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[])
-{
- return qla1280_biosparam(disk->device, NULL, disk->capacity, geom);
-}
-#endif
/* disable risc and host interrupts */
static inline void
@@ -1295,7 +1147,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
ENTER_INTR ("qla1280_intr_handler");
ha = (struct scsi_qla_host *)dev_id;
- spin_lock(HOST_LOCK);
+ spin_lock(ha->host->host_lock);
ha->isr_count++;
reg = ha->iobase;
@@ -1311,7 +1163,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
if (!list_empty(&ha->done_q))
qla1280_done(ha);
- spin_unlock(HOST_LOCK);
+ spin_unlock(ha->host->host_lock);
qla1280_enable_intrs(ha);
@@ -1411,11 +1263,9 @@ qla1280_slave_configure(struct scsi_device *device)
scsi_adjust_queue_depth(device, 0, default_depth);
}
-#if LINUX_VERSION_CODE > 0x020500
nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
nv->bus[bus].target[target].parameter.enable_wide = device->wdtr;
nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr;
-#endif
if (driver_setup.no_sync ||
(driver_setup.sync_mask &&
@@ -1432,38 +1282,14 @@ qla1280_slave_configure(struct scsi_device *device)
nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
}
- spin_lock_irqsave(HOST_LOCK, flags);
+ spin_lock_irqsave(ha->host->host_lock, flags);
if (nv->bus[bus].target[target].parameter.enable_sync)
status = qla1280_set_target_parameters(ha, bus, target);
qla1280_get_target_parameters(ha, device);
- spin_unlock_irqrestore(HOST_LOCK, flags);
+ spin_unlock_irqrestore(ha->host->host_lock, flags);
return status;
}
-#if LINUX_VERSION_CODE < 0x020545
-/**************************************************************************
- * qla1280_select_queue_depth
- *
- * Sets the queue depth for each SCSI device hanging off the input
- * host adapter. We use a queue depth of 2 for devices that do not
- * support tagged queueing.
- **************************************************************************/
-static void
-qla1280_select_queue_depth(struct Scsi_Host *host, struct scsi_device *sdev_q)
-{
- struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
- struct scsi_device *sdev;
-
- ENTER("qla1280_select_queue_depth");
- for (sdev = sdev_q; sdev; sdev = sdev->next)
- if (sdev->host == host)
- qla1280_slave_configure(sdev);
-
- if (sdev_q)
- qla1280_check_for_dead_scsi_bus(ha, sdev_q->channel);
- LEAVE("qla1280_select_queue_depth");
-}
-#endif
/*
* qla1280_done
@@ -1523,10 +1349,6 @@ qla1280_done(struct scsi_qla_host *ha)
CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE;
ha->actthreads--;
-#if LINUX_VERSION_CODE < 0x020500
- if (cmd->cmnd[0] == INQUIRY)
- qla1280_get_target_options(cmd, ha);
-#endif
(*(cmd)->scsi_done)(cmd);
if(sp->wait != NULL)
@@ -1655,9 +1477,7 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
struct device_reg __iomem *reg;
int status;
int bus;
-#if LINUX_VERSION_CODE > 0x020500
unsigned long flags;
-#endif
ENTER("qla1280_initialize_adapter");
@@ -1695,15 +1515,12 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
"NVRAM\n");
}
-#if LINUX_VERSION_CODE >= 0x020500
/*
* It's necessary to grab the spin here as qla1280_mailbox_command
* needs to be able to drop the lock unconditionally to wait
* for completion.
- * In 2.4 ->detect is called with the io_request_lock held.
*/
- spin_lock_irqsave(HOST_LOCK, flags);
-#endif
+ spin_lock_irqsave(ha->host->host_lock, flags);
status = qla1280_load_firmware(ha);
if (status) {
@@ -1735,9 +1552,8 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
ha->flags.online = 1;
out:
-#if LINUX_VERSION_CODE >= 0x020500
- spin_unlock_irqrestore(HOST_LOCK, flags);
-#endif
+ spin_unlock_irqrestore(ha->host->host_lock, flags);
+
if (status)
dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n");
@@ -2650,14 +2466,14 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb)
timer.function = qla1280_mailbox_timeout;
add_timer(&timer);
- spin_unlock_irq(HOST_LOCK);
+ spin_unlock_irq(ha->host->host_lock);
WRT_REG_WORD(&reg->host_cmd, HC_SET_HOST_INT);
data = qla1280_debounce_register(&reg->istatus);
wait_for_completion(&wait);
del_timer_sync(&timer);
- spin_lock_irq(HOST_LOCK);
+ spin_lock_irq(ha->host->host_lock);
ha->mailbox_wait = NULL;
@@ -2770,9 +2586,9 @@ qla1280_bus_reset(struct scsi_qla_host *ha, int bus)
ha->bus_settings[bus].scsi_bus_dead = 1;
ha->bus_settings[bus].failed_reset_count++;
} else {
- spin_unlock_irq(HOST_LOCK);
+ spin_unlock_irq(ha->host->host_lock);
ssleep(reset_delay);
- spin_lock_irq(HOST_LOCK);
+ spin_lock_irq(ha->host->host_lock);
ha->bus_settings[bus].scsi_bus_dead = 0;
ha->bus_settings[bus].failed_reset_count = 0;
@@ -3078,7 +2894,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
/* Enable simple tag queuing if device supports it. */
- if (DEV_SIMPLE_TAGS(cmd->device))
+ if (cmd->device->simple_tags)
pkt->control_flags |= cpu_to_le16(BIT_3);
/* Load SCSI command packet. */
@@ -3377,7 +3193,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
/* Enable simple tag queuing if device supports it. */
- if (DEV_SIMPLE_TAGS(cmd->device))
+ if (cmd->device->simple_tags)
pkt->control_flags |= cpu_to_le16(BIT_3);
/* Load SCSI command packet. */
@@ -3889,50 +3705,6 @@ qla1280_rst_aen(struct scsi_qla_host *ha)
}
-#if LINUX_VERSION_CODE < 0x020500
-/*
- *
- */
-static void
-qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha)
-{
- unsigned char *result;
- struct nvram *n;
- int bus, target, lun;
-
- bus = SCSI_BUS_32(cmd);
- target = SCSI_TCN_32(cmd);
- lun = SCSI_LUN_32(cmd);
-
- /*
- * Make sure to not touch anything if someone is using the
- * sg interface.
- */
- if (cmd->use_sg || (CMD_RESULT(cmd) >> 16) != DID_OK || lun)
- return;
-
- result = cmd->request_buffer;
- n = &ha->nvram;
-
- n->bus[bus].target[target].parameter.enable_wide = 0;
- n->bus[bus].target[target].parameter.enable_sync = 0;
- n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
-
- if (result[7] & 0x60)
- n->bus[bus].target[target].parameter.enable_wide = 1;
- if (result[7] & 0x10)
- n->bus[bus].target[target].parameter.enable_sync = 1;
- if ((result[2] >= 3) && (result[4] + 5 > 56) &&
- (result[56] & 0x4))
- n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
-
- dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n",
- n->bus[bus].target[target].parameter.enable_wide,
- n->bus[bus].target[target].parameter.enable_sync,
- n->bus[bus].target[target].ppr_1x160.flags.enable_ppr);
-}
-#endif
-
/*
* qla1280_status_entry
* Processes received ISP status entry.
@@ -4271,7 +4043,7 @@ qla1280_get_target_parameters(struct scsi_qla_host *ha,
} else
printk(" Async");
- if (DEV_SIMPLE_TAGS(device))
+ if (device->simple_tags)
printk(", Tagged queuing: depth %d", device->queue_depth);
printk("\n");
}
@@ -4485,7 +4257,7 @@ qla1280_get_token(char *str)
return ret;
}
-#if LINUX_VERSION_CODE >= 0x020600
+
static struct scsi_host_template qla1280_driver_template = {
.module = THIS_MODULE,
.proc_name = "qla1280",
@@ -4504,27 +4276,7 @@ static struct scsi_host_template qla1280_driver_template = {
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
};
-#else
-static struct scsi_host_template qla1280_driver_template = {
- .proc_name = "qla1280",
- .name = "Qlogic ISP 1280/12160",
- .detect = qla1280_detect,
- .release = qla1280_release,
- .info = qla1280_info,
- .queuecommand = qla1280_queuecommand,
- .eh_abort_handler = qla1280_eh_abort,
- .eh_device_reset_handler= qla1280_eh_device_reset,
- .eh_bus_reset_handler = qla1280_eh_bus_reset,
- .eh_host_reset_handler = qla1280_eh_adapter_reset,
- .bios_param = qla1280_biosparam_old,
- .can_queue = 0xfffff,
- .this_id = -1,
- .sg_tablesize = SG_ALL,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
- .use_new_eh_code = 1,
-};
-#endif
+
static int __devinit
qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -4615,10 +4367,6 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
host->max_sectors = 1024;
host->unique_id = host->host_no;
-#if LINUX_VERSION_CODE < 0x020545
- host->select_queue_depths = qla1280_select_queue_depth;
-#endif
-
error = -ENODEV;
#if MEMORY_MAPPED_IO
@@ -4666,21 +4414,15 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, host);
-#if LINUX_VERSION_CODE >= 0x020600
error = scsi_add_host(host, &pdev->dev);
if (error)
goto error_disable_adapter;
scsi_scan_host(host);
-#else
- scsi_set_pci_device(host, pdev);
-#endif
return 0;
-#if LINUX_VERSION_CODE >= 0x020600
error_disable_adapter:
qla1280_disable_intrs(ha);
-#endif
error_free_irq:
free_irq(pdev->irq, ha);
error_release_region:
@@ -4712,9 +4454,7 @@ qla1280_remove_one(struct pci_dev *pdev)
struct Scsi_Host *host = pci_get_drvdata(pdev);
struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
-#if LINUX_VERSION_CODE >= 0x020600
scsi_remove_host(host);
-#endif
qla1280_disable_intrs(ha);
@@ -4738,7 +4478,6 @@ qla1280_remove_one(struct pci_dev *pdev)
scsi_host_put(host);
}
-#if LINUX_VERSION_CODE >= 0x020600
static struct pci_driver qla1280_pci_driver = {
.name = "qla1280",
.id_table = qla1280_pci_tbl,
@@ -4784,10 +4523,6 @@ qla1280_exit(void)
module_init(qla1280_init);
module_exit(qla1280_exit);
-#else
-# define driver_template qla1280_driver_template
-# include "scsi_module.c"
-#endif
MODULE_AUTHOR("Qlogic & Jes Sorensen");
MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index b17ee62dd1a..92b3e13e906 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -7,7 +7,6 @@
#include "qla_def.h"
#include <linux/vmalloc.h>
-#include <scsi/scsi_transport_fc.h>
/* SYSFS attributes --------------------------------------------------------- */
@@ -114,7 +113,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
struct device, kobj)));
unsigned long flags;
- if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
+ if (!capable(CAP_SYS_ADMIN) || off != 0)
return 0;
/* Read NVRAM. */
@@ -123,7 +122,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
ha->nvram_size);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- return (count);
+ return ha->nvram_size;
}
static ssize_t
@@ -175,19 +174,150 @@ static struct bin_attribute sysfs_nvram_attr = {
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
- .size = 0,
+ .size = 512,
.read = qla2x00_sysfs_read_nvram,
.write = qla2x00_sysfs_write_nvram,
};
+static ssize_t
+qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+
+ if (ha->optrom_state != QLA_SREADING)
+ return 0;
+ if (off > ha->optrom_size)
+ return 0;
+ if (off + count > ha->optrom_size)
+ count = ha->optrom_size - off;
+
+ memcpy(buf, &ha->optrom_buffer[off], count);
+
+ return count;
+}
+
+static ssize_t
+qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+
+ if (ha->optrom_state != QLA_SWRITING)
+ return -EINVAL;
+ if (off > ha->optrom_size)
+ return -ERANGE;
+ if (off + count > ha->optrom_size)
+ count = ha->optrom_size - off;
+
+ memcpy(&ha->optrom_buffer[off], buf, count);
+
+ return count;
+}
+
+static struct bin_attribute sysfs_optrom_attr = {
+ .attr = {
+ .name = "optrom",
+ .mode = S_IRUSR | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = OPTROM_SIZE_24XX,
+ .read = qla2x00_sysfs_read_optrom,
+ .write = qla2x00_sysfs_write_optrom,
+};
+
+static ssize_t
+qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+ int val;
+
+ if (off)
+ return 0;
+
+ if (sscanf(buf, "%d", &val) != 1)
+ return -EINVAL;
+
+ switch (val) {
+ case 0:
+ if (ha->optrom_state != QLA_SREADING &&
+ ha->optrom_state != QLA_SWRITING)
+ break;
+
+ ha->optrom_state = QLA_SWAITING;
+ vfree(ha->optrom_buffer);
+ ha->optrom_buffer = NULL;
+ break;
+ case 1:
+ if (ha->optrom_state != QLA_SWAITING)
+ break;
+
+ ha->optrom_state = QLA_SREADING;
+ ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
+ if (ha->optrom_buffer == NULL) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to allocate memory for optrom retrieval "
+ "(%x).\n", ha->optrom_size);
+
+ ha->optrom_state = QLA_SWAITING;
+ return count;
+ }
+
+ memset(ha->optrom_buffer, 0, ha->optrom_size);
+ ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0,
+ ha->optrom_size);
+ break;
+ case 2:
+ if (ha->optrom_state != QLA_SWAITING)
+ break;
+
+ ha->optrom_state = QLA_SWRITING;
+ ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
+ if (ha->optrom_buffer == NULL) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to allocate memory for optrom update "
+ "(%x).\n", ha->optrom_size);
+
+ ha->optrom_state = QLA_SWAITING;
+ return count;
+ }
+ memset(ha->optrom_buffer, 0, ha->optrom_size);
+ break;
+ case 3:
+ if (ha->optrom_state != QLA_SWRITING)
+ break;
+
+ ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0,
+ ha->optrom_size);
+ break;
+ }
+ return count;
+}
+
+static struct bin_attribute sysfs_optrom_ctl_attr = {
+ .attr = {
+ .name = "optrom_ctl",
+ .mode = S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = 0,
+ .write = qla2x00_sysfs_write_optrom_ctl,
+};
+
void
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
{
struct Scsi_Host *host = ha->host;
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
- sysfs_nvram_attr.size = ha->nvram_size;
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
+ sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
+ sysfs_create_bin_file(&host->shost_gendev.kobj,
+ &sysfs_optrom_ctl_attr);
}
void
@@ -197,6 +327,12 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
+ sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
+ sysfs_remove_bin_file(&host->shost_gendev.kobj,
+ &sysfs_optrom_ctl_attr);
+
+ if (ha->beacon_blink_led == 1)
+ ha->isp_ops.beacon_off(ha);
}
/* Scsi_Host attributes. */
@@ -384,6 +520,50 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
return strlen(buf);
}
+static ssize_t
+qla2x00_beacon_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ int len = 0;
+
+ if (ha->beacon_blink_led)
+ len += snprintf(buf + len, PAGE_SIZE-len, "Enabled\n");
+ else
+ len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
+ return len;
+}
+
+static ssize_t
+qla2x00_beacon_store(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ int val = 0;
+ int rval;
+
+ if (IS_QLA2100(ha) || IS_QLA2200(ha))
+ return -EPERM;
+
+ if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) {
+ qla_printk(KERN_WARNING, ha,
+ "Abort ISP active -- ignoring beacon request.\n");
+ return -EBUSY;
+ }
+
+ if (sscanf(buf, "%d", &val) != 1)
+ return -EINVAL;
+
+ if (val)
+ rval = ha->isp_ops.beacon_on(ha);
+ else
+ rval = ha->isp_ops.beacon_off(ha);
+
+ if (rval != QLA_SUCCESS)
+ count = 0;
+
+ return count;
+}
+
static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
NULL);
static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
@@ -398,6 +578,8 @@ static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show,
qla2x00_zio_store);
static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
qla2x00_zio_timer_store);
+static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
+ qla2x00_beacon_store);
struct class_device_attribute *qla2x00_host_attrs[] = {
&class_device_attr_driver_version,
@@ -411,6 +593,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = {
&class_device_attr_state,
&class_device_attr_zio,
&class_device_attr_zio_timer,
+ &class_device_attr_beacon,
NULL,
};
@@ -426,6 +609,49 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost)
}
static void
+qla2x00_get_host_speed(struct Scsi_Host *shost)
+{
+ scsi_qla_host_t *ha = to_qla_host(shost);
+ uint32_t speed = 0;
+
+ switch (ha->link_data_rate) {
+ case LDR_1GB:
+ speed = 1;
+ break;
+ case LDR_2GB:
+ speed = 2;
+ break;
+ case LDR_4GB:
+ speed = 4;
+ break;
+ }
+ fc_host_speed(shost) = speed;
+}
+
+static void
+qla2x00_get_host_port_type(struct Scsi_Host *shost)
+{
+ scsi_qla_host_t *ha = to_qla_host(shost);
+ uint32_t port_type = FC_PORTTYPE_UNKNOWN;
+
+ switch (ha->current_topology) {
+ case ISP_CFG_NL:
+ port_type = FC_PORTTYPE_LPORT;
+ break;
+ case ISP_CFG_FL:
+ port_type = FC_PORTTYPE_NLPORT;
+ break;
+ case ISP_CFG_N:
+ port_type = FC_PORTTYPE_PTP;
+ break;
+ case ISP_CFG_F:
+ port_type = FC_PORTTYPE_NPORT;
+ break;
+ }
+ fc_host_port_type(shost) = port_type;
+}
+
+static void
qla2x00_get_starget_node_name(struct scsi_target *starget)
{
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
@@ -512,6 +738,41 @@ qla2x00_issue_lip(struct Scsi_Host *shost)
return 0;
}
+static struct fc_host_statistics *
+qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
+{
+ scsi_qla_host_t *ha = to_qla_host(shost);
+ int rval;
+ uint16_t mb_stat[1];
+ link_stat_t stat_buf;
+ struct fc_host_statistics *pfc_host_stat;
+
+ pfc_host_stat = &ha->fc_host_stat;
+ memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
+
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf,
+ sizeof(stat_buf) / 4, mb_stat);
+ } else {
+ rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf,
+ mb_stat);
+ }
+ if (rval != 0) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to retrieve host statistics (%d).\n", mb_stat[0]);
+ return pfc_host_stat;
+ }
+
+ pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt;
+ pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt;
+ pfc_host_stat->loss_of_signal_count = stat_buf.loss_sig_cnt;
+ pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt;
+ pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt;
+ pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt;
+
+ return pfc_host_stat;
+}
+
struct fc_function_template qla2xxx_transport_functions = {
.show_host_node_name = 1,
@@ -520,6 +781,10 @@ struct fc_function_template qla2xxx_transport_functions = {
.get_host_port_id = qla2x00_get_host_port_id,
.show_host_port_id = 1,
+ .get_host_speed = qla2x00_get_host_speed,
+ .show_host_speed = 1,
+ .get_host_port_type = qla2x00_get_host_port_type,
+ .show_host_port_type = 1,
.dd_fcrport_size = sizeof(struct fc_port *),
.show_rport_supported_classes = 1,
@@ -536,6 +801,7 @@ struct fc_function_template qla2xxx_transport_functions = {
.show_rport_dev_loss_tmo = 1,
.issue_fc_host_lip = qla2x00_issue_lip,
+ .get_fc_host_stats = qla2x00_get_fc_host_stats,
};
void
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 79d8a914f9d..b31a03bbd14 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -29,6 +29,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_transport_fc.h>
#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE)
@@ -181,6 +182,13 @@
#define WRT_REG_DWORD(addr, data) writel(data,addr)
/*
+ * The ISP2312 v2 chip cannot access the FLASH/GPIO registers via MMIO in an
+ * 133Mhz slot.
+ */
+#define RD_REG_WORD_PIO(addr) (inw((unsigned long)addr))
+#define WRT_REG_WORD_PIO(addr, data) (outw(data,(unsigned long)addr))
+
+/*
* Fibre Channel device definitions.
*/
#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */
@@ -432,6 +440,9 @@ struct device_reg_2xxx {
#define GPIO_LED_GREEN_ON_AMBER_OFF 0x0040
#define GPIO_LED_GREEN_OFF_AMBER_ON 0x0080
#define GPIO_LED_GREEN_ON_AMBER_ON 0x00C0
+#define GPIO_LED_ALL_OFF 0x0000
+#define GPIO_LED_RED_ON_OTHER_OFF 0x0001 /* isp2322 */
+#define GPIO_LED_RGA_ON 0x00C1 /* isp2322: red green amber */
union {
struct {
@@ -1680,7 +1691,8 @@ typedef struct fc_port {
uint8_t mp_byte; /* multi-path byte (not used) */
uint8_t cur_path; /* current path id */
- struct fc_rport *rport;
+ spinlock_t rport_lock;
+ struct fc_rport *rport, *drport;
u32 supported_classes;
struct work_struct rport_add_work;
struct work_struct rport_del_work;
@@ -2198,6 +2210,15 @@ struct isp_operations {
void (*fw_dump) (struct scsi_qla_host *, int);
void (*ascii_fw_dump) (struct scsi_qla_host *);
+
+ int (*beacon_on) (struct scsi_qla_host *);
+ int (*beacon_off) (struct scsi_qla_host *);
+ void (*beacon_blink) (struct scsi_qla_host *);
+
+ uint8_t * (*read_optrom) (struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+ int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t,
+ uint32_t);
};
/*
@@ -2270,6 +2291,7 @@ typedef struct scsi_qla_host {
#define LOOP_RESET_NEEDED 24
#define BEACON_BLINK_NEEDED 25
#define REGISTER_FDMI_NEEDED 26
+#define FCPORT_UPDATE_NEEDED 27
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
@@ -2329,6 +2351,10 @@ typedef struct scsi_qla_host {
uint16_t min_external_loopid; /* First external loop Id */
uint16_t link_data_rate; /* F/W operating speed */
+#define LDR_1GB 0
+#define LDR_2GB 1
+#define LDR_4GB 3
+#define LDR_UNKNOWN 0xFFFF
uint8_t current_topology;
uint8_t prev_topology;
@@ -2484,12 +2510,26 @@ typedef struct scsi_qla_host {
uint8_t *port_name;
uint32_t isp_abort_cnt;
+ /* Option ROM information. */
+ char *optrom_buffer;
+ uint32_t optrom_size;
+ int optrom_state;
+#define QLA_SWAITING 0
+#define QLA_SREADING 1
+#define QLA_SWRITING 2
+
/* Needed for BEACON */
uint16_t beacon_blink_led;
- uint16_t beacon_green_on;
+ uint8_t beacon_color_state;
+#define QLA_LED_GRN_ON 0x01
+#define QLA_LED_YLW_ON 0x02
+#define QLA_LED_ABR_ON 0x04
+#define QLA_LED_ALL_ON 0x07 /* yellow, green, amber. */
+ /* ISP2322: red, green, amber. */
uint16_t zio_mode;
uint16_t zio_timer;
+ struct fc_host_statistics fc_host_stat;
} scsi_qla_host_t;
@@ -2555,7 +2595,9 @@ struct _qla2x00stats {
/*
* Flash support definitions
*/
-#define FLASH_IMAGE_SIZE 131072
+#define OPTROM_SIZE_2300 0x20000
+#define OPTROM_SIZE_2322 0x100000
+#define OPTROM_SIZE_24XX 0x100000
#include "qla_gbl.h"
#include "qla_dbg.h"
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 32be4c14ccc..ffdc2680f04 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -47,9 +47,11 @@ extern int qla2x00_local_device_login(scsi_qla_host_t *, uint16_t);
extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
extern void qla2x00_rescan_fcports(scsi_qla_host_t *);
+extern void qla2x00_update_fcports(scsi_qla_host_t *);
extern int qla2x00_abort_isp(scsi_qla_host_t *);
+extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *);
/*
@@ -70,15 +72,15 @@ extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
extern void qla2x00_cmd_timeout(srb_t *);
-extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int);
-extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *);
-
-extern void qla2x00_blink_led(scsi_qla_host_t *);
+extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
+extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
extern int qla2x00_down_timeout(struct semaphore *, unsigned long);
extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
+extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
+
/*
* Global Function Prototypes in qla_iocb.c source file.
*/
@@ -183,6 +185,13 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *,
extern int
qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
+extern int
+qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, link_stat_t *,
+ uint16_t *);
+
+extern int
+qla24xx_get_isp_stats(scsi_qla_host_t *, uint32_t *, uint32_t, uint16_t *);
+
extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
extern int qla24xx_abort_target(fc_port_t *);
@@ -226,6 +235,22 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
+extern int qla2x00_beacon_on(struct scsi_qla_host *);
+extern int qla2x00_beacon_off(struct scsi_qla_host *);
+extern void qla2x00_beacon_blink(struct scsi_qla_host *);
+extern int qla24xx_beacon_on(struct scsi_qla_host *);
+extern int qla24xx_beacon_off(struct scsi_qla_host *);
+extern void qla24xx_beacon_blink(struct scsi_qla_host *);
+
+extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+extern int qla2x00_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+ uint32_t, uint32_t);
+
/*
* Global Function Prototypes in qla_dbg.c source file.
*/
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a91fea69ad6..634ee174bff 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/vmalloc.h>
-#include <scsi/scsi_transport_fc.h>
#include "qla_devtbl.h"
@@ -32,7 +31,6 @@ static int qla2x00_fw_ready(scsi_qla_host_t *);
static int qla2x00_configure_hba(scsi_qla_host_t *);
static int qla2x00_configure_loop(scsi_qla_host_t *);
static int qla2x00_configure_local_loop(scsi_qla_host_t *);
-static void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
static int qla2x00_configure_fabric(scsi_qla_host_t *);
static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *, struct list_head *);
static int qla2x00_device_resync(scsi_qla_host_t *);
@@ -1688,10 +1686,16 @@ static void
qla2x00_rport_del(void *data)
{
fc_port_t *fcport = data;
+ struct fc_rport *rport;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fcport->rport_lock, flags);
+ rport = fcport->drport;
+ fcport->drport = NULL;
+ spin_unlock_irqrestore(&fcport->rport_lock, flags);
+ if (rport)
+ fc_remote_port_delete(rport);
- if (fcport->rport)
- fc_remote_port_delete(fcport->rport);
- fcport->rport = NULL;
}
/**
@@ -1719,6 +1723,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
atomic_set(&fcport->state, FCS_UNCONFIGURED);
fcport->flags = FCF_RLC_SUPPORT;
fcport->supported_classes = FC_COS_UNSPECIFIED;
+ spin_lock_init(&fcport->rport_lock);
INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
@@ -2008,7 +2013,7 @@ qla2x00_probe_for_all_luns(scsi_qla_host_t *ha)
{
fc_port_t *fcport;
- qla2x00_mark_all_devices_lost(ha);
+ qla2x00_mark_all_devices_lost(ha, 0);
list_for_each_entry(fcport, &ha->fcports, list) {
if (fcport->port_type != FCT_TARGET)
continue;
@@ -2032,13 +2037,9 @@ qla2x00_probe_for_all_luns(scsi_qla_host_t *ha)
* Context:
* Kernel context.
*/
-static void
+void
qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
{
- uint16_t index;
- unsigned long flags;
- srb_t *sp;
-
fcport->ha = ha;
fcport->login_retry = 0;
fcport->port_login_retry_count = ha->port_down_retry_count *
@@ -2047,28 +2048,6 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
PORT_RETRY_TIME);
fcport->flags &= ~FCF_LOGIN_NEEDED;
- /*
- * Check for outstanding cmd on tape Bypass LUN discovery if active
- * command on tape.
- */
- if (fcport->flags & FCF_TAPE_PRESENT) {
- spin_lock_irqsave(&ha->hardware_lock, flags);
- for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
- fc_port_t *sfcp;
-
- if ((sp = ha->outstanding_cmds[index]) != 0) {
- sfcp = sp->fcport;
- if (sfcp == fcport) {
- atomic_set(&fcport->state, FCS_ONLINE);
- spin_unlock_irqrestore(
- &ha->hardware_lock, flags);
- return;
- }
- }
- }
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- }
-
if (fcport->port_type == FCT_INITIATOR ||
fcport->port_type == FCT_BROADCAST)
fcport->device_type = TYPE_PROCESSOR;
@@ -2084,24 +2063,29 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
{
struct fc_rport_identifiers rport_ids;
struct fc_rport *rport;
+ unsigned long flags;
- if (fcport->rport) {
- fc_remote_port_delete(fcport->rport);
- fcport->rport = NULL;
- }
+ if (fcport->drport)
+ qla2x00_rport_del(fcport);
+ if (fcport->rport)
+ return;
rport_ids.node_name = wwn_to_u64(fcport->node_name);
rport_ids.port_name = wwn_to_u64(fcport->port_name);
rport_ids.port_id = fcport->d_id.b.domain << 16 |
fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
- fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids);
+ rport = fc_remote_port_add(ha->host, 0, &rport_ids);
if (!rport) {
qla_printk(KERN_WARNING, ha,
"Unable to allocate fc remote port!\n");
return;
}
+ spin_lock_irqsave(&fcport->rport_lock, flags);
+ fcport->rport = rport;
*((fc_port_t **)rport->dd_data) = fcport;
+ spin_unlock_irqrestore(&fcport->rport_lock, flags);
+
rport->supported_classes = fcport->supported_classes;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
@@ -2217,12 +2201,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
qla2x00_mark_device_lost(ha, fcport,
- ql2xplogiabsentdevice);
+ ql2xplogiabsentdevice, 0);
if (fcport->loop_id != FC_NO_LOOP_ID &&
(fcport->flags & FCF_TAPE_PRESENT) == 0 &&
fcport->port_type != FCT_INITIATOR &&
fcport->port_type != FCT_BROADCAST) {
-
ha->isp_ops.fabric_logout(ha,
fcport->loop_id,
fcport->d_id.b.domain,
@@ -2694,7 +2677,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
if (atomic_read(&fcport->state) == FCS_ONLINE) {
if (format != 3 ||
fcport->port_type != FCT_INITIATOR) {
- qla2x00_mark_device_lost(ha, fcport, 0);
+ qla2x00_mark_device_lost(ha, fcport,
+ 0, 0);
}
}
fcport->flags &= ~FCF_FARP_DONE;
@@ -2741,8 +2725,7 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport,
ha->isp_ops.fabric_logout(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa);
- qla2x00_mark_device_lost(ha, fcport, 1);
-
+ qla2x00_mark_device_lost(ha, fcport, 1, 0);
} else {
qla2x00_update_fcport(ha, fcport);
}
@@ -2855,7 +2838,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
ha->isp_ops.fabric_logout(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa);
- qla2x00_mark_device_lost(ha, fcport, 1);
+ qla2x00_mark_device_lost(ha, fcport, 1, 0);
rval = 1;
break;
@@ -2990,6 +2973,17 @@ qla2x00_rescan_fcports(scsi_qla_host_t *ha)
qla2x00_probe_for_all_luns(ha);
}
+void
+qla2x00_update_fcports(scsi_qla_host_t *ha)
+{
+ fc_port_t *fcport;
+
+ /* Go with deferred removal of rport references. */
+ list_for_each_entry(fcport, &ha->fcports, list)
+ if (fcport->drport)
+ qla2x00_rport_del(fcport);
+}
+
/*
* qla2x00_abort_isp
* Resets ISP and aborts all outstanding commands.
@@ -3019,7 +3013,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
- qla2x00_mark_all_devices_lost(ha);
+ qla2x00_mark_all_devices_lost(ha, 0);
} else {
if (!atomic_read(&ha->loop_down_timer))
atomic_set(&ha->loop_down_timer,
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 7ec0b8d6f07..6544b6d0891 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -814,6 +814,7 @@ qla24xx_start_scsi(srb_t *sp)
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
+ host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
/* Load SCSI command packet. */
memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f63af081d4f..42aa7a7c1a7 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -389,7 +389,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(ha);
+ qla2x00_mark_all_devices_lost(ha, 1);
}
set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
@@ -402,9 +402,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break;
case MBA_LOOP_UP: /* Loop Up Event */
- ha->link_data_rate = 0;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
link_speed = link_speeds[0];
+ ha->link_data_rate = LDR_1GB;
} else {
link_speed = link_speeds[LS_UNKNOWN];
if (mb[1] < 5)
@@ -432,11 +432,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
atomic_set(&ha->loop_state, LOOP_DOWN);
atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
ha->device_flags |= DFLG_NO_CABLE;
- qla2x00_mark_all_devices_lost(ha);
+ qla2x00_mark_all_devices_lost(ha, 1);
}
ha->flags.management_server_logged_in = 0;
- ha->link_data_rate = 0;
+ ha->link_data_rate = LDR_UNKNOWN;
if (ql2xfdmienable)
set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
@@ -453,7 +453,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(ha);
+ qla2x00_mark_all_devices_lost(ha, 1);
}
set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -482,7 +482,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
if (!atomic_read(&ha->loop_down_timer))
atomic_set(&ha->loop_down_timer,
LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(ha);
+ qla2x00_mark_all_devices_lost(ha, 1);
}
if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) {
@@ -506,7 +506,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
if (!atomic_read(&ha->loop_down_timer))
atomic_set(&ha->loop_down_timer,
LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(ha);
+ qla2x00_mark_all_devices_lost(ha, 1);
}
set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
@@ -580,7 +580,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
*/
atomic_set(&ha->loop_state, LOOP_UP);
- qla2x00_mark_all_devices_lost(ha);
+ qla2x00_mark_all_devices_lost(ha, 1);
ha->flags.rscn_queue_overflow = 1;
@@ -1091,7 +1091,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
cp->result = DID_BUS_BUSY << 16;
if (atomic_read(&fcport->state) == FCS_ONLINE) {
- qla2x00_mark_device_lost(ha, fcport, 1);
+ qla2x00_mark_device_lost(ha, fcport, 1, 1);
}
break;
@@ -1135,7 +1135,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
/* Check to see if logout occurred. */
if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
- qla2x00_mark_device_lost(ha, fcport, 1);
+ qla2x00_mark_device_lost(ha, fcport, 1, 1);
break;
case CS_QUEUE_FULL:
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 3099b379de9..363dfdd042b 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -7,7 +7,6 @@
#include "qla_def.h"
#include <linux/delay.h>
-#include <scsi/scsi_transport_fc.h>
static void
qla2x00_mbx_sem_timeout(unsigned long data)
@@ -1874,7 +1873,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
mcp->mb[3] = LSW(id_list_dma);
mcp->mb[6] = MSW(MSD(id_list_dma));
mcp->mb[7] = LSW(MSD(id_list_dma));
- mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2;
+ mcp->mb[8] = 0;
+ mcp->out_mb |= MBX_8|MBX_7|MBX_6|MBX_3|MBX_2;
} else {
mcp->mb[1] = MSW(id_list_dma);
mcp->mb[2] = LSW(id_list_dma);
@@ -2017,8 +2017,109 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map)
return rval;
}
+#endif
+
+/*
+ * qla2x00_get_link_status
+ *
+ * Input:
+ * ha = adapter block pointer.
+ * loop_id = device loop ID.
+ * ret_buf = pointer to link status return buffer.
+ *
+ * Returns:
+ * 0 = success.
+ * BIT_0 = mem alloc error.
+ * BIT_1 = mailbox error.
+ */
+int
+qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
+ link_stat_t *ret_buf, uint16_t *status)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ link_stat_t *stat_buf;
+ dma_addr_t stat_buf_dma;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+
+ stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma);
+ if (stat_buf == NULL) {
+ DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
+ __func__, ha->host_no));
+ return BIT_0;
+ }
+ memset(stat_buf, 0, sizeof(link_stat_t));
+
+ mcp->mb[0] = MBC_GET_LINK_STATUS;
+ mcp->mb[2] = MSW(stat_buf_dma);
+ mcp->mb[3] = LSW(stat_buf_dma);
+ mcp->mb[6] = MSW(MSD(stat_buf_dma));
+ mcp->mb[7] = LSW(MSD(stat_buf_dma));
+ mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
+ mcp->in_mb = MBX_0;
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ mcp->mb[1] = loop_id;
+ mcp->mb[4] = 0;
+ mcp->mb[10] = 0;
+ mcp->out_mb |= MBX_10|MBX_4|MBX_1;
+ mcp->in_mb |= MBX_1;
+ } else if (HAS_EXTENDED_IDS(ha)) {
+ mcp->mb[1] = loop_id;
+ mcp->mb[10] = 0;
+ mcp->out_mb |= MBX_10|MBX_1;
+ } else {
+ mcp->mb[1] = loop_id << 8;
+ mcp->out_mb |= MBX_1;
+ }
+ mcp->tov = 30;
+ mcp->flags = IOCTL_CMD;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+ if (rval == QLA_SUCCESS) {
+ if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
+ DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
+ __func__, ha->host_no, mcp->mb[0]);)
+ status[0] = mcp->mb[0];
+ rval = BIT_1;
+ } else {
+ /* copy over data -- firmware data is LE. */
+ ret_buf->link_fail_cnt =
+ le32_to_cpu(stat_buf->link_fail_cnt);
+ ret_buf->loss_sync_cnt =
+ le32_to_cpu(stat_buf->loss_sync_cnt);
+ ret_buf->loss_sig_cnt =
+ le32_to_cpu(stat_buf->loss_sig_cnt);
+ ret_buf->prim_seq_err_cnt =
+ le32_to_cpu(stat_buf->prim_seq_err_cnt);
+ ret_buf->inval_xmit_word_cnt =
+ le32_to_cpu(stat_buf->inval_xmit_word_cnt);
+ ret_buf->inval_crc_cnt =
+ le32_to_cpu(stat_buf->inval_crc_cnt);
+
+ DEBUG11(printk("%s(%ld): stat dump: fail_cnt=%d "
+ "loss_sync=%d loss_sig=%d seq_err=%d "
+ "inval_xmt_word=%d inval_crc=%d.\n", __func__,
+ ha->host_no, stat_buf->link_fail_cnt,
+ stat_buf->loss_sync_cnt, stat_buf->loss_sig_cnt,
+ stat_buf->prim_seq_err_cnt,
+ stat_buf->inval_xmit_word_cnt,
+ stat_buf->inval_crc_cnt);)
+ }
+ } else {
+ /* Failed. */
+ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+ ha->host_no, rval);)
+ rval = BIT_1;
+ }
+
+ dma_pool_free(ha->s_dma_pool, stat_buf, stat_buf_dma);
-uint8_t
+ return rval;
+}
+
+int
qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
uint16_t *status)
{
@@ -2080,7 +2181,6 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
return rval;
}
-#endif
int
qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4916847d84e..9f91f1a2054 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -366,6 +366,12 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
goto qc_fail_command;
}
+ /* Close window on fcport/rport state-transitioning. */
+ if (!*(fc_port_t **)rport->dd_data) {
+ cmd->result = DID_IMM_RETRY << 16;
+ goto qc_fail_command;
+ }
+
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
@@ -421,6 +427,12 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
goto qc24_fail_command;
}
+ /* Close window on fcport/rport state-transitioning. */
+ if (!*(fc_port_t **)rport->dd_data) {
+ cmd->result = DID_IMM_RETRY << 16;
+ goto qc24_fail_command;
+ }
+
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
@@ -513,7 +525,7 @@ qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
* Success (Adapter is online) : 0
* Failed (Adapter is offline/disabled) : 1
*/
-static int
+int
qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
{
int return_status;
@@ -756,7 +768,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
if (ret == SUCCESS) {
if (fcport->flags & FC_FABRIC_DEVICE) {
ha->isp_ops.fabric_logout(ha, fcport->loop_id);
- qla2x00_mark_device_lost(ha, fcport);
+ qla2x00_mark_device_lost(ha, fcport, 0, 0);
}
}
#endif
@@ -1312,6 +1324,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->ports = MAX_BUSES;
ha->init_cb_size = sizeof(init_cb_t);
ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
+ ha->link_data_rate = LDR_UNKNOWN;
+ ha->optrom_size = OPTROM_SIZE_2300;
/* Assign ISP specific operations. */
ha->isp_ops.pci_config = qla2100_pci_config;
@@ -1339,6 +1353,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.write_nvram = qla2x00_write_nvram_data;
ha->isp_ops.fw_dump = qla2100_fw_dump;
ha->isp_ops.ascii_fw_dump = qla2100_ascii_fw_dump;
+ ha->isp_ops.read_optrom = qla2x00_read_optrom_data;
+ ha->isp_ops.write_optrom = qla2x00_write_optrom_data;
if (IS_QLA2100(ha)) {
host->max_id = MAX_TARGETS_2100;
ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
@@ -1364,7 +1380,12 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.intr_handler = qla2300_intr_handler;
ha->isp_ops.fw_dump = qla2300_fw_dump;
ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump;
+ ha->isp_ops.beacon_on = qla2x00_beacon_on;
+ ha->isp_ops.beacon_off = qla2x00_beacon_off;
+ ha->isp_ops.beacon_blink = qla2x00_beacon_blink;
ha->gid_list_info_size = 6;
+ if (IS_QLA2322(ha) || IS_QLA6322(ha))
+ ha->optrom_size = OPTROM_SIZE_2322;
} else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
@@ -1400,7 +1421,13 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
ha->isp_ops.fw_dump = qla24xx_fw_dump;
ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump;
+ ha->isp_ops.read_optrom = qla24xx_read_optrom_data;
+ ha->isp_ops.write_optrom = qla24xx_write_optrom_data;
+ ha->isp_ops.beacon_on = qla24xx_beacon_on;
+ ha->isp_ops.beacon_off = qla24xx_beacon_off;
+ ha->isp_ops.beacon_blink = qla24xx_beacon_blink;
ha->gid_list_info_size = 8;
+ ha->optrom_size = OPTROM_SIZE_24XX;
}
host->can_queue = ha->request_q_length + 128;
@@ -1642,6 +1669,33 @@ qla2x00_free_device(scsi_qla_host_t *ha)
pci_disable_device(ha->pdev);
}
+static inline void
+qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
+ int defer)
+{
+ unsigned long flags;
+ struct fc_rport *rport;
+
+ if (!fcport->rport)
+ return;
+
+ rport = fcport->rport;
+ if (defer) {
+ spin_lock_irqsave(&fcport->rport_lock, flags);
+ fcport->drport = rport;
+ fcport->rport = NULL;
+ *(fc_port_t **)rport->dd_data = NULL;
+ spin_unlock_irqrestore(&fcport->rport_lock, flags);
+ set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
+ } else {
+ spin_lock_irqsave(&fcport->rport_lock, flags);
+ fcport->rport = NULL;
+ *(fc_port_t **)rport->dd_data = NULL;
+ spin_unlock_irqrestore(&fcport->rport_lock, flags);
+ fc_remote_port_delete(rport);
+ }
+}
+
/*
* qla2x00_mark_device_lost Updates fcport state when device goes offline.
*
@@ -1652,10 +1706,10 @@ qla2x00_free_device(scsi_qla_host_t *ha)
* Context:
*/
void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
- int do_login)
+ int do_login, int defer)
{
- if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
- schedule_work(&fcport->rport_del_work);
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qla2x00_schedule_rport_del(ha, fcport, defer);
/*
* We may need to retry the login, so don't change the state of the
@@ -1702,7 +1756,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
* Context:
*/
void
-qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha)
+qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
{
fc_port_t *fcport;
@@ -1716,10 +1770,13 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha)
*/
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
continue;
- if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
- schedule_work(&fcport->rport_del_work);
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qla2x00_schedule_rport_del(ha, fcport, defer);
atomic_set(&fcport->state, FCS_DEVICE_LOST);
}
+
+ if (defer && ha->dpc_wait && !ha->dpc_active)
+ up(ha->dpc_wait);
}
/*
@@ -2038,6 +2095,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
ha->fw_dumped = 0;
ha->fw_dump_reading = 0;
ha->fw_dump_buffer = NULL;
+
+ vfree(ha->optrom_buffer);
}
/*
@@ -2161,6 +2220,9 @@ qla2x00_do_dpc(void *data)
ha->host_no));
}
+ if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
+ qla2x00_update_fcports(ha);
+
if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) {
DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n",
ha->host_no));
@@ -2219,13 +2281,8 @@ qla2x00_do_dpc(void *data)
DEBUG(printk("scsi(%ld): port login OK: logged in ID 0x%x\n",
ha->host_no, fcport->loop_id));
- fcport->port_login_retry_count =
- ha->port_down_retry_count * PORT_RETRY_TIME;
- atomic_set(&fcport->state, FCS_ONLINE);
- atomic_set(&fcport->port_down_timer,
- ha->port_down_retry_count * PORT_RETRY_TIME);
-
- fcport->login_retry = 0;
+ qla2x00_update_fcport(ha,
+ fcport);
} else if (status == 1) {
set_bit(RELOGIN_NEEDED, &ha->dpc_flags);
/* retry the login again */
@@ -2288,6 +2345,9 @@ qla2x00_do_dpc(void *data)
if (!ha->interrupts_on)
ha->isp_ops.enable_intrs(ha);
+ if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags))
+ ha->isp_ops.beacon_blink(ha);
+
ha->dpc_active = 0;
} /* End of while(1) */
@@ -2465,13 +2525,21 @@ qla2x00_timer(scsi_qla_host_t *ha)
atomic_read(&ha->loop_down_timer)));
}
+ /* Check if beacon LED needs to be blinked */
+ if (ha->beacon_blink_led == 1) {
+ set_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags);
+ start_dpc++;
+ }
+
/* Schedule the DPC routine if needed */
if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) ||
+ test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags) ||
start_dpc ||
test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
+ test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) &&
ha->dpc_wait && !ha->dpc_active) {
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
index 2c3342108dd..b70bebe18c0 100644
--- a/drivers/scsi/qla2xxx/qla_rscn.c
+++ b/drivers/scsi/qla2xxx/qla_rscn.c
@@ -6,8 +6,6 @@
*/
#include "qla_def.h"
-#include <scsi/scsi_transport_fc.h>
-
/**
* IO descriptor handle definitions.
*
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index f4d755a643e..3866a5760f1 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -695,3 +695,966 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
return ret;
}
+
+
+static inline void
+qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
+{
+ if (IS_QLA2322(ha)) {
+ /* Flip all colors. */
+ if (ha->beacon_color_state == QLA_LED_ALL_ON) {
+ /* Turn off. */
+ ha->beacon_color_state = 0;
+ *pflags = GPIO_LED_ALL_OFF;
+ } else {
+ /* Turn on. */
+ ha->beacon_color_state = QLA_LED_ALL_ON;
+ *pflags = GPIO_LED_RGA_ON;
+ }
+ } else {
+ /* Flip green led only. */
+ if (ha->beacon_color_state == QLA_LED_GRN_ON) {
+ /* Turn off. */
+ ha->beacon_color_state = 0;
+ *pflags = GPIO_LED_GREEN_OFF_AMBER_OFF;
+ } else {
+ /* Turn on. */
+ ha->beacon_color_state = QLA_LED_GRN_ON;
+ *pflags = GPIO_LED_GREEN_ON_AMBER_OFF;
+ }
+ }
+}
+
+void
+qla2x00_beacon_blink(struct scsi_qla_host *ha)
+{
+ uint16_t gpio_enable;
+ uint16_t gpio_data;
+ uint16_t led_color = 0;
+ unsigned long flags;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ if (ha->pio_address)
+ reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ /* Save the Original GPIOE. */
+ if (ha->pio_address) {
+ gpio_enable = RD_REG_WORD_PIO(&reg->gpioe);
+ gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
+ } else {
+ gpio_enable = RD_REG_WORD(&reg->gpioe);
+ gpio_data = RD_REG_WORD(&reg->gpiod);
+ }
+
+ /* Set the modified gpio_enable values */
+ gpio_enable |= GPIO_LED_MASK;
+
+ if (ha->pio_address) {
+ WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
+ } else {
+ WRT_REG_WORD(&reg->gpioe, gpio_enable);
+ RD_REG_WORD(&reg->gpioe);
+ }
+
+ qla2x00_flip_colors(ha, &led_color);
+
+ /* Clear out any previously set LED color. */
+ gpio_data &= ~GPIO_LED_MASK;
+
+ /* Set the new input LED color to GPIOD. */
+ gpio_data |= led_color;
+
+ /* Set the modified gpio_data values */
+ if (ha->pio_address) {
+ WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
+ } else {
+ WRT_REG_WORD(&reg->gpiod, gpio_data);
+ RD_REG_WORD(&reg->gpiod);
+ }
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+int
+qla2x00_beacon_on(struct scsi_qla_host *ha)
+{
+ uint16_t gpio_enable;
+ uint16_t gpio_data;
+ unsigned long flags;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
+ ha->fw_options[1] |= FO1_DISABLE_GPIO6_7;
+
+ if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to update fw options (beacon on).\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ if (ha->pio_address)
+ reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
+
+ /* Turn off LEDs. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ if (ha->pio_address) {
+ gpio_enable = RD_REG_WORD_PIO(&reg->gpioe);
+ gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
+ } else {
+ gpio_enable = RD_REG_WORD(&reg->gpioe);
+ gpio_data = RD_REG_WORD(&reg->gpiod);
+ }
+ gpio_enable |= GPIO_LED_MASK;
+
+ /* Set the modified gpio_enable values. */
+ if (ha->pio_address) {
+ WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
+ } else {
+ WRT_REG_WORD(&reg->gpioe, gpio_enable);
+ RD_REG_WORD(&reg->gpioe);
+ }
+
+ /* Clear out previously set LED colour. */
+ gpio_data &= ~GPIO_LED_MASK;
+ if (ha->pio_address) {
+ WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
+ } else {
+ WRT_REG_WORD(&reg->gpiod, gpio_data);
+ RD_REG_WORD(&reg->gpiod);
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ /*
+ * Let the per HBA timer kick off the blinking process based on
+ * the following flags. No need to do anything else now.
+ */
+ ha->beacon_blink_led = 1;
+ ha->beacon_color_state = 0;
+
+ return QLA_SUCCESS;
+}
+
+int
+qla2x00_beacon_off(struct scsi_qla_host *ha)
+{
+ int rval = QLA_SUCCESS;
+
+ ha->beacon_blink_led = 0;
+
+ /* Set the on flag so when it gets flipped it will be off. */
+ if (IS_QLA2322(ha))
+ ha->beacon_color_state = QLA_LED_ALL_ON;
+ else
+ ha->beacon_color_state = QLA_LED_GRN_ON;
+
+ ha->isp_ops.beacon_blink(ha); /* This turns green LED off */
+
+ ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
+ ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7;
+
+ rval = qla2x00_set_fw_options(ha, ha->fw_options);
+ if (rval != QLA_SUCCESS)
+ qla_printk(KERN_WARNING, ha,
+ "Unable to update fw options (beacon off).\n");
+ return rval;
+}
+
+
+static inline void
+qla24xx_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
+{
+ /* Flip all colors. */
+ if (ha->beacon_color_state == QLA_LED_ALL_ON) {
+ /* Turn off. */
+ ha->beacon_color_state = 0;
+ *pflags = 0;
+ } else {
+ /* Turn on. */
+ ha->beacon_color_state = QLA_LED_ALL_ON;
+ *pflags = GPDX_LED_YELLOW_ON | GPDX_LED_AMBER_ON;
+ }
+}
+
+void
+qla24xx_beacon_blink(struct scsi_qla_host *ha)
+{
+ uint16_t led_color = 0;
+ uint32_t gpio_data;
+ unsigned long flags;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+ /* Save the Original GPIOD. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+
+ /* Enable the gpio_data reg for update. */
+ gpio_data |= GPDX_LED_UPDATE_MASK;
+
+ WRT_REG_DWORD(&reg->gpiod, gpio_data);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+
+ /* Set the color bits. */
+ qla24xx_flip_colors(ha, &led_color);
+
+ /* Clear out any previously set LED color. */
+ gpio_data &= ~GPDX_LED_COLOR_MASK;
+
+ /* Set the new input LED color to GPIOD. */
+ gpio_data |= led_color;
+
+ /* Set the modified gpio_data values. */
+ WRT_REG_DWORD(&reg->gpiod, gpio_data);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+int
+qla24xx_beacon_on(struct scsi_qla_host *ha)
+{
+ uint32_t gpio_data;
+ unsigned long flags;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+ if (ha->beacon_blink_led == 0) {
+ /* Enable firmware for update */
+ ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL;
+
+ if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS)
+ return QLA_FUNCTION_FAILED;
+
+ if (qla2x00_get_fw_options(ha, ha->fw_options) !=
+ QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to update fw options (beacon on).\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+
+ /* Enable the gpio_data reg for update. */
+ gpio_data |= GPDX_LED_UPDATE_MASK;
+ WRT_REG_DWORD(&reg->gpiod, gpio_data);
+ RD_REG_DWORD(&reg->gpiod);
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ }
+
+ /* So all colors blink together. */
+ ha->beacon_color_state = 0;
+
+ /* Let the per HBA timer kick off the blinking process. */
+ ha->beacon_blink_led = 1;
+
+ return QLA_SUCCESS;
+}
+
+int
+qla24xx_beacon_off(struct scsi_qla_host *ha)
+{
+ uint32_t gpio_data;
+ unsigned long flags;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+ ha->beacon_blink_led = 0;
+ ha->beacon_color_state = QLA_LED_ALL_ON;
+
+ ha->isp_ops.beacon_blink(ha); /* Will flip to all off. */
+
+ /* Give control back to firmware. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ gpio_data = RD_REG_DWORD(&reg->gpiod);
+
+ /* Disable the gpio_data reg for update. */
+ gpio_data &= ~GPDX_LED_UPDATE_MASK;
+ WRT_REG_DWORD(&reg->gpiod, gpio_data);
+ RD_REG_DWORD(&reg->gpiod);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ ha->fw_options[1] &= ~ADD_FO1_DISABLE_GPIO_LED_CTRL;
+
+ if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to update fw options (beacon off).\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ if (qla2x00_get_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to get fw options (beacon off).\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ return QLA_SUCCESS;
+}
+
+
+/*
+ * Flash support routines
+ */
+
+/**
+ * qla2x00_flash_enable() - Setup flash for reading and writing.
+ * @ha: HA context
+ */
+static void
+qla2x00_flash_enable(scsi_qla_host_t *ha)
+{
+ uint16_t data;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ data = RD_REG_WORD(&reg->ctrl_status);
+ data |= CSR_FLASH_ENABLE;
+ WRT_REG_WORD(&reg->ctrl_status, data);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+}
+
+/**
+ * qla2x00_flash_disable() - Disable flash and allow RISC to run.
+ * @ha: HA context
+ */
+static void
+qla2x00_flash_disable(scsi_qla_host_t *ha)
+{
+ uint16_t data;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ data = RD_REG_WORD(&reg->ctrl_status);
+ data &= ~(CSR_FLASH_ENABLE);
+ WRT_REG_WORD(&reg->ctrl_status, data);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+}
+
+/**
+ * qla2x00_read_flash_byte() - Reads a byte from flash
+ * @ha: HA context
+ * @addr: Address in flash to read
+ *
+ * A word is read from the chip, but, only the lower byte is valid.
+ *
+ * Returns the byte read from flash @addr.
+ */
+static uint8_t
+qla2x00_read_flash_byte(scsi_qla_host_t *ha, uint32_t addr)
+{
+ uint16_t data;
+ uint16_t bank_select;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ bank_select = RD_REG_WORD(&reg->ctrl_status);
+
+ if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ /* Specify 64K address range: */
+ /* clear out Module Select and Flash Address bits [19:16]. */
+ bank_select &= ~0xf8;
+ bank_select |= addr >> 12 & 0xf0;
+ bank_select |= CSR_FLASH_64K_BANK;
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+
+ WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
+ data = RD_REG_WORD(&reg->flash_data);
+
+ return (uint8_t)data;
+ }
+
+ /* Setup bit 16 of flash address. */
+ if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
+ bank_select |= CSR_FLASH_64K_BANK;
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ } else if (((addr & BIT_16) == 0) &&
+ (bank_select & CSR_FLASH_64K_BANK)) {
+ bank_select &= ~(CSR_FLASH_64K_BANK);
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ }
+
+ /* Always perform IO mapped accesses to the FLASH registers. */
+ if (ha->pio_address) {
+ uint16_t data2;
+
+ reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
+ WRT_REG_WORD_PIO(&reg->flash_address, (uint16_t)addr);
+ do {
+ data = RD_REG_WORD_PIO(&reg->flash_data);
+ barrier();
+ cpu_relax();
+ data2 = RD_REG_WORD_PIO(&reg->flash_data);
+ } while (data != data2);
+ } else {
+ WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
+ data = qla2x00_debounce_register(&reg->flash_data);
+ }
+
+ return (uint8_t)data;
+}
+
+/**
+ * qla2x00_write_flash_byte() - Write a byte to flash
+ * @ha: HA context
+ * @addr: Address in flash to write
+ * @data: Data to write
+ */
+static void
+qla2x00_write_flash_byte(scsi_qla_host_t *ha, uint32_t addr, uint8_t data)
+{
+ uint16_t bank_select;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ bank_select = RD_REG_WORD(&reg->ctrl_status);
+ if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ /* Specify 64K address range: */
+ /* clear out Module Select and Flash Address bits [19:16]. */
+ bank_select &= ~0xf8;
+ bank_select |= addr >> 12 & 0xf0;
+ bank_select |= CSR_FLASH_64K_BANK;
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+
+ WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ WRT_REG_WORD(&reg->flash_data, (uint16_t)data);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+
+ return;
+ }
+
+ /* Setup bit 16 of flash address. */
+ if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
+ bank_select |= CSR_FLASH_64K_BANK;
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ } else if (((addr & BIT_16) == 0) &&
+ (bank_select & CSR_FLASH_64K_BANK)) {
+ bank_select &= ~(CSR_FLASH_64K_BANK);
+ WRT_REG_WORD(&reg->ctrl_status, bank_select);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ }
+
+ /* Always perform IO mapped accesses to the FLASH registers. */
+ if (ha->pio_address) {
+ reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
+ WRT_REG_WORD_PIO(&reg->flash_address, (uint16_t)addr);
+ WRT_REG_WORD_PIO(&reg->flash_data, (uint16_t)data);
+ } else {
+ WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ WRT_REG_WORD(&reg->flash_data, (uint16_t)data);
+ RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
+ }
+}
+
+/**
+ * qla2x00_poll_flash() - Polls flash for completion.
+ * @ha: HA context
+ * @addr: Address in flash to poll
+ * @poll_data: Data to be polled
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ *
+ * This function polls the device until bit 7 of what is read matches data
+ * bit 7 or until data bit 5 becomes a 1. If that hapens, the flash ROM timed
+ * out (a fatal error). The flash book recommeds reading bit 7 again after
+ * reading bit 5 as a 1.
+ *
+ * Returns 0 on success, else non-zero.
+ */
+static int
+qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data,
+ uint8_t man_id, uint8_t flash_id)
+{
+ int status;
+ uint8_t flash_data;
+ uint32_t cnt;
+
+ status = 1;
+
+ /* Wait for 30 seconds for command to finish. */
+ poll_data &= BIT_7;
+ for (cnt = 3000000; cnt; cnt--) {
+ flash_data = qla2x00_read_flash_byte(ha, addr);
+ if ((flash_data & BIT_7) == poll_data) {
+ status = 0;
+ break;
+ }
+
+ if (man_id != 0x40 && man_id != 0xda) {
+ if ((flash_data & BIT_5) && cnt > 2)
+ cnt = 2;
+ }
+ udelay(10);
+ barrier();
+ }
+ return status;
+}
+
+#define IS_OEM_001(ha) \
+ ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322 && \
+ (ha)->pdev->subsystem_vendor == 0x1028 && \
+ (ha)->pdev->subsystem_device == 0x0170)
+
+/**
+ * qla2x00_program_flash_address() - Programs a flash address
+ * @ha: HA context
+ * @addr: Address in flash to program
+ * @data: Data to be written in flash
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ *
+ * Returns 0 on success, else non-zero.
+ */
+static int
+qla2x00_program_flash_address(scsi_qla_host_t *ha, uint32_t addr, uint8_t data,
+ uint8_t man_id, uint8_t flash_id)
+{
+ /* Write Program Command Sequence. */
+ if (IS_OEM_001(ha)) {
+ qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x555, 0x55);
+ qla2x00_write_flash_byte(ha, 0xaaa, 0xa0);
+ qla2x00_write_flash_byte(ha, addr, data);
+ } else {
+ if (man_id == 0xda && flash_id == 0xc1) {
+ qla2x00_write_flash_byte(ha, addr, data);
+ if (addr & 0x7e)
+ return 0;
+ } else {
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xa0);
+ qla2x00_write_flash_byte(ha, addr, data);
+ }
+ }
+
+ udelay(150);
+
+ /* Wait for write to complete. */
+ return qla2x00_poll_flash(ha, addr, data, man_id, flash_id);
+}
+
+/**
+ * qla2x00_erase_flash() - Erase the flash.
+ * @ha: HA context
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ *
+ * Returns 0 on success, else non-zero.
+ */
+static int
+qla2x00_erase_flash(scsi_qla_host_t *ha, uint8_t man_id, uint8_t flash_id)
+{
+ /* Individual Sector Erase Command Sequence */
+ if (IS_OEM_001(ha)) {
+ qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x555, 0x55);
+ qla2x00_write_flash_byte(ha, 0xaaa, 0x80);
+ qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x555, 0x55);
+ qla2x00_write_flash_byte(ha, 0xaaa, 0x10);
+ } else {
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0x80);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0x10);
+ }
+
+ udelay(150);
+
+ /* Wait for erase to complete. */
+ return qla2x00_poll_flash(ha, 0x00, 0x80, man_id, flash_id);
+}
+
+/**
+ * qla2x00_erase_flash_sector() - Erase a flash sector.
+ * @ha: HA context
+ * @addr: Flash sector to erase
+ * @sec_mask: Sector address mask
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ *
+ * Returns 0 on success, else non-zero.
+ */
+static int
+qla2x00_erase_flash_sector(scsi_qla_host_t *ha, uint32_t addr,
+ uint32_t sec_mask, uint8_t man_id, uint8_t flash_id)
+{
+ /* Individual Sector Erase Command Sequence */
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0x80);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ if (man_id == 0x1f && flash_id == 0x13)
+ qla2x00_write_flash_byte(ha, addr & sec_mask, 0x10);
+ else
+ qla2x00_write_flash_byte(ha, addr & sec_mask, 0x30);
+
+ udelay(150);
+
+ /* Wait for erase to complete. */
+ return qla2x00_poll_flash(ha, addr, 0x80, man_id, flash_id);
+}
+
+/**
+ * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip.
+ * @man_id: Flash manufacturer ID
+ * @flash_id: Flash ID
+ */
+static void
+qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
+ uint8_t *flash_id)
+{
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0x90);
+ *man_id = qla2x00_read_flash_byte(ha, 0x0000);
+ *flash_id = qla2x00_read_flash_byte(ha, 0x0001);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555, 0xf0);
+}
+
+
+static inline void
+qla2x00_suspend_hba(struct scsi_qla_host *ha)
+{
+ int cnt;
+ unsigned long flags;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ /* Suspend HBA. */
+ scsi_block_requests(ha->host);
+ ha->isp_ops.disable_intrs(ha);
+ set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+
+ /* Pause RISC. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
+ RD_REG_WORD(&reg->hccr);
+ if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
+ for (cnt = 0; cnt < 30000; cnt++) {
+ if ((RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) != 0)
+ break;
+ udelay(100);
+ }
+ } else {
+ udelay(10);
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+static inline void
+qla2x00_resume_hba(struct scsi_qla_host *ha)
+{
+ /* Resume HBA. */
+ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ up(ha->dpc_wait);
+ qla2x00_wait_for_hba_online(ha);
+ scsi_unblock_requests(ha->host);
+}
+
+uint8_t *
+qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+ uint32_t offset, uint32_t length)
+{
+ unsigned long flags;
+ uint32_t addr, midpoint;
+ uint8_t *data;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ /* Suspend HBA. */
+ qla2x00_suspend_hba(ha);
+
+ /* Go with read. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ midpoint = ha->optrom_size / 2;
+
+ qla2x00_flash_enable(ha);
+ WRT_REG_WORD(&reg->nvram, 0);
+ RD_REG_WORD(&reg->nvram); /* PCI Posting. */
+ for (addr = offset, data = buf; addr < length; addr++, data++) {
+ if (addr == midpoint) {
+ WRT_REG_WORD(&reg->nvram, NVR_SELECT);
+ RD_REG_WORD(&reg->nvram); /* PCI Posting. */
+ }
+
+ *data = qla2x00_read_flash_byte(ha, addr);
+ }
+ qla2x00_flash_disable(ha);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ /* Resume HBA. */
+ qla2x00_resume_hba(ha);
+
+ return buf;
+}
+
+int
+qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+ uint32_t offset, uint32_t length)
+{
+
+ int rval;
+ unsigned long flags;
+ uint8_t man_id, flash_id, sec_number, data;
+ uint16_t wd;
+ uint32_t addr, liter, sec_mask, rest_addr;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+
+ /* Suspend HBA. */
+ qla2x00_suspend_hba(ha);
+
+ rval = QLA_SUCCESS;
+ sec_number = 0;
+
+ /* Reset ISP chip. */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
+ pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
+
+ /* Go with write. */
+ qla2x00_flash_enable(ha);
+ do { /* Loop once to provide quick error exit */
+ /* Structure of flash memory based on manufacturer */
+ if (IS_OEM_001(ha)) {
+ /* OEM variant with special flash part. */
+ man_id = flash_id = 0;
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ goto update_flash;
+ }
+ qla2x00_get_flash_manufacturer(ha, &man_id, &flash_id);
+ switch (man_id) {
+ case 0x20: /* ST flash. */
+ if (flash_id == 0xd2 || flash_id == 0xe3) {
+ /*
+ * ST m29w008at part - 64kb sector size with
+ * 32kb,8kb,8kb,16kb sectors at memory address
+ * 0xf0000.
+ */
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ break;
+ }
+ /*
+ * ST m29w010b part - 16kb sector size
+ * Default to 16kb sectors
+ */
+ rest_addr = 0x3fff;
+ sec_mask = 0x1c000;
+ break;
+ case 0x40: /* Mostel flash. */
+ /* Mostel v29c51001 part - 512 byte sector size. */
+ rest_addr = 0x1ff;
+ sec_mask = 0x1fe00;
+ break;
+ case 0xbf: /* SST flash. */
+ /* SST39sf10 part - 4kb sector size. */
+ rest_addr = 0xfff;
+ sec_mask = 0x1f000;
+ break;
+ case 0xda: /* Winbond flash. */
+ /* Winbond W29EE011 part - 256 byte sector size. */
+ rest_addr = 0x7f;
+ sec_mask = 0x1ff80;
+ break;
+ case 0xc2: /* Macronix flash. */
+ /* 64k sector size. */
+ if (flash_id == 0x38 || flash_id == 0x4f) {
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ break;
+ }
+ /* Fall through... */
+
+ case 0x1f: /* Atmel flash. */
+ /* 512k sector size. */
+ if (flash_id == 0x13) {
+ rest_addr = 0x7fffffff;
+ sec_mask = 0x80000000;
+ break;
+ }
+ /* Fall through... */
+
+ case 0x01: /* AMD flash. */
+ if (flash_id == 0x38 || flash_id == 0x40 ||
+ flash_id == 0x4f) {
+ /* Am29LV081 part - 64kb sector size. */
+ /* Am29LV002BT part - 64kb sector size. */
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ break;
+ } else if (flash_id == 0x3e) {
+ /*
+ * Am29LV008b part - 64kb sector size with
+ * 32kb,8kb,8kb,16kb sector at memory address
+ * h0xf0000.
+ */
+ rest_addr = 0xffff;
+ sec_mask = 0x10000;
+ break;
+ } else if (flash_id == 0x20 || flash_id == 0x6e) {
+ /*
+ * Am29LV010 part or AM29f010 - 16kb sector
+ * size.
+ */
+ rest_addr = 0x3fff;
+ sec_mask = 0x1c000;
+ break;
+ } else if (flash_id == 0x6d) {
+ /* Am29LV001 part - 8kb sector size. */
+ rest_addr = 0x1fff;
+ sec_mask = 0x1e000;
+ break;
+ }
+ default:
+ /* Default to 16 kb sector size. */
+ rest_addr = 0x3fff;
+ sec_mask = 0x1c000;
+ break;
+ }
+
+update_flash:
+ if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ if (qla2x00_erase_flash(ha, man_id, flash_id)) {
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ }
+ }
+
+ for (addr = offset, liter = 0; liter < length; liter++,
+ addr++) {
+ data = buf[liter];
+ /* Are we at the beginning of a sector? */
+ if ((addr & rest_addr) == 0) {
+ if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ if (addr >= 0x10000UL) {
+ if (((addr >> 12) & 0xf0) &&
+ ((man_id == 0x01 &&
+ flash_id == 0x3e) ||
+ (man_id == 0x20 &&
+ flash_id == 0xd2))) {
+ sec_number++;
+ if (sec_number == 1) {
+ rest_addr =
+ 0x7fff;
+ sec_mask =
+ 0x18000;
+ } else if (
+ sec_number == 2 ||
+ sec_number == 3) {
+ rest_addr =
+ 0x1fff;
+ sec_mask =
+ 0x1e000;
+ } else if (
+ sec_number == 4) {
+ rest_addr =
+ 0x3fff;
+ sec_mask =
+ 0x1c000;
+ }
+ }
+ }
+ } else if (addr == ha->optrom_size / 2) {
+ WRT_REG_WORD(&reg->nvram, NVR_SELECT);
+ RD_REG_WORD(&reg->nvram);
+ }
+
+ if (flash_id == 0xda && man_id == 0xc1) {
+ qla2x00_write_flash_byte(ha, 0x5555,
+ 0xaa);
+ qla2x00_write_flash_byte(ha, 0x2aaa,
+ 0x55);
+ qla2x00_write_flash_byte(ha, 0x5555,
+ 0xa0);
+ } else if (!IS_QLA2322(ha) && !IS_QLA6322(ha)) {
+ /* Then erase it */
+ if (qla2x00_erase_flash_sector(ha,
+ addr, sec_mask, man_id,
+ flash_id)) {
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ }
+ if (man_id == 0x01 && flash_id == 0x6d)
+ sec_number++;
+ }
+ }
+
+ if (man_id == 0x01 && flash_id == 0x6d) {
+ if (sec_number == 1 &&
+ addr == (rest_addr - 1)) {
+ rest_addr = 0x0fff;
+ sec_mask = 0x1f000;
+ } else if (sec_number == 3 && (addr & 0x7ffe)) {
+ rest_addr = 0x3fff;
+ sec_mask = 0x1c000;
+ }
+ }
+
+ if (qla2x00_program_flash_address(ha, addr, data,
+ man_id, flash_id)) {
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ }
+ }
+ } while (0);
+ qla2x00_flash_disable(ha);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ /* Resume HBA. */
+ qla2x00_resume_hba(ha);
+
+ return rval;
+}
+
+uint8_t *
+qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+ uint32_t offset, uint32_t length)
+{
+ /* Suspend HBA. */
+ scsi_block_requests(ha->host);
+ ha->isp_ops.disable_intrs(ha);
+ set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+
+ /* Go with read. */
+ qla24xx_read_flash_data(ha, (uint32_t *)buf, offset >> 2, length >> 2);
+
+ /* Resume HBA. */
+ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+ ha->isp_ops.enable_intrs(ha);
+ scsi_unblock_requests(ha->host);
+
+ return buf;
+}
+
+int
+qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
+ uint32_t offset, uint32_t length)
+{
+ int rval;
+
+ /* Suspend HBA. */
+ scsi_block_requests(ha->host);
+ ha->isp_ops.disable_intrs(ha);
+ set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+
+ /* Go with write. */
+ rval = qla24xx_write_flash_data(ha, (uint32_t *)buf, offset >> 2,
+ length >> 2);
+
+ /* Resume HBA -- RISC reset needed. */
+ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ up(ha->dpc_wait);
+ qla2x00_wait_for_hba_online(ha);
+ scsi_unblock_requests(ha->host);
+
+ return rval;
+}
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index cd54244058b..2770005324b 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -510,6 +510,12 @@ static const struct mv_hw_ops mv6xxx_ops = {
};
/*
+ * module options
+ */
+static int msi; /* Use PCI msi; either zero (off, default) or non-zero */
+
+
+/*
* Functions
*/
@@ -991,6 +997,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
case ATA_CMD_READ_EXT:
case ATA_CMD_WRITE:
case ATA_CMD_WRITE_EXT:
+ case ATA_CMD_WRITE_FUA_EXT:
mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
break;
#ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */
@@ -2191,7 +2198,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Enable interrupts */
- if (pci_enable_msi(pdev) == 0) {
+ if (msi && pci_enable_msi(pdev) == 0) {
hpriv->hp_flags |= MV_HP_FLAG_MSI;
} else {
pci_intx(pdev, 1);
@@ -2246,5 +2253,8 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+module_param(msi, int, 0444);
+MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
+
module_init(mv_init);
module_exit(mv_exit);
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 3d1ea09a06a..b0b0a69b356 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -66,6 +66,7 @@ enum {
board_2037x = 0, /* FastTrak S150 TX2plus */
board_20319 = 1, /* FastTrak S150 TX4 */
board_20619 = 2, /* FastTrak TX4000 */
+ board_20771 = 3, /* FastTrak TX2300 */
PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */
@@ -190,6 +191,16 @@ static const struct ata_port_info pdc_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_pata_ops,
},
+
+ /* board_20771 */
+ {
+ .sht = &pdc_ata_sht,
+ .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &pdc_sata_ops,
+ },
};
static const struct pci_device_id pdc_ata_pci_tbl[] = {
@@ -226,6 +237,8 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20619 },
+ { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20771 },
{ } /* terminate list */
};
@@ -706,6 +719,9 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
case board_2037x:
probe_ent->n_ports = 2;
break;
+ case board_20771:
+ probe_ent->n_ports = 2;
+ break;
case board_20619:
probe_ent->n_ports = 4;
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index b017f85e6d6..17f74d3c10e 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -231,6 +231,10 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+static int slow_down = 0;
+module_param(slow_down, int, 0444);
+MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)");
+
static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
{
@@ -354,8 +358,10 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
}
/* limit requests to 15 sectors */
- if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) {
- printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
+ if (slow_down ||
+ ((ap->flags & SIL_FLAG_MOD15WRITE) &&
+ (quirks & SIL_QUIRK_MOD15WRITE))) {
+ printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
ap->id, dev->devno);
ap->host->max_sectors = 15;
ap->host->hostt->max_sectors = 15;
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 668373590aa..d8472563fde 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -470,6 +470,7 @@ static const struct pci_device_id k2_sata_pci_tbl[] = {
{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
{ 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { 0x1166, 0x024b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ }
};
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 2e2c3b7acb0..e484e8db681 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -81,6 +81,19 @@
/* Port stride */
#define VSC_SATA_PORT_OFFSET 0x200
+/* Error interrupt status bit offsets */
+#define VSC_SATA_INT_ERROR_E_OFFSET 2
+#define VSC_SATA_INT_ERROR_P_OFFSET 4
+#define VSC_SATA_INT_ERROR_T_OFFSET 5
+#define VSC_SATA_INT_ERROR_M_OFFSET 1
+#define is_vsc_sata_int_err(port_idx, int_status) \
+ (int_status & ((1 << (VSC_SATA_INT_ERROR_E_OFFSET + (8 * port_idx))) | \
+ (1 << (VSC_SATA_INT_ERROR_P_OFFSET + (8 * port_idx))) | \
+ (1 << (VSC_SATA_INT_ERROR_T_OFFSET + (8 * port_idx))) | \
+ (1 << (VSC_SATA_INT_ERROR_M_OFFSET + (8 * port_idx))) \
+ )\
+ )
+
static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
@@ -201,13 +214,28 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
struct ata_port *ap;
ap = host_set->ports[i];
+
+ if (is_vsc_sata_int_err(i, int_status)) {
+ u32 err_status;
+ printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
+ err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
+ vsc_sata_scr_write(ap, SCR_ERROR, err_status);
+ handled++;
+ }
+
if (ap && !(ap->flags &
(ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
handled += ata_host_intr(ap, qc);
+ } else {
+ printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
+ ata_chk_status(ap);
+ handled++;
+ }
+
}
}
}
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 245ca99a641..c551bb84dbf 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1245,7 +1245,7 @@ static int __init init_scsi(void)
if (error)
goto cleanup_sysctl;
- for (i = 0; i < NR_CPUS; i++)
+ for_each_cpu(i)
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
devfs_mk_dir("scsi");
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index a2333d2c7af..5cc97b72166 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1350,7 +1350,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
cmnd[4] = SCSI_REMOVAL_PREVENT;
cmnd[5] = 0;
- scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ,
+ scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ,
5, NULL, NULL, GFP_KERNEL);
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 3574ba935af..4362dcde74a 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/hardirq.h>
#include <scsi/scsi.h>
#include <scsi/scsi_dbg.h>
@@ -436,6 +437,7 @@ free_bios:
* scsi_execute_async - insert request
* @sdev: scsi device
* @cmd: scsi command
+ * @cmd_len: length of scsi cdb
* @data_direction: data direction
* @buffer: data buffer (this can be a kernel buffer or scatterlist)
* @bufflen: len of buffer
@@ -445,7 +447,7 @@ free_bios:
* @flags: or into request flags
**/
int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
- int data_direction, void *buffer, unsigned bufflen,
+ int cmd_len, int data_direction, void *buffer, unsigned bufflen,
int use_sg, int timeout, int retries, void *privdata,
void (*done)(void *, char *, int, int), gfp_t gfp)
{
@@ -472,7 +474,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
if (err)
goto free_req;
- req->cmd_len = COMMAND_SIZE(cmd[0]);
+ req->cmd_len = cmd_len;
memcpy(req->cmd, cmd, req->cmd_len);
req->sense = sioc->sense;
req->sense_len = 0;
@@ -2247,3 +2249,61 @@ scsi_target_unblock(struct device *dev)
device_for_each_child(dev, NULL, target_unblock);
}
EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+
+struct work_queue_work {
+ struct work_struct work;
+ void (*fn)(void *);
+ void *data;
+};
+
+static void execute_in_process_context_work(void *data)
+{
+ void (*fn)(void *data);
+ struct work_queue_work *wqw = data;
+
+ fn = wqw->fn;
+ data = wqw->data;
+
+ kfree(wqw);
+
+ fn(data);
+}
+
+/**
+ * scsi_execute_in_process_context - reliably execute the routine with user context
+ * @fn: the function to execute
+ * @data: data to pass to the function
+ *
+ * Executes the function immediately if process context is available,
+ * otherwise schedules the function for delayed execution.
+ *
+ * Returns: 0 - function was executed
+ * 1 - function was scheduled for execution
+ * <0 - error
+ */
+int scsi_execute_in_process_context(void (*fn)(void *data), void *data)
+{
+ struct work_queue_work *wqw;
+
+ if (!in_interrupt()) {
+ fn(data);
+ return 0;
+ }
+
+ wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC);
+
+ if (unlikely(!wqw)) {
+ printk(KERN_ERR "Failed to allocate memory\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&wqw->work, execute_in_process_context_work, wqw);
+ wqw->fn = fn;
+ wqw->data = data;
+ schedule_work(&wqw->work);
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(scsi_execute_in_process_context);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 752fb5da3de..5acb83ca5ae 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -387,19 +387,12 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
return found_target;
}
-struct work_queue_wrapper {
- struct work_struct work;
- struct scsi_target *starget;
-};
-
-static void scsi_target_reap_work(void *data) {
- struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
- struct scsi_target *starget = wqw->starget;
+static void scsi_target_reap_usercontext(void *data)
+{
+ struct scsi_target *starget = data;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
unsigned long flags;
- kfree(wqw);
-
spin_lock_irqsave(shost->host_lock, flags);
if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
@@ -428,18 +421,7 @@ static void scsi_target_reap_work(void *data) {
*/
void scsi_target_reap(struct scsi_target *starget)
{
- struct work_queue_wrapper *wqw =
- kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
-
- if (!wqw) {
- starget_printk(KERN_ERR, starget,
- "Failed to allocate memory in scsi_reap_target()\n");
- return;
- }
-
- INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
- wqw->starget = starget;
- schedule_work(&wqw->work);
+ scsi_execute_in_process_context(scsi_target_reap_usercontext, starget);
}
/**
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index a77b32deaf8..902a5def8e6 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -217,8 +217,9 @@ static void scsi_device_cls_release(struct class_device *class_dev)
put_device(&sdev->sdev_gendev);
}
-static void scsi_device_dev_release(struct device *dev)
+static void scsi_device_dev_release_usercontext(void *data)
{
+ struct device *dev = data;
struct scsi_device *sdev;
struct device *parent;
struct scsi_target *starget;
@@ -237,6 +238,7 @@ static void scsi_device_dev_release(struct device *dev)
if (sdev->request_queue) {
sdev->request_queue->queuedata = NULL;
+ /* user context needed to free queue */
scsi_free_queue(sdev->request_queue);
/* temporary expedient, try to catch use of queue lock
* after free of sdev */
@@ -252,6 +254,11 @@ static void scsi_device_dev_release(struct device *dev)
put_device(parent);
}
+static void scsi_device_dev_release(struct device *dev)
+{
+ scsi_execute_in_process_context(scsi_device_dev_release_usercontext, dev);
+}
+
static struct class sdev_class = {
.name = "scsi_device",
.release = scsi_device_cls_release,
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 59a1c9d9d3b..71e54a64adc 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -39,10 +39,6 @@ struct iscsi_internal {
struct iscsi_transport *iscsi_transport;
struct list_head list;
/*
- * List of sessions for this transport
- */
- struct list_head sessions;
- /*
* based on transport capabilities, at register time we set these
* bits to tell the transport class it wants attributes displayed
* in sysfs or that it can support different iSCSI Data-Path
@@ -164,9 +160,43 @@ static struct mempool_zone *z_reply;
#define Z_MAX_ERROR 16
#define Z_HIWAT_ERROR 12
+static LIST_HEAD(sesslist);
+static DEFINE_SPINLOCK(sesslock);
static LIST_HEAD(connlist);
static DEFINE_SPINLOCK(connlock);
+static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
+{
+ unsigned long flags;
+ struct iscsi_cls_session *sess;
+
+ spin_lock_irqsave(&sesslock, flags);
+ list_for_each_entry(sess, &sesslist, sess_list) {
+ if (sess == iscsi_ptr(handle)) {
+ spin_unlock_irqrestore(&sesslock, flags);
+ return sess;
+ }
+ }
+ spin_unlock_irqrestore(&sesslock, flags);
+ return NULL;
+}
+
+static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle)
+{
+ unsigned long flags;
+ struct iscsi_cls_conn *conn;
+
+ spin_lock_irqsave(&connlock, flags);
+ list_for_each_entry(conn, &connlist, conn_list) {
+ if (conn == iscsi_ptr(handle)) {
+ spin_unlock_irqrestore(&connlock, flags);
+ return conn;
+ }
+ }
+ spin_unlock_irqrestore(&connlock, flags);
+ return NULL;
+}
+
/*
* The following functions can be used by LLDs that allocate
* their own scsi_hosts or by software iscsi LLDs
@@ -365,6 +395,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
{
struct iscsi_cls_session *session;
struct Scsi_Host *shost;
+ unsigned long flags;
shost = scsi_host_alloc(transport->host_template,
hostdata_privsize(transport));
@@ -389,6 +420,9 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
goto remove_host;
*(unsigned long*)shost->hostdata = (unsigned long)session;
+ spin_lock_irqsave(&sesslock, flags);
+ list_add(&session->sess_list, &sesslist);
+ spin_unlock_irqrestore(&sesslock, flags);
return shost;
remove_host:
@@ -410,9 +444,13 @@ EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
int iscsi_transport_destroy_session(struct Scsi_Host *shost)
{
struct iscsi_cls_session *session;
+ unsigned long flags;
scsi_remove_host(shost);
session = hostdata_session(shost->hostdata);
+ spin_lock_irqsave(&sesslock, flags);
+ list_del(&session->sess_list);
+ spin_unlock_irqrestore(&sesslock, flags);
iscsi_destroy_session(session);
/* ref from host alloc */
scsi_host_put(shost);
@@ -424,22 +462,6 @@ EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
/*
* iscsi interface functions
*/
-static struct iscsi_cls_conn*
-iscsi_if_find_conn(uint64_t key)
-{
- unsigned long flags;
- struct iscsi_cls_conn *conn;
-
- spin_lock_irqsave(&connlock, flags);
- list_for_each_entry(conn, &connlist, conn_list)
- if (conn->connh == key) {
- spin_unlock_irqrestore(&connlock, flags);
- return conn;
- }
- spin_unlock_irqrestore(&connlock, flags);
- return NULL;
-}
-
static struct iscsi_internal *
iscsi_if_transport_lookup(struct iscsi_transport *tt)
{
@@ -463,7 +485,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
}
static void*
-mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
+mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
{
struct mempool_zone *zone = pool_data;
@@ -504,6 +526,12 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
if (!zp)
return NULL;
+ zp->size = size;
+ zp->hiwat = hiwat;
+ INIT_LIST_HEAD(&zp->freequeue);
+ spin_lock_init(&zp->freelock);
+ atomic_set(&zp->allocated, 0);
+
zp->pool = mempool_create(max, mempool_zone_alloc_skb,
mempool_zone_free_skb, zp);
if (!zp->pool) {
@@ -511,13 +539,6 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
return NULL;
}
- zp->size = size;
- zp->hiwat = hiwat;
-
- INIT_LIST_HEAD(&zp->freequeue);
- spin_lock_init(&zp->freelock);
- atomic_set(&zp->allocated, 0);
-
return zp;
}
@@ -559,25 +580,21 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
return 0;
}
-int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
+int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
char *data, uint32_t data_size)
{
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- struct iscsi_cls_conn *conn;
char *pdu;
int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
data_size);
- conn = iscsi_if_find_conn(connh);
- BUG_ON(!conn);
-
mempool_zone_complete(conn->z_pdu);
skb = mempool_zone_get_skb(conn->z_pdu);
if (!skb) {
- iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
"control PDU: OOM\n");
return -ENOMEM;
@@ -590,7 +607,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
ev->type = ISCSI_KEVENT_RECV_PDU;
if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
ev->iferror = -ENOMEM;
- ev->r.recv_req.conn_handle = connh;
+ ev->r.recv_req.conn_handle = iscsi_handle(conn);
pdu = (char*)ev + sizeof(*ev);
memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
@@ -599,17 +616,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
}
EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
-void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
+void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
{
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- struct iscsi_cls_conn *conn;
int len = NLMSG_SPACE(sizeof(*ev));
- conn = iscsi_if_find_conn(connh);
- BUG_ON(!conn);
-
mempool_zone_complete(conn->z_error);
skb = mempool_zone_get_skb(conn->z_error);
@@ -626,7 +639,7 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
ev->iferror = -ENOMEM;
ev->r.connerror.error = error;
- ev->r.connerror.conn_handle = connh;
+ ev->r.connerror.conn_handle = iscsi_handle(conn);
iscsi_unicast_skb(conn->z_error, skb);
@@ -662,8 +675,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
}
static int
-iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
- struct nlmsghdr *nlh)
+iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
{
struct iscsi_uevent *ev = NLMSG_DATA(nlh);
struct iscsi_stats *stats;
@@ -677,7 +689,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
ISCSI_STATS_CUSTOM_MAX);
int err = 0;
- conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
+ conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle);
if (!conn)
return -EEXIST;
@@ -707,14 +719,14 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
((char*)evstat + sizeof(*evstat));
memset(stats, 0, sizeof(*stats));
- transport->get_stats(ev->u.get_stats.conn_handle, stats);
+ transport->get_stats(conn, stats);
actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
sizeof(struct iscsi_stats) +
sizeof(struct iscsi_stats_custom) *
stats->custom_length);
actual_size -= sizeof(*nlhstat);
actual_size = NLMSG_LENGTH(actual_size);
- skb_trim(skb, NLMSG_ALIGN(actual_size));
+ skb_trim(skbstat, NLMSG_ALIGN(actual_size));
nlhstat->nlmsg_len = actual_size;
err = iscsi_unicast_skb(conn->z_pdu, skbstat);
@@ -727,58 +739,34 @@ static int
iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
{
struct iscsi_transport *transport = priv->iscsi_transport;
- struct Scsi_Host *shost;
-
- if (!transport->create_session)
- return -EINVAL;
+ struct iscsi_cls_session *session;
+ uint32_t sid;
- shost = transport->create_session(&priv->t,
- ev->u.c_session.initial_cmdsn);
- if (!shost)
+ session = transport->create_session(&priv->t,
+ ev->u.c_session.initial_cmdsn,
+ &sid);
+ if (!session)
return -ENOMEM;
- ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
- ev->r.c_session_ret.sid = shost->host_no;
+ ev->r.c_session_ret.session_handle = iscsi_handle(session);
+ ev->r.c_session_ret.sid = sid;
return 0;
}
static int
-iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
{
- struct iscsi_transport *transport = priv->iscsi_transport;
-
- struct Scsi_Host *shost;
-
- if (!transport->destroy_session)
- return -EINVAL;
-
- shost = scsi_host_lookup(ev->u.d_session.sid);
- if (shost == ERR_PTR(-ENXIO))
- return -EEXIST;
-
- if (transport->destroy_session)
- transport->destroy_session(shost);
- /* ref from host lookup */
- scsi_host_put(shost);
- return 0;
-}
-
-static int
-iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
- struct Scsi_Host *shost;
struct iscsi_cls_conn *conn;
+ struct iscsi_cls_session *session;
unsigned long flags;
- if (!transport->create_conn)
+ session = iscsi_session_lookup(ev->u.c_conn.session_handle);
+ if (!session)
return -EINVAL;
- shost = scsi_host_lookup(ev->u.c_conn.sid);
- if (shost == ERR_PTR(-ENXIO))
- return -EEXIST;
-
- conn = transport->create_conn(shost, ev->u.c_conn.cid);
+ conn = transport->create_conn(session, ev->u.c_conn.cid);
if (!conn)
- goto release_ref;
+ return -ENOMEM;
conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
NLMSG_SPACE(sizeof(struct iscsi_uevent) +
@@ -800,14 +788,13 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
goto free_pdu_pool;
}
- ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
+ ev->r.handle = iscsi_handle(conn);
spin_lock_irqsave(&connlock, flags);
list_add(&conn->conn_list, &connlist);
conn->active = 1;
spin_unlock_irqrestore(&connlock, flags);
- scsi_host_put(shost);
return 0;
free_pdu_pool:
@@ -815,8 +802,6 @@ free_pdu_pool:
destroy_conn:
if (transport->destroy_conn)
transport->destroy_conn(conn->dd_data);
-release_ref:
- scsi_host_put(shost);
return -ENOMEM;
}
@@ -827,13 +812,9 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
struct iscsi_cls_conn *conn;
struct mempool_zone *z_error, *z_pdu;
- conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
+ conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle);
if (!conn)
- return -EEXIST;
-
- if (!transport->destroy_conn)
return -EINVAL;
-
spin_lock_irqsave(&connlock, flags);
conn->active = 0;
list_del(&conn->conn_list);
@@ -858,23 +839,27 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct iscsi_uevent *ev = NLMSG_DATA(nlh);
struct iscsi_transport *transport = NULL;
struct iscsi_internal *priv;
-
- if (NETLINK_CREDS(skb)->uid)
- return -EPERM;
+ struct iscsi_cls_session *session;
+ struct iscsi_cls_conn *conn;
priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
if (!priv)
return -EINVAL;
transport = priv->iscsi_transport;
- daemon_pid = NETLINK_CREDS(skb)->pid;
+ if (!try_module_get(transport->owner))
+ return -EINVAL;
switch (nlh->nlmsg_type) {
case ISCSI_UEVENT_CREATE_SESSION:
err = iscsi_if_create_session(priv, ev);
break;
case ISCSI_UEVENT_DESTROY_SESSION:
- err = iscsi_if_destroy_session(priv, ev);
+ session = iscsi_session_lookup(ev->u.d_session.session_handle);
+ if (session)
+ transport->destroy_session(session);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_CREATE_CONN:
err = iscsi_if_create_conn(transport, ev);
@@ -883,56 +868,64 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
err = iscsi_if_destroy_conn(transport, ev);
break;
case ISCSI_UEVENT_BIND_CONN:
- if (!iscsi_if_find_conn(ev->u.b_conn.conn_handle))
- return -EEXIST;
- ev->r.retcode = transport->bind_conn(
- ev->u.b_conn.session_handle,
- ev->u.b_conn.conn_handle,
- ev->u.b_conn.transport_fd,
- ev->u.b_conn.is_leading);
+ session = iscsi_session_lookup(ev->u.b_conn.session_handle);
+ conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle);
+
+ if (session && conn)
+ ev->r.retcode = transport->bind_conn(session, conn,
+ ev->u.b_conn.transport_fd,
+ ev->u.b_conn.is_leading);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_SET_PARAM:
- if (!iscsi_if_find_conn(ev->u.set_param.conn_handle))
- return -EEXIST;
- ev->r.retcode = transport->set_param(
- ev->u.set_param.conn_handle,
- ev->u.set_param.param, ev->u.set_param.value);
+ conn = iscsi_conn_lookup(ev->u.set_param.conn_handle);
+ if (conn)
+ ev->r.retcode = transport->set_param(conn,
+ ev->u.set_param.param, ev->u.set_param.value);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_START_CONN:
- if (!iscsi_if_find_conn(ev->u.start_conn.conn_handle))
- return -EEXIST;
- ev->r.retcode = transport->start_conn(
- ev->u.start_conn.conn_handle);
+ conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle);
+ if (conn)
+ ev->r.retcode = transport->start_conn(conn);
+ else
+ err = -EINVAL;
+
break;
case ISCSI_UEVENT_STOP_CONN:
- if (!iscsi_if_find_conn(ev->u.stop_conn.conn_handle))
- return -EEXIST;
- transport->stop_conn(ev->u.stop_conn.conn_handle,
- ev->u.stop_conn.flag);
+ conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle);
+ if (conn)
+ transport->stop_conn(conn, ev->u.stop_conn.flag);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_SEND_PDU:
- if (!iscsi_if_find_conn(ev->u.send_pdu.conn_handle))
- return -EEXIST;
- ev->r.retcode = transport->send_pdu(
- ev->u.send_pdu.conn_handle,
- (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
- (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
- ev->u.send_pdu.data_size);
+ conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle);
+ if (conn)
+ ev->r.retcode = transport->send_pdu(conn,
+ (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
+ (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
+ ev->u.send_pdu.data_size);
+ else
+ err = -EINVAL;
break;
case ISCSI_UEVENT_GET_STATS:
- err = iscsi_if_get_stats(transport, skb, nlh);
+ err = iscsi_if_get_stats(transport, nlh);
break;
default:
err = -EINVAL;
break;
}
+ module_put(transport->owner);
return err;
}
/* Get message from skb (based on rtnetlink_rcv_skb). Each message is
* processed by iscsi_if_recv_msg. Malformed skbs with wrong length are
- * discarded silently. */
+ * or invalid creds discarded silently. */
static void
iscsi_if_rx(struct sock *sk, int len)
{
@@ -940,6 +933,12 @@ iscsi_if_rx(struct sock *sk, int len)
mutex_lock(&rx_queue_mutex);
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ if (NETLINK_CREDS(skb)->uid) {
+ skb_pull(skb, skb->len);
+ goto free_skb;
+ }
+ daemon_pid = NETLINK_CREDS(skb)->pid;
+
while (skb->len >= NLMSG_SPACE(0)) {
int err;
uint32_t rlen;
@@ -951,10 +950,12 @@ iscsi_if_rx(struct sock *sk, int len)
skb->len < nlh->nlmsg_len) {
break;
}
+
ev = NLMSG_DATA(nlh);
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
if (rlen > skb->len)
rlen = skb->len;
+
err = iscsi_if_recv_msg(skb, nlh);
if (err) {
ev->type = ISCSI_KEVENT_IF_ERROR;
@@ -978,6 +979,7 @@ iscsi_if_rx(struct sock *sk, int len)
} while (err < 0 && err != -ECONNREFUSED);
skb_pull(skb, rlen);
}
+free_skb:
kfree_skb(skb);
}
mutex_unlock(&rx_queue_mutex);
@@ -997,7 +999,7 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf) \
struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
struct iscsi_transport *t = conn->transport; \
\
- t->get_conn_param(conn->dd_data, param, &value); \
+ t->get_conn_param(conn, param, &value); \
return snprintf(buf, 20, format"\n", value); \
}
@@ -1024,10 +1026,9 @@ show_session_int_param_##param(struct class_device *cdev, char *buf) \
{ \
uint32_t value = 0; \
struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
- struct Scsi_Host *shost = iscsi_session_to_shost(session); \
struct iscsi_transport *t = session->transport; \
\
- t->get_session_param(shost, param, &value); \
+ t->get_session_param(session, param, &value); \
return snprintf(buf, 20, format"\n", value); \
}
@@ -1121,7 +1122,6 @@ iscsi_register_transport(struct iscsi_transport *tt)
return NULL;
memset(priv, 0, sizeof(*priv));
INIT_LIST_HEAD(&priv->list);
- INIT_LIST_HEAD(&priv->sessions);
priv->iscsi_transport = tt;
priv->cdev.class = &iscsi_transport_class;
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index a3e0b7bc2d7..210dab5879f 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -377,7 +377,7 @@ static void sas_phy_release(struct device *dev)
/**
* sas_phy_alloc -- allocates and initialize a SAS PHY structure
* @parent: Parent device
- * @number: Port number
+ * @number: Phy index
*
* Allocates an SAS PHY structure. It will be added in the device tree
* below the device specified by @parent, which has to be either a Scsi_Host
@@ -595,8 +595,8 @@ struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent)
device_initialize(&rphy->dev);
rphy->dev.parent = get_device(&parent->dev);
rphy->dev.release = sas_rphy_release;
- sprintf(rphy->dev.bus_id, "rphy-%d:%d",
- shost->host_no, parent->number);
+ sprintf(rphy->dev.bus_id, "rphy-%d:%d-%d",
+ shost->host_no, parent->port_identifier, parent->number);
transport_setup_device(&rphy->dev);
return rphy;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 78aad9582bc..2a547538d44 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -741,7 +741,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
hp->duration = jiffies_to_msecs(jiffies);
/* Now send everything of to mid-level. The next time we hear about this
packet is when sg_cmd_done() is called (i.e. a callback). */
- if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer,
+ if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer,
hp->dxfer_len, srp->data.k_use_sg, timeout,
SG_DEFAULT_RETRIES, srp, sg_cmd_done,
GFP_ATOMIC)) {
@@ -1679,7 +1679,7 @@ static int
sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
{
int sg_bufflen = tablesize * sizeof(struct scatterlist);
- unsigned int gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
+ gfp_t gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
/*
* TODO: test without low_dma, we should not need it since
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 13b1d3aac26..7f96f33c1bb 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -508,7 +508,7 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd
STp->buffer->cmdstat.have_sense = 0;
STp->buffer->syscall_result = 0;
- if (scsi_execute_async(STp->device, cmd, direction,
+ if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction,
&((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
/* could not allocate the buffer or request was too large */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 8260f040d39..f4854c33f48 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -3588,7 +3588,7 @@ static int sym_evaluate_dp(struct sym_hcb *np, struct sym_ccb *cp, u32 scr, int
if (pm) {
dp_scr = scr_to_cpu(pm->ret);
- dp_ofs -= scr_to_cpu(pm->sg.size);
+ dp_ofs -= scr_to_cpu(pm->sg.size) & 0x00ffffff;
}
/*
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 221999bcf8f..8c5c276c557 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -362,11 +362,11 @@ static struct uart_ops serial21285_ops = {
static struct uart_port serial21285_port = {
.mapbase = 0x42000160,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = NO_IRQ,
.fifosize = 16,
.ops = &serial21285_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
};
static void serial21285_setup_ports(void)
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 8cbf0fc5a22..7f0f35a05dc 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -332,7 +332,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg
* Make sure that we do not overflow the buffer
*/
if (tty_request_buffer_room(tty, 1) == 0) {
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
return;
}
@@ -353,7 +353,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg
} while((rx = uart->urx.w) & URX_DATA_READY);
#endif
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
clear_and_exit:
return;
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 60f5a5dc17f..9843ae3d420 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -509,7 +509,7 @@ static _INLINE_ void receive_chars(ser_info_t *info)
info->rx_cur = (QUICC_BD *)bdp;
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
}
static _INLINE_ void receive_break(ser_info_t *info)
@@ -521,7 +521,7 @@ static _INLINE_ void receive_break(ser_info_t *info)
* the break. If not, we exit now, losing the break. FIXME
*/
tty_insert_flip_char(tty, 0, TTY_BREAK);
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
}
static _INLINE_ void transmit_chars(ser_info_t *info)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index d9ce8c54941..244e8ff1197 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -31,7 +31,6 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
-#include <linux/mca.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
@@ -2027,12 +2026,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
int ret;
/*
- * Don't probe for MCA ports on non-MCA machines.
- */
- if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus)
- return;
-
- /*
* Find the region that we can probe for. This in turn
* tells us whether we can probe for the type of port.
*/
@@ -2164,7 +2157,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
/*
* Wait for transmitter & holding register to empty
*/
-static inline void wait_for_xmitr(struct uart_8250_port *up)
+static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
{
unsigned int status, tmout = 10000;
@@ -2178,7 +2171,7 @@ static inline void wait_for_xmitr(struct uart_8250_port *up)
if (--tmout == 0)
break;
udelay(1);
- } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+ } while ((status & bits) != bits);
/* Wait up to 1s for flow control if necessary */
if (up->port.flags & UPF_CONS_FLOW) {
@@ -2205,7 +2198,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
touch_nmi_watchdog();
/*
- * First save the UER then disable the interrupts
+ * First save the IER then disable the interrupts
*/
ier = serial_in(up, UART_IER);
@@ -2218,7 +2211,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
* Now, do each character
*/
for (i = 0; i < count; i++, s++) {
- wait_for_xmitr(up);
+ wait_for_xmitr(up, UART_LSR_THRE);
/*
* Send the character out.
@@ -2226,7 +2219,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
*/
serial_out(up, UART_TX, *s);
if (*s == 10) {
- wait_for_xmitr(up);
+ wait_for_xmitr(up, UART_LSR_THRE);
serial_out(up, UART_TX, 13);
}
}
@@ -2235,8 +2228,9 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
* Finally, wait for transmitter to become empty
* and restore the IER
*/
- wait_for_xmitr(up);
- serial_out(up, UART_IER, ier);
+ wait_for_xmitr(up, BOTH_EMPTY);
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, ier | UART_IER_THRI);
}
static int serial8250_console_setup(struct console *co, char *options)
@@ -2595,15 +2589,11 @@ static int __init serial8250_init(void)
if (ret)
goto out;
- ret = platform_driver_register(&serial8250_isa_driver);
- if (ret)
- goto unreg_uart_drv;
-
serial8250_isa_devs = platform_device_alloc("serial8250",
PLAT8250_DEV_LEGACY);
if (!serial8250_isa_devs) {
ret = -ENOMEM;
- goto unreg_plat_drv;
+ goto unreg_uart_drv;
}
ret = platform_device_add(serial8250_isa_devs);
@@ -2612,12 +2602,13 @@ static int __init serial8250_init(void)
serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
- goto out;
+ ret = platform_driver_register(&serial8250_isa_driver);
+ if (ret == 0)
+ goto out;
+ platform_device_del(serial8250_isa_devs);
put_dev:
platform_device_put(serial8250_isa_devs);
- unreg_plat_drv:
- platform_driver_unregister(&serial8250_isa_driver);
unreg_uart_drv:
uart_unregister_driver(&serial8250_reg);
out:
diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c
index a802bdce6e5..809f89ab965 100644
--- a/drivers/serial/8250_acpi.c
+++ b/drivers/serial/8250_acpi.c
@@ -27,7 +27,7 @@ struct serial_private {
static acpi_status acpi_serial_mmio(struct uart_port *port,
struct acpi_resource_address64 *addr)
{
- port->mapbase = addr->min_address_range;
+ port->mapbase = addr->minimum;
port->iotype = UPIO_MEM;
port->flags |= UPF_IOREMAP;
return AE_OK;
@@ -36,8 +36,8 @@ static acpi_status acpi_serial_mmio(struct uart_port *port,
static acpi_status acpi_serial_port(struct uart_port *port,
struct acpi_resource_io *io)
{
- if (io->range_length) {
- port->iobase = io->min_base_address;
+ if (io->address_length) {
+ port->iobase = io->minimum;
port->iotype = UPIO_PORT;
} else
printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__);
@@ -45,13 +45,13 @@ static acpi_status acpi_serial_port(struct uart_port *port,
}
static acpi_status acpi_serial_ext_irq(struct uart_port *port,
- struct acpi_resource_ext_irq *ext_irq)
+ struct acpi_resource_extended_irq *ext_irq)
{
int rc;
- if (ext_irq->number_of_interrupts > 0) {
+ if (ext_irq->interrupt_count > 0) {
rc = acpi_register_gsi(ext_irq->interrupts[0],
- ext_irq->edge_level, ext_irq->active_high_low);
+ ext_irq->triggering, ext_irq->polarity);
if (rc < 0)
return AE_ERROR;
port->irq = rc;
@@ -64,9 +64,9 @@ static acpi_status acpi_serial_irq(struct uart_port *port,
{
int rc;
- if (irq->number_of_interrupts > 0) {
+ if (irq->interrupt_count > 0) {
rc = acpi_register_gsi(irq->interrupts[0],
- irq->edge_level, irq->active_high_low);
+ irq->triggering, irq->polarity);
if (rc < 0)
return AE_ERROR;
port->irq = rc;
@@ -83,11 +83,11 @@ static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data)
status = acpi_resource_to_address64(res, &addr);
if (ACPI_SUCCESS(status))
return acpi_serial_mmio(port, &addr);
- else if (res->id == ACPI_RSTYPE_IO)
+ else if (res->type == ACPI_RESOURCE_TYPE_IO)
return acpi_serial_port(port, &res->data.io);
- else if (res->id == ACPI_RSTYPE_EXT_IRQ)
+ else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ)
return acpi_serial_ext_irq(port, &res->data.extended_irq);
- else if (res->id == ACPI_RSTYPE_IRQ)
+ else if (res->type == ACPI_RESOURCE_TYPE_IRQ)
return acpi_serial_irq(port, &res->data.irq);
return AE_OK;
}
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
index 06ae8fbcc94..8d8d7a70d03 100644
--- a/drivers/serial/8250_au1x00.c
+++ b/drivers/serial/8250_au1x00.c
@@ -56,7 +56,6 @@ static struct plat_serial8250_port au1x00_data[] = {
#elif defined(CONFIG_SOC_AU1550)
PORT(UART0_ADDR, AU1550_UART0_INT),
PORT(UART1_ADDR, AU1550_UART1_INT),
- PORT(UART2_ADDR, AU1550_UART2_INT),
PORT(UART3_ADDR, AU1550_UART3_INT),
#elif defined(CONFIG_SOC_AU1200)
PORT(UART0_ADDR, AU1200_UART0_INT),
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 589fb076654..94886c000d2 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -439,6 +439,20 @@ static int pci_siig_init(struct pci_dev *dev)
return -ENODEV;
}
+static int pci_siig_setup(struct serial_private *priv,
+ struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
+
+ if (idx > 3) {
+ bar = 4;
+ offset = (idx - 4) * 8;
+ }
+
+ return setup_port(priv, port, bar, offset, 0);
+}
+
/*
* Timedia has an explosion of boards, and to avoid the PCI table from
* growing *huge*, we use this function to collapse some 70 entries
@@ -748,7 +762,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_siig_init,
- .setup = pci_default_setup,
+ .setup = pci_siig_setup,
},
/*
* Titan cards
@@ -940,6 +954,7 @@ enum pci_board_num_t {
pbn_b2_bt_2_921600,
pbn_b2_bt_4_921600,
+ pbn_b3_2_115200,
pbn_b3_4_115200,
pbn_b3_8_115200,
@@ -1311,6 +1326,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 8,
},
+ [pbn_b3_2_115200] = {
+ .flags = FL_BASE3,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
[pbn_b3_4_115200] = {
.flags = FL_BASE3,
.num_ports = 4,
@@ -1861,6 +1882,10 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
pbn_b0_4_1843200 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_VENDOR_ID_AFAVLAB,
+ PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0,
+ pbn_b0_4_1152000 },
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
@@ -2134,6 +2159,15 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_4_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_8_921600 },
/*
* Computone devices submitted by Doug McNash dmcnash@computone.com
@@ -2272,6 +2306,9 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_nec_nile4 },
+ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b3_2_115200 },
{ PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b3_4_115200 },
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 5e7199f7b59..b3c561abe3f 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -23,7 +23,7 @@ config SERIAL_8250
work.)
To compile this driver as a module, choose M here: the
- module will be called serial.
+ module will be called 8250.
[WARNING: Do not compile this driver as a module if you are using
non-standard serial ports, since the configuration information will
be lost when the driver is unloaded. This limitation may be lifted
@@ -98,6 +98,7 @@ config SERIAL_8250_NR_UARTS
config SERIAL_8250_RUNTIME_UARTS
int "Number of 8250/16550 serial ports to register at runtime"
depends on SERIAL_8250
+ range 0 SERIAL_8250_NR_UARTS
default "4"
help
Set this to the maximum number of serial ports you want
@@ -301,7 +302,7 @@ config SERIAL_AT91_TTYAT
depends on SERIAL_AT91=y
help
Say Y here if you wish to have the five internal AT91RM9200 UARTs
- appear as /dev/ttyAT0-4 (major 240, minor 0-4) instead of the
+ appear as /dev/ttyAT0-4 (major 204, minor 154-158) instead of the
normal /dev/ttyS0-4 (major 4, minor 64-68). This is necessary if
you also want other UARTs, such as external 8250/16C550 compatible
UARTs.
@@ -892,20 +893,20 @@ config SERIAL_VR41XX_CONSOLE
a console on a serial port, say Y. Otherwise, say N.
config SERIAL_JSM
- tristate "Digi International NEO PCI Support"
- depends on PCI && BROKEN
- select SERIAL_CORE
- help
- This is a driver for Digi International's Neo series
- of cards which provide multiple serial ports. You would need
- something like this to connect more than two modems to your Linux
- box, for instance in order to become a dial-in server. This driver
- supports PCI boards only.
- If you have a card like this, say Y here and read the file
- <file:Documentation/jsm.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called jsm.
+ tristate "Digi International NEO PCI Support"
+ depends on PCI
+ select SERIAL_CORE
+ help
+ This is a driver for Digi International's Neo series
+ of cards which provide multiple serial ports. You would need
+ something like this to connect more than two modems to your Linux
+ box, for instance in order to become a dial-in server. This driver
+ supports PCI boards only.
+
+ If you have a card like this, say Y here, otherwise say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called jsm.
config SERIAL_SGI_IOC4
tristate "SGI IOC4 controller serial support"
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 3490022e9fd..321a3b3a572 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -561,12 +561,12 @@ static struct uart_amba_port amba_ports[UART_NR] = {
.port = {
.membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
.mapbase = INTEGRATOR_UART0_BASE,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UARTINT0,
.uartclk = 14745600,
.fifosize = 16,
.ops = &amba_pl010_pops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.dtr_mask = 1 << 5,
@@ -576,12 +576,12 @@ static struct uart_amba_port amba_ports[UART_NR] = {
.port = {
.membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
.mapbase = INTEGRATOR_UART1_BASE,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UARTINT1,
.uartclk = 14745600,
.fifosize = 16,
.ops = &amba_pl010_pops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.dtr_mask = 1 << 7,
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c
index 0e206063d68..2113feb75c3 100644
--- a/drivers/serial/at91_serial.c
+++ b/drivers/serial/at91_serial.c
@@ -222,8 +222,6 @@ static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
while (status & (AT91_US_RXRDY)) {
ch = UART_GET_CHAR(port);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
port->icount.rx++;
flg = TTY_NORMAL;
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index ceb5d7f37bb..344022fe53e 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -892,7 +892,7 @@ serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res
int ret = 0;
switch (up->port.iotype) {
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
if (up->port.mapbase) {
*res = request_mem_region(up->port.mapbase, size, "serial");
if (!*res)
@@ -900,8 +900,8 @@ serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res
}
break;
- case SERIAL_IO_HUB6:
- case SERIAL_IO_PORT:
+ case UPIO_HUB6:
+ case UPIO_PORT:
*res = request_region(up->port.iobase, size, "serial");
if (!*res)
ret = -EBUSY;
@@ -919,7 +919,7 @@ static void serial8250_release_port(struct uart_port *port)
size <<= up->port.regshift;
switch (up->port.iotype) {
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
if (up->port.mapbase) {
/*
* Unmap the area.
@@ -935,8 +935,8 @@ static void serial8250_release_port(struct uart_port *port)
}
break;
- case SERIAL_IO_HUB6:
- case SERIAL_IO_PORT:
+ case UPIO_HUB6:
+ case UPIO_PORT:
start = up->port.iobase;
if (size)
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 8ef999481f9..ce7b2e4ecd1 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -410,7 +410,7 @@ static struct uart_port clps711x_ports[UART_NR] = {
.fifosize = 16,
.ops = &clps711x_pops,
.line = 0,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
},
{
.iobase = SYSCON2,
@@ -419,7 +419,7 @@ static struct uart_port clps711x_ports[UART_NR] = {
.fifosize = 16,
.ops = &clps711x_pops,
.line = 1,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
}
};
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 16af5626c24..b7bf4c698a4 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -252,12 +252,9 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
/* If we have not enough room in tty flip buffer, then we try
* later, which will be the next rx-interrupt or a timeout
*/
- if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
- tty->flip.work.func((void *)tty);
- if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
- printk(KERN_WARNING "TTY_DONT_FLIP set\n");
- return;
- }
+ if(tty_buffer_request_room(tty, i) < i) {
+ printk(KERN_WARNING "No room in flip buffer\n");
+ return;
}
/* get pointer */
@@ -276,9 +273,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
continue;
error_return:
- *tty->flip.char_buf_ptr++ = ch;
- *tty->flip.flag_buf_ptr++ = flg;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flg);
} /* End while (i--) */
@@ -908,7 +903,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SMC1_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.flags = FLAG_SMC,
@@ -922,7 +917,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SMC2_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.flags = FLAG_SMC,
@@ -939,7 +934,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SCC1_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
@@ -953,7 +948,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SCC2_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
@@ -967,7 +962,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SCC3_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
@@ -981,7 +976,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.port = {
.irq = SCC4_IRQ,
.ops = &cpm_uart_pops,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index a64ba26a94e..ba5541de673 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -262,6 +262,7 @@ static inline void dz_receive_chars(struct dz_port *dport)
}
tty_insert_flip_char(tty, ch, flag);
ignore_char:
+ ;
} while (status & DZ_DVAL);
if (tty)
@@ -650,7 +651,7 @@ static void __init dz_init_ports(void)
for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {
spin_lock_init(&dport->port.lock);
dport->port.membase = (char *) base;
- dport->port.iotype = SERIAL_IO_PORT;
+ dport->port.iotype = UPIO_PORT;
dport->port.irq = dec_interrupt[DEC_IRQ_DZ11];
dport->port.line = i;
dport->port.fifosize = 1;
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 587cc6a9511..4d53fb5ca87 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -402,10 +402,10 @@ static int imx_startup(struct uart_port *port)
DRIVER_NAME, sport);
if (retval) goto error_out2;
- retval = request_irq(sport->rtsirq, imx_rtsint, 0,
+ retval = request_irq(sport->rtsirq, imx_rtsint,
+ SA_TRIGGER_FALLING | SA_TRIGGER_RISING,
DRIVER_NAME, sport);
if (retval) goto error_out3;
- set_irq_type(sport->rtsirq, IRQT_BOTHEDGE);
/*
* Finally, clear and enable interrupts
@@ -668,13 +668,13 @@ static struct imx_port imx_ports[] = {
.rtsirq = UART1_MINT_RTS,
.port = {
.type = PORT_IMX,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.membase = (void *)IMX_UART1_BASE,
.mapbase = IMX_UART1_BASE, /* FIXME */
.irq = UART1_MINT_RX,
.uartclk = 16000000,
.fifosize = 8,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.ops = &imx_pops,
.line = 0,
},
@@ -684,13 +684,13 @@ static struct imx_port imx_ports[] = {
.rtsirq = UART2_MINT_RTS,
.port = {
.type = PORT_IMX,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.membase = (void *)IMX_UART2_BASE,
.mapbase = IMX_UART2_BASE, /* FIXME */
.irq = UART2_MINT_RX,
.uartclk = 16000000,
.fifosize = 8,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.ops = &imx_pops,
.line = 1,
},
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 1d85533d46d..f3763d2ccb8 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -1717,11 +1717,9 @@ ioc4_change_speed(struct uart_port *the_port,
}
if (cflag & CRTSCTS) {
- info->flags |= ASYNC_CTS_FLOW;
port->ip_sscr |= IOC4_SSCR_HFC_EN;
}
else {
- info->flags &= ~ASYNC_CTS_FLOW;
port->ip_sscr &= ~IOC4_SSCR_HFC_EN;
}
writel(port->ip_sscr, &port->ip_serial_regs->sscr);
@@ -1760,18 +1758,6 @@ static inline int ic4_startup_local(struct uart_port *the_port)
info = the_port->info;
- if (info->tty) {
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- info->tty->alt_speed = 57600;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- info->tty->alt_speed = 115200;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- info->tty->alt_speed = 230400;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- info->tty->alt_speed = 460800;
- }
local_open(port);
/* set the speed of the serial port */
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index 66f117d1506..419dd3cd786 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -215,7 +215,7 @@ static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs)
/* Lower and upper byte of baud rate generator divisor. */
write_zsreg(channel, R12, regs[R12]);
write_zsreg(channel, R13, regs[R13]);
-
+
/* Now rewrite R14, with BRENAB (if set). */
write_zsreg(channel, R14, regs[R14]);
@@ -571,7 +571,7 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
else
clear_bits |= DTR;
- /* NOTE: Not subject to 'transmitter active' rule. */
+ /* NOTE: Not subject to 'transmitter active' rule. */
up->curregs[R5] |= set_bits;
up->curregs[R5] &= ~clear_bits;
write_zsreg(channel, R5, up->curregs[R5]);
@@ -654,7 +654,7 @@ static void ip22zilog_enable_ms(struct uart_port *port)
if (new_reg != up->curregs[R15]) {
up->curregs[R15] = new_reg;
- /* NOTE: Not subject to 'transmitter active' rule. */
+ /* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(channel, R15, up->curregs[R15]);
}
}
@@ -680,7 +680,7 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state)
if (new_reg != up->curregs[R5]) {
up->curregs[R5] = new_reg;
- /* NOTE: Not subject to 'transmitter active' rule. */
+ /* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(channel, R5, up->curregs[R5]);
}
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index 18753193f59..dfc1e86d3aa 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -380,7 +380,6 @@ struct neo_uart_struct {
extern struct uart_driver jsm_uart_driver;
extern struct board_ops jsm_neo_ops;
extern int jsm_debug;
-extern int jsm_rawreadok;
/*************************************************************************
*
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 7e56c782419..b1b66e71d28 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -49,11 +49,8 @@ struct uart_driver jsm_uart_driver = {
};
int jsm_debug;
-int jsm_rawreadok;
module_param(jsm_debug, int, 0);
-module_param(jsm_rawreadok, int, 0);
MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
-MODULE_PARM_DESC(jsm_rawreadok, "Bypass flip buffers on input");
static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index 6f22b42d933..87e4e2cf8ce 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -965,56 +965,47 @@ static void neo_param(struct jsm_channel *ch)
baud = ch->ch_custom_speed;
if (ch->ch_flags & CH_BAUD0)
ch->ch_flags &= ~(CH_BAUD0);
- } else {
- int iindex = 0;
- int jindex = 0;
-
- const u64 bauds[4][16] = {
- {
- 0, 50, 75, 110,
- 134, 150, 200, 300,
- 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400 },
- {
- 0, 57600, 115200, 230400,
- 460800, 150, 200, 921600,
- 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400 },
- {
- 0, 57600, 76800, 115200,
- 131657, 153600, 230400, 460800,
- 921600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400 },
- {
- 0, 57600, 115200, 230400,
- 460800, 150, 200, 921600,
- 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400 }
- };
-
- baud = C_BAUD(ch->uart_port.info->tty) & 0xff;
-
- if (ch->ch_c_cflag & CBAUDEX)
- iindex = 1;
-
- jindex = baud;
-
- if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16))
- baud = bauds[iindex][jindex];
- else {
- jsm_printk(IOCTL, DEBUG, &ch->ch_bd->pci_dev,
- "baud indices were out of range (%d)(%d)",
- iindex, jindex);
- baud = 0;
+ } else {
+ int i;
+ unsigned int cflag;
+ static struct {
+ unsigned int rate;
+ unsigned int cflag;
+ } baud_rates[] = {
+ { 921600, B921600 },
+ { 460800, B460800 },
+ { 230400, B230400 },
+ { 115200, B115200 },
+ { 57600, B57600 },
+ { 38400, B38400 },
+ { 19200, B19200 },
+ { 9600, B9600 },
+ { 4800, B4800 },
+ { 2400, B2400 },
+ { 1200, B1200 },
+ { 600, B600 },
+ { 300, B300 },
+ { 200, B200 },
+ { 150, B150 },
+ { 134, B134 },
+ { 110, B110 },
+ { 75, B75 },
+ { 50, B50 },
+ };
+
+ cflag = C_BAUD(ch->uart_port.info->tty);
+ baud = 9600;
+ for (i = 0; i < ARRAY_SIZE(baud_rates); i++) {
+ if (baud_rates[i].cflag == cflag) {
+ baud = baud_rates[i].rate;
+ break;
}
-
- if (baud == 0)
- baud = 9600;
-
- if (ch->ch_flags & CH_BAUD0)
- ch->ch_flags &= ~(CH_BAUD0);
}
+ if (ch->ch_flags & CH_BAUD0)
+ ch->ch_flags &= ~(CH_BAUD0);
+ }
+
if (ch->ch_c_cflag & PARENB)
lcr |= UART_LCR_PARITY;
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 6fa0d62d6f6..4d48b625cd3 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -20,8 +20,10 @@
*
* Contact Information:
* Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
- *
+ * Ananda Venkatarman <mansarov@us.ibm.com>
+ * Modifications:
+ * 01/19/06: changed jsm_input routine to use the dynamically allocated
+ * tty_buffer changes. Contributors: Scott Kilau and Ananda V.
***********************************************************************/
#include <linux/tty.h>
#include <linux/tty_flip.h>
@@ -497,16 +499,15 @@ void jsm_input(struct jsm_channel *ch)
{
struct jsm_board *bd;
struct tty_struct *tp;
+ struct tty_ldisc *ld;
u32 rmask;
u16 head;
u16 tail;
int data_len;
unsigned long lock_flags;
- int flip_len;
+ int flip_len = 0;
int len = 0;
int n = 0;
- char *buf = NULL;
- char *buf2 = NULL;
int s = 0;
int i = 0;
@@ -574,56 +575,50 @@ void jsm_input(struct jsm_channel *ch)
/*
* If the rxbuf is empty and we are not throttled, put as much
- * as we can directly into the linux TTY flip buffer.
- * The jsm_rawreadok case takes advantage of carnal knowledge that
- * the char_buf and the flag_buf are next to each other and
- * are each of (2 * TTY_FLIPBUF_SIZE) size.
+ * as we can directly into the linux TTY buffer.
*
- * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf
- *actually still uses the flag buffer, so you can't
- *use it for input data
*/
- if (jsm_rawreadok) {
- if (tp->real_raw)
- flip_len = MYFLIPLEN;
- else
- flip_len = 2 * TTY_FLIPBUF_SIZE;
- } else
- flip_len = TTY_FLIPBUF_SIZE - tp->flip.count;
+ flip_len = TTY_FLIPBUF_SIZE;
len = min(data_len, flip_len);
len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);
+ ld = tty_ldisc_ref(tp);
- if (len <= 0) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
- return;
- }
+ /*
+ * If the DONT_FLIP flag is on, don't flush our buffer, and act
+ * like the ld doesn't have any space to put the data right now.
+ */
+ if (test_bit(TTY_DONT_FLIP, &tp->flags))
+ len = 0;
/*
- * If we're bypassing flip buffers on rx, we can blast it
- * right into the beginning of the buffer.
+ * If we were unable to get a reference to the ld,
+ * don't flush our buffer, and act like the ld doesn't
+ * have any space to put the data right now.
*/
- if (jsm_rawreadok) {
- if (tp->real_raw) {
- if (ch->ch_flags & CH_FLIPBUF_IN_USE) {
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "JSM - FLIPBUF in use. delaying input\n");
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- return;
- }
- ch->ch_flags |= CH_FLIPBUF_IN_USE;
- buf = ch->ch_bd->flipbuf;
- buf2 = NULL;
- } else {
- buf = tp->flip.char_buf;
- buf2 = tp->flip.flag_buf;
- }
+ if (!ld) {
+ len = 0;
} else {
- buf = tp->flip.char_buf_ptr;
- buf2 = tp->flip.flag_buf_ptr;
+ /*
+ * If ld doesn't have a pointer to a receive_buf function,
+ * flush the data, then act like the ld doesn't have any
+ * space to put the data right now.
+ */
+ if (!ld->receive_buf) {
+ ch->ch_r_head = ch->ch_r_tail;
+ len = 0;
+ }
}
+ if (len <= 0) {
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
+ if (ld)
+ tty_ldisc_deref(ld);
+ return;
+ }
+
+ len = tty_buffer_request_room(tp, len);
n = len;
/*
@@ -638,121 +633,47 @@ void jsm_input(struct jsm_channel *ch)
if (s <= 0)
break;
- memcpy(buf, ch->ch_rqueue + tail, s);
-
- /* buf2 is only set when port isn't raw */
- if (buf2)
- memcpy(buf2, ch->ch_equeue + tail, s);
-
- tail += s;
- buf += s;
- if (buf2)
- buf2 += s;
- n -= s;
- /* Flip queue if needed */
- tail &= rmask;
- }
+ /*
+ * If conditions are such that ld needs to see all
+ * UART errors, we will have to walk each character
+ * and error byte and send them to the buffer one at
+ * a time.
+ */
- /*
- * In high performance mode, we don't have to update
- * flag_buf or any of the counts or pointers into flip buf.
- */
- if (!jsm_rawreadok) {
if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
- for (i = 0; i < len; i++) {
+ for (i = 0; i < s; i++) {
/*
* Give the Linux ld the flags in the
* format it likes.
*/
- if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
- tp->flip.flag_buf_ptr[i] = TTY_BREAK;
- else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
- tp->flip.flag_buf_ptr[i] = TTY_PARITY;
- else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
- tp->flip.flag_buf_ptr[i] = TTY_FRAME;
+ if (*(ch->ch_equeue +tail +i) & UART_LSR_BI)
+ tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_BREAK);
+ else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE)
+ tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY);
+ else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE)
+ tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME);
else
- tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
+ tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
}
} else {
- memset(tp->flip.flag_buf_ptr, 0, len);
+ tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ;
}
-
- tp->flip.char_buf_ptr += len;
- tp->flip.flag_buf_ptr += len;
- tp->flip.count += len;
- }
- else if (!tp->real_raw) {
- if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
- for (i = 0; i < len; i++) {
- /*
- * Give the Linux ld the flags in the
- * format it likes.
- */
- if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
- tp->flip.flag_buf_ptr[i] = TTY_BREAK;
- else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
- tp->flip.flag_buf_ptr[i] = TTY_PARITY;
- else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
- tp->flip.flag_buf_ptr[i] = TTY_FRAME;
- else
- tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
- }
- } else
- memset(tp->flip.flag_buf, 0, len);
+ tail += s;
+ n -= s;
+ /* Flip queue if needed */
+ tail &= rmask;
}
- /*
- * If we're doing raw reads, jam it right into the
- * line disc bypassing the flip buffers.
- */
- if (jsm_rawreadok) {
- if (tp->real_raw) {
- ch->ch_r_tail = tail & rmask;
- ch->ch_e_tail = tail & rmask;
-
- jsm_check_queue_flow_control(ch);
-
- /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
+ ch->ch_r_tail = tail & rmask;
+ ch->ch_e_tail = tail & rmask;
+ jsm_check_queue_flow_control(ch);
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ /* Tell the tty layer its okay to "eat" the data now */
+ tty_flip_buffer_push(tp);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "jsm_input. %d real_raw len:%d calling receive_buf for board %d\n",
- __LINE__, len, ch->ch_bd->boardnum);
- tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
-
- /* Allow use of channel flip buffer again */
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- ch->ch_flags &= ~CH_FLIPBUF_IN_USE;
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- } else {
- ch->ch_r_tail = tail & rmask;
- ch->ch_e_tail = tail & rmask;
-
- jsm_check_queue_flow_control(ch);
-
- /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n",
- __LINE__, len, ch->ch_bd->boardnum);
-
- tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len);
- }
- } else {
- ch->ch_r_tail = tail & rmask;
- ch->ch_e_tail = tail & rmask;
-
- jsm_check_queue_flow_control(ch);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__);
- tty_schedule_flip(tp);
- }
+ if (ld)
+ tty_ldisc_deref(ld);
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
}
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index b48066a64a7..242a0410439 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -80,7 +80,7 @@
#include <asm/serial.h>
/* Standard COM flags */
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
/*
* SERIAL_PORT_DFNS tells us about built-in ports that have no
diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h
index 07d0dd80aa3..7c3ec24f7e5 100644
--- a/drivers/serial/m32r_sio.h
+++ b/drivers/serial/m32r_sio.h
@@ -37,7 +37,7 @@ struct old_serial_port {
unsigned int irq;
unsigned int flags;
unsigned char io_type;
- unsigned char *iomem_base;
+ unsigned char __iomem *iomem_base;
unsigned short iomem_reg_shift;
};
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index d957a3a9edf..8cbbb954df2 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -57,20 +57,16 @@ struct timer_list mcfrs_timer_struct;
* keep going. Perhaps one day the cflag settings for the
* console can be used instead.
*/
-#if defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
- defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
-#define CONSOLE_BAUD_RATE 19200
-#define DEFAULT_CBAUD B19200
-#endif
-
#if defined(CONFIG_HW_FEITH)
#define CONSOLE_BAUD_RATE 38400
#define DEFAULT_CBAUD B38400
-#endif
-
-#if defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
+#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
#define CONSOLE_BAUD_RATE 115200
#define DEFAULT_CBAUD B115200
+#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
+ defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
+#define CONSOLE_BAUD_RATE 19200
+#define DEFAULT_CBAUD B19200
#endif
#ifndef CONSOLE_BAUD_RATE
@@ -350,8 +346,7 @@ static inline void receive_chars(struct mcf_serial *info)
}
tty_insert_flip_char(tty, ch, flag);
}
-
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
return;
}
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 4e49168c317..868eaf4a1a6 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -462,7 +462,7 @@ static int __init mux_probe(struct parisc_device *dev)
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->iotype = UPIO_MEM;
port->type = PORT_MUX;
port->irq = NO_IRQ;
port->uartclk = 0;
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 4e03a87f3fb..9b7ed58cb53 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -1492,7 +1492,7 @@ no_dma:
/*
* Init remaining bits of "port" structure
*/
- uap->port.iotype = SERIAL_IO_MEM;
+ uap->port.iotype = UPIO_MEM;
uap->port.irq = np->intrs[0].line;
uap->port.uartclk = ZS_CLOCK;
uap->port.fifosize = 1;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index eb4883efb7c..7410e093a6b 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -161,7 +161,11 @@ s3c24xx_serial_dbg(const char *fmt, ...)
/* we can support 3 uarts, but not always use them */
+#ifdef CONFIG_CPU_S3C2400
+#define NR_PORTS (2)
+#else
#define NR_PORTS (3)
+#endif
/* port irq numbers */
@@ -1060,7 +1064,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
port->mapbase = res->start;
- port->membase = S3C24XX_VA_UART + (res->start - S3C2410_PA_UART);
+ port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
port->irq = platform_get_irq(platdev, 0);
ourport->clk = clk_get(&platdev->dev, "uart");
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 1bd93168f50..2c00b862585 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -628,7 +628,7 @@ static void __init sa1100_init_ports(void)
sa1100_ports[i].port.ops = &sa1100_pops;
sa1100_ports[i].port.fifosize = 8;
sa1100_ports[i].port.line = i;
- sa1100_ports[i].port.iotype = SERIAL_IO_MEM;
+ sa1100_ports[i].port.iotype = UPIO_MEM;
init_timer(&sa1100_ports[i].timer);
sa1100_ports[i].timer.function = sa1100_timeout;
sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i];
@@ -665,21 +665,21 @@ void __init sa1100_register_uart(int idx, int port)
sa1100_ports[idx].port.membase = (void __iomem *)&Ser1UTCR0;
sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
sa1100_ports[idx].port.irq = IRQ_Ser1UART;
- sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
+ sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF;
break;
case 2:
sa1100_ports[idx].port.membase = (void __iomem *)&Ser2UTCR0;
sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
sa1100_ports[idx].port.irq = IRQ_Ser2ICP;
- sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
+ sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF;
break;
case 3:
sa1100_ports[idx].port.membase = (void __iomem *)&Ser3UTCR0;
sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
sa1100_ports[idx].port.irq = IRQ_Ser3UART;
- sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
+ sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF;
break;
default:
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 943770470b9..95fb4939c67 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -332,7 +332,7 @@ uart_get_baud_rate(struct uart_port *port, struct termios *termios,
struct termios *old, unsigned int min, unsigned int max)
{
unsigned int try, baud, altbaud = 38400;
- unsigned int flags = port->flags & UPF_SPD_MASK;
+ upf_t flags = port->flags & UPF_SPD_MASK;
if (flags == UPF_SPD_HI)
altbaud = 57600;
@@ -615,8 +615,9 @@ static int uart_set_info(struct uart_state *state,
struct serial_struct new_serial;
struct uart_port *port = state->port;
unsigned long new_port;
- unsigned int change_irq, change_port, old_flags, closing_wait;
+ unsigned int change_irq, change_port, closing_wait;
unsigned int old_custom_divisor, close_delay;
+ upf_t old_flags, new_flags;
int retval = 0;
if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
@@ -655,6 +656,7 @@ static int uart_set_info(struct uart_state *state,
new_serial.type != port->type;
old_flags = port->flags;
+ new_flags = new_serial.flags;
old_custom_divisor = port->custom_divisor;
if (!capable(CAP_SYS_ADMIN)) {
@@ -664,10 +666,10 @@ static int uart_set_info(struct uart_state *state,
(close_delay != state->close_delay) ||
(closing_wait != state->closing_wait) ||
(new_serial.xmit_fifo_size != port->fifosize) ||
- (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0))
+ (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
goto exit;
port->flags = ((port->flags & ~UPF_USR_MASK) |
- (new_serial.flags & UPF_USR_MASK));
+ (new_flags & UPF_USR_MASK));
port->custom_divisor = new_serial.custom_divisor;
goto check_and_exit;
}
@@ -764,7 +766,7 @@ static int uart_set_info(struct uart_state *state,
port->irq = new_serial.irq;
port->uartclk = new_serial.baud_base * 16;
port->flags = (port->flags & ~UPF_CHANGE_MASK) |
- (new_serial.flags & UPF_CHANGE_MASK);
+ (new_flags & UPF_CHANGE_MASK);
port->custom_divisor = new_serial.custom_divisor;
state->close_delay = close_delay;
state->closing_wait = closing_wait;
@@ -1870,7 +1872,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
mutex_lock(&state->mutex);
if (state->info && state->info->flags & UIF_INITIALIZED) {
- struct uart_ops *ops = port->ops;
+ const struct uart_ops *ops = port->ops;
spin_lock_irq(&port->lock);
ops->stop_tx(port);
@@ -1932,7 +1934,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
}
if (state->info && state->info->flags & UIF_INITIALIZED) {
- struct uart_ops *ops = port->ops;
+ const struct uart_ops *ops = port->ops;
int ret;
ops->set_mctrl(port, 0);
@@ -2235,7 +2237,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
* If this port is a console, then the spinlock is already
* initialised.
*/
- if (!uart_console(port))
+ if (!(uart_console(port) && (port->cons->flags & CON_ENABLED)))
spin_lock_init(&port->lock);
uart_configure_port(drv, state, port);
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index d4a1f0e798c..04186eaae22 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -501,12 +501,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
.port = {
.membase = (void*) io_p2v (UART1_PHYS),
.mapbase = UART1_PHYS,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UART1INTR,
.uartclk = 14745600/2,
.fifosize = 16,
.ops = &lh7a40x_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
},
@@ -514,12 +514,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
.port = {
.membase = (void*) io_p2v (UART2_PHYS),
.mapbase = UART2_PHYS,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UART2INTR,
.uartclk = 14745600/2,
.fifosize = 16,
.ops = &lh7a40x_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
},
@@ -527,12 +527,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
.port = {
.membase = (void*) io_p2v (UART3_PHYS),
.mapbase = UART3_PHYS,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = IRQ_UART3INTR,
.uartclk = 14745600/2,
.fifosize = 16,
.ops = &lh7a40x_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 2,
},
},
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index a9e07075962..44f6bf79bbe 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -42,6 +42,7 @@
#include <linux/delay.h>
#include <linux/console.h>
#include <linux/bitops.h>
+#include <linux/generic_serial.h>
#ifdef CONFIG_CPU_FREQ
#include <linux/notifier.h>
@@ -53,7 +54,9 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
-#include <linux/generic_serial.h>
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#include <asm/clock.h>
+#endif
#ifdef CONFIG_SH_STANDARD_BIOS
#include <asm/sh_bios.h>
@@ -86,9 +89,11 @@ static void sci_stop_rx(struct uart_port *port);
static int sci_request_irq(struct sci_port *port);
static void sci_free_irq(struct sci_port *port);
-static struct sci_port sci_ports[SCI_NPORTS];
+static struct sci_port sci_ports[];
static struct uart_driver sci_uart_driver;
+#define SCI_NPORTS sci_uart_driver.nr
+
#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
static void handle_error(struct uart_port *port)
@@ -168,7 +173,7 @@ static void put_string(struct sci_port *sci_port, const char *buffer, int count)
int usegdb=0;
#ifdef CONFIG_SH_STANDARD_BIOS
- /* This call only does a trap the first time it is
+ /* This call only does a trap the first time it is
* called, and so is safe to do here unconditionally
*/
usegdb |= sh_bios_in_gdb_mode();
@@ -324,47 +329,46 @@ static void sci_init_pins_sci(struct uart_port* port, unsigned int cflag)
/* tx mark output*/
H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx;
}
-#else
-static void sci_init_pins_sci(struct uart_port *port, unsigned int cflag)
-{
-}
#endif
#endif
#if defined(SCIF_ONLY) || defined(SCI_AND_SCIF)
-#if defined(CONFIG_CPU_SH3)
-/* For SH7705, SH7707, SH7709, SH7709A, SH7729, SH7300*/
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+/* SH7300 doesn't use RTS/CTS */
+static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+{
+ sci_out(port, SCFCR, 0);
+}
+#elif defined(CONFIG_CPU_SH3)
+/* For SH7705, SH7707, SH7709, SH7709A, SH7729 */
static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
{
unsigned int fcr_val = 0;
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300) /* SH7300 doesn't use RTS/CTS */
- {
- unsigned short data;
+ unsigned short data;
+
+ /* We need to set SCPCR to enable RTS/CTS */
+ data = ctrl_inw(SCPCR);
+ /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
+ ctrl_outw(data & 0x0fcf, SCPCR);
- /* We need to set SCPCR to enable RTS/CTS */
- data = ctrl_inw(SCPCR);
- /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
- ctrl_outw(data&0x0fcf, SCPCR);
- }
if (cflag & CRTSCTS)
fcr_val |= SCFCR_MCE;
else {
- unsigned short data;
-
/* We need to set SCPCR to enable RTS/CTS */
data = ctrl_inw(SCPCR);
/* Clear out SCP7MD1,0, SCP4MD1,0,
Set SCP6MD1,0 = {01} (output) */
- ctrl_outw((data&0x0fcf)|0x1000, SCPCR);
+ ctrl_outw((data & 0x0fcf) | 0x1000, SCPCR);
data = ctrl_inb(SCPDR);
/* Set /RTS2 (bit6) = 0 */
- ctrl_outb(data&0xbf, SCPDR);
+ ctrl_outb(data & 0xbf, SCPDR);
}
-#endif
+
sci_out(port, SCFCR, fcr_val);
}
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag)
{
unsigned int fcr_val = 0;
@@ -374,7 +378,7 @@ static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag)
sci_out(port, SCFCR, fcr_val);
}
-
+#endif
#else
/* For SH7750 */
@@ -385,7 +389,11 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
if (cflag & CRTSCTS) {
fcr_val |= SCFCR_MCE;
} else {
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+ ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
+#else
ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
+#endif
}
sci_out(port, SCFCR, fcr_val);
}
@@ -422,7 +430,11 @@ static void sci_transmit_chars(struct uart_port *port)
#if !defined(SCI_ONLY)
if (port->type == PORT_SCIF) {
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+ txroom = SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f);
+#else
txroom = SCIF_TXROOM_MAX - (sci_in(port, SCFDR)>>8);
+#endif
} else {
txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0;
}
@@ -491,7 +503,11 @@ static inline void sci_receive_chars(struct uart_port *port,
while (1) {
#if !defined(SCI_ONLY)
if (port->type == PORT_SCIF) {
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+ count = sci_in(port, SCRFDR) & 0x7f;
+#else
count = sci_in(port, SCFDR)&SCIF_RFDC_MASK ;
+#endif
} else {
count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0;
}
@@ -652,7 +668,7 @@ static inline int sci_handle_breaks(struct uart_port *port)
struct tty_struct *tty = port->info->tty;
struct sci_port *s = &sci_ports[port->line];
- if (!s->break_flag && status & SCxSR_BRK(port))
+ if (!s->break_flag && status & SCxSR_BRK(port)) {
#if defined(CONFIG_CPU_SH3)
/* Debounce break */
s->break_flag = 1;
@@ -783,6 +799,7 @@ static int sci_notifier(struct notifier_block *self, unsigned long phase, void *
(phase == CPUFREQ_RESUMECHANGE)){
for (i = 0; i < SCI_NPORTS; i++) {
struct uart_port *port = &sci_ports[i].port;
+ struct clk *clk;
/*
* Update the uartclk per-port if frequency has
@@ -795,7 +812,9 @@ static int sci_notifier(struct notifier_block *self, unsigned long phase, void *
*
* Clean this up later..
*/
- port->uartclk = current_cpu_data.module_clock * 16;
+ clk = clk_get("module_clk");
+ port->uartclk = clk_get_rate(clk) * 16;
+ clk_put(clk);
}
printk("%s: got a postchange notification for cpu %d (old %d, new %d)\n",
@@ -1008,15 +1027,20 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
sci_out(port, SCSMR, smr_val);
switch (baud) {
- case 0: t = -1; break;
- case 2400: t = BPS_2400; break;
- case 4800: t = BPS_4800; break;
- case 9600: t = BPS_9600; break;
- case 19200: t = BPS_19200; break;
- case 38400: t = BPS_38400; break;
- case 57600: t = BPS_57600; break;
- case 115200: t = BPS_115200; break;
- default: t = SCBRR_VALUE(baud); break;
+ case 0:
+ t = -1;
+ break;
+ default:
+ {
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+ struct clk *clk = clk_get("module_clk");
+ t = SCBRR_VALUE(baud, clk_get_rate(clk));
+ clk_put(clk);
+#else
+ t = SCBRR_VALUE(baud);
+#endif
+ }
+ break;
}
if (t > 0) {
@@ -1030,7 +1054,9 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
}
- s->init_pins(port, termios->c_cflag);
+ if (likely(s->init_pins))
+ s->init_pins(port, termios->c_cflag);
+
sci_out(port, SCSCR, SCSCR_INIT(port));
if ((termios->c_cflag & CREAD) != 0)
@@ -1107,31 +1133,30 @@ static struct uart_ops sci_uart_ops = {
.verify_port = sci_verify_port,
};
-static struct sci_port sci_ports[SCI_NPORTS] = {
+static struct sci_port sci_ports[] = {
#if defined(CONFIG_CPU_SUBTYPE_SH7708)
{
.port = {
.membase = (void *)0xfffffe80,
.mapbase = 0xfffffe80,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 25,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCI,
.irqs = SCI_IRQS,
- .init_pins = sci_init_pins_sci,
},
#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
{
.port = {
.membase = (void *)SCIF0,
.mapbase = SCIF0,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 55,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
@@ -1142,10 +1167,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)SCIF2,
.mapbase = SCIF2,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 59,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCIF,
@@ -1157,24 +1182,23 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xfffffe80,
.mapbase = 0xfffffe80,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 25,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCI,
.irqs = SCI_IRQS,
- .init_pins = sci_init_pins_sci,
},
{
.port = {
.membase = (void *)0xa4000150,
.mapbase = 0xa4000150,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 59,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCIF,
@@ -1185,10 +1209,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xa4000140,
.mapbase = 0xa4000140,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 55,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 2,
},
.type = PORT_IRDA,
@@ -1200,10 +1224,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xA4430000,
.mapbase = 0xA4430000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 25,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
@@ -1215,25 +1239,25 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xffe00000,
.mapbase = 0xffe00000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 25,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
.irqs = SH73180_SCIF_IRQS,
.init_pins = sci_init_pins_scif,
},
-#elif defined(CONFIG_SH_RTS7751R2D)
+#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
{
.port = {
.membase = (void *)0xffe80000,
.mapbase = 0xffe80000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 43,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
@@ -1245,24 +1269,23 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xffe00000,
.mapbase = 0xffe00000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 25,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCI,
.irqs = SCI_IRQS,
- .init_pins = sci_init_pins_sci,
},
{
.port = {
.membase = (void *)0xffe80000,
.mapbase = 0xffe80000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 43,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCIF,
@@ -1274,10 +1297,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xfe600000,
.mapbase = 0xfe600000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 55,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
@@ -1288,10 +1311,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xfe610000,
.mapbase = 0xfe610000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 75,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCIF,
@@ -1302,40 +1325,25 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xfe620000,
.mapbase = 0xfe620000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 79,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 2,
},
.type = PORT_SCIF,
.irqs = SH7760_SCIF2_IRQS,
.init_pins = sci_init_pins_scif,
},
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
- {
- .port = {
- .membase = (void *)0xffe80000,
- .mapbase = 0xffe80000,
- .iotype = SERIAL_IO_MEM,
- .irq = 43,
- .ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
- .line = 0,
- },
- .type = PORT_SCIF,
- .irqs = SH4_SCIF_IRQS,
- .init_pins = sci_init_pins_scif,
- },
#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
{
.port = {
.membase = (void *)0xffe00000,
.mapbase = 0xffe00000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 26,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
@@ -1346,10 +1354,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0xffe80000,
.mapbase = 0xffe80000,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 43,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCIF,
@@ -1359,10 +1367,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
{
.port = {
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 42,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCIF,
@@ -1374,10 +1382,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0x00ffffb0,
.mapbase = 0x00ffffb0,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 54,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCI,
@@ -1388,10 +1396,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0x00ffffb8,
.mapbase = 0x00ffffb8,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 58,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCI,
@@ -1402,10 +1410,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0x00ffffc0,
.mapbase = 0x00ffffc0,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 62,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 2,
},
.type = PORT_SCI,
@@ -1417,10 +1425,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0x00ffff78,
.mapbase = 0x00ffff78,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 90,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
},
.type = PORT_SCI,
@@ -1431,10 +1439,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0x00ffff80,
.mapbase = 0x00ffff80,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 94,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 1,
},
.type = PORT_SCI,
@@ -1445,16 +1453,88 @@ static struct sci_port sci_ports[SCI_NPORTS] = {
.port = {
.membase = (void *)0x00ffff88,
.mapbase = 0x00ffff88,
- .iotype = SERIAL_IO_MEM,
+ .iotype = UPIO_MEM,
.irq = 98,
.ops = &sci_uart_ops,
- .flags = ASYNC_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 2,
},
.type = PORT_SCI,
.irqs = H8S_SCI_IRQS2,
.init_pins = sci_init_pins_sci,
},
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+ {
+ .port = {
+ .membase = (void *)0xff923000,
+ .mapbase = 0xff923000,
+ .iotype = UPIO_MEM,
+ .irq = 61,
+ .ops = &sci_uart_ops,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 0,
+ },
+ .type = PORT_SCIF,
+ .irqs = SH7770_SCIF0_IRQS,
+ .init_pins = sci_init_pins_scif,
+ },
+ {
+ .port = {
+ .membase = (void *)0xff924000,
+ .mapbase = 0xff924000,
+ .iotype = UPIO_MEM,
+ .irq = 62,
+ .ops = &sci_uart_ops,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 1,
+ },
+ .type = PORT_SCIF,
+ .irqs = SH7770_SCIF1_IRQS,
+ .init_pins = sci_init_pins_scif,
+ },
+ {
+ .port = {
+ .membase = (void *)0xff925000,
+ .mapbase = 0xff925000,
+ .iotype = UPIO_MEM,
+ .irq = 63,
+ .ops = &sci_uart_ops,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 2,
+ },
+ .type = PORT_SCIF,
+ .irqs = SH7770_SCIF2_IRQS,
+ .init_pins = sci_init_pins_scif,
+ },
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+ {
+ .port = {
+ .membase = (void *)0xffe00000,
+ .mapbase = 0xffe00000,
+ .iotype = UPIO_MEM,
+ .irq = 43,
+ .ops = &sci_uart_ops,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 0,
+ },
+ .type = PORT_SCIF,
+ .irqs = SH7780_SCIF0_IRQS,
+ .init_pins = sci_init_pins_scif,
+ },
+ {
+ .port = {
+ .membase = (void *)0xffe10000,
+ .mapbase = 0xffe10000,
+ .iotype = UPIO_MEM,
+ .irq = 79,
+ .ops = &sci_uart_ops,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 1,
+ },
+ .type = PORT_SCIF,
+ .irqs = SH7780_SCIF1_IRQS,
+ .init_pins = sci_init_pins_scif,
+ },
#else
#error "CPU subtype not defined"
#endif
@@ -1480,9 +1560,6 @@ static int __init serial_console_setup(struct console *co, char *options)
int flow = 'n';
int ret;
- if (co->index >= SCI_NPORTS)
- co->index = 0;
-
serial_console_port = &sci_ports[co->index];
port = &serial_console_port->port;
port->type = serial_console_port->type;
@@ -1496,14 +1573,21 @@ static int __init serial_console_setup(struct console *co, char *options)
* We need to set the initial uartclk here, since otherwise it will
* only ever be setup at sci_init() time.
*/
-#if !defined(__H8300H__) && !defined(__H8300S__)
- port->uartclk = current_cpu_data.module_clock * 16;
-#else
+#if defined(__H8300H__) || defined(__H8300S__)
port->uartclk = CONFIG_CPU_CLOCK;
-#endif
+
#if defined(__H8300S__)
h8300_sci_enable(port, sci_enable);
#endif
+#elif defined(CONFIG_SUPERH64)
+ port->uartclk = current_cpu_info.module_clock * 16;
+#else
+ {
+ struct clk *clk = clk_get("module_clk");
+ port->uartclk = clk_get_rate(clk) * 16;
+ clk_put(clk);
+ }
+#endif
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -1566,7 +1650,7 @@ int __init kgdb_console_setup(struct console *co, char *options)
int parity = 'n';
int flow = 'n';
- if (co->index >= SCI_NPORTS || co->index != kgdb_portnum)
+ if (co->index != kgdb_portnum)
co->index = kgdb_portnum;
if (options)
@@ -1606,7 +1690,7 @@ console_initcall(kgdb_console_init);
#elif defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
#define SCI_CONSOLE &serial_console
#else
-#define SCI_CONSOLE 0
+#define SCI_CONSOLE 0
#endif
static char banner[] __initdata =
@@ -1621,7 +1705,6 @@ static struct uart_driver sci_uart_driver = {
.dev_name = "ttySC",
.major = SCI_MAJOR,
.minor = SCI_MINOR_START,
- .nr = SCI_NPORTS,
.cons = SCI_CONSOLE,
};
@@ -1631,15 +1714,21 @@ static int __init sci_init(void)
printk("%s", banner);
+ sci_uart_driver.nr = ARRAY_SIZE(sci_ports);
+
ret = uart_register_driver(&sci_uart_driver);
if (ret == 0) {
for (chan = 0; chan < SCI_NPORTS; chan++) {
struct sci_port *sciport = &sci_ports[chan];
-#if !defined(__H8300H__) && !defined(__H8300S__)
- sciport->port.uartclk = (current_cpu_data.module_clock * 16);
-#else
+#if defined(__H8300H__) || defined(__H8300S__)
sciport->port.uartclk = CONFIG_CPU_CLOCK;
+#elif defined(CONFIG_SUPERH64)
+ sciport->port.uartclk = current_cpu_info.module_clock * 16;
+#else
+ struct clk *clk = clk_get("module_clk");
+ sciport->port.uartclk = clk_get_rate(clk) * 16;
+ clk_put(clk);
#endif
uart_add_one_port(&sci_uart_driver, &sciport->port);
sciport->break_timer.data = (unsigned long)sciport;
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 2892169eff0..1f14bb4382f 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -46,14 +46,17 @@
#define H8S_SCI_IRQS1 {92, 93, 94, 0 }
#define H8S_SCI_IRQS2 {96, 97, 98, 0 }
#define SH5_SCIF_IRQS {39, 40, 42, 0 }
+#define SH7770_SCIF0_IRQS {61, 61, 61, 61 }
+#define SH7770_SCIF1_IRQS {62, 62, 62, 62 }
+#define SH7770_SCIF2_IRQS {63, 63, 63, 63 }
+#define SH7780_SCIF0_IRQS {40, 41, 43, 42 }
+#define SH7780_SCIF1_IRQS {76, 77, 79, 78 }
#if defined(CONFIG_CPU_SUBTYPE_SH7708)
-# define SCI_NPORTS 1
# define SCSPTR 0xffffff7c /* 8 bit */
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
# define SCI_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-# define SCI_NPORTS 3
# define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */
# define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
@@ -61,9 +64,8 @@
#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
# define SCIF0 0xA4400000
# define SCIF2 0xA4410000
-# define SCSMR_Ir 0xA44A0000
-# define IRDA_SCIF SCIF0
-# define SCI_NPORTS 2
+# define SCSMR_Ir 0xA44A0000
+# define IRDA_SCIF SCIF0
# define SCPCR 0xA4000116
# define SCPDR 0xA4000136
@@ -74,14 +76,11 @@
# define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0
# define SCIF_ONLY
#elif defined(CONFIG_SH_RTS7751R2D)
-# define SCI_NPORTS 1
-# define SCSPTR1 0xffe0001c /* 8 bit SCI */
# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
-# define SCI_NPORTS 2
# define SCSPTR1 0xffe0001c /* 8 bit SCI */
# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
@@ -90,34 +89,29 @@
0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ )
# define SCI_AND_SCIF
#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-# define SCI_NPORTS 3
-# define SCSPTR0 0xfe600000 /* 16 bit SCIF */
-# define SCSPTR1 0xfe610000 /* 16 bit SCIF */
-# define SCSPTR2 0xfe620000 /* 16 bit SCIF */
+# define SCSPTR0 0xfe600024 /* 16 bit SCIF */
+# define SCSPTR1 0xfe610024 /* 16 bit SCIF */
+# define SCSPTR2 0xfe620024 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
-# define SCI_NPORTS 1
# define SCPCR 0xA4050116 /* 16 bit SCIF */
# define SCPDR 0xA4050136 /* 16 bit SCIF */
# define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
-# define SCI_NPORTS 1
# define SCPDR 0xA4050138 /* 16 bit SCIF */
# define SCSPTR2 SCPDR
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-# define SCI_NPORTS 1
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-# define SCI_NPORTS 2
# define SCSPTR1 0xffe00020 /* 16 bit SCIF */
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
@@ -129,26 +123,32 @@
# define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
# define SCIF_PTR2_OFFS 0x0000020
# define SCIF_LSR2_OFFS 0x0000024
-# define SCI_NPORTS 1
-# define SCI_INIT { \
- { {}, PORT_SCIF, 0, \
- SH5_SCIF_IRQS, sci_init_pins_scif } \
-}
# define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
# define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,
TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
-# define SCI_NPORTS 3
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
# define SCI_ONLY
# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
#elif defined(CONFIG_H8S2678)
-# define SCI_NPORTS 3
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
# define SCI_ONLY
# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+# define SCSPTR0 0xff923020 /* 16 bit SCIF */
+# define SCSPTR1 0xff924020 /* 16 bit SCIF */
+# define SCSPTR2 0xff925020 /* 16 bit SCIF */
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) 0x3c /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,cke=2 */
+# define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
+# define SCSPTR1 0xffe10024 /* 16 bit SCIF */
+# define SCIF_OPER 0x0001 /* Overrun error bit */
+# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
#else
# error CPU subtype not defined
#endif
@@ -158,7 +158,7 @@
#define SCI_CTRL_FLAGS_RIE 0x40 /* all */
#define SCI_CTRL_FLAGS_TE 0x20 /* all */
#define SCI_CTRL_FLAGS_RE 0x10 /* all */
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
+#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_SH7780)
#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
#else
#define SCI_CTRL_FLAGS_REIE 0
@@ -213,7 +213,7 @@
# define SCxSR_RDxF_CLEAR(port) 0xbc
# define SCxSR_ERROR_CLEAR(port) 0xc4
# define SCxSR_TDxE_CLEAR(port) 0x78
-# define SCxSR_BREAK_CLEAR(port) 0xc4
+# define SCxSR_BREAK_CLEAR(port) 0xc4
#elif defined(SCIF_ONLY)
# define SCxSR_TEND(port) SCIF_TEND
# define SCxSR_ERRORS(port) SCIF_ERRORS
@@ -237,7 +237,7 @@
# define SCxSR_RDxF_CLEAR(port) 0x00fc
# define SCxSR_ERROR_CLEAR(port) 0x0073
# define SCxSR_TDxE_CLEAR(port) 0x00df
-# define SCxSR_BREAK_CLEAR(port) 0x00e3
+# define SCxSR_BREAK_CLEAR(port) 0x00e3
#endif
#else
# define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND)
@@ -285,14 +285,14 @@ struct sci_port {
#define SCI_IN(size, offset) \
unsigned int addr = port->mapbase + (offset); \
- if ((size) == 8) { \
+ if ((size) == 8) { \
return ctrl_inb(addr); \
- } else { \
+ } else { \
return ctrl_inw(addr); \
}
#define SCI_OUT(size, offset, value) \
unsigned int addr = port->mapbase + (offset); \
- if ((size) == 8) { \
+ if ((size) == 8) { \
ctrl_outb(value, addr); \
} else { \
ctrl_outw(value, addr); \
@@ -301,10 +301,10 @@ struct sci_port {
#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
static inline unsigned int sci_##name##_in(struct uart_port *port) \
{ \
- if (port->type == PORT_SCI) { \
+ if (port->type == PORT_SCI) { \
SCI_IN(sci_size, sci_offset) \
} else { \
- SCI_IN(scif_size, scif_offset); \
+ SCI_IN(scif_size, scif_offset); \
} \
} \
static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
@@ -319,7 +319,7 @@ struct sci_port {
#define CPU_SCIF_FNS(name, scif_offset, scif_size) \
static inline unsigned int sci_##name##_in(struct uart_port *port) \
{ \
- SCI_IN(scif_size, scif_offset); \
+ SCI_IN(scif_size, scif_offset); \
} \
static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
{ \
@@ -329,7 +329,7 @@ struct sci_port {
#define CPU_SCI_FNS(name, sci_offset, sci_size) \
static inline unsigned int sci_##name##_in(struct uart_port* port) \
{ \
- SCI_IN(sci_size, sci_offset); \
+ SCI_IN(sci_size, sci_offset); \
} \
static inline void sci_##name##_out(struct uart_port* port, unsigned int value) \
{ \
@@ -385,10 +385,17 @@ SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8, 0x03, 8)
SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8)
SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8)
SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16)
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16)
+SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16)
+SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
+SCIF_FNS(SCLSR, 0, 0, 0x28, 16)
+#else
SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
#endif
+#endif
#define sci_in(port, reg) sci_##reg##_in(port)
#define sci_out(port, reg, value) sci_##reg##_out(port, value)
@@ -518,6 +525,24 @@ static inline int sci_rxd_in(struct uart_port *port)
int ch = (port->mapbase - SMR0) >> 3;
return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ if (port->mapbase == 0xff923000)
+ return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xff924000)
+ return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xff925000)
+ return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ if (port->mapbase == 0xffe00000)
+ return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xffe10000)
+ return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+}
#endif
/*
@@ -552,22 +577,15 @@ static inline int sci_rxd_in(struct uart_port *port)
* -- Mitch Davis - 15 Jul 2000
*/
-#define PCLK (current_cpu_data.module_clock)
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-#define SCBRR_VALUE(bps) ((PCLK+16*bps)/(16*bps)-1)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-#define SCBRR_VALUE(bps) (((PCLK*2)+16*bps)/(32*bps)-1)
-#elif !defined(__H8300H__) && !defined(__H8300S__)
-#define SCBRR_VALUE(bps) ((PCLK+16*bps)/(32*bps)-1)
-#else
+#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
+#elif defined(__H8300H__) || defined(__H8300S__)
#define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1)
+#elif defined(CONFIG_SUPERH64)
+#define SCBRR_VALUE(bps) ((current_cpu_data.module_clock+16*bps)/(32*bps)-1)
+#else /* Generic SH */
+#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
#endif
-#define BPS_2400 SCBRR_VALUE(2400)
-#define BPS_4800 SCBRR_VALUE(4800)
-#define BPS_9600 SCBRR_VALUE(9600)
-#define BPS_19200 SCBRR_VALUE(19200)
-#define BPS_38400 SCBRR_VALUE(38400)
-#define BPS_57600 SCBRR_VALUE(57600)
-#define BPS_115200 SCBRR_VALUE(115200)
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 5468e5a767e..43e67d6c29d 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -6,7 +6,7 @@
* driver for that.
*
*
- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -829,8 +829,8 @@ static int __init sn_sal_module_init(void)
misc.name = DEVICE_NAME_DYNAMIC;
retval = misc_register(&misc);
if (retval != 0) {
- printk
- ("Failed to register console device using misc_register.\n");
+ printk(KERN_WARNING "Failed to register console "
+ "device using misc_register.\n");
return -ENODEV;
}
sal_console_uart.major = MISC_MAJOR;
@@ -942,88 +942,75 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count)
{
unsigned long flags = 0;
struct sn_cons_port *port = &sal_console_port;
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static int stole_lock = 0;
-#endif
BUG_ON(!port->sc_is_asynch);
/* We can't look at the xmit buffer if we're not registered with serial core
* yet. So only do the fancy recovery after registering
*/
- if (port->sc_port.info) {
-
- /* somebody really wants this output, might be an
- * oops, kdb, panic, etc. make sure they get it. */
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
- if (spin_is_locked(&port->sc_port.lock)) {
- int lhead = port->sc_port.info->xmit.head;
- int ltail = port->sc_port.info->xmit.tail;
- int counter, got_lock = 0;
+ if (!port->sc_port.info) {
+ /* Not yet registered with serial core - simple case */
+ puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+ return;
+ }
- /*
- * We attempt to determine if someone has died with the
- * lock. We wait ~20 secs after the head and tail ptrs
- * stop moving and assume the lock holder is not functional
- * and plow ahead. If the lock is freed within the time out
- * period we re-get the lock and go ahead normally. We also
- * remember if we have plowed ahead so that we don't have
- * to wait out the time out period again - the asumption
- * is that we will time out again.
- */
+ /* somebody really wants this output, might be an
+ * oops, kdb, panic, etc. make sure they get it. */
+ if (spin_is_locked(&port->sc_port.lock)) {
+ int lhead = port->sc_port.info->xmit.head;
+ int ltail = port->sc_port.info->xmit.tail;
+ int counter, got_lock = 0;
+
+ /*
+ * We attempt to determine if someone has died with the
+ * lock. We wait ~20 secs after the head and tail ptrs
+ * stop moving and assume the lock holder is not functional
+ * and plow ahead. If the lock is freed within the time out
+ * period we re-get the lock and go ahead normally. We also
+ * remember if we have plowed ahead so that we don't have
+ * to wait out the time out period again - the asumption
+ * is that we will time out again.
+ */
- for (counter = 0; counter < 150; mdelay(125), counter++) {
- if (!spin_is_locked(&port->sc_port.lock)
- || stole_lock) {
- if (!stole_lock) {
- spin_lock_irqsave(&port->
- sc_port.lock,
- flags);
- got_lock = 1;
- }
- break;
- } else {
- /* still locked */
- if ((lhead !=
- port->sc_port.info->xmit.head)
- || (ltail !=
- port->sc_port.info->xmit.
- tail)) {
- lhead =
- port->sc_port.info->xmit.
- head;
- ltail =
- port->sc_port.info->xmit.
- tail;
- counter = 0;
- }
+ for (counter = 0; counter < 150; mdelay(125), counter++) {
+ if (!spin_is_locked(&port->sc_port.lock)
+ || stole_lock) {
+ if (!stole_lock) {
+ spin_lock_irqsave(&port->sc_port.lock,
+ flags);
+ got_lock = 1;
}
- }
- /* flush anything in the serial core xmit buffer, raw */
- sn_transmit_chars(port, 1);
- if (got_lock) {
- spin_unlock_irqrestore(&port->sc_port.lock,
- flags);
- stole_lock = 0;
+ break;
} else {
- /* fell thru */
- stole_lock = 1;
+ /* still locked */
+ if ((lhead != port->sc_port.info->xmit.head)
+ || (ltail !=
+ port->sc_port.info->xmit.tail)) {
+ lhead =
+ port->sc_port.info->xmit.head;
+ ltail =
+ port->sc_port.info->xmit.tail;
+ counter = 0;
+ }
}
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
- } else {
- stole_lock = 0;
-#endif
- spin_lock_irqsave(&port->sc_port.lock, flags);
- sn_transmit_chars(port, 1);
+ }
+ /* flush anything in the serial core xmit buffer, raw */
+ sn_transmit_chars(port, 1);
+ if (got_lock) {
spin_unlock_irqrestore(&port->sc_port.lock, flags);
-
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+ stole_lock = 0;
+ } else {
+ /* fell thru */
+ stole_lock = 1;
}
-#endif
- }
- else {
- /* Not yet registered with serial core - simple case */
+ puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+ } else {
+ stole_lock = 0;
+ spin_lock_irqsave(&port->sc_port.lock, flags);
+ sn_transmit_chars(port, 1);
+ spin_unlock_irqrestore(&port->sc_port.lock, flags);
+
puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
}
}
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index 5fc4a62173d..fa4ae94243c 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -34,6 +34,7 @@ sunserial_console_termios(struct console *con)
char *mode_prop = "ttyX-mode";
char *cd_prop = "ttyX-ignore-cd";
char *dtr_prop = "ttyX-rts-dtr-off";
+ char *ssp_console_modes_prop = "ssp-console-modes";
int baud, bits, stop, cflag;
char parity;
int carrier = 0;
@@ -43,14 +44,39 @@ sunserial_console_termios(struct console *con)
if (!serial_console)
return;
- if (serial_console == 1) {
+ switch (serial_console) {
+ case PROMDEV_OTTYA:
mode_prop[3] = 'a';
cd_prop[3] = 'a';
dtr_prop[3] = 'a';
- } else {
+ break;
+
+ case PROMDEV_OTTYB:
mode_prop[3] = 'b';
cd_prop[3] = 'b';
dtr_prop[3] = 'b';
+ break;
+
+ case PROMDEV_ORSC:
+
+ nd = prom_pathtoinode("rsc");
+ if (!nd) {
+ strcpy(mode, "115200,8,n,1,-");
+ goto no_options;
+ }
+
+ if (!prom_node_has_property(nd, ssp_console_modes_prop)) {
+ strcpy(mode, "115200,8,n,1,-");
+ goto no_options;
+ }
+
+ memset(mode, 0, sizeof(mode));
+ prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode));
+ goto no_options;
+
+ default:
+ strcpy(mode, "9600,8,n,1,-");
+ goto no_options;
}
topnd = prom_getchild(prom_root_node);
@@ -110,6 +136,10 @@ no_options:
case 9600: cflag |= B9600; break;
case 19200: cflag |= B19200; break;
case 38400: cflag |= B38400; break;
+ case 57600: cflag |= B57600; break;
+ case 115200: cflag |= B115200; break;
+ case 230400: cflag |= B230400; break;
+ case 460800: cflag |= B460800; break;
default: baud = 9600; cflag |= B9600; break;
}
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 7e773ff76c6..85664228a0b 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -897,9 +897,6 @@ static int sunsab_console_setup(struct console *con, char *options)
sunserial_console_termios(con);
- /* Firmware console speed is limited to 150-->38400 baud so
- * this hackish cflag thing is OK.
- */
switch (con->cflag & CBAUD) {
case B150: baud = 150; break;
case B300: baud = 300; break;
@@ -910,6 +907,10 @@ static int sunsab_console_setup(struct console *con, char *options)
default: case B9600: baud = 9600; break;
case B19200: baud = 19200; break;
case B38400: baud = 38400; break;
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
};
/*
@@ -1035,7 +1036,7 @@ static void __init sab_attach_callback(struct linux_ebus_device *edev, void *arg
up->port.irq = edev->irqs[0];
up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
up->port.mapbase = (unsigned long)up->regs;
- up->port.iotype = SERIAL_IO_MEM;
+ up->port.iotype = UPIO_MEM;
writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 9a3665b34d9..30870456694 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -109,11 +109,11 @@ static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset)
offset <<= up->port.regshift;
switch (up->port.iotype) {
- case SERIAL_IO_HUB6:
+ case UPIO_HUB6:
outb(up->port.hub6 - 1 + offset, up->port.iobase);
return inb(up->port.iobase + 1);
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
return readb(up->port.membase + offset);
default:
@@ -139,12 +139,12 @@ serial_out(struct uart_sunsu_port *up, int offset, int value)
offset <<= up->port.regshift;
switch (up->port.iotype) {
- case SERIAL_IO_HUB6:
+ case UPIO_HUB6:
outb(up->port.hub6 - 1 + offset, up->port.iobase);
outb(value, up->port.iobase + 1);
break;
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
writeb(value, up->port.membase + offset);
break;
@@ -669,7 +669,7 @@ static int sunsu_startup(struct uart_port *port)
* if it is, then bail out, because there's likely no UART
* here.
*/
- if (!(up->port.flags & ASYNC_BUGGY_UART) &&
+ if (!(up->port.flags & UPF_BUGGY_UART) &&
(serial_inp(up, UART_LSR) == 0xff)) {
printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
return -ENODEV;
@@ -707,7 +707,7 @@ static int sunsu_startup(struct uart_port *port)
up->ier = UART_IER_RLSI | UART_IER_RDI;
serial_outp(up, UART_IER, up->ier);
- if (up->port.flags & ASYNC_FOURPORT) {
+ if (up->port.flags & UPF_FOURPORT) {
unsigned int icp;
/*
* Enable interrupts on the AST Fourport board
@@ -740,7 +740,7 @@ static void sunsu_shutdown(struct uart_port *port)
serial_outp(up, UART_IER, 0);
spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & ASYNC_FOURPORT) {
+ if (up->port.flags & UPF_FOURPORT) {
/* reset interrupts on the AST Fourport board */
inb((up->port.iobase & 0xfe0) | 0x1f);
up->port.mctrl |= TIOCM_OUT1;
@@ -1052,7 +1052,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
return;
up->type_probed = PORT_UNKNOWN;
- up->port.iotype = SERIAL_IO_MEM;
+ up->port.iotype = UPIO_MEM;
/*
* First we look for Ebus-bases su's
@@ -1132,7 +1132,7 @@ ebus_done:
spin_lock_irqsave(&up->port.lock, flags);
- if (!(up->port.flags & ASYNC_BUGGY_UART)) {
+ if (!(up->port.flags & UPF_BUGGY_UART)) {
/*
* Do a simple existence test first; if we fail this, there's
* no point trying anything else.
@@ -1170,7 +1170,7 @@ ebus_done:
* manufacturer would be stupid enough to design a board
* that conflicts with COM 1-4 --- we hope!
*/
- if (!(up->port.flags & ASYNC_SKIP_TEST)) {
+ if (!(up->port.flags & UPF_SKIP_TEST)) {
serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
status1 = serial_inp(up, UART_MSR) & 0xF0;
serial_outp(up, UART_MCR, save_mcr);
@@ -1371,7 +1371,7 @@ static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up)
} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
/* Wait up to 1s for flow control if necessary */
- if (up->port.flags & ASYNC_CONS_FLOW) {
+ if (up->port.flags & UPF_CONS_FLOW) {
tmout = 1000000;
while (--tmout &&
((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
@@ -1513,7 +1513,7 @@ static int __init sunsu_serial_init(void)
up->su_type == SU_PORT_KBD)
continue;
- up->port.flags |= ASYNC_BOOT_AUTOCONF;
+ up->port.flags |= UPF_BOOT_AUTOCONF;
up->port.type = PORT_UNKNOWN;
up->port.uartclk = (SU_BASE_BAUD * 16);
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 3c72484adea..5cc4d4c2935 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1487,7 +1487,7 @@ static void __init sunzilog_prepare(void)
up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB;
/* Channel A */
- up[(chip * 2) + 0].port.iotype = SERIAL_IO_MEM;
+ up[(chip * 2) + 0].port.iotype = UPIO_MEM;
up[(chip * 2) + 0].port.irq = zilog_irq;
up[(chip * 2) + 0].port.uartclk = ZS_CLOCK;
up[(chip * 2) + 0].port.fifosize = 1;
@@ -1498,7 +1498,7 @@ static void __init sunzilog_prepare(void)
up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
/* Channel B */
- up[(chip * 2) + 1].port.iotype = SERIAL_IO_MEM;
+ up[(chip * 2) + 1].port.iotype = UPIO_MEM;
up[(chip * 2) + 1].port.irq = zilog_irq;
up[(chip * 2) + 1].port.uartclk = ZS_CLOCK;
up[(chip * 2) + 1].port.fifosize = 1;
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
index 9378895a8d5..df705fda424 100644
--- a/drivers/serial/v850e_uart.c
+++ b/drivers/serial/v850e_uart.c
@@ -496,7 +496,7 @@ static int __init v850e_uart_init (void)
port->ops = &v850e_uart_ops;
port->line = chan;
- port->iotype = SERIAL_IO_MEM;
+ port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
/* We actually use multiple IRQs, but the serial
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index aaa009f4a7b..12357e1fa55 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -38,10 +38,10 @@ static inline unsigned mcr_pack(unsigned pulse, unsigned sample)
static int nic_wait(struct ioc3_driver_data *idd)
{
- volatile unsigned mcr;
+ unsigned mcr;
do {
- mcr = (volatile unsigned)idd->vma->mcr;
+ mcr = readl(&idd->vma->mcr);
} while (!(mcr & 2));
return mcr & 1;
@@ -53,7 +53,7 @@ static int nic_reset(struct ioc3_driver_data *idd)
unsigned long flags;
local_irq_save(flags);
- idd->vma->mcr = mcr_pack(500, 65);
+ writel(mcr_pack(500, 65), &idd->vma->mcr);
presence = nic_wait(idd);
local_irq_restore(flags);
@@ -68,7 +68,7 @@ static inline int nic_read_bit(struct ioc3_driver_data *idd)
unsigned long flags;
local_irq_save(flags);
- idd->vma->mcr = mcr_pack(6, 13);
+ writel(mcr_pack(6, 13), &idd->vma->mcr);
result = nic_wait(idd);
local_irq_restore(flags);
@@ -80,9 +80,9 @@ static inline int nic_read_bit(struct ioc3_driver_data *idd)
static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit)
{
if (bit)
- idd->vma->mcr = mcr_pack(6, 110);
+ writel(mcr_pack(6, 110), &idd->vma->mcr);
else
- idd->vma->mcr = mcr_pack(80, 30);
+ writel(mcr_pack(80, 30), &idd->vma->mcr);
nic_wait(idd);
}
@@ -337,7 +337,7 @@ static void probe_nic(struct ioc3_driver_data *idd)
int save = 0, loops = 3;
unsigned long first, addr;
- idd->vma->gpcr_s = GPCR_MLAN_EN;
+ writel(GPCR_MLAN_EN, &idd->vma->gpcr_s);
while(loops>0) {
idd->nic_part[0] = 0;
@@ -408,7 +408,7 @@ static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs)
read_lock_irqsave(&ioc3_submodules_lock, flags);
- if(idd->dual_irq && idd->vma->eisr) {
+ if(idd->dual_irq && readb(&idd->vma->eisr)) {
/* send Ethernet IRQ to the driver */
if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
ioc3_ethernet->intr) {
@@ -682,7 +682,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
idd->id = ioc3_counter++;
up_write(&ioc3_devices_rwsem);
- idd->gpdr_shadow = idd->vma->gpdr;
+ idd->gpdr_shadow = readl(&idd->vma->gpdr);
/* Read IOC3 NIC contents */
probe_nic(idd);
@@ -843,9 +843,9 @@ MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>");
MODULE_DESCRIPTION("PCI driver for SGI IOC3");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(ioc3_register_submodule);
-EXPORT_SYMBOL(ioc3_unregister_submodule);
-EXPORT_SYMBOL(ioc3_ack);
-EXPORT_SYMBOL(ioc3_gpcr_set);
-EXPORT_SYMBOL(ioc3_disable);
-EXPORT_SYMBOL(ioc3_enable);
+EXPORT_SYMBOL_GPL(ioc3_register_submodule);
+EXPORT_SYMBOL_GPL(ioc3_unregister_submodule);
+EXPORT_SYMBOL_GPL(ioc3_ack);
+EXPORT_SYMBOL_GPL(ioc3_gpcr_set);
+EXPORT_SYMBOL_GPL(ioc3_disable);
+EXPORT_SYMBOL_GPL(ioc3_enable);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b77dbd63e59..7a75faeb052 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -75,16 +75,6 @@ config SPI_BUTTERFLY
inexpensive battery powered microcontroller evaluation board.
This same cable can be used to flash new firmware.
-config SPI_BUTTERFLY
- tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
- depends on SPI_MASTER && PARPORT && EXPERIMENTAL
- select SPI_BITBANG
- help
- This uses a custom parallel port cable to connect to an AVR
- Butterfly <http://www.atmel.com/products/avr/butterfly>, an
- inexpensive battery powered microcontroller evaluation board.
- This same cable can be used to flash new firmware.
-
#
# Add new SPI master controllers in alphabetical order above this line
#
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 791c4dc550a..94f5e8ed83a 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -90,7 +90,7 @@ static int spi_suspend(struct device *dev, pm_message_t message)
int value;
struct spi_driver *drv = to_spi_driver(dev->driver);
- if (!drv->suspend)
+ if (!drv || !drv->suspend)
return 0;
/* suspend will stop irqs and dma; no more i/o */
@@ -105,7 +105,7 @@ static int spi_resume(struct device *dev)
int value;
struct spi_driver *drv = to_spi_driver(dev->driver);
- if (!drv->resume)
+ if (!drv || !drv->resume)
return 0;
/* resume may restart the i/o queue */
@@ -449,7 +449,6 @@ void spi_unregister_master(struct spi_master *master)
{
(void) device_for_each_child(master->cdev.dev, NULL, __unregister);
class_device_unregister(&master->cdev);
- master->cdev.dev = NULL;
}
EXPORT_SYMBOL_GPL(spi_unregister_master);
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
index 79a3c59615a..ff9e5faa4dc 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi_butterfly.c
@@ -163,21 +163,20 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
struct butterfly *pp = spidev_to_pp(spi);
/* set default clock polarity */
- if (value)
+ if (value != BITBANG_CS_INACTIVE)
setsck(spi, spi->mode & SPI_CPOL);
/* no chipselect on this USI link config */
if (is_usidev(spi))
return;
- /* here, value == "activate or not" */
-
- /* most PARPORT_CONTROL_* bits are negated */
+ /* here, value == "activate or not";
+ * most PARPORT_CONTROL_* bits are negated, so we must
+ * morph it to value == "bit value to write in control register"
+ */
if (spi_cs_bit == PARPORT_CONTROL_INIT)
value = !value;
- /* here, value == "bit value to write in control register" */
-
parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
}
@@ -202,7 +201,9 @@ butterfly_txrx_word_mode0(struct spi_device *spi,
/* override default partitioning with cmdlinepart */
static struct mtd_partition partitions[] = { {
- /* JFFS2 wants partitions of 4*N blocks for this device ... */
+ /* JFFS2 wants partitions of 4*N blocks for this device,
+ * so sectors 0 and 1 can't be partitions by themselves.
+ */
/* sector 0 = 8 pages * 264 bytes/page (1 block)
* sector 1 = 248 pages * 264 bytes/page
@@ -316,8 +317,9 @@ static void butterfly_attach(struct parport *p)
if (status < 0)
goto clean2;
- /* Bus 1 lets us talk to at45db041b (firmware disables AVR)
- * or AVR (firmware resets at45, acts as spi slave)
+ /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
+ * (firmware resets at45, acts as spi slave) or neither (we ignore
+ * both, AVR uses AT45). Here we expect firmware for the first option.
*/
pp->info[0].max_speed_hz = 15 * 1000 * 1000;
strcpy(pp->info[0].modalias, "mtd_dataflash");
@@ -330,7 +332,9 @@ static void butterfly_attach(struct parport *p)
pp->dataflash->dev.bus_id);
#ifdef HAVE_USI
- /* even more custom AVR firmware */
+ /* Bus 2 is only for talking to the AVR, and it can work no
+ * matter who masters bus 1; needs appropriate AVR firmware.
+ */
pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
strcpy(pp->info[1].modalias, "butterfly");
// pp->info[1].platform_data = ... TBD ... ;
@@ -378,13 +382,8 @@ static void butterfly_detach(struct parport *p)
pp = butterfly;
butterfly = NULL;
-#ifdef HAVE_USI
- spi_unregister_device(pp->butterfly);
- pp->butterfly = NULL;
-#endif
- spi_unregister_device(pp->dataflash);
- pp->dataflash = NULL;
-
+ /* stop() unregisters child devices too */
+ pdev = to_platform_device(pp->bitbang.master->cdev.dev);
status = spi_bitbang_stop(&pp->bitbang);
/* turn off VCC */
@@ -394,8 +393,6 @@ static void butterfly_detach(struct parport *p)
parport_release(pp->pd);
parport_unregister_device(pp->pd);
- pdev = to_platform_device(pp->bitbang.master->cdev.dev);
-
(void) spi_master_put(pp->bitbang.master);
platform_device_unregister(pdev);
@@ -420,4 +417,5 @@ static void __exit butterfly_exit(void)
}
module_exit(butterfly_exit);
+MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
MODULE_LICENSE("GPL");
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c
index a0e5af638e0..4a51e56f85b 100644
--- a/drivers/tc/tc.c
+++ b/drivers/tc/tc.c
@@ -17,7 +17,6 @@
#include <linux/types.h>
#include <asm/addrspace.h>
-#include <asm/bug.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/paccess.h>
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index f6704688ee8..5578a9dd04e 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -3558,10 +3558,16 @@ static void ixj_write_frame(IXJ *j)
}
/* Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG */
if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) {
- if(j->write_buffer_rp + cnt == 0 && j->write_buffer_rp + cnt + 1 == 0 && j->write_buffer_rp + cnt + 2 == 0 &&
- j->write_buffer_rp + cnt + 3 == 0 && j->write_buffer_rp + cnt + 4 == 0 && j->write_buffer_rp + cnt + 5 == 0 &&
- j->write_buffer_rp + cnt + 6 == 0 && j->write_buffer_rp + cnt + 7 == 0 && j->write_buffer_rp + cnt + 8 == 0 &&
- j->write_buffer_rp + cnt + 9 == 0) {
+ if (j->write_buffer_rp[cnt] == 0 &&
+ j->write_buffer_rp[cnt + 1] == 0 &&
+ j->write_buffer_rp[cnt + 2] == 0 &&
+ j->write_buffer_rp[cnt + 3] == 0 &&
+ j->write_buffer_rp[cnt + 4] == 0 &&
+ j->write_buffer_rp[cnt + 5] == 0 &&
+ j->write_buffer_rp[cnt + 6] == 0 &&
+ j->write_buffer_rp[cnt + 7] == 0 &&
+ j->write_buffer_rp[cnt + 8] == 0 &&
+ j->write_buffer_rp[cnt + 9] == 0) {
/* someone is trying to write silence lets make this a type 0 frame. */
outb_p(0x00, j->DSPbase + 0x0C);
outb_p(0x00, j->DSPbase + 0x0D);
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 3639c3f8d35..36e476dd912 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_USB_XPAD) += input/
obj-$(CONFIG_USB_DABUSB) += media/
obj-$(CONFIG_USB_DSBR) += media/
+obj-$(CONFIG_USB_ET61X251) += media/
obj-$(CONFIG_USB_IBMCAM) += media/
obj-$(CONFIG_USB_KONICAWC) += media/
obj-$(CONFIG_USB_OV511) += media/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index af0a41e7870..04631dcbabb 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/device.h> /* FIXME: linux/firmware.h should include it itself */
#include <linux/firmware.h>
+#include <linux/mutex.h>
#include "usbatm.h"
@@ -160,7 +161,7 @@ struct cxacru_data {
struct work_struct poll_work;
/* contol handles */
- struct semaphore cm_serialize;
+ struct mutex cm_serialize;
u8 *rcv_buf;
u8 *snd_buf;
struct urb *rcv_urb;
@@ -219,7 +220,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
goto fail;
}
- down(&instance->cm_serialize);
+ mutex_lock(&instance->cm_serialize);
/* submit reading urb before the writing one */
init_completion(&instance->rcv_done);
@@ -288,7 +289,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
ret = offd;
dbg("cm %#x", cm);
fail:
- up(&instance->cm_serialize);
+ mutex_unlock(&instance->cm_serialize);
return ret;
}
@@ -352,7 +353,6 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev)
{
struct cxacru_data *instance = usbatm_instance->driver_data;
- struct device *dev = &usbatm_instance->usb_intf->dev;
/*
struct atm_dev *atm_dev = usbatm_instance->atm_dev;
*/
@@ -364,14 +364,14 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0,
atm_dev->esi, sizeof(atm_dev->esi));
if (ret < 0) {
- dev_err(dev, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
+ atm_err(usbatm_instance, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
return ret;
}
/* start ADSL */
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
if (ret < 0) {
- dev_err(dev, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
+ atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
return ret;
}
@@ -383,13 +383,13 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
static void cxacru_poll_status(struct cxacru_data *instance)
{
u32 buf[CXINF_MAX] = {};
- struct device *dev = &instance->usbatm->usb_intf->dev;
- struct atm_dev *atm_dev = instance->usbatm->atm_dev;
+ struct usbatm_data *usbatm = instance->usbatm;
+ struct atm_dev *atm_dev = usbatm->atm_dev;
int ret;
ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX);
if (ret < 0) {
- dev_warn(dev, "poll status: error %d\n", ret);
+ atm_warn(usbatm, "poll status: error %d\n", ret);
goto reschedule;
}
@@ -400,50 +400,50 @@ static void cxacru_poll_status(struct cxacru_data *instance)
switch (instance->line_status) {
case 0:
atm_dev->signal = ATM_PHY_SIG_LOST;
- dev_info(dev, "ADSL line: down\n");
+ atm_info(usbatm, "ADSL line: down\n");
break;
case 1:
atm_dev->signal = ATM_PHY_SIG_LOST;
- dev_info(dev, "ADSL line: attemtping to activate\n");
+ atm_info(usbatm, "ADSL line: attempting to activate\n");
break;
case 2:
atm_dev->signal = ATM_PHY_SIG_LOST;
- dev_info(dev, "ADSL line: training\n");
+ atm_info(usbatm, "ADSL line: training\n");
break;
case 3:
atm_dev->signal = ATM_PHY_SIG_LOST;
- dev_info(dev, "ADSL line: channel analysis\n");
+ atm_info(usbatm, "ADSL line: channel analysis\n");
break;
case 4:
atm_dev->signal = ATM_PHY_SIG_LOST;
- dev_info(dev, "ADSL line: exchange\n");
+ atm_info(usbatm, "ADSL line: exchange\n");
break;
case 5:
atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424;
atm_dev->signal = ATM_PHY_SIG_FOUND;
- dev_info(dev, "ADSL line: up (%d kb/s down | %d kb/s up)\n",
+ atm_info(usbatm, "ADSL line: up (%d kb/s down | %d kb/s up)\n",
buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]);
break;
case 6:
atm_dev->signal = ATM_PHY_SIG_LOST;
- dev_info(dev, "ADSL line: waiting\n");
+ atm_info(usbatm, "ADSL line: waiting\n");
break;
case 7:
atm_dev->signal = ATM_PHY_SIG_LOST;
- dev_info(dev, "ADSL line: initializing\n");
+ atm_info(usbatm, "ADSL line: initializing\n");
break;
default:
atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
- dev_info(dev, "Unknown line state %02x\n", instance->line_status);
+ atm_info(usbatm, "Unknown line state %02x\n", instance->line_status);
break;
}
reschedule:
@@ -504,8 +504,8 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
{
int ret;
int off;
- struct usb_device *usb_dev = instance->usbatm->usb_dev;
- struct device *dev = &instance->usbatm->usb_intf->dev;
+ struct usbatm_data *usbatm = instance->usbatm;
+ struct usb_device *usb_dev = usbatm->usb_dev;
u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct };
u32 val;
@@ -515,7 +515,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
val = cpu_to_le32(instance->modem_type->pll_f_clk);
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
if (ret) {
- dev_err(dev, "FirmwarePllFClkValue failed: %d\n", ret);
+ usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret);
return;
}
@@ -523,7 +523,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
val = cpu_to_le32(instance->modem_type->pll_b_clk);
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
if (ret) {
- dev_err(dev, "FirmwarePllBClkValue failed: %d\n", ret);
+ usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret);
return;
}
@@ -531,14 +531,14 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
val = cpu_to_le32(SDRAM_ENA);
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
if (ret) {
- dev_err(dev, "Enable SDRAM failed: %d\n", ret);
+ usb_err(usbatm, "Enable SDRAM failed: %d\n", ret);
return;
}
/* Firmware */
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
if (ret) {
- dev_err(dev, "Firmware upload failed: %d\n", ret);
+ usb_err(usbatm, "Firmware upload failed: %d\n", ret);
return;
}
@@ -546,7 +546,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
if (instance->modem_type->boot_rom_patch) {
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
if (ret) {
- dev_err(dev, "Boot ROM patching failed: %d\n", ret);
+ usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
return;
}
}
@@ -554,7 +554,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
/* Signature */
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);
if (ret) {
- dev_err(dev, "Signature storing failed: %d\n", ret);
+ usb_err(usbatm, "Signature storing failed: %d\n", ret);
return;
}
@@ -566,7 +566,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
}
if (ret) {
- dev_err(dev, "Passing control to firmware failed: %d\n", ret);
+ usb_err(usbatm, "Passing control to firmware failed: %d\n", ret);
return;
}
@@ -580,7 +580,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
if (ret < 0) {
- dev_err(dev, "modem failed to initialize: %d\n", ret);
+ usb_err(usbatm, "modem failed to initialize: %d\n", ret);
return;
}
@@ -597,7 +597,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,
(u8 *) buf, len, NULL, 0);
if (ret < 0) {
- dev_err(dev, "load config data failed: %d\n", ret);
+ usb_err(usbatm, "load config data failed: %d\n", ret);
return;
}
}
@@ -608,18 +608,19 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
static int cxacru_find_firmware(struct cxacru_data *instance,
char* phase, const struct firmware **fw_p)
{
- struct device *dev = &instance->usbatm->usb_intf->dev;
+ struct usbatm_data *usbatm = instance->usbatm;
+ struct device *dev = &usbatm->usb_intf->dev;
char buf[16];
sprintf(buf, "cxacru-%s.bin", phase);
dbg("cxacru_find_firmware: looking for %s", buf);
if (request_firmware(fw_p, buf, dev)) {
- dev_dbg(dev, "no stage %s firmware found\n", phase);
+ usb_dbg(usbatm, "no stage %s firmware found\n", phase);
return -ENOENT;
}
- dev_info(dev, "found firmware %s\n", buf);
+ usb_info(usbatm, "found firmware %s\n", buf);
return 0;
}
@@ -627,20 +628,19 @@ static int cxacru_find_firmware(struct cxacru_data *instance,
static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
struct usb_interface *usb_intf)
{
- struct device *dev = &usbatm_instance->usb_intf->dev;
const struct firmware *fw, *bp, *cf;
struct cxacru_data *instance = usbatm_instance->driver_data;
int ret = cxacru_find_firmware(instance, "fw", &fw);
if (ret) {
- dev_warn(dev, "firmware (cxacru-fw.bin) unavailable (hotplug misconfiguration?)\n");
+ usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
return ret;
}
if (instance->modem_type->boot_rom_patch) {
ret = cxacru_find_firmware(instance, "bp", &bp);
if (ret) {
- dev_warn(dev, "boot ROM patch (cxacru-bp.bin) unavailable (hotplug misconfiguration?)\n");
+ usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n");
release_firmware(fw);
return ret;
}
@@ -667,22 +667,19 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
}
static int cxacru_bind(struct usbatm_data *usbatm_instance,
- struct usb_interface *intf, const struct usb_device_id *id,
- int *need_heavy_init)
+ struct usb_interface *intf, const struct usb_device_id *id)
{
struct cxacru_data *instance;
struct usb_device *usb_dev = interface_to_usbdev(intf);
int ret;
/* instance init */
- instance = kmalloc(sizeof(*instance), GFP_KERNEL);
+ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
if (!instance) {
dbg("cxacru_bind: no memory for instance data");
return -ENOMEM;
}
- memset(instance, 0, sizeof(*instance));
-
instance->usbatm = usbatm_instance;
instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
@@ -721,13 +718,13 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
instance->snd_buf, PAGE_SIZE,
cxacru_blocking_completion, &instance->snd_done, 4);
- init_MUTEX(&instance->cm_serialize);
+ mutex_init(&instance->cm_serialize);
INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance);
usbatm_instance->driver_data = instance;
- *need_heavy_init = cxacru_card_status(instance);
+ usbatm_instance->flags = (cxacru_card_status(instance) ? 0 : UDSL_SKIP_HEAVY_INIT);
return 0;
@@ -787,12 +784,12 @@ static const struct usb_device_id cxacru_usb_ids[] = {
{ /* V = Conexant P = ADSL modem (Hasbani project) */
USB_DEVICE(0x0572, 0xcb00), .driver_info = (unsigned long) &cxacru_cb00
},
- { /* V = Conexant P = ADSL modem (Well PTI-800 */
- USB_DEVICE(0x0572, 0xcb02), .driver_info = (unsigned long) &cxacru_cb00
- },
{ /* V = Conexant P = ADSL modem */
USB_DEVICE(0x0572, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00
},
+ { /* V = Conexant P = ADSL modem (Well PTI-800) */
+ USB_DEVICE(0x0572, 0xcb02), .driver_info = (unsigned long) &cxacru_cb00
+ },
{ /* V = Conexant P = ADSL modem */
USB_DEVICE(0x0572, 0xcb06), .driver_info = (unsigned long) &cxacru_cb00
},
@@ -835,14 +832,13 @@ static const struct usb_device_id cxacru_usb_ids[] = {
MODULE_DEVICE_TABLE(usb, cxacru_usb_ids);
static struct usbatm_driver cxacru_driver = {
- .owner = THIS_MODULE,
.driver_name = cxacru_driver_name,
.bind = cxacru_bind,
.heavy_init = cxacru_heavy_init,
.unbind = cxacru_unbind,
.atm_start = cxacru_atm_start,
- .in = CXACRU_EP_DATA,
- .out = CXACRU_EP_DATA,
+ .bulk_in = CXACRU_EP_DATA,
+ .bulk_out = CXACRU_EP_DATA,
.rx_padding = 3,
.tx_padding = 11,
};
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index c1b47d74e20..7860c8a5800 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -35,12 +35,14 @@
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/usb_ch9.h>
#include <linux/workqueue.h>
#include "usbatm.h"
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
-#define DRIVER_VERSION "1.9"
+#define DRIVER_VERSION "1.10"
#define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION
static const char speedtch_driver_name[] = "speedtch";
@@ -66,31 +68,42 @@ static const char speedtch_driver_name[] = "speedtch";
#define RESUBMIT_DELAY 1000 /* milliseconds */
-#define DEFAULT_ALTSETTING 1
+#define DEFAULT_BULK_ALTSETTING 1
+#define DEFAULT_ISOC_ALTSETTING 2
#define DEFAULT_DL_512_FIRST 0
+#define DEFAULT_ENABLE_ISOC 0
#define DEFAULT_SW_BUFFERING 0
-static int altsetting = DEFAULT_ALTSETTING;
+static unsigned int altsetting = 0; /* zero means: use the default */
static int dl_512_first = DEFAULT_DL_512_FIRST;
+static int enable_isoc = DEFAULT_ENABLE_ISOC;
static int sw_buffering = DEFAULT_SW_BUFFERING;
-module_param(altsetting, int, S_IRUGO | S_IWUSR);
+module_param(altsetting, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(altsetting,
- "Alternative setting for data interface (default: "
- __MODULE_STRING(DEFAULT_ALTSETTING) ")");
+ "Alternative setting for data interface (bulk_default: "
+ __MODULE_STRING(DEFAULT_BULK_ALTSETTING) "; isoc_default: "
+ __MODULE_STRING(DEFAULT_ISOC_ALTSETTING) ")");
module_param(dl_512_first, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(dl_512_first,
"Read 512 bytes before sending firmware (default: "
__MODULE_STRING(DEFAULT_DL_512_FIRST) ")");
+module_param(enable_isoc, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_isoc,
+ "Use isochronous transfers if available (default: "
+ __MODULE_STRING(DEFAULT_ENABLE_ISOC) ")");
+
module_param(sw_buffering, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(sw_buffering,
"Enable software buffering (default: "
__MODULE_STRING(DEFAULT_SW_BUFFERING) ")");
+#define INTERFACE_DATA 1
#define ENDPOINT_INT 0x81
-#define ENDPOINT_DATA 0x07
+#define ENDPOINT_BULK_DATA 0x07
+#define ENDPOINT_ISOC_DATA 0x07
#define ENDPOINT_FIRMWARE 0x05
#define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) )
@@ -98,6 +111,8 @@ MODULE_PARM_DESC(sw_buffering,
struct speedtch_instance_data {
struct usbatm_data *usbatm;
+ unsigned int altsetting;
+
struct work_struct status_checker;
unsigned char last_status;
@@ -205,7 +220,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
buffer, 0x200, &actual_length, 2000);
if (ret < 0 && ret != -ETIMEDOUT)
- usb_dbg(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret);
+ usb_warn(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret);
else
usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret);
}
@@ -219,7 +234,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
buffer, thislen, &actual_length, DATA_TIMEOUT);
if (ret < 0) {
- usb_dbg(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret);
+ usb_err(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret);
goto out_free;
}
usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size);
@@ -232,7 +247,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
buffer, 0x200, &actual_length, DATA_TIMEOUT);
if (ret < 0) {
- usb_dbg(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret);
+ usb_err(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret);
goto out_free;
}
usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length);
@@ -246,7 +261,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
buffer, thislen, &actual_length, DATA_TIMEOUT);
if (ret < 0) {
- usb_dbg(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret);
+ usb_err(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret);
goto out_free;
}
}
@@ -259,7 +274,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
buffer, 0x200, &actual_length, DATA_TIMEOUT);
if (ret < 0) {
- usb_dbg(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret);
+ usb_err(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret);
goto out_free;
}
@@ -270,6 +285,11 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
because we're in our own kernel thread anyway. */
msleep_interruptible(1000);
+ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
+ usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret);
+ goto out_free;
+ }
+
/* Enable software buffering, if requested */
if (sw_buffering)
speedtch_set_swbuff(instance, 1);
@@ -285,8 +305,8 @@ out:
return ret;
}
-static int speedtch_find_firmware(struct usb_interface *intf, int phase,
- const struct firmware **fw_p)
+static int speedtch_find_firmware(struct usbatm_data *usbatm, struct usb_interface *intf,
+ int phase, const struct firmware **fw_p)
{
struct device *dev = &intf->dev;
const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice);
@@ -295,24 +315,24 @@ static int speedtch_find_firmware(struct usb_interface *intf, int phase,
char buf[24];
sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision);
- dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
+ usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
if (request_firmware(fw_p, buf, dev)) {
sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision);
- dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
+ usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
if (request_firmware(fw_p, buf, dev)) {
sprintf(buf, "speedtch-%d.bin", phase);
- dev_dbg(dev, "%s: looking for %s\n", __func__, buf);
+ usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);
if (request_firmware(fw_p, buf, dev)) {
- dev_warn(dev, "no stage %d firmware found!\n", phase);
+ usb_err(usbatm, "%s: no stage %d firmware found!\n", __func__, phase);
return -ENOENT;
}
}
}
- dev_info(dev, "found stage %d firmware %s\n", phase, buf);
+ usb_info(usbatm, "found stage %d firmware %s\n", phase, buf);
return 0;
}
@@ -323,15 +343,16 @@ static int speedtch_heavy_init(struct usbatm_data *usbatm, struct usb_interface
struct speedtch_instance_data *instance = usbatm->driver_data;
int ret;
- if ((ret = speedtch_find_firmware(intf, 1, &fw1)) < 0)
- return ret;
+ if ((ret = speedtch_find_firmware(usbatm, intf, 1, &fw1)) < 0)
+ return ret;
- if ((ret = speedtch_find_firmware(intf, 2, &fw2)) < 0) {
+ if ((ret = speedtch_find_firmware(usbatm, intf, 2, &fw2)) < 0) {
release_firmware(fw1);
return ret;
}
- ret = speedtch_upload_firmware(instance, fw1, fw2);
+ if ((ret = speedtch_upload_firmware(instance, fw1, fw2)) < 0)
+ usb_err(usbatm, "%s: firmware upload failed (%d)!\n", __func__, ret);
release_firmware(fw2);
release_firmware(fw1);
@@ -428,7 +449,9 @@ static void speedtch_check_status(struct speedtch_instance_data *instance)
int down_speed, up_speed, ret;
unsigned char status;
+#ifdef VERBOSE_DEBUG
atm_dbg(usbatm, "%s entered\n", __func__);
+#endif
ret = speedtch_read_status(instance);
if (ret < 0) {
@@ -441,9 +464,9 @@ static void speedtch_check_status(struct speedtch_instance_data *instance)
status = buf[OFFSET_7];
- atm_dbg(usbatm, "%s: line state %02x\n", __func__, status);
-
if ((status != instance->last_status) || !status) {
+ atm_dbg(usbatm, "%s: line state 0x%02x\n", __func__, status);
+
switch (status) {
case 0:
atm_dev->signal = ATM_PHY_SIG_LOST;
@@ -484,7 +507,7 @@ static void speedtch_check_status(struct speedtch_instance_data *instance)
default:
atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
- atm_info(usbatm, "Unknown line state %02x\n", status);
+ atm_info(usbatm, "unknown line state %02x\n", status);
break;
}
@@ -583,11 +606,6 @@ static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_de
atm_dbg(usbatm, "%s entered\n", __func__);
- if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) {
- atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret);
- return ret;
- }
-
/* Set MAC address, it is stored in the serial number */
memset(atm_dev->esi, 0, sizeof(atm_dev->esi));
if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) {
@@ -678,20 +696,27 @@ static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_inte
static int speedtch_bind(struct usbatm_data *usbatm,
struct usb_interface *intf,
- const struct usb_device_id *id,
- int *need_heavy_init)
+ const struct usb_device_id *id)
{
struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct usb_interface *cur_intf;
+ struct usb_interface *cur_intf, *data_intf;
struct speedtch_instance_data *instance;
int ifnum = intf->altsetting->desc.bInterfaceNumber;
int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces;
int i, ret;
+ int use_isoc;
usb_dbg(usbatm, "%s entered\n", __func__);
+ /* sanity checks */
+
if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
- usb_dbg(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass);
+ usb_err(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass);
+ return -ENODEV;
+ }
+
+ if (!(data_intf = usb_ifnum_to_if(usb_dev, INTERFACE_DATA))) {
+ usb_err(usbatm, "%s: data interface not found!\n", __func__);
return -ENODEV;
}
@@ -704,25 +729,71 @@ static int speedtch_bind(struct usbatm_data *usbatm,
ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm);
if (ret < 0) {
- usb_dbg(usbatm, "%s: failed to claim interface %d (%d)\n", __func__, i, ret);
+ usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, i, ret);
speedtch_release_interfaces(usb_dev, i);
return ret;
}
}
}
- instance = kmalloc(sizeof(*instance), GFP_KERNEL);
+ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
if (!instance) {
- usb_dbg(usbatm, "%s: no memory for instance data!\n", __func__);
+ usb_err(usbatm, "%s: no memory for instance data!\n", __func__);
ret = -ENOMEM;
goto fail_release;
}
- memset(instance, 0, sizeof(struct speedtch_instance_data));
-
instance->usbatm = usbatm;
+ /* altsetting and enable_isoc may change at any moment, so take a snapshot */
+ instance->altsetting = altsetting;
+ use_isoc = enable_isoc;
+
+ if (instance->altsetting)
+ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
+ usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret);
+ instance->altsetting = 0; /* fall back to default */
+ }
+
+ if (!instance->altsetting && use_isoc)
+ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) {
+ usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret);
+ use_isoc = 0; /* fall back to bulk */
+ }
+
+ if (use_isoc) {
+ const struct usb_host_interface *desc = data_intf->cur_altsetting;
+ const __u8 target_address = USB_DIR_IN | usbatm->driver->isoc_in;
+ int i;
+
+ use_isoc = 0; /* fall back to bulk if endpoint not found */
+
+ for (i=0; i<desc->desc.bNumEndpoints; i++) {
+ const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
+
+ if ((endpoint_desc->bEndpointAddress == target_address)) {
+ use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_ISOC;
+ break;
+ }
+ }
+
+ if (!use_isoc)
+ usb_info(usbatm, "isochronous transfer not supported - using bulk\n");
+ }
+
+ if (!use_isoc && !instance->altsetting)
+ if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) {
+ usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret);
+ goto fail_free;
+ }
+
+ if (!instance->altsetting)
+ instance->altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING;
+
+ usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
+
INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
instance->status_checker.timer.function = speedtch_status_poll;
@@ -749,13 +820,15 @@ static int speedtch_bind(struct usbatm_data *usbatm,
0x12, 0xc0, 0x07, 0x00,
instance->scratch_buffer + OFFSET_7, SIZE_7, 500);
- *need_heavy_init = (ret != SIZE_7);
+ usbatm->flags |= (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0);
- usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already");
+ usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, usbatm->flags & UDSL_SKIP_HEAVY_INIT ? "already" : "not");
- if (*need_heavy_init)
- if ((ret = usb_reset_device(usb_dev)) < 0)
+ if (!(usbatm->flags & UDSL_SKIP_HEAVY_INIT))
+ if ((ret = usb_reset_device(usb_dev)) < 0) {
+ usb_err(usbatm, "%s: device reset failed (%d)!\n", __func__, ret);
goto fail_free;
+ }
usbatm->driver_data = instance;
@@ -787,15 +860,15 @@ static void speedtch_unbind(struct usbatm_data *usbatm, struct usb_interface *in
***********/
static struct usbatm_driver speedtch_usbatm_driver = {
- .owner = THIS_MODULE,
.driver_name = speedtch_driver_name,
.bind = speedtch_bind,
.heavy_init = speedtch_heavy_init,
.unbind = speedtch_unbind,
.atm_start = speedtch_atm_start,
.atm_stop = speedtch_atm_stop,
- .in = ENDPOINT_DATA,
- .out = ENDPOINT_DATA
+ .bulk_in = ENDPOINT_BULK_DATA,
+ .bulk_out = ENDPOINT_BULK_DATA,
+ .isoc_in = ENDPOINT_ISOC_DATA
};
static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 7d2a679989e..830d2c98267 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -63,11 +63,12 @@
#include <linux/ctype.h>
#include <linux/kthread.h>
#include <linux/version.h>
+#include <linux/mutex.h>
#include <asm/unaligned.h>
#include "usbatm.h"
-#define EAGLEUSBVERSION "ueagle 1.1"
+#define EAGLEUSBVERSION "ueagle 1.2"
/*
@@ -358,16 +359,19 @@ struct intr_pkt {
#define INTR_PKT_SIZE 28
static struct usb_driver uea_driver;
-static DECLARE_MUTEX(uea_semaphore);
+static DEFINE_MUTEX(uea_mutex);
static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"};
static int modem_index;
static unsigned int debug;
+static int use_iso[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = 1};
static int sync_wait[NB_MODEM];
static char *cmv_file[NB_MODEM];
module_param(debug, uint, 0644);
MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)");
+module_param_array(use_iso, bool, NULL, 0644);
+MODULE_PARM_DESC(use_iso, "use isochronous usb pipe for incoming traffic");
module_param_array(sync_wait, bool, NULL, 0644);
MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM");
module_param_array(cmv_file, charp, NULL, 0644);
@@ -628,8 +632,7 @@ static int request_dsp(struct uea_softc *sc)
dsp_name = FW_DIR "DSPep.bin";
}
- ret = request_firmware(&sc->dsp_firm,
- dsp_name, &sc->usb_dev->dev);
+ ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev);
if (ret < 0) {
uea_err(INS_TO_USBDEV(sc),
"requesting firmware %s failed with error %d\n",
@@ -744,7 +747,6 @@ static inline int wait_cmv_ack(struct uea_softc *sc)
return ret;
return (ret == 0) ? -ETIMEDOUT : 0;
-
}
#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
@@ -935,6 +937,7 @@ static int uea_stat(struct uea_softc *sc)
* ADI930 don't support it (-EPIPE error).
*/
if (UEA_CHIP_VERSION(sc) != ADI930
+ && !use_iso[sc->modem_index]
&& sc->stats.phy.dsrate != (data >> 16) * 32) {
/* Original timming from ADI(used in windows driver)
* 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits
@@ -1010,7 +1013,7 @@ static int request_cmvs(struct uea_softc *sc,
int ret, size;
u8 *data;
char *file;
- static char cmv_name[256] = FW_DIR;
+ char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */
if (cmv_file[sc->modem_index] == NULL) {
if (UEA_CHIP_VERSION(sc) == ADI930)
@@ -1184,8 +1187,7 @@ static int load_XILINX_firmware(struct uea_softc *sc)
}
}
- /* finish to send the fpga
- */
+ /* finish to send the fpga */
ret = uea_request(sc, 0xe, 1, 0, NULL);
if (ret < 0) {
uea_err(INS_TO_USBDEV(sc),
@@ -1193,9 +1195,7 @@ static int load_XILINX_firmware(struct uea_softc *sc)
goto err1;
}
- /*
- * Tell the modem we finish : de-assert reset
- */
+ /* Tell the modem we finish : de-assert reset */
value = 0;
ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
if (ret < 0)
@@ -1209,6 +1209,7 @@ err0:
return ret;
}
+/* The modem send us an ack. First with check if it right */
static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
{
uea_enters(INS_TO_USBDEV(sc));
@@ -1268,23 +1269,19 @@ bad1:
*/
static void uea_intr(struct urb *urb, struct pt_regs *regs)
{
- struct uea_softc *sc = (struct uea_softc *)urb->context;
- struct intr_pkt *intr;
+ struct uea_softc *sc = urb->context;
+ struct intr_pkt *intr = urb->transfer_buffer;
uea_enters(INS_TO_USBDEV(sc));
- if (urb->status < 0) {
+ if (unlikely(urb->status < 0)) {
uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
urb->status);
return;
}
- intr = (struct intr_pkt *) urb->transfer_buffer;
-
/* device-to-host interrupt */
if (intr->bType != 0x08 || sc->booting) {
- uea_err(INS_TO_USBDEV(sc), "wrong intr\n");
- // rebooting ?
- // sc->reset = 1;
+ uea_err(INS_TO_USBDEV(sc), "wrong interrupt\n");
goto resubmit;
}
@@ -1300,7 +1297,7 @@ static void uea_intr(struct urb *urb, struct pt_regs *regs)
break;
default:
- uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n",
+ uea_err(INS_TO_USBDEV(sc), "unknown interrupt %u\n",
le16_to_cpu(intr->wInterrupt));
}
@@ -1379,7 +1376,7 @@ static void uea_stop(struct uea_softc *sc)
int ret;
uea_enters(INS_TO_USBDEV(sc));
ret = kthread_stop(sc->kthread);
- uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
+ uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
/* stop any pending boot process */
flush_scheduled_work();
@@ -1418,13 +1415,13 @@ static ssize_t read_status(struct device *dev, struct device_attribute *attr,
int ret = -ENODEV;
struct uea_softc *sc;
- down(&uea_semaphore);
+ mutex_lock(&uea_mutex);
sc = dev_to_uea(dev);
if (!sc)
goto out;
ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);
out:
- up(&uea_semaphore);
+ mutex_unlock(&uea_mutex);
return ret;
}
@@ -1434,14 +1431,14 @@ static ssize_t reboot(struct device *dev, struct device_attribute *attr,
int ret = -ENODEV;
struct uea_softc *sc;
- down(&uea_semaphore);
+ mutex_lock(&uea_mutex);
sc = dev_to_uea(dev);
if (!sc)
goto out;
sc->reset = 1;
ret = count;
out:
- up(&uea_semaphore);
+ mutex_unlock(&uea_mutex);
return ret;
}
@@ -1453,7 +1450,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at
int ret = -ENODEV;
struct uea_softc *sc;
- down(&uea_semaphore);
+ mutex_lock(&uea_mutex);
sc = dev_to_uea(dev);
if (!sc)
goto out;
@@ -1473,7 +1470,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at
break;
}
out:
- up(&uea_semaphore);
+ mutex_unlock(&uea_mutex);
return ret;
}
@@ -1485,7 +1482,7 @@ static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
int ret = -ENODEV;
struct uea_softc *sc;
- down(&uea_semaphore);
+ mutex_lock(&uea_mutex);
sc = dev_to_uea(dev);
if (!sc)
goto out;
@@ -1497,7 +1494,7 @@ static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
else
ret = sprintf(buf, "GOOD\n");
out:
- up(&uea_semaphore);
+ mutex_unlock(&uea_mutex);
return ret;
}
@@ -1511,7 +1508,7 @@ static ssize_t read_##name(struct device *dev, \
int ret = -ENODEV; \
struct uea_softc *sc; \
\
- down(&uea_semaphore); \
+ mutex_lock(&uea_mutex); \
sc = dev_to_uea(dev); \
if (!sc) \
goto out; \
@@ -1519,7 +1516,7 @@ static ssize_t read_##name(struct device *dev, \
if (reset) \
sc->stats.phy.name = 0; \
out: \
- up(&uea_semaphore); \
+ mutex_unlock(&uea_mutex); \
return ret; \
} \
\
@@ -1617,7 +1614,7 @@ static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
}
static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
- const struct usb_device_id *id, int *heavy)
+ const struct usb_device_id *id)
{
struct usb_device *usb = interface_to_usbdev(intf);
struct uea_softc *sc;
@@ -1629,16 +1626,14 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
if (ifnum != UEA_INTR_IFACE_NO)
return -ENODEV;
- *heavy = sync_wait[modem_index];
+ usbatm->flags = (sync_wait[modem_index] ? 0 : UDSL_SKIP_HEAVY_INIT);
/* interface 1 is for outbound traffic */
ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);
if (ret < 0)
return ret;
- /* ADI930 has only 2 interfaces and inbound traffic
- * is on interface 1
- */
+ /* ADI930 has only 2 interfaces and inbound traffic is on interface 1 */
if (UEA_CHIP_VERSION(id) != ADI930) {
/* interface 2 is for inbound traffic */
ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO);
@@ -1658,6 +1653,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0;
sc->driver_info = id->driver_info;
+ /* ADI930 don't support iso */
+ if (UEA_CHIP_VERSION(id) != ADI930 && use_iso[sc->modem_index]) {
+ int i;
+
+ /* try set fastest alternate for inbound traffic interface */
+ for (i = FASTEST_ISO_INTF; i > 0; i--)
+ if (usb_set_interface(usb, UEA_DS_IFACE_NO, i) == 0)
+ break;
+
+ if (i > 0) {
+ uea_dbg(usb, "set alternate %d for 2 interface\n", i);
+ uea_info(usb, "using iso mode\n");
+ usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ;
+ } else {
+ uea_err(usb, "setting any alternate failed for "
+ "2 interface, using bulk mode\n");
+ }
+ }
+
ret = uea_boot(sc);
if (ret < 0) {
kfree(sc);
@@ -1701,13 +1715,13 @@ static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
static struct usbatm_driver uea_usbatm_driver = {
.driver_name = "ueagle-atm",
- .owner = THIS_MODULE,
.bind = uea_bind,
.atm_start = uea_atm_open,
.unbind = uea_unbind,
.heavy_init = uea_heavy,
- .in = UEA_BULK_DATA_PIPE,
- .out = UEA_BULK_DATA_PIPE,
+ .bulk_in = UEA_BULK_DATA_PIPE,
+ .bulk_out = UEA_BULK_DATA_PIPE,
+ .isoc_in = UEA_ISO_DATA_PIPE,
};
static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -1738,9 +1752,9 @@ static void uea_disconnect(struct usb_interface *intf)
* Pre-firmware device has one interface
*/
if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {
- down(&uea_semaphore);
+ mutex_lock(&uea_mutex);
usbatm_usb_disconnect(intf);
- up(&uea_semaphore);
+ mutex_unlock(&uea_mutex);
uea_info(usb, "ADSL device removed\n");
}
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 7af1883d4bf..c1211fc037d 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -72,6 +72,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/signal.h>
@@ -91,19 +92,18 @@ static int usbatm_print_packet(const unsigned char *data, int len);
#endif
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
-#define DRIVER_VERSION "1.9"
+#define DRIVER_VERSION "1.10"
#define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION
static const char usbatm_driver_name[] = "usbatm";
#define UDSL_MAX_RCV_URBS 16
#define UDSL_MAX_SND_URBS 16
-#define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */
-#define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */
+#define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */
#define UDSL_DEFAULT_RCV_URBS 4
#define UDSL_DEFAULT_SND_URBS 4
-#define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */
-#define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */
+#define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
+#define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
@@ -111,8 +111,8 @@ static const char usbatm_driver_name[] = "usbatm";
static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS;
static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS;
-static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE;
-static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE;
+static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE;
+static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE;
module_param(num_rcv_urbs, uint, S_IRUGO);
MODULE_PARM_DESC(num_rcv_urbs,
@@ -126,15 +126,15 @@ MODULE_PARM_DESC(num_snd_urbs,
__MODULE_STRING(UDSL_MAX_SND_URBS) ", default: "
__MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")");
-module_param(rcv_buf_size, uint, S_IRUGO);
-MODULE_PARM_DESC(rcv_buf_size,
- "Size of the buffers used for reception in ATM cells (range: 1-"
- __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: "
+module_param(rcv_buf_bytes, uint, S_IRUGO);
+MODULE_PARM_DESC(rcv_buf_bytes,
+ "Size of the buffers used for reception, in bytes (range: 1-"
+ __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
__MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")");
-module_param(snd_buf_size, uint, S_IRUGO);
-MODULE_PARM_DESC(snd_buf_size,
- "Size of the buffers used for transmission in ATM cells (range: 1-"
+module_param(snd_buf_bytes, uint, S_IRUGO);
+MODULE_PARM_DESC(snd_buf_bytes,
+ "Size of the buffers used for transmission, in bytes (range: 1-"
__MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
__MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
@@ -166,10 +166,10 @@ struct usbatm_control {
/* ATM */
-static void usbatm_atm_dev_close(struct atm_dev *dev);
+static void usbatm_atm_dev_close(struct atm_dev *atm_dev);
static int usbatm_atm_open(struct atm_vcc *vcc);
static void usbatm_atm_close(struct atm_vcc *vcc);
-static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg);
+static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg);
static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);
@@ -199,7 +199,7 @@ static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
if (vcc->pop)
vcc->pop(vcc, skb);
else
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
@@ -234,8 +234,9 @@ static int usbatm_submit_urb(struct urb *urb)
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) {
- atm_dbg(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n",
- __func__, urb, ret);
+ if (printk_ratelimit())
+ atm_warn(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n",
+ __func__, urb, ret);
/* consider all errors transient and return the buffer back to the queue */
urb->status = -EAGAIN;
@@ -269,10 +270,16 @@ static void usbatm_complete(struct urb *urb, struct pt_regs *regs)
spin_unlock_irqrestore(&channel->lock, flags);
- if (unlikely(urb->status))
+ if (unlikely(urb->status) &&
+ (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) ||
+ urb->status != -EILSEQ ))
+ {
+ if (printk_ratelimit())
+ atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
+ __func__, urb, urb->status);
/* throttle processing in case of an error */
mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS));
- else
+ } else
tasklet_schedule(&channel->tasklet);
}
@@ -284,129 +291,167 @@ static void usbatm_complete(struct urb *urb, struct pt_regs *regs)
static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance,
short vpi, int vci)
{
- struct usbatm_vcc_data *vcc;
+ struct usbatm_vcc_data *vcc_data;
- list_for_each_entry(vcc, &instance->vcc_list, list)
- if ((vcc->vci == vci) && (vcc->vpi == vpi))
- return vcc;
+ list_for_each_entry(vcc_data, &instance->vcc_list, list)
+ if ((vcc_data->vci == vci) && (vcc_data->vpi == vpi))
+ return vcc_data;
return NULL;
}
-static void usbatm_extract_cells(struct usbatm_data *instance,
- unsigned char *source, unsigned int avail_data)
+static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char *source)
{
- struct usbatm_vcc_data *cached_vcc = NULL;
struct atm_vcc *vcc;
struct sk_buff *sarb;
- unsigned int stride = instance->rx_channel.stride;
- int vci, cached_vci = 0;
- short vpi, cached_vpi = 0;
- u8 pti;
+ short vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4);
+ int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
+ u8 pti = ((source[3] & 0xe) >> 1);
- for (; avail_data >= stride; avail_data -= stride, source += stride) {
- vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4);
- vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
- pti = ((source[3] & 0xe) >> 1);
+ vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
- vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
+ if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) {
+ instance->cached_vpi = vpi;
+ instance->cached_vci = vci;
- if ((vci != cached_vci) || (vpi != cached_vpi)) {
- cached_vpi = vpi;
- cached_vci = vci;
+ instance->cached_vcc = usbatm_find_vcc(instance, vpi, vci);
- cached_vcc = usbatm_find_vcc(instance, vpi, vci);
+ if (!instance->cached_vcc)
+ atm_rldbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
+ }
- if (!cached_vcc)
- atm_dbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci);
- }
+ if (!instance->cached_vcc)
+ return;
- if (!cached_vcc)
- continue;
+ vcc = instance->cached_vcc->vcc;
- vcc = cached_vcc->vcc;
+ /* OAM F5 end-to-end */
+ if (pti == ATM_PTI_E2EF5) {
+ if (printk_ratelimit())
+ atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
+ __func__, vpi, vci);
+ atomic_inc(&vcc->stats->rx_err);
+ return;
+ }
- /* OAM F5 end-to-end */
- if (pti == ATM_PTI_E2EF5) {
- atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", __func__, vpi, vci);
- atomic_inc(&vcc->stats->rx_err);
- continue;
- }
+ sarb = instance->cached_vcc->sarb;
- sarb = cached_vcc->sarb;
+ if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
+ atm_rldbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
+ __func__, sarb->len, vcc);
+ /* discard cells already received */
+ skb_trim(sarb, 0);
+ UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
+ }
- if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
- atm_dbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n",
- __func__, sarb->len, vcc);
- /* discard cells already received */
- skb_trim(sarb, 0);
- UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end);
- }
+ memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
+ __skb_put(sarb, ATM_CELL_PAYLOAD);
- memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
- __skb_put(sarb, ATM_CELL_PAYLOAD);
+ if (pti & 1) {
+ struct sk_buff *skb;
+ unsigned int length;
+ unsigned int pdu_length;
- if (pti & 1) {
- struct sk_buff *skb;
- unsigned int length;
- unsigned int pdu_length;
+ length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];
- length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5];
+ /* guard against overflow */
+ if (length > ATM_MAX_AAL5_PDU) {
+ atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
+ __func__, length, vcc);
+ atomic_inc(&vcc->stats->rx_err);
+ goto out;
+ }
- /* guard against overflow */
- if (length > ATM_MAX_AAL5_PDU) {
- atm_dbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
- __func__, length, vcc);
- atomic_inc(&vcc->stats->rx_err);
- goto out;
- }
+ pdu_length = usbatm_pdu_length(length);
- pdu_length = usbatm_pdu_length(length);
+ if (sarb->len < pdu_length) {
+ atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
+ __func__, pdu_length, sarb->len, vcc);
+ atomic_inc(&vcc->stats->rx_err);
+ goto out;
+ }
- if (sarb->len < pdu_length) {
- atm_dbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
- __func__, pdu_length, sarb->len, vcc);
- atomic_inc(&vcc->stats->rx_err);
- goto out;
- }
+ if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
+ atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
+ __func__, vcc);
+ atomic_inc(&vcc->stats->rx_err);
+ goto out;
+ }
- if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
- atm_dbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
- __func__, vcc);
- atomic_inc(&vcc->stats->rx_err);
- goto out;
- }
+ vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
- vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
+ if (!(skb = dev_alloc_skb(length))) {
+ if (printk_ratelimit())
+ atm_err(instance, "%s: no memory for skb (length: %u)!\n",
+ __func__, length);
+ atomic_inc(&vcc->stats->rx_drop);
+ goto out;
+ }
- if (!(skb = dev_alloc_skb(length))) {
- atm_dbg(instance, "%s: no memory for skb (length: %u)!\n", __func__, length);
- atomic_inc(&vcc->stats->rx_drop);
- goto out;
- }
+ vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
- vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
+ if (!atm_charge(vcc, skb->truesize)) {
+ atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n",
+ __func__, skb->truesize);
+ dev_kfree_skb_any(skb);
+ goto out; /* atm_charge increments rx_drop */
+ }
- if (!atm_charge(vcc, skb->truesize)) {
- atm_dbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", __func__, skb->truesize);
- dev_kfree_skb(skb);
- goto out; /* atm_charge increments rx_drop */
- }
+ memcpy(skb->data, sarb->tail - pdu_length, length);
+ __skb_put(skb, length);
- memcpy(skb->data, sarb->tail - pdu_length, length);
- __skb_put(skb, length);
+ vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
+ __func__, skb, skb->len, skb->truesize);
- vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
- __func__, skb, skb->len, skb->truesize);
+ PACKETDEBUG(skb->data, skb->len);
- PACKETDEBUG(skb->data, skb->len);
+ vcc->push(vcc, skb);
- vcc->push(vcc, skb);
+ atomic_inc(&vcc->stats->rx);
+ out:
+ skb_trim(sarb, 0);
+ }
+}
- atomic_inc(&vcc->stats->rx);
- out:
- skb_trim(sarb, 0);
+static void usbatm_extract_cells(struct usbatm_data *instance,
+ unsigned char *source, unsigned int avail_data)
+{
+ unsigned int stride = instance->rx_channel.stride;
+ unsigned int buf_usage = instance->buf_usage;
+
+ /* extract cells from incoming data, taking into account that
+ * the length of avail data may not be a multiple of stride */
+
+ if (buf_usage > 0) {
+ /* we have a partially received atm cell */
+ unsigned char *cell_buf = instance->cell_buf;
+ unsigned int space_left = stride - buf_usage;
+
+ UDSL_ASSERT(buf_usage <= stride);
+
+ if (avail_data >= space_left) {
+ /* add new data and process cell */
+ memcpy(cell_buf + buf_usage, source, space_left);
+ source += space_left;
+ avail_data -= space_left;
+ usbatm_extract_one_cell(instance, cell_buf);
+ instance->buf_usage = 0;
+ } else {
+ /* not enough data to fill the cell */
+ memcpy(cell_buf + buf_usage, source, avail_data);
+ instance->buf_usage = buf_usage + avail_data;
+ return;
}
}
+
+ for (; avail_data >= stride; avail_data -= stride, source += stride)
+ usbatm_extract_one_cell(instance, source);
+
+ if (avail_data > 0) {
+ /* length was not a multiple of stride -
+ * save remaining data for next call */
+ memcpy(instance->cell_buf, source, avail_data);
+ instance->buf_usage = avail_data;
+ }
}
@@ -420,14 +465,14 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance,
{
struct usbatm_control *ctrl = UDSL_SKB(skb);
struct atm_vcc *vcc = ctrl->atm.vcc;
- unsigned int num_written;
+ unsigned int bytes_written;
unsigned int stride = instance->tx_channel.stride;
vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space);
UDSL_ASSERT(!(avail_space % stride));
- for (num_written = 0; num_written < avail_space && ctrl->len;
- num_written += stride, target += stride) {
+ for (bytes_written = 0; bytes_written < avail_space && ctrl->len;
+ bytes_written += stride, target += stride) {
unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD);
unsigned int left = ATM_CELL_PAYLOAD - data_len;
u8 *ptr = target;
@@ -470,7 +515,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance,
ctrl->crc = crc32_be(ctrl->crc, ptr, left);
}
- return num_written;
+ return bytes_written;
}
@@ -487,16 +532,40 @@ static void usbatm_rx_process(unsigned long data)
vdbg("%s: processing urb 0x%p", __func__, urb);
if (usb_pipeisoc(urb->pipe)) {
+ unsigned char *merge_start = NULL;
+ unsigned int merge_length = 0;
+ const unsigned int packet_size = instance->rx_channel.packet_size;
int i;
- for (i = 0; i < urb->number_of_packets; i++)
- if (!urb->iso_frame_desc[i].status)
- usbatm_extract_cells(instance,
- (u8 *)urb->transfer_buffer + urb->iso_frame_desc[i].offset,
- urb->iso_frame_desc[i].actual_length);
- }
- else
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ if (!urb->iso_frame_desc[i].status) {
+ unsigned int actual_length = urb->iso_frame_desc[i].actual_length;
+
+ UDSL_ASSERT(actual_length <= packet_size);
+
+ if (!merge_length)
+ merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+ merge_length += actual_length;
+ if (merge_length && (actual_length < packet_size)) {
+ usbatm_extract_cells(instance, merge_start, merge_length);
+ merge_length = 0;
+ }
+ } else {
+ atm_rldbg(instance, "%s: status %d in frame %d!\n", __func__, urb->status, i);
+ if (merge_length)
+ usbatm_extract_cells(instance, merge_start, merge_length);
+ merge_length = 0;
+ instance->buf_usage = 0;
+ }
+ }
+
+ if (merge_length)
+ usbatm_extract_cells(instance, merge_start, merge_length);
+ } else
if (!urb->status)
usbatm_extract_cells(instance, urb->transfer_buffer, urb->actual_length);
+ else
+ instance->buf_usage = 0;
if (usbatm_submit_urb(urb))
return;
@@ -514,7 +583,7 @@ static void usbatm_tx_process(unsigned long data)
struct sk_buff *skb = instance->current_skb;
struct urb *urb = NULL;
const unsigned int buf_size = instance->tx_channel.buf_size;
- unsigned int num_written = 0;
+ unsigned int bytes_written = 0;
u8 *buffer = NULL;
if (!skb)
@@ -526,16 +595,16 @@ static void usbatm_tx_process(unsigned long data)
if (!urb)
break; /* no more senders */
buffer = urb->transfer_buffer;
- num_written = (urb->status == -EAGAIN) ?
+ bytes_written = (urb->status == -EAGAIN) ?
urb->transfer_buffer_length : 0;
}
- num_written += usbatm_write_cells(instance, skb,
- buffer + num_written,
- buf_size - num_written);
+ bytes_written += usbatm_write_cells(instance, skb,
+ buffer + bytes_written,
+ buf_size - bytes_written);
vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p",
- __func__, num_written, skb, urb);
+ __func__, bytes_written, skb, urb);
if (!UDSL_SKB(skb)->len) {
struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc;
@@ -546,8 +615,8 @@ static void usbatm_tx_process(unsigned long data)
skb = skb_dequeue(&instance->sndqueue);
}
- if (num_written == buf_size || (!skb && num_written)) {
- urb->transfer_buffer_length = num_written;
+ if (bytes_written == buf_size || (!skb && bytes_written)) {
+ urb->transfer_buffer_length = bytes_written;
if (usbatm_submit_urb(urb))
break;
@@ -593,20 +662,24 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len);
- if (!instance) {
- dbg("%s: NULL data!", __func__);
+ /* racy disconnection check - fine */
+ if (!instance || instance->disconnected) {
+#ifdef DEBUG
+ if (printk_ratelimit())
+ printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
+#endif
err = -ENODEV;
goto fail;
}
if (vcc->qos.aal != ATM_AAL5) {
- atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
+ atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
err = -EINVAL;
goto fail;
}
if (skb->len > ATM_MAX_AAL5_PDU) {
- atm_dbg(instance, "%s: packet too long (%d vs %d)!\n",
+ atm_rldbg(instance, "%s: packet too long (%d vs %d)!\n",
__func__, skb->len, ATM_MAX_AAL5_PDU);
err = -EINVAL;
goto fail;
@@ -665,16 +738,16 @@ static void usbatm_put_instance(struct usbatm_data *instance)
** ATM **
**********/
-static void usbatm_atm_dev_close(struct atm_dev *dev)
+static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
{
- struct usbatm_data *instance = dev->dev_data;
+ struct usbatm_data *instance = atm_dev->dev_data;
dbg("%s", __func__);
if (!instance)
return;
- dev->dev_data = NULL;
+ atm_dev->dev_data = NULL; /* catch bugs */
usbatm_put_instance(instance); /* taken in usbatm_atm_init */
}
@@ -706,15 +779,19 @@ static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *pag
atomic_read(&atm_dev->stats.aal5.rx_err),
atomic_read(&atm_dev->stats.aal5.rx_drop));
- if (!left--)
- switch (atm_dev->signal) {
- case ATM_PHY_SIG_FOUND:
- return sprintf(page, "Line up\n");
- case ATM_PHY_SIG_LOST:
- return sprintf(page, "Line down\n");
- default:
- return sprintf(page, "Line state unknown\n");
- }
+ if (!left--) {
+ if (instance->disconnected)
+ return sprintf(page, "Disconnected\n");
+ else
+ switch (atm_dev->signal) {
+ case ATM_PHY_SIG_FOUND:
+ return sprintf(page, "Line up\n");
+ case ATM_PHY_SIG_LOST:
+ return sprintf(page, "Line down\n");
+ default:
+ return sprintf(page, "Line state unknown\n");
+ }
+ }
return 0;
}
@@ -735,13 +812,24 @@ static int usbatm_atm_open(struct atm_vcc *vcc)
atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci);
/* only support AAL5 */
- if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0)
- || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {
- atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
+ if ((vcc->qos.aal != ATM_AAL5)) {
+ atm_warn(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
+ return -EINVAL;
+ }
+
+ /* sanity checks */
+ if ((vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {
+ atm_dbg(instance, "%s: max_sdu %d out of range!\n", __func__, vcc->qos.rxtp.max_sdu);
return -EINVAL;
}
- down(&instance->serialize); /* vs self, usbatm_atm_close */
+ mutex_lock(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */
+
+ if (instance->disconnected) {
+ atm_dbg(instance, "%s: disconnected!\n", __func__);
+ ret = -ENODEV;
+ goto fail;
+ }
if (usbatm_find_vcc(instance, vpi, vci)) {
atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci);
@@ -749,20 +837,19 @@ static int usbatm_atm_open(struct atm_vcc *vcc)
goto fail;
}
- if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
- atm_dbg(instance, "%s: no memory for vcc_data!\n", __func__);
+ if (!(new = kzalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
+ atm_err(instance, "%s: no memory for vcc_data!\n", __func__);
ret = -ENOMEM;
goto fail;
}
- memset(new, 0, sizeof(struct usbatm_vcc_data));
new->vcc = vcc;
new->vpi = vpi;
new->vci = vci;
new->sarb = alloc_skb(usbatm_pdu_length(vcc->qos.rxtp.max_sdu), GFP_KERNEL);
if (!new->sarb) {
- atm_dbg(instance, "%s: no memory for SAR buffer!\n", __func__);
+ atm_err(instance, "%s: no memory for SAR buffer!\n", __func__);
ret = -ENOMEM;
goto fail;
}
@@ -770,6 +857,9 @@ static int usbatm_atm_open(struct atm_vcc *vcc)
vcc->dev_data = new;
tasklet_disable(&instance->rx_channel.tasklet);
+ instance->cached_vcc = new;
+ instance->cached_vpi = vpi;
+ instance->cached_vci = vci;
list_add(&new->list, &instance->vcc_list);
tasklet_enable(&instance->rx_channel.tasklet);
@@ -777,7 +867,7 @@ static int usbatm_atm_open(struct atm_vcc *vcc)
set_bit(ATM_VF_PARTIAL, &vcc->flags);
set_bit(ATM_VF_READY, &vcc->flags);
- up(&instance->serialize);
+ mutex_unlock(&instance->serialize);
atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new);
@@ -785,7 +875,7 @@ static int usbatm_atm_open(struct atm_vcc *vcc)
fail:
kfree(new);
- up(&instance->serialize);
+ mutex_unlock(&instance->serialize);
return ret;
}
@@ -806,9 +896,14 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
usbatm_cancel_send(instance, vcc);
- down(&instance->serialize); /* vs self, usbatm_atm_open */
+ mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
tasklet_disable(&instance->rx_channel.tasklet);
+ if (instance->cached_vcc == vcc_data) {
+ instance->cached_vcc = NULL;
+ instance->cached_vpi = ATM_VPI_UNSPEC;
+ instance->cached_vci = ATM_VCI_UNSPEC;
+ }
list_del(&vcc_data->list);
tasklet_enable(&instance->rx_channel.tasklet);
@@ -824,14 +919,21 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
clear_bit(ATM_VF_PARTIAL, &vcc->flags);
clear_bit(ATM_VF_ADDR, &vcc->flags);
- up(&instance->serialize);
+ mutex_unlock(&instance->serialize);
atm_dbg(instance, "%s successful\n", __func__);
}
-static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd,
+static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
void __user * arg)
{
+ struct usbatm_data *instance = atm_dev->dev_data;
+
+ if (!instance || instance->disconnected) {
+ dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance");
+ return -ENODEV;
+ }
+
switch (cmd) {
case ATM_QUERYLOOP:
return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0;
@@ -845,10 +947,13 @@ static int usbatm_atm_init(struct usbatm_data *instance)
struct atm_dev *atm_dev;
int ret, i;
- /* ATM init */
+ /* ATM init. The ATM initialization scheme suffers from an intrinsic race
+ * condition: callbacks we register can be executed at once, before we have
+ * initialized the struct atm_dev. To protect against this, all callbacks
+ * abort if atm_dev->dev_data is NULL. */
atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
if (!atm_dev) {
- usb_dbg(instance, "%s: failed to register ATM device!\n", __func__);
+ usb_err(instance, "%s: failed to register ATM device!\n", __func__);
return -1;
}
@@ -862,12 +967,13 @@ static int usbatm_atm_init(struct usbatm_data *instance)
atm_dev->link_rate = 128 * 1000 / 424;
if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
- atm_dbg(instance, "%s: atm_start failed: %d!\n", __func__, ret);
+ atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
goto fail;
}
- /* ready for ATM callbacks */
usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */
+
+ /* ready for ATM callbacks */
mb();
atm_dev->dev_data = instance;
@@ -903,9 +1009,9 @@ static int usbatm_do_heavy_init(void *arg)
if (!ret)
ret = usbatm_atm_init(instance);
- down(&instance->serialize);
+ mutex_lock(&instance->serialize);
instance->thread_pid = -1;
- up(&instance->serialize);
+ mutex_unlock(&instance->serialize);
complete_and_exit(&instance->thread_exited, ret);
}
@@ -915,13 +1021,13 @@ static int usbatm_heavy_init(struct usbatm_data *instance)
int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);
if (ret < 0) {
- usb_dbg(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
+ usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
return ret;
}
- down(&instance->serialize);
+ mutex_lock(&instance->serialize);
instance->thread_pid = ret;
- up(&instance->serialize);
+ mutex_unlock(&instance->serialize);
wait_for_completion(&instance->thread_started);
@@ -951,9 +1057,9 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
char *buf;
int error = -ENOMEM;
int i, length;
- int need_heavy;
+ unsigned int maxpacket, num_packets;
- dev_dbg(dev, "%s: trying driver %s with vendor=0x%x, product=0x%x, ifnum %d\n",
+ dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",
__func__, driver->driver_name,
le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct),
@@ -962,7 +1068,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
/* instance init */
instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
if (!instance) {
- dev_dbg(dev, "%s: no memory for instance data!\n", __func__);
+ dev_err(dev, "%s: no memory for instance data!\n", __func__);
return -ENOMEM;
}
@@ -996,66 +1102,96 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
snprintf(buf, length, ")");
bind:
- need_heavy = 1;
- if (driver->bind && (error = driver->bind(instance, intf, id, &need_heavy)) < 0) {
- dev_dbg(dev, "%s: bind failed: %d!\n", __func__, error);
+ if (driver->bind && (error = driver->bind(instance, intf, id)) < 0) {
+ dev_err(dev, "%s: bind failed: %d!\n", __func__, error);
goto fail_free;
}
/* private fields */
kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */
- init_MUTEX(&instance->serialize);
+ mutex_init(&instance->serialize);
instance->thread_pid = -1;
init_completion(&instance->thread_started);
init_completion(&instance->thread_exited);
INIT_LIST_HEAD(&instance->vcc_list);
+ skb_queue_head_init(&instance->sndqueue);
usbatm_init_channel(&instance->rx_channel);
usbatm_init_channel(&instance->tx_channel);
tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance);
tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance);
- instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->in);
- instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out);
instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding;
instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding;
- instance->rx_channel.buf_size = rcv_buf_size * instance->rx_channel.stride;
- instance->tx_channel.buf_size = snd_buf_size * instance->tx_channel.stride;
instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance;
- skb_queue_head_init(&instance->sndqueue);
+ if ((instance->flags & UDSL_USE_ISOC) && driver->isoc_in)
+ instance->rx_channel.endpoint = usb_rcvisocpipe(usb_dev, driver->isoc_in);
+ else
+ instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->bulk_in);
+
+ instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out);
+
+ /* tx buffer size must be a positive multiple of the stride */
+ instance->tx_channel.buf_size = max (instance->tx_channel.stride,
+ snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride));
+
+ /* rx buffer size must be a positive multiple of the endpoint maxpacket */
+ maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint, 0);
+
+ if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) {
+ dev_err(dev, "%s: invalid endpoint %02x!\n", __func__,
+ usb_pipeendpoint(instance->rx_channel.endpoint));
+ error = -EINVAL;
+ goto fail_unbind;
+ }
+
+ num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */
+
+ if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE)
+ num_packets--;
+
+ instance->rx_channel.buf_size = num_packets * maxpacket;
+ instance->rx_channel.packet_size = maxpacket;
+
+#ifdef DEBUG
+ for (i = 0; i < 2; i++) {
+ struct usbatm_channel *channel = i ?
+ &instance->tx_channel : &instance->rx_channel;
+
+ dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel);
+ }
+#endif
+
+ /* initialize urbs */
for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
- struct urb *urb;
u8 *buffer;
- unsigned int iso_packets = 0, iso_size = 0;
struct usbatm_channel *channel = i < num_rcv_urbs ?
&instance->rx_channel : &instance->tx_channel;
+ struct urb *urb;
+ unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0;
- if (usb_pipeisoc(channel->endpoint)) {
- /* don't expect iso out endpoints */
- iso_size = usb_maxpacket(instance->usb_dev, channel->endpoint, 0);
- iso_size -= iso_size % channel->stride; /* alignment */
- BUG_ON(!iso_size);
- iso_packets = (channel->buf_size - 1) / iso_size + 1;
- }
+ UDSL_ASSERT(!usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));
urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
if (!urb) {
- dev_dbg(dev, "%s: no memory for urb %d!\n", __func__, i);
+ dev_err(dev, "%s: no memory for urb %d!\n", __func__, i);
+ error = -ENOMEM;
goto fail_unbind;
}
instance->urbs[i] = urb;
- buffer = kmalloc(channel->buf_size, GFP_KERNEL);
+ /* zero the tx padding to avoid leaking information */
+ buffer = kzalloc(channel->buf_size, GFP_KERNEL);
if (!buffer) {
- dev_dbg(dev, "%s: no memory for buffer %d!\n", __func__, i);
+ dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i);
+ error = -ENOMEM;
goto fail_unbind;
}
- memset(buffer, 0, channel->buf_size);
usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint,
buffer, channel->buf_size, usbatm_complete, channel);
@@ -1065,9 +1201,8 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
urb->transfer_flags = URB_ISO_ASAP;
urb->number_of_packets = iso_packets;
for (j = 0; j < iso_packets; j++) {
- urb->iso_frame_desc[j].offset = iso_size * j;
- urb->iso_frame_desc[j].length = min_t(int, iso_size,
- channel->buf_size - urb->iso_frame_desc[j].offset);
+ urb->iso_frame_desc[j].offset = channel->packet_size * j;
+ urb->iso_frame_desc[j].length = channel->packet_size;
}
}
@@ -1079,7 +1214,17 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
__func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);
}
- if (need_heavy && driver->heavy_init) {
+ instance->cached_vpi = ATM_VPI_UNSPEC;
+ instance->cached_vci = ATM_VCI_UNSPEC;
+ instance->cell_buf = kmalloc(instance->rx_channel.stride, GFP_KERNEL);
+
+ if (!instance->cell_buf) {
+ dev_err(dev, "%s: no memory for cell buffer!\n", __func__);
+ error = -ENOMEM;
+ goto fail_unbind;
+ }
+
+ if (!(instance->flags & UDSL_SKIP_HEAVY_INIT) && driver->heavy_init) {
error = usbatm_heavy_init(instance);
} else {
complete(&instance->thread_exited); /* pretend that heavy_init was run */
@@ -1098,6 +1243,8 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
if (instance->driver->unbind)
instance->driver->unbind(instance, intf);
fail_free:
+ kfree(instance->cell_buf);
+
for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
if (instance->urbs[i])
kfree(instance->urbs[i]->transfer_buffer);
@@ -1114,6 +1261,7 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
{
struct device *dev = &intf->dev;
struct usbatm_data *instance = usb_get_intfdata(intf);
+ struct usbatm_vcc_data *vcc_data;
int i;
dev_dbg(dev, "%s entered\n", __func__);
@@ -1125,13 +1273,19 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
- down(&instance->serialize);
+ mutex_lock(&instance->serialize);
+ instance->disconnected = 1;
if (instance->thread_pid >= 0)
kill_proc(instance->thread_pid, SIGTERM, 1);
- up(&instance->serialize);
+ mutex_unlock(&instance->serialize);
wait_for_completion(&instance->thread_exited);
+ mutex_lock(&instance->serialize);
+ list_for_each_entry(vcc_data, &instance->vcc_list, list)
+ vcc_release_async(vcc_data->vcc, -EPIPE);
+ mutex_unlock(&instance->serialize);
+
tasklet_disable(&instance->rx_channel.tasklet);
tasklet_disable(&instance->tx_channel.tasklet);
@@ -1141,6 +1295,14 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
del_timer_sync(&instance->rx_channel.delay);
del_timer_sync(&instance->tx_channel.delay);
+ /* turn usbatm_[rt]x_process into something close to a no-op */
+ /* no need to take the spinlock */
+ INIT_LIST_HEAD(&instance->rx_channel.list);
+ INIT_LIST_HEAD(&instance->tx_channel.list);
+
+ tasklet_enable(&instance->rx_channel.tasklet);
+ tasklet_enable(&instance->tx_channel.tasklet);
+
if (instance->atm_dev && instance->driver->atm_stop)
instance->driver->atm_stop(instance, instance->atm_dev);
@@ -1149,19 +1311,13 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
instance->driver_data = NULL;
- /* turn usbatm_[rt]x_process into noop */
- /* no need to take the spinlock */
- INIT_LIST_HEAD(&instance->rx_channel.list);
- INIT_LIST_HEAD(&instance->tx_channel.list);
-
- tasklet_enable(&instance->rx_channel.tasklet);
- tasklet_enable(&instance->tx_channel.tasklet);
-
for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
kfree(instance->urbs[i]->transfer_buffer);
usb_free_urb(instance->urbs[i]);
}
+ kfree(instance->cell_buf);
+
/* ATM finalize */
if (instance->atm_dev)
atm_dev_deregister(instance->atm_dev);
@@ -1186,10 +1342,10 @@ static int __init usbatm_usb_init(void)
if ((num_rcv_urbs > UDSL_MAX_RCV_URBS)
|| (num_snd_urbs > UDSL_MAX_SND_URBS)
- || (rcv_buf_size < 1)
- || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE)
- || (snd_buf_size < 1)
- || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE))
+ || (rcv_buf_bytes < 1)
+ || (rcv_buf_bytes > UDSL_MAX_BUF_SIZE)
+ || (snd_buf_bytes < 1)
+ || (snd_buf_bytes > UDSL_MAX_BUF_SIZE))
return -EINVAL;
return 0;
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
index 1adacd60d71..ff8551e9337 100644
--- a/drivers/usb/atm/usbatm.h
+++ b/drivers/usb/atm/usbatm.h
@@ -24,21 +24,21 @@
#ifndef _USBATM_H_
#define _USBATM_H_
-#include <linux/config.h>
-
-/*
-#define VERBOSE_DEBUG
-*/
-
#include <asm/semaphore.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/completion.h>
#include <linux/device.h>
+#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/stringify.h>
#include <linux/usb.h>
+#include <linux/mutex.h>
+
+/*
+#define VERBOSE_DEBUG
+*/
#ifdef DEBUG
#define UDSL_ASSERT(x) BUG_ON(!(x))
@@ -52,8 +52,13 @@
dev_info(&(instance)->usb_intf->dev , format , ## arg)
#define usb_warn(instance, format, arg...) \
dev_warn(&(instance)->usb_intf->dev , format , ## arg)
+#ifdef DEBUG
#define usb_dbg(instance, format, arg...) \
- dev_dbg(&(instance)->usb_intf->dev , format , ## arg)
+ dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg)
+#else
+#define usb_dbg(instance, format, arg...) \
+ do {} while (0)
+#endif
/* FIXME: move to dev_* once ATM is driver model aware */
#define atm_printk(level, instance, format, arg...) \
@@ -69,12 +74,24 @@
#ifdef DEBUG
#define atm_dbg(instance, format, arg...) \
atm_printk(KERN_DEBUG, instance , format , ## arg)
+#define atm_rldbg(instance, format, arg...) \
+ if (printk_ratelimit()) \
+ atm_printk(KERN_DEBUG, instance , format , ## arg)
#else
#define atm_dbg(instance, format, arg...) \
do {} while (0)
+#define atm_rldbg(instance, format, arg...) \
+ do {} while (0)
#endif
+/* flags, set by mini-driver in bind() */
+
+#define UDSL_SKIP_HEAVY_INIT (1<<0)
+#define UDSL_USE_ISOC (1<<1)
+#define UDSL_IGNORE_EILSEQ (1<<2)
+
+
/* mini driver */
struct usbatm_data;
@@ -86,16 +103,11 @@ struct usbatm_data;
*/
struct usbatm_driver {
- struct module *owner;
-
const char *driver_name;
- /*
- * init device ... can sleep, or cause probe() failure. Drivers with a heavy_init
- * method can avoid having it called by setting need_heavy_init to zero.
- */
+ /* init device ... can sleep, or cause probe() failure */
int (*bind) (struct usbatm_data *, struct usb_interface *,
- const struct usb_device_id *id, int *need_heavy_init);
+ const struct usb_device_id *id);
/* additional device initialization that is too slow to be done in probe() */
int (*heavy_init) (struct usbatm_data *, struct usb_interface *);
@@ -109,8 +121,9 @@ struct usbatm_driver {
/* cleanup ATM device ... can sleep, but can't fail */
void (*atm_stop) (struct usbatm_data *, struct atm_dev *);
- int in; /* rx endpoint */
- int out; /* tx endpoint */
+ int bulk_in; /* bulk rx endpoint */
+ int isoc_in; /* isochronous rx endpoint */
+ int bulk_out; /* bulk tx endpoint */
unsigned rx_padding;
unsigned tx_padding;
@@ -125,6 +138,7 @@ struct usbatm_channel {
int endpoint; /* usb pipe */
unsigned int stride; /* ATM cell size + padding */
unsigned int buf_size; /* urb buffer size */
+ unsigned int packet_size; /* endpoint maxpacket */
spinlock_t lock;
struct list_head list;
struct tasklet_struct tasklet;
@@ -143,6 +157,7 @@ struct usbatm_data {
struct usbatm_driver *driver;
void *driver_data;
char driver_name[16];
+ unsigned int flags; /* set by mini-driver in bind() */
/* USB device */
struct usb_device *usb_dev;
@@ -157,7 +172,8 @@ struct usbatm_data {
********************************/
struct kref refcount;
- struct semaphore serialize;
+ struct mutex serialize;
+ int disconnected;
/* heavy init */
int thread_pid;
@@ -171,7 +187,14 @@ struct usbatm_data {
struct usbatm_channel tx_channel;
struct sk_buff_head sndqueue;
- struct sk_buff *current_skb; /* being emptied */
+ struct sk_buff *current_skb; /* being emptied */
+
+ struct usbatm_vcc_data *cached_vcc;
+ int cached_vci;
+ short cached_vpi;
+
+ unsigned char *cell_buf; /* holds partial rx cell */
+ unsigned int buf_usage;
struct urb *urbs[0];
};
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 5c76e3aaaa5..42d6823b82b 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -41,6 +41,8 @@ XUSBATM_PARM(rx_endpoint, unsigned char, byte, "rx endpoint number");
XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number");
XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)");
XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)");
+XUSBATM_PARM(rx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
+XUSBATM_PARM(tx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
static const char xusbatm_driver_name[] = "xusbatm";
@@ -48,82 +50,118 @@ static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX];
static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];
static struct usb_driver xusbatm_usb_driver;
-static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep)
+static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep)
{
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
int i, j;
- for (i = 0; i < intf->num_altsetting; i++) {
- struct usb_host_interface *alt = intf->altsetting;
- for (j = 0; j < alt->desc.bNumEndpoints; j++)
- if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep)
- return 1;
+ for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++)
+ if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting)))
+ for (j = 0; j < alt->desc.bNumEndpoints; j++)
+ if (alt->endpoint[j].desc.bEndpointAddress == ep)
+ return intf;
+ return NULL;
+}
+
+static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev,
+ struct usb_interface *intf, int altsetting, int claim)
+{
+ int ifnum = intf->altsetting->desc.bInterfaceNumber;
+ int ret;
+
+ if (claim && (ret = usb_driver_claim_interface(&xusbatm_usb_driver, intf, usbatm))) {
+ usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, ifnum, ret);
+ return ret;
+ }
+ if ((ret = usb_set_interface(usb_dev, ifnum, altsetting))) {
+ usb_err(usbatm, "%s: altsetting %2d for interface %2d failed (%d)!\n", __func__, altsetting, ifnum, ret);
+ return ret;
}
return 0;
}
-static int xusbatm_bind(struct usbatm_data *usbatm_instance,
- struct usb_interface *intf, const struct usb_device_id *id,
- int *need_heavy_init)
+static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed)
+{
+ if (claimed) {
+ usb_set_intfdata(intf, NULL);
+ usb_driver_release_interface(&xusbatm_usb_driver, intf);
+ }
+}
+
+static int xusbatm_bind(struct usbatm_data *usbatm,
+ struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *usb_dev = interface_to_usbdev(intf);
int drv_ix = id - xusbatm_usb_ids;
- int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]);
- int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]);
- u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix];
- int i, ret;
-
- usb_dbg(usbatm_instance, "%s: binding driver %d: vendor %#x product %#x"
- " rx: ep %#x padd %d tx: ep %#x padd %d\n",
+ int rx_alt = rx_altsetting[drv_ix];
+ int tx_alt = tx_altsetting[drv_ix];
+ struct usb_interface *rx_intf = xusbatm_find_intf(usb_dev, rx_alt, rx_endpoint[drv_ix]);
+ struct usb_interface *tx_intf = xusbatm_find_intf(usb_dev, tx_alt, tx_endpoint[drv_ix]);
+ int ret;
+
+ usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x"
+ " rx: ep %02x padd %d alt %2d tx: ep %02x padd %d alt %2d\n",
__func__, drv_ix, vendor[drv_ix], product[drv_ix],
- rx_endpoint[drv_ix], rx_padding[drv_ix],
- tx_endpoint[drv_ix], tx_padding[drv_ix]);
+ rx_endpoint[drv_ix], rx_padding[drv_ix], rx_alt,
+ tx_endpoint[drv_ix], tx_padding[drv_ix], tx_alt);
+
+ if (!rx_intf || !tx_intf) {
+ if (!rx_intf)
+ usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
+ __func__, rx_endpoint[drv_ix], rx_alt);
+ if (!tx_intf)
+ usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
+ __func__, tx_endpoint[drv_ix], tx_alt);
+ return -ENODEV;
+ }
- if (!rx_ep_present && !tx_ep_present) {
- usb_dbg(usbatm_instance, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",
- __func__, intf->altsetting->desc.bInterfaceNumber,
- rx_endpoint[drv_ix], tx_endpoint[drv_ix]);
+ if ((rx_intf != intf) && (tx_intf != intf))
return -ENODEV;
+
+ if ((rx_intf == tx_intf) && (rx_alt != tx_alt)) {
+ usb_err(usbatm, "%s: altsettings clash on interface %2d (%2d vs %2d)!\n", __func__,
+ rx_intf->altsetting->desc.bInterfaceNumber, rx_alt, tx_alt);
+ return -EINVAL;
}
- if (rx_ep_present && tx_ep_present)
- return 0;
+ usb_dbg(usbatm, "%s: rx If#=%2d; tx If#=%2d\n", __func__,
+ rx_intf->altsetting->desc.bInterfaceNumber,
+ tx_intf->altsetting->desc.bInterfaceNumber);
- for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
- struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
-
- if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) {
- ret = usb_driver_claim_interface(&xusbatm_usb_driver,
- cur_if, usbatm_instance);
- if (!ret)
- usb_err(usbatm_instance, "%s: failed to claim interface #%d (%d)\n",
- __func__, cur_if->altsetting->desc.bInterfaceNumber, ret);
- return ret;
- }
+ if ((ret = xusbatm_capture_intf(usbatm, usb_dev, rx_intf, rx_alt, rx_intf != intf)))
+ return ret;
+
+ if ((tx_intf != rx_intf) && (ret = xusbatm_capture_intf(usbatm, usb_dev, tx_intf, tx_alt, tx_intf != intf))) {
+ xusbatm_release_intf(usb_dev, rx_intf, rx_intf != intf);
+ return ret;
}
- usb_err(usbatm_instance, "%s: no interface has endpoint %#x\n",
- __func__, searched_ep);
- return -ENODEV;
+ return 0;
}
-static void xusbatm_unbind(struct usbatm_data *usbatm_instance,
+static void xusbatm_unbind(struct usbatm_data *usbatm,
struct usb_interface *intf)
{
struct usb_device *usb_dev = interface_to_usbdev(intf);
int i;
- usb_dbg(usbatm_instance, "%s entered\n", __func__);
+
+ usb_dbg(usbatm, "%s entered\n", __func__);
for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
- struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
- usb_set_intfdata(cur_if, NULL);
- usb_driver_release_interface(&xusbatm_usb_driver, cur_if);
+ struct usb_interface *cur_intf = usb_dev->actconfig->interface[i];
+
+ if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) {
+ usb_set_intfdata(cur_intf, NULL);
+ usb_driver_release_interface(&xusbatm_usb_driver, cur_intf);
+ }
}
}
-static int xusbatm_atm_start(struct usbatm_data *usbatm_instance,
+static int xusbatm_atm_start(struct usbatm_data *usbatm,
struct atm_dev *atm_dev)
{
- atm_dbg(usbatm_instance, "%s entered\n", __func__);
+ atm_dbg(usbatm, "%s entered\n", __func__);
/* use random MAC as we've no way to get it from the device */
random_ether_addr(atm_dev->esi);
@@ -161,18 +199,19 @@ static int __init xusbatm_init(void)
}
for (i = 0; i < num_vendor; i++) {
+ rx_endpoint[i] |= USB_DIR_IN;
+ tx_endpoint[i] &= USB_ENDPOINT_NUMBER_MASK;
+
xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
xusbatm_usb_ids[i].idVendor = vendor[i];
xusbatm_usb_ids[i].idProduct = product[i];
-
- xusbatm_drivers[i].owner = THIS_MODULE;
xusbatm_drivers[i].driver_name = xusbatm_driver_name;
xusbatm_drivers[i].bind = xusbatm_bind;
xusbatm_drivers[i].unbind = xusbatm_unbind;
xusbatm_drivers[i].atm_start = xusbatm_atm_start;
- xusbatm_drivers[i].in = rx_endpoint[i];
- xusbatm_drivers[i].out = tx_endpoint[i];
+ xusbatm_drivers[i].bulk_in = rx_endpoint[i];
+ xusbatm_drivers[i].bulk_out = tx_endpoint[i];
xusbatm_drivers[i].rx_padding = rx_padding[i];
xusbatm_drivers[i].tx_padding = tx_padding[i];
}
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index b9fd39fd1b5..97bdeb1c218 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1014,8 +1014,13 @@ static void acm_disconnect(struct usb_interface *intf)
}
down(&open_sem);
+ if (!usb_get_intfdata(intf)) {
+ up(&open_sem);
+ return;
+ }
acm->dev = NULL;
- usb_set_intfdata (intf, NULL);
+ usb_set_intfdata(acm->control, NULL);
+ usb_set_intfdata(acm->data, NULL);
tasklet_disable(&acm->urb_task);
@@ -1036,7 +1041,7 @@ static void acm_disconnect(struct usb_interface *intf)
for (i = 0; i < ACM_NRB; i++)
usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
- usb_driver_release_interface(&acm_driver, acm->data);
+ usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf);
if (!acm->used) {
acm_tty_unregister(acm);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index dba4cc02607..d34848ac30b 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -7,6 +7,7 @@
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
# Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
# Copyright (c) 2001 David Paschal <paschal@rcsis.com>
+ * Copyright (c) 2006 Oliver Neukum <oliver@neukum.name>
*
* USB Printer Device Class driver for USB printers and printer cables
*
@@ -273,13 +274,16 @@ static void usblp_bulk_read(struct urb *urb, struct pt_regs *regs)
{
struct usblp *usblp = urb->context;
- if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
+ if (unlikely(!usblp || !usblp->dev || !usblp->used))
return;
+ if (unlikely(!usblp->present))
+ goto unplug;
if (unlikely(urb->status))
warn("usblp%d: nonzero read/write bulk status received: %d",
usblp->minor, urb->status);
usblp->rcomplete = 1;
+unplug:
wake_up_interruptible(&usblp->wait);
}
@@ -287,13 +291,15 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs)
{
struct usblp *usblp = urb->context;
- if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
+ if (unlikely(!usblp || !usblp->dev || !usblp->used))
return;
-
+ if (unlikely(!usblp->present))
+ goto unplug;
if (unlikely(urb->status))
warn("usblp%d: nonzero read/write bulk status received: %d",
usblp->minor, urb->status);
usblp->wcomplete = 1;
+unplug:
wake_up_interruptible(&usblp->wait);
}
@@ -627,9 +633,8 @@ done:
static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
- DECLARE_WAITQUEUE(wait, current);
struct usblp *usblp = file->private_data;
- int timeout, err = 0, transfer_length = 0;
+ int timeout, rv, err = 0, transfer_length = 0;
size_t writecount = 0;
while (writecount < count) {
@@ -641,24 +646,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
}
timeout = USBLP_WRITE_TIMEOUT;
- add_wait_queue(&usblp->wait, &wait);
- while ( 1==1 ) {
- if (signal_pending(current)) {
- remove_wait_queue(&usblp->wait, &wait);
- return writecount ? writecount : -EINTR;
- }
- set_current_state(TASK_INTERRUPTIBLE);
- if (timeout && !usblp->wcomplete) {
- timeout = schedule_timeout(timeout);
- } else {
- set_current_state(TASK_RUNNING);
- break;
- }
- }
- remove_wait_queue(&usblp->wait, &wait);
+ rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout);
+ if (rv < 0)
+ return writecount ? writecount : -EINTR;
}
-
down (&usblp->sem);
if (!usblp->present) {
up (&usblp->sem);
@@ -724,7 +716,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
- DECLARE_WAITQUEUE(wait, current);
+ int rv;
if (!usblp->bidir)
return -EINVAL;
@@ -742,26 +734,13 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
count = -EAGAIN;
goto done;
}
-
- add_wait_queue(&usblp->wait, &wait);
- while (1==1) {
- if (signal_pending(current)) {
- count = -EINTR;
- remove_wait_queue(&usblp->wait, &wait);
- goto done;
- }
- up (&usblp->sem);
- set_current_state(TASK_INTERRUPTIBLE);
- if (!usblp->rcomplete) {
- schedule();
- } else {
- set_current_state(TASK_RUNNING);
- down(&usblp->sem);
- break;
- }
- down (&usblp->sem);
+ up(&usblp->sem);
+ rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
+ down(&usblp->sem);
+ if (rv < 0) {
+ count = -EINTR;
+ goto done;
}
- remove_wait_queue(&usblp->wait, &wait);
}
if (!usblp->present) {
@@ -874,11 +853,10 @@ static int usblp_probe(struct usb_interface *intf,
/* Malloc and start initializing usblp structure so we can use it
* directly. */
- if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
+ if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
err("out of memory for usblp");
goto abort;
}
- memset(usblp, 0, sizeof(struct usblp));
usblp->dev = dev;
init_MUTEX (&usblp->sem);
init_waitqueue_head(&usblp->wait);
@@ -1214,10 +1192,9 @@ static int __init usblp_init(void)
{
int retval;
retval = usb_register(&usblp_driver);
- if (retval)
- goto out;
- info(DRIVER_VERSION ": " DRIVER_DESC);
-out:
+ if (!retval)
+ info(DRIVER_VERSION ": " DRIVER_DESC);
+
return retval;
}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 076462c8ba2..dce9d987f0f 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -378,7 +378,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
return NULL;
}
-EXPORT_SYMBOL_GPL(usb_match_id);
+EXPORT_SYMBOL(usb_match_id);
int usb_device_match(struct device *dev, struct device_driver *drv)
{
@@ -446,7 +446,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
return retval;
}
-EXPORT_SYMBOL_GPL(usb_register_driver);
+EXPORT_SYMBOL(usb_register_driver);
/**
* usb_deregister - unregister a USB driver
@@ -469,4 +469,4 @@ void usb_deregister(struct usb_driver *driver)
usbfs_update_special();
}
-EXPORT_SYMBOL_GPL(usb_deregister);
+EXPORT_SYMBOL(usb_deregister);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 319de03944e..7135e542679 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -13,6 +13,7 @@
#include <linux/ctype.h>
#include <linux/device.h>
#include <asm/byteorder.h>
+#include <asm/scatterlist.h>
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 081796726b9..dad4d8fd818 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -468,6 +468,7 @@ int usb_unlink_urb(struct urb *urb)
*/
void usb_kill_urb(struct urb *urb)
{
+ might_sleep();
if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op))
return;
spin_lock_irq(&urb->lock);
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 9a4edc5657a..0aab7d24c76 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -135,6 +135,7 @@ struct dev_data {
setup_out_ready : 1,
setup_out_error : 1,
setup_abort : 1;
+ unsigned setup_wLength;
/* the rest is basically write-once */
struct usb_config_descriptor *config, *hs_config;
@@ -942,6 +943,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
}
req->complete = ep0_complete;
req->length = len;
+ req->zero = 0;
return 0;
}
@@ -1161,10 +1163,13 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
spin_unlock_irq (&dev->lock);
if (copy_from_user (dev->req->buf, buf, len))
retval = -EFAULT;
- else
+ else {
+ if (len < dev->setup_wLength)
+ dev->req->zero = 1;
retval = usb_ep_queue (
dev->gadget->ep0, dev->req,
GFP_KERNEL);
+ }
if (retval < 0) {
spin_lock_irq (&dev->lock);
clean_req (dev->gadget->ep0, dev->req);
@@ -1483,6 +1488,7 @@ unrecognized:
delegate:
dev->setup_in = (ctrl->bRequestType & USB_DIR_IN)
? 1 : 0;
+ dev->setup_wLength = w_length;
dev->setup_out_ready = 0;
dev->setup_out_error = 0;
value = 0;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index c32e1f7476d..67b13ab2f3f 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -47,6 +47,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 2fc110d3ad5..ae7a1c0f574 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -165,8 +165,8 @@ static unsigned buflen = 4096;
static unsigned qlen = 32;
static unsigned pattern = 0;
-module_param (buflen, uint, S_IRUGO|S_IWUSR);
-module_param (qlen, uint, S_IRUGO|S_IWUSR);
+module_param (buflen, uint, S_IRUGO);
+module_param (qlen, uint, S_IRUGO);
module_param (pattern, uint, S_IRUGO|S_IWUSR);
/*
@@ -1127,8 +1127,10 @@ zero_unbind (struct usb_gadget *gadget)
DBG (dev, "unbind\n");
/* we've already been disconnected ... no i/o is active */
- if (dev->req)
+ if (dev->req) {
+ dev->req->length = USB_BUFSIZ;
free_ep_req (gadget->ep0, dev->req);
+ }
del_timer_sync (&dev->resume);
kfree (dev);
set_gadget_data (gadget, NULL);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 08ca0f849da..3a6687df559 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -24,46 +24,11 @@
/*-------------------------------------------------------------------------*/
-/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
- * off the controller (maybe it can boot from highspeed USB disks).
- */
-static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap)
-{
- struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-
- /* always say Linux will own the hardware */
- pci_write_config_byte(pdev, where + 3, 1);
-
- /* maybe wait a while for BIOS to respond */
- if (cap & (1 << 16)) {
- int msec = 5000;
-
- do {
- msleep(10);
- msec -= 10;
- pci_read_config_dword(pdev, where, &cap);
- } while ((cap & (1 << 16)) && msec);
- if (cap & (1 << 16)) {
- ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
- where, cap);
- // some BIOS versions seem buggy...
- // return 1;
- ehci_warn(ehci, "continuing after BIOS bug...\n");
- /* disable all SMIs, and clear "BIOS owns" flag */
- pci_write_config_dword(pdev, where + 4, 0);
- pci_write_config_byte(pdev, where + 2, 0);
- } else
- ehci_dbg(ehci, "BIOS handoff succeeded\n");
- }
- return 0;
-}
-
/* called after powerup, by probe or system-pm "wakeup" */
static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
{
u32 temp;
int retval;
- unsigned count = 256/4;
/* optional debug port, normally in the first BAR */
temp = pci_find_capability(pdev, 0x0a);
@@ -84,32 +49,9 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
}
}
- temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params));
-
- /* EHCI 0.96 and later may have "extended capabilities" */
- while (temp && count--) {
- u32 cap;
-
- pci_read_config_dword(pdev, temp, &cap);
- ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp);
- switch (cap & 0xff) {
- case 1: /* BIOS/SMM/... handoff */
- if (bios_handoff(ehci, temp, cap) != 0)
- return -EOPNOTSUPP;
- break;
- case 0: /* illegal reserved capability */
- ehci_dbg(ehci, "illegal capability!\n");
- cap = 0;
- /* FALLTHROUGH */
- default: /* unknown */
- break;
- }
- temp = (cap >> 8) & 0xff;
- }
- if (!count) {
- ehci_err(ehci, "bogus capabilities ... PCI problems!\n");
- return -EIO;
- }
+ /* we expect static quirk code to handle the "extended capabilities"
+ * (currently just BIOS handoff) allowed starting with EHCI 0.96
+ */
/* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */
retval = pci_set_mwi(pdev);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 57e77374d22..ebcca970067 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1063,6 +1063,7 @@ sitd_slot_ok (
/* for IN, check CSPLIT */
if (stream->c_usecs) {
+ uf = uframe & 7;
max_used = 100 - stream->c_usecs;
do {
tmp = 1 << uf;
@@ -1843,8 +1844,7 @@ done:
#else
static inline int
-sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
- unsigned mem_flags)
+sitd_submit (struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags)
{
ehci_dbg (ehci, "split iso support is disabled\n");
return -ENOSYS;
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 584b8dc6511..972ce04889f 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1420,20 +1420,22 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd)
int ret = 0;
spin_lock_irqsave(&isp116x->lock, flags);
-
val = isp116x_read_reg32(isp116x, HCCONTROL);
+
switch (val & HCCONTROL_HCFS) {
case HCCONTROL_USB_OPER:
+ spin_unlock_irqrestore(&isp116x->lock, flags);
val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
val |= HCCONTROL_USB_SUSPEND;
if (device_may_wakeup(&hcd->self.root_hub->dev))
val |= HCCONTROL_RWE;
/* Wait for usb transfers to finish */
- mdelay(2);
+ msleep(2);
+ spin_lock_irqsave(&isp116x->lock, flags);
isp116x_write_reg32(isp116x, HCCONTROL, val);
+ spin_unlock_irqrestore(&isp116x->lock, flags);
/* Wait for devices to suspend */
- mdelay(5);
- case HCCONTROL_USB_SUSPEND:
+ msleep(5);
break;
case HCCONTROL_USB_RESUME:
isp116x_write_reg32(isp116x, HCCONTROL,
@@ -1441,12 +1443,11 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd)
HCCONTROL_USB_RESET);
case HCCONTROL_USB_RESET:
ret = -EBUSY;
+ default: /* HCCONTROL_USB_SUSPEND */
+ spin_unlock_irqrestore(&isp116x->lock, flags);
break;
- default:
- ret = -EINVAL;
}
- spin_unlock_irqrestore(&isp116x->lock, flags);
return ret;
}
@@ -1715,9 +1716,9 @@ static struct platform_driver isp116x_driver = {
.remove = isp116x_remove,
.suspend = isp116x_suspend,
.resume = isp116x_resume,
- .driver = {
- .name = (char *)hcd_name,
- },
+ .driver = {
+ .name = (char *)hcd_name,
+ },
};
/*-----------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 77cd6ac07e3..db280ca7b7a 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -67,7 +67,7 @@ static void au1xxx_stop_hc(struct platform_device *dev)
": stopping Au1xxx OHCI USB Controller\n");
/* Disable clock */
- au_writel(readl((void *)USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
+ au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
}
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 3ef2c0cdf1d..118288d9442 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -190,9 +190,10 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
msleep(10);
}
if (wait_time <= 0)
- printk(KERN_WARNING "%s %s: early BIOS handoff "
- "failed (BIOS bug ?)\n",
- pdev->dev.bus_id, "OHCI");
+ printk(KERN_WARNING "%s %s: BIOS handoff "
+ "failed (BIOS bug ?) %08x\n",
+ pdev->dev.bus_id, "OHCI",
+ readl(base + OHCI_CONTROL));
/* reset controller, preserving RWC */
writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
@@ -212,8 +213,9 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
{
int wait_time, delta;
void __iomem *base, *op_reg_base;
- u32 hcc_params, val, temp;
- u8 cap_length;
+ u32 hcc_params, val;
+ u8 offset, cap_length;
+ int count = 256/4;
if (!mmio_resource_enabled(pdev, 0))
return;
@@ -224,51 +226,87 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
cap_length = readb(base);
op_reg_base = base + cap_length;
+
+ /* EHCI 0.96 and later may have "extended capabilities"
+ * spec section 5.1 explains the bios handoff, e.g. for
+ * booting from USB disk or using a usb keyboard
+ */
hcc_params = readl(base + EHCI_HCC_PARAMS);
- hcc_params = (hcc_params >> 8) & 0xff;
- if (hcc_params) {
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- &val);
- if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
- /*
- * Ok, BIOS is in smm mode, try to hand off...
+ offset = (hcc_params >> 8) & 0xff;
+ while (offset && count--) {
+ u32 cap;
+ int msec;
+
+ pci_read_config_dword(pdev, offset, &cap);
+ switch (cap & 0xff) {
+ case 1: /* BIOS/SMM/... handoff support */
+ if ((cap & EHCI_USBLEGSUP_BIOS)) {
+ pr_debug("%s %s: BIOS handoff\n",
+ pdev->dev.bus_id, "EHCI");
+
+#if 0
+/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on,
+ * but that seems dubious in general (the BIOS left it off intentionally)
+ * and is known to prevent some systems from booting. so we won't do this
+ * unless maybe we can determine when we're on a system that needs SMI forced.
+ */
+ /* BIOS workaround (?): be sure the
+ * pre-Linux code receives the SMI
+ */
+ pci_read_config_dword(pdev,
+ offset + EHCI_USBLEGCTLSTS,
+ &val);
+ pci_write_config_dword(pdev,
+ offset + EHCI_USBLEGCTLSTS,
+ val | EHCI_USBLEGCTLSTS_SOOE);
+#endif
+ }
+
+ /* always say Linux will own the hardware
+ * by setting EHCI_USBLEGSUP_OS.
*/
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- &temp);
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- temp | EHCI_USBLEGCTLSTS_SOOE);
- val |= EHCI_USBLEGSUP_OS;
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- val);
+ pci_write_config_byte(pdev, offset + 3, 1);
- wait_time = 500;
- do {
+ /* if boot firmware now owns EHCI, spin till
+ * it hands it over.
+ */
+ msec = 5000;
+ while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
msleep(10);
- wait_time -= 10;
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- &val);
- } while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
- if (!wait_time) {
- /*
- * well, possibly buggy BIOS...
+ msec -= 10;
+ pci_read_config_dword(pdev, offset, &cap);
+ }
+
+ if (cap & EHCI_USBLEGSUP_BIOS) {
+ /* well, possibly buggy BIOS... try to shut
+ * it down, and hope nothing goes too wrong
*/
- printk(KERN_WARNING "%s %s: early BIOS handoff "
- "failed (BIOS bug ?)\n",
- pdev->dev.bus_id, "EHCI");
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- EHCI_USBLEGSUP_OS);
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- 0);
+ printk(KERN_WARNING "%s %s: BIOS handoff "
+ "failed (BIOS bug ?) %08x\n",
+ pdev->dev.bus_id, "EHCI", cap);
+ pci_write_config_byte(pdev, offset + 2, 0);
}
+
+ /* just in case, always disable EHCI SMIs */
+ pci_write_config_dword(pdev,
+ offset + EHCI_USBLEGCTLSTS,
+ 0);
+ break;
+ case 0: /* illegal reserved capability */
+ cap = 0;
+ /* FALLTHROUGH */
+ default:
+ printk(KERN_WARNING "%s %s: unrecognized "
+ "capability %02x\n",
+ pdev->dev.bus_id, "EHCI",
+ cap & 0xff);
+ break;
}
+ offset = (cap >> 8) & 0xff;
}
+ if (!count)
+ printk(KERN_DEBUG "%s %s: capability loop?\n",
+ pdev->dev.bus_id, "EHCI");
/*
* halt EHCI & disable its interrupts in any case
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 466384d7c79..134d2000128 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -101,7 +101,7 @@ static struct resource resources[] = {
},
};
-extern struct device_driver sl811h_driver;
+extern struct platform_driver sl811h_driver;
static struct platform_device platform_dev = {
.id = -1,
@@ -132,7 +132,7 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
* initialized already because of the link order dependency created
* by referencing "sl811h_driver".
*/
- platform_dev.name = sl811h_driver.name;
+ platform_dev.name = sl811h_driver.driver.name;
return platform_device_register(&platform_dev);
}
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index b6076004a43..782398045f9 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -672,9 +672,9 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
/* Low-speed transfers get a different queue, and won't hog the bus.
* Also, some devices enumerate better without FSBR; the easiest way
* to do that is to put URBs on the low-speed queue while the device
- * is in the DEFAULT state. */
+ * isn't in the CONFIGURED state. */
if (urb->dev->speed == USB_SPEED_LOW ||
- urb->dev->state == USB_STATE_DEFAULT)
+ urb->dev->state != USB_STATE_CONFIGURED)
skelqh = uhci->skel_ls_control_qh;
else {
skelqh = uhci->skel_fs_control_qh;
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index a91e72c4141..772478086bd 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1307,7 +1307,7 @@ void hid_init_reports(struct hid_device *hid)
}
if (err)
- warn("timeout initializing reports\n");
+ warn("timeout initializing reports");
}
#define USB_VENDOR_ID_WACOM 0x056a
@@ -1435,17 +1435,20 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
#define USB_VENDOR_ID_LD 0x0f11
-#define USB_DEVICE_ID_CASSY 0x1000
-#define USB_DEVICE_ID_POCKETCASSY 0x1010
-#define USB_DEVICE_ID_MOBILECASSY 0x1020
-#define USB_DEVICE_ID_JWM 0x1080
-#define USB_DEVICE_ID_DMMP 0x1081
-#define USB_DEVICE_ID_UMIP 0x1090
-#define USB_DEVICE_ID_VIDEOCOM 0x1200
-#define USB_DEVICE_ID_COM3LAB 0x2000
-#define USB_DEVICE_ID_TELEPORT 0x2010
-#define USB_DEVICE_ID_NETWORKANALYSER 0x2020
-#define USB_DEVICE_ID_POWERCONTROL 0x2030
+#define USB_DEVICE_ID_LD_CASSY 0x1000
+#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010
+#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020
+#define USB_DEVICE_ID_LD_JWM 0x1080
+#define USB_DEVICE_ID_LD_DMMP 0x1081
+#define USB_DEVICE_ID_LD_UMIP 0x1090
+#define USB_DEVICE_ID_LD_XRAY1 0x1100
+#define USB_DEVICE_ID_LD_XRAY2 0x1101
+#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200
+#define USB_DEVICE_ID_LD_COM3LAB 0x2000
+#define USB_DEVICE_ID_LD_TELEPORT 0x2010
+#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
+#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030
+#define USB_DEVICE_ID_LD_MACHINETEST 0x2040
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
@@ -1453,6 +1456,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_CHERRY 0x046a
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
+#define USB_VENDOR_ID_HP 0x03f0
+#define USB_DEVICE_ID_HP_USBHUB_KB 0x020c
+
/*
* Alphabetically sorted blacklist by quirk type.
*/
@@ -1488,17 +1494,20 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
@@ -1566,6 +1575,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET},
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
+ { USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
@@ -1828,9 +1838,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
- /* May be needed for some devices */
- usb_clear_halt(hid->dev, hid->urbin->pipe);
-
return hid;
fail:
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 4dff8473553..925f5aba06f 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -35,7 +35,6 @@
#include <linux/usb.h>
#include "hid.h"
#include <linux/hiddev.h>
-#include <linux/devfs_fs_kernel.h>
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define HIDDEV_MINOR_BASE 0
@@ -632,7 +631,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
(uref_multi->num_values > HID_MAX_MULTI_USAGES ||
- uref->usage_index + uref_multi->num_values >= field->report_count))
+ uref->usage_index + uref_multi->num_values > field->report_count))
goto inval;
}
@@ -832,12 +831,10 @@ static /* const */ struct usb_driver hiddev_driver = {
int __init hiddev_init(void)
{
- devfs_mk_dir("usb/hid");
return usb_register(&hiddev_driver);
}
void hiddev_exit(void)
{
usb_deregister(&hiddev_driver);
- devfs_remove("usb/hid");
}
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 3b3c7b4120a..697c5e573a1 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -337,6 +337,9 @@ static int touchkit_probe(struct usb_interface *intf,
touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
touchkit_irq, touchkit, endpoint->bInterval);
+ touchkit->irq->transfer_dma = touchkit->data_dma;
+ touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
input_register_device(touchkit->input);
usb_set_intfdata(intf, touchkit);
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 1bfc105ad4d..37d2f0ba031 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -59,7 +59,7 @@
#include "map_to_7segment.h"
#include "yealink.h"
-#define DRIVER_VERSION "yld-20050816"
+#define DRIVER_VERSION "yld-20051230"
#define DRIVER_AUTHOR "Henk Vergonet"
#define DRIVER_DESC "Yealink phone driver"
@@ -786,16 +786,25 @@ static struct attribute_group yld_attr_group = {
* Linux interface and usb initialisation
******************************************************************************/
-static const struct yld_device {
- u16 idVendor;
- u16 idProduct;
+struct driver_info {
char *name;
-} yld_device[] = {
- { 0x6993, 0xb001, "Yealink usb-p1k" },
};
-static struct usb_device_id usb_table [] = {
- { USB_INTERFACE_INFO(USB_CLASS_HID, 0, 0) },
+static const struct driver_info info_P1K = {
+ .name = "Yealink usb-p1k",
+};
+
+static const struct usb_device_id usb_table [] = {
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+ USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x6993,
+ .idProduct = 0xb001,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .driver_info = (kernel_ulong_t)&info_P1K
+ },
{ }
};
@@ -842,33 +851,16 @@ static void usb_disconnect(struct usb_interface *intf)
usb_cleanup(yld, 0);
}
-static int usb_match(struct usb_device *udev)
-{
- int i;
- u16 idVendor = le16_to_cpu(udev->descriptor.idVendor);
- u16 idProduct = le16_to_cpu(udev->descriptor.idProduct);
-
- for (i = 0; i < ARRAY_SIZE(yld_device); i++) {
- if ((idVendor == yld_device[i].idVendor) &&
- (idProduct == yld_device[i].idProduct))
- return i;
- }
- return -ENODEV;
-}
-
static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev (intf);
+ struct driver_info *nfo = (struct driver_info *)id->driver_info;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct yealink_dev *yld;
struct input_dev *input_dev;
int ret, pipe, i;
- i = usb_match(udev);
- if (i < 0)
- return -ENODEV;
-
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & USB_DIR_IN))
@@ -915,7 +907,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
if (ret != USB_PKT_LEN)
- err("invalid payload size %d, expected %d", ret, USB_PKT_LEN);
+ err("invalid payload size %d, expected %zd", ret, USB_PKT_LEN);
/* initialise irq urb */
usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data,
@@ -948,7 +940,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
strlcat(yld->phys, "/input0", sizeof(yld->phys));
/* register settings for the input device */
- input_dev->name = yld_device[i].name;
+ input_dev->name = nfo->name;
input_dev->phys = yld->phys;
usb_to_input_id(udev, &input_dev->id);
input_dev->cdev.dev = &intf->dev;
diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
index 21232ee2974..0d3d2cc5d7b 100644
--- a/drivers/usb/media/Kconfig
+++ b/drivers/usb/media/Kconfig
@@ -53,6 +53,21 @@ config USB_DSBR
To compile this driver as a module, choose M here: the
module will be called dsbr100.
+config USB_ET61X251
+ tristate "USB ET61X[12]51 PC Camera Controller support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want support for cameras based on Etoms ET61X151
+ or ET61X251 PC Camera Controllers.
+
+ See <file:Documentation/usb/et61x251.txt> for more informations.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" to use this driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called et61x251.
+
config USB_IBMCAM
tristate "USB IBM (Xirlink) C-it Camera support"
depends on USB && VIDEO_DEV
@@ -209,5 +224,3 @@ config USB_PWC
To compile this driver as a module, choose M here: the
module will be called pwc.
-
-
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index d83adffa925..3957aa1be0f 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -3,9 +3,11 @@
#
sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
+et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
+obj-$(CONFIG_USB_ET61X251) += et61x251.o
obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o
obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o
obj-$(CONFIG_USB_OV511) += ov511.o
diff --git a/drivers/usb/media/et61x251.h b/drivers/usb/media/et61x251.h
new file mode 100644
index 00000000000..652238f329f
--- /dev/null
+++ b/drivers/usb/media/et61x251.h
@@ -0,0 +1,220 @@
+/***************************************************************************
+ * V4L2 driver for ET61X[12]51 PC Camera Controllers *
+ * *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#ifndef _ET61X251_H_
+#define _ET61X251_H_
+
+#include <linux/version.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/types.h>
+#include <linux/param.h>
+#include <linux/rwsem.h>
+#include <asm/semaphore.h>
+
+#include "et61x251_sensor.h"
+
+/*****************************************************************************/
+
+#define ET61X251_DEBUG
+#define ET61X251_DEBUG_LEVEL 2
+#define ET61X251_MAX_DEVICES 64
+#define ET61X251_PRESERVE_IMGSCALE 0
+#define ET61X251_FORCE_MUNMAP 0
+#define ET61X251_MAX_FRAMES 32
+#define ET61X251_COMPRESSION_QUALITY 0
+#define ET61X251_URBS 2
+#define ET61X251_ISO_PACKETS 7
+#define ET61X251_ALTERNATE_SETTING 13
+#define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS)
+#define ET61X251_CTRL_TIMEOUT 100
+
+/*****************************************************************************/
+
+static const struct usb_device_id et61x251_id_table[] = {
+ { USB_DEVICE(0x102c, 0x6151), },
+ { USB_DEVICE(0x102c, 0x6251), },
+ { USB_DEVICE(0x102c, 0x6253), },
+ { USB_DEVICE(0x102c, 0x6254), },
+ { USB_DEVICE(0x102c, 0x6255), },
+ { USB_DEVICE(0x102c, 0x6256), },
+ { USB_DEVICE(0x102c, 0x6257), },
+ { USB_DEVICE(0x102c, 0x6258), },
+ { USB_DEVICE(0x102c, 0x6259), },
+ { USB_DEVICE(0x102c, 0x625a), },
+ { USB_DEVICE(0x102c, 0x625b), },
+ { USB_DEVICE(0x102c, 0x625c), },
+ { USB_DEVICE(0x102c, 0x625d), },
+ { USB_DEVICE(0x102c, 0x625e), },
+ { USB_DEVICE(0x102c, 0x625f), },
+ { USB_DEVICE(0x102c, 0x6260), },
+ { USB_DEVICE(0x102c, 0x6261), },
+ { USB_DEVICE(0x102c, 0x6262), },
+ { USB_DEVICE(0x102c, 0x6263), },
+ { USB_DEVICE(0x102c, 0x6264), },
+ { USB_DEVICE(0x102c, 0x6265), },
+ { USB_DEVICE(0x102c, 0x6266), },
+ { USB_DEVICE(0x102c, 0x6267), },
+ { USB_DEVICE(0x102c, 0x6268), },
+ { USB_DEVICE(0x102c, 0x6269), },
+ { }
+};
+
+ET61X251_SENSOR_TABLE
+
+/*****************************************************************************/
+
+enum et61x251_frame_state {
+ F_UNUSED,
+ F_QUEUED,
+ F_GRABBING,
+ F_DONE,
+ F_ERROR,
+};
+
+struct et61x251_frame_t {
+ void* bufmem;
+ struct v4l2_buffer buf;
+ enum et61x251_frame_state state;
+ struct list_head frame;
+ unsigned long vma_use_count;
+};
+
+enum et61x251_dev_state {
+ DEV_INITIALIZED = 0x01,
+ DEV_DISCONNECTED = 0x02,
+ DEV_MISCONFIGURED = 0x04,
+};
+
+enum et61x251_io_method {
+ IO_NONE,
+ IO_READ,
+ IO_MMAP,
+};
+
+enum et61x251_stream_state {
+ STREAM_OFF,
+ STREAM_INTERRUPT,
+ STREAM_ON,
+};
+
+struct et61x251_sysfs_attr {
+ u8 reg, i2c_reg;
+};
+
+struct et61x251_module_param {
+ u8 force_munmap;
+};
+
+static DECLARE_MUTEX(et61x251_sysfs_lock);
+static DECLARE_RWSEM(et61x251_disconnect);
+
+struct et61x251_device {
+ struct video_device* v4ldev;
+
+ struct et61x251_sensor* sensor;
+
+ struct usb_device* usbdev;
+ struct urb* urb[ET61X251_URBS];
+ void* transfer_buffer[ET61X251_URBS];
+ u8* control_buffer;
+
+ struct et61x251_frame_t *frame_current, frame[ET61X251_MAX_FRAMES];
+ struct list_head inqueue, outqueue;
+ u32 frame_count, nbuffers, nreadbuffers;
+
+ enum et61x251_io_method io;
+ enum et61x251_stream_state stream;
+
+ struct v4l2_jpegcompression compression;
+
+ struct et61x251_sysfs_attr sysfs;
+ struct et61x251_module_param module_param;
+
+ enum et61x251_dev_state state;
+ u8 users;
+
+ struct semaphore dev_sem, fileop_sem;
+ spinlock_t queue_lock;
+ wait_queue_head_t open, wait_frame, wait_stream;
+};
+
+/*****************************************************************************/
+
+void
+et61x251_attach_sensor(struct et61x251_device* cam,
+ struct et61x251_sensor* sensor)
+{
+ cam->sensor = sensor;
+ cam->sensor->usbdev = cam->usbdev;
+}
+
+/*****************************************************************************/
+
+#undef DBG
+#undef KDBG
+#ifdef ET61X251_DEBUG
+# define DBG(level, fmt, args...) \
+do { \
+ if (debug >= (level)) { \
+ if ((level) == 1) \
+ dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
+ else if ((level) == 2) \
+ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
+ else if ((level) >= 3) \
+ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
+ __FUNCTION__, __LINE__ , ## args); \
+ } \
+} while (0)
+# define KDBG(level, fmt, args...) \
+do { \
+ if (debug >= (level)) { \
+ if ((level) == 1 || (level) == 2) \
+ pr_info("et61x251: " fmt "\n", ## args); \
+ else if ((level) == 3) \
+ pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \
+ __LINE__ , ## args); \
+ } \
+} while (0)
+# define V4LDBG(level, name, cmd) \
+do { \
+ if (debug >= (level)) \
+ v4l_print_ioctl(name, cmd); \
+} while (0)
+#else
+# define DBG(level, fmt, args...) do {;} while(0)
+# define KDBG(level, fmt, args...) do {;} while(0)
+# define V4LDBG(level, name, cmd) do {;} while(0)
+#endif
+
+#undef PDBG
+#define PDBG(fmt, args...) \
+dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
+
+#undef PDBGG
+#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+
+#endif /* _ET61X251_H_ */
diff --git a/drivers/usb/media/et61x251_core.c b/drivers/usb/media/et61x251_core.c
new file mode 100644
index 00000000000..2c0171a5ad6
--- /dev/null
+++ b/drivers/usb/media/et61x251_core.c
@@ -0,0 +1,2605 @@
+/***************************************************************************
+ * V4L2 driver for ET61X[12]51 PC Camera Controllers *
+ * *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/stddef.h>
+#include <linux/compiler.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/stat.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/page-flags.h>
+#include <linux/byteorder/generic.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+
+#include "et61x251.h"
+
+/*****************************************************************************/
+
+#define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \
+ "PC Camera Controllers"
+#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia"
+#define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
+#define ET61X251_MODULE_LICENSE "GPL"
+#define ET61X251_MODULE_VERSION "1:1.01"
+#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1)
+
+/*****************************************************************************/
+
+MODULE_DEVICE_TABLE(usb, et61x251_id_table);
+
+MODULE_AUTHOR(ET61X251_MODULE_AUTHOR " " ET61X251_AUTHOR_EMAIL);
+MODULE_DESCRIPTION(ET61X251_MODULE_NAME);
+MODULE_VERSION(ET61X251_MODULE_VERSION);
+MODULE_LICENSE(ET61X251_MODULE_LICENSE);
+
+static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1};
+module_param_array(video_nr, short, NULL, 0444);
+MODULE_PARM_DESC(video_nr,
+ "\n<-1|n[,...]> Specify V4L2 minor mode number."
+ "\n -1 = use next available (default)"
+ "\n n = use minor number n (integer >= 0)"
+ "\nYou can specify up to "
+ __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way."
+ "\nFor example:"
+ "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+ "\nthe second registered camera and use auto for the first"
+ "\none and for every other camera."
+ "\n");
+
+static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] =
+ ET61X251_FORCE_MUNMAP};
+module_param_array(force_munmap, bool, NULL, 0444);
+MODULE_PARM_DESC(force_munmap,
+ "\n<0|1[,...]> Force the application to unmap previously"
+ "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+ "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+ "\nthis feature. This parameter is specific for each"
+ "\ndetected camera."
+ "\n 0 = do not force memory unmapping"
+ "\n 1 = force memory unmapping (save memory)"
+ "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+ "\n");
+
+#ifdef ET61X251_DEBUG
+static unsigned short debug = ET61X251_DEBUG_LEVEL;
+module_param(debug, ushort, 0644);
+MODULE_PARM_DESC(debug,
+ "\n<n> Debugging information level, from 0 to 3:"
+ "\n0 = none (use carefully)"
+ "\n1 = critical errors"
+ "\n2 = significant informations"
+ "\n3 = more verbose messages"
+ "\nLevel 3 is useful for testing only, when only "
+ "one device is used."
+ "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"."
+ "\n");
+#endif
+
+/*****************************************************************************/
+
+static u32
+et61x251_request_buffers(struct et61x251_device* cam, u32 count,
+ enum et61x251_io_method io)
+{
+ struct v4l2_pix_format* p = &(cam->sensor->pix_format);
+ struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
+ const size_t imagesize = cam->module_param.force_munmap ||
+ io == IO_READ ?
+ (p->width * p->height * p->priv) / 8 :
+ (r->width * r->height * p->priv) / 8;
+ void* buff = NULL;
+ u32 i;
+
+ if (count > ET61X251_MAX_FRAMES)
+ count = ET61X251_MAX_FRAMES;
+
+ cam->nbuffers = count;
+ while (cam->nbuffers > 0) {
+ if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+ break;
+ cam->nbuffers--;
+ }
+
+ for (i = 0; i < cam->nbuffers; i++) {
+ cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
+ cam->frame[i].buf.index = i;
+ cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
+ cam->frame[i].buf.length = imagesize;
+ cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cam->frame[i].buf.sequence = 0;
+ cam->frame[i].buf.field = V4L2_FIELD_NONE;
+ cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
+ cam->frame[i].buf.flags = 0;
+ }
+
+ return cam->nbuffers;
+}
+
+
+static void et61x251_release_buffers(struct et61x251_device* cam)
+{
+ if (cam->nbuffers) {
+ vfree(cam->frame[0].bufmem);
+ cam->nbuffers = 0;
+ }
+ cam->frame_current = NULL;
+}
+
+
+static void et61x251_empty_framequeues(struct et61x251_device* cam)
+{
+ u32 i;
+
+ INIT_LIST_HEAD(&cam->inqueue);
+ INIT_LIST_HEAD(&cam->outqueue);
+
+ for (i = 0; i < ET61X251_MAX_FRAMES; i++) {
+ cam->frame[i].state = F_UNUSED;
+ cam->frame[i].buf.bytesused = 0;
+ }
+}
+
+
+static void et61x251_requeue_outqueue(struct et61x251_device* cam)
+{
+ struct et61x251_frame_t *i;
+
+ list_for_each_entry(i, &cam->outqueue, frame) {
+ i->state = F_QUEUED;
+ list_add(&i->frame, &cam->inqueue);
+ }
+
+ INIT_LIST_HEAD(&cam->outqueue);
+}
+
+
+static void et61x251_queue_unusedframes(struct et61x251_device* cam)
+{
+ unsigned long lock_flags;
+ u32 i;
+
+ for (i = 0; i < cam->nbuffers; i++)
+ if (cam->frame[i].state == F_UNUSED) {
+ cam->frame[i].state = F_QUEUED;
+ spin_lock_irqsave(&cam->queue_lock, lock_flags);
+ list_add_tail(&cam->frame[i].frame, &cam->inqueue);
+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+ }
+}
+
+/*****************************************************************************/
+
+int et61x251_write_reg(struct et61x251_device* cam, u8 value, u16 index)
+{
+ struct usb_device* udev = cam->usbdev;
+ u8* buff = cam->control_buffer;
+ int res;
+
+ *buff = value;
+
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
+ if (res < 0) {
+ DBG(3, "Failed to write a register (value 0x%02X, index "
+ "0x%02X, error %d)", value, index, res);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int et61x251_read_reg(struct et61x251_device* cam, u16 index)
+{
+ struct usb_device* udev = cam->usbdev;
+ u8* buff = cam->control_buffer;
+ int res;
+
+ res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
+ 0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+ DBG(3, "Failed to read a register (index 0x%02X, error %d)",
+ index, res);
+
+ return (res >= 0) ? (int)(*buff) : -1;
+}
+
+
+static int
+et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor)
+{
+ int i, r;
+
+ for (i = 1; i <= 8; i++) {
+ if (sensor->interface == ET61X251_I2C_3WIRES) {
+ r = et61x251_read_reg(cam, 0x8e);
+ if (!(r & 0x02) && (r >= 0))
+ return 0;
+ } else {
+ r = et61x251_read_reg(cam, 0x8b);
+ if (!(r & 0x01) && (r >= 0))
+ return 0;
+ }
+ if (r < 0)
+ return -EIO;
+ udelay(8*8); /* minimum for sensors at 400kHz */
+ }
+
+ return -EBUSY;
+}
+
+
+int
+et61x251_i2c_try_read(struct et61x251_device* cam,
+ struct et61x251_sensor* sensor, u8 address)
+{
+ struct usb_device* udev = cam->usbdev;
+ u8* data = cam->control_buffer;
+ int err = 0, res;
+
+ data[0] = address;
+ data[1] = cam->sensor->i2c_slave_id;
+ data[2] = cam->sensor->rsta | 0x10;
+ data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02);
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+ err += res;
+
+ err += et61x251_i2c_wait(cam, sensor);
+
+ res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
+ 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+ err += res;
+
+ if (err)
+ DBG(3, "I2C read failed for %s image sensor", sensor->name);
+
+ PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]);
+
+ return err ? -1 : (int)data[0];
+}
+
+
+int
+et61x251_i2c_try_write(struct et61x251_device* cam,
+ struct et61x251_sensor* sensor, u8 address, u8 value)
+{
+ struct usb_device* udev = cam->usbdev;
+ u8* data = cam->control_buffer;
+ int err = 0, res;
+
+ data[0] = address;
+ data[1] = cam->sensor->i2c_slave_id;
+ data[2] = cam->sensor->rsta | 0x12;
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+ err += res;
+
+ data[0] = value;
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+ err += res;
+
+ err += et61x251_i2c_wait(cam, sensor);
+
+ if (err)
+ DBG(3, "I2C write failed for %s image sensor", sensor->name);
+
+ PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value);
+
+ return err ? -1 : 0;
+}
+
+
+int
+et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2,
+ u8 data3, u8 data4, u8 data5, u8 data6, u8 data7,
+ u8 data8, u8 address)
+{
+ struct usb_device* udev = cam->usbdev;
+ u8* data = cam->control_buffer;
+ int err = 0, res;
+
+ if (!cam->sensor)
+ return -1;
+
+ data[0] = data2;
+ data[1] = data3;
+ data[2] = data4;
+ data[3] = data5;
+ data[4] = data6;
+ data[5] = data7;
+ data[6] = data8;
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+ err += res;
+
+ data[0] = address;
+ data[1] = cam->sensor->i2c_slave_id;
+ data[2] = cam->sensor->rsta | 0x02 | (n << 4);
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+ err += res;
+
+ /* Start writing through the serial interface */
+ data[0] = data1;
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+ err += res;
+
+ err += et61x251_i2c_wait(cam, cam->sensor);
+
+ if (err)
+ DBG(3, "I2C raw write failed for %s image sensor",
+ cam->sensor->name);
+
+ PDBGG("I2C raw write: %u bytes, address = 0x%02X, data1 = 0x%02X, "
+ "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X,"
+ " data6 = 0x%02X, data7 = 0x%02X, data8 = 0x%02X", n, address,
+ data1, data2, data3, data4, data5, data6, data7, data8);
+
+ return err ? -1 : 0;
+
+}
+
+
+int et61x251_i2c_read(struct et61x251_device* cam, u8 address)
+{
+ if (!cam->sensor)
+ return -1;
+
+ return et61x251_i2c_try_read(cam, cam->sensor, address);
+}
+
+
+int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value)
+{
+ if (!cam->sensor)
+ return -1;
+
+ return et61x251_i2c_try_write(cam, cam->sensor, address, value);
+}
+
+/*****************************************************************************/
+
+static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
+{
+ struct et61x251_device* cam = urb->context;
+ struct et61x251_frame_t** f;
+ size_t imagesize;
+ u8 i;
+ int err = 0;
+
+ if (urb->status == -ENOENT)
+ return;
+
+ f = &cam->frame_current;
+
+ if (cam->stream == STREAM_INTERRUPT) {
+ cam->stream = STREAM_OFF;
+ if ((*f))
+ (*f)->state = F_QUEUED;
+ DBG(3, "Stream interrupted");
+ wake_up_interruptible(&cam->wait_stream);
+ }
+
+ if (cam->state & DEV_DISCONNECTED)
+ return;
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ wake_up_interruptible(&cam->wait_frame);
+ return;
+ }
+
+ if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
+ goto resubmit_urb;
+
+ if (!(*f))
+ (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t,
+ frame);
+
+ imagesize = (cam->sensor->pix_format.width *
+ cam->sensor->pix_format.height *
+ cam->sensor->pix_format.priv) / 8;
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ unsigned int len, status;
+ void *pos;
+ u8* b1, * b2, sof;
+ const u8 VOID_BYTES = 6;
+ size_t imglen;
+
+ len = urb->iso_frame_desc[i].actual_length;
+ status = urb->iso_frame_desc[i].status;
+ pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
+
+ if (status) {
+ DBG(3, "Error in isochronous frame");
+ (*f)->state = F_ERROR;
+ continue;
+ }
+
+ b1 = pos++;
+ b2 = pos++;
+ sof = ((*b1 & 0x3f) == 63);
+ imglen = ((*b1 & 0xc0) << 2) | *b2;
+
+ PDBGG("Isochrnous frame: length %u, #%u i, image length %zu",
+ len, i, imglen);
+
+ if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR)
+start_of_frame:
+ if (sof) {
+ (*f)->state = F_GRABBING;
+ (*f)->buf.bytesused = 0;
+ do_gettimeofday(&(*f)->buf.timestamp);
+ pos += 22;
+ DBG(3, "SOF detected: new video frame");
+ }
+
+ if ((*f)->state == F_GRABBING) {
+ if (sof && (*f)->buf.bytesused) {
+ if (cam->sensor->pix_format.pixelformat ==
+ V4L2_PIX_FMT_ET61X251)
+ goto end_of_frame;
+ else {
+ DBG(3, "Not expected SOF detected "
+ "after %lu bytes",
+ (unsigned long)(*f)->buf.bytesused);
+ (*f)->state = F_ERROR;
+ continue;
+ }
+ }
+
+ if ((*f)->buf.bytesused + imglen > imagesize) {
+ DBG(3, "Video frame size exceeded");
+ (*f)->state = F_ERROR;
+ continue;
+ }
+
+ pos += VOID_BYTES;
+
+ memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, imglen);
+ (*f)->buf.bytesused += imglen;
+
+ if ((*f)->buf.bytesused == imagesize) {
+ u32 b;
+end_of_frame:
+ b = (*f)->buf.bytesused;
+ (*f)->state = F_DONE;
+ (*f)->buf.sequence= ++cam->frame_count;
+ spin_lock(&cam->queue_lock);
+ list_move_tail(&(*f)->frame, &cam->outqueue);
+ if (!list_empty(&cam->inqueue))
+ (*f) = list_entry(cam->inqueue.next,
+ struct et61x251_frame_t,
+ frame);
+ else
+ (*f) = NULL;
+ spin_unlock(&cam->queue_lock);
+ DBG(3, "Video frame captured: : %lu bytes",
+ (unsigned long)(b));
+
+ if (!(*f))
+ goto resubmit_urb;
+
+ if (sof &&
+ cam->sensor->pix_format.pixelformat ==
+ V4L2_PIX_FMT_ET61X251)
+ goto start_of_frame;
+ }
+ }
+ }
+
+resubmit_urb:
+ urb->dev = cam->usbdev;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0 && err != -EPERM) {
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "usb_submit_urb() failed");
+ }
+
+ wake_up_interruptible(&cam->wait_frame);
+}
+
+
+static int et61x251_start_transfer(struct et61x251_device* cam)
+{
+ struct usb_device *udev = cam->usbdev;
+ struct urb* urb;
+ const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832,
+ 864, 896, 920, 956, 980, 1000,
+ 1022};
+ const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING];
+ s8 i, j;
+ int err = 0;
+
+ for (i = 0; i < ET61X251_URBS; i++) {
+ cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz,
+ GFP_KERNEL);
+ if (!cam->transfer_buffer[i]) {
+ err = -ENOMEM;
+ DBG(1, "Not enough memory");
+ goto free_buffers;
+ }
+ }
+
+ for (i = 0; i < ET61X251_URBS; i++) {
+ urb = usb_alloc_urb(ET61X251_ISO_PACKETS, GFP_KERNEL);
+ cam->urb[i] = urb;
+ if (!urb) {
+ err = -ENOMEM;
+ DBG(1, "usb_alloc_urb() failed");
+ goto free_urbs;
+ }
+ urb->dev = udev;
+ urb->context = cam;
+ urb->pipe = usb_rcvisocpipe(udev, 1);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->number_of_packets = ET61X251_ISO_PACKETS;
+ urb->complete = et61x251_urb_complete;
+ urb->transfer_buffer = cam->transfer_buffer[i];
+ urb->transfer_buffer_length = psz * ET61X251_ISO_PACKETS;
+ urb->interval = 1;
+ for (j = 0; j < ET61X251_ISO_PACKETS; j++) {
+ urb->iso_frame_desc[j].offset = psz * j;
+ urb->iso_frame_desc[j].length = psz;
+ }
+ }
+
+ err = et61x251_write_reg(cam, 0x01, 0x03);
+ err = et61x251_write_reg(cam, 0x00, 0x03);
+ err = et61x251_write_reg(cam, 0x08, 0x03);
+ if (err) {
+ err = -EIO;
+ DBG(1, "I/O hardware error");
+ goto free_urbs;
+ }
+
+ err = usb_set_interface(udev, 0, ET61X251_ALTERNATE_SETTING);
+ if (err) {
+ DBG(1, "usb_set_interface() failed");
+ goto free_urbs;
+ }
+
+ cam->frame_current = NULL;
+
+ for (i = 0; i < ET61X251_URBS; i++) {
+ err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
+ if (err) {
+ for (j = i-1; j >= 0; j--)
+ usb_kill_urb(cam->urb[j]);
+ DBG(1, "usb_submit_urb() failed, error %d", err);
+ goto free_urbs;
+ }
+ }
+
+ return 0;
+
+free_urbs:
+ for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++)
+ usb_free_urb(cam->urb[i]);
+
+free_buffers:
+ for (i = 0; (i < ET61X251_URBS) && cam->transfer_buffer[i]; i++)
+ kfree(cam->transfer_buffer[i]);
+
+ return err;
+}
+
+
+static int et61x251_stop_transfer(struct et61x251_device* cam)
+{
+ struct usb_device *udev = cam->usbdev;
+ s8 i;
+ int err = 0;
+
+ if (cam->state & DEV_DISCONNECTED)
+ return 0;
+
+ for (i = ET61X251_URBS-1; i >= 0; i--) {
+ usb_kill_urb(cam->urb[i]);
+ usb_free_urb(cam->urb[i]);
+ kfree(cam->transfer_buffer[i]);
+ }
+
+ err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
+ if (err)
+ DBG(3, "usb_set_interface() failed");
+
+ return err;
+}
+
+
+static int et61x251_stream_interrupt(struct et61x251_device* cam)
+{
+ int err = 0;
+
+ cam->stream = STREAM_INTERRUPT;
+ err = wait_event_timeout(cam->wait_stream,
+ (cam->stream == STREAM_OFF) ||
+ (cam->state & DEV_DISCONNECTED),
+ ET61X251_URB_TIMEOUT);
+ if (cam->state & DEV_DISCONNECTED)
+ return -ENODEV;
+ else if (err) {
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "URB timeout reached. The camera is misconfigured. To "
+ "use it, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return err;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count)
+{
+ char str[5];
+ char* endp;
+ unsigned long val;
+
+ if (len < 4) {
+ strncpy(str, buff, len);
+ str[len+1] = '\0';
+ } else {
+ strncpy(str, buff, 4);
+ str[4] = '\0';
+ }
+
+ val = simple_strtoul(str, &endp, 0);
+
+ *count = 0;
+ if (val <= 0xff)
+ *count = (ssize_t)(endp - str);
+ if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
+ *count += 1;
+
+ return (u8)val;
+}
+
+/*
+ NOTE 1: being inside one of the following methods implies that the v4l
+ device exists for sure (see kobjects and reference counters)
+ NOTE 2: buffers are PAGE_SIZE long
+*/
+
+static ssize_t et61x251_show_reg(struct class_device* cd, char* buf)
+{
+ struct et61x251_device* cam;
+ ssize_t count;
+
+ if (down_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+ up(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ count = sprintf(buf, "%u\n", cam->sysfs.reg);
+
+ up(&et61x251_sysfs_lock);
+
+ return count;
+}
+
+
+static ssize_t
+et61x251_store_reg(struct class_device* cd, const char* buf, size_t len)
+{
+ struct et61x251_device* cam;
+ u8 index;
+ ssize_t count;
+
+ if (down_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+ up(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ index = et61x251_strtou8(buf, len, &count);
+ if (index > 0x8e || !count) {
+ up(&et61x251_sysfs_lock);
+ return -EINVAL;
+ }
+
+ cam->sysfs.reg = index;
+
+ DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg);
+ DBG(3, "Written bytes: %zd", count);
+
+ up(&et61x251_sysfs_lock);
+
+ return count;
+}
+
+
+static ssize_t et61x251_show_val(struct class_device* cd, char* buf)
+{
+ struct et61x251_device* cam;
+ ssize_t count;
+ int val;
+
+ if (down_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+ up(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) {
+ up(&et61x251_sysfs_lock);
+ return -EIO;
+ }
+
+ count = sprintf(buf, "%d\n", val);
+
+ DBG(3, "Read bytes: %zd", count);
+
+ up(&et61x251_sysfs_lock);
+
+ return count;
+}
+
+
+static ssize_t
+et61x251_store_val(struct class_device* cd, const char* buf, size_t len)
+{
+ struct et61x251_device* cam;
+ u8 value;
+ ssize_t count;
+ int err;
+
+ if (down_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+ up(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ value = et61x251_strtou8(buf, len, &count);
+ if (!count) {
+ up(&et61x251_sysfs_lock);
+ return -EINVAL;
+ }
+
+ err = et61x251_write_reg(cam, value, cam->sysfs.reg);
+ if (err) {
+ up(&et61x251_sysfs_lock);
+ return -EIO;
+ }
+
+ DBG(2, "Written ET61X[12]51 reg. 0x%02X, val. 0x%02X",
+ cam->sysfs.reg, value);
+ DBG(3, "Written bytes: %zd", count);
+
+ up(&et61x251_sysfs_lock);
+
+ return count;
+}
+
+
+static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf)
+{
+ struct et61x251_device* cam;
+ ssize_t count;
+
+ if (down_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+ up(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
+
+ DBG(3, "Read bytes: %zd", count);
+
+ up(&et61x251_sysfs_lock);
+
+ return count;
+}
+
+
+static ssize_t
+et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
+{
+ struct et61x251_device* cam;
+ u8 index;
+ ssize_t count;
+
+ if (down_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+ up(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ index = et61x251_strtou8(buf, len, &count);
+ if (!count) {
+ up(&et61x251_sysfs_lock);
+ return -EINVAL;
+ }
+
+ cam->sysfs.i2c_reg = index;
+
+ DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
+ DBG(3, "Written bytes: %zd", count);
+
+ up(&et61x251_sysfs_lock);
+
+ return count;
+}
+
+
+static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf)
+{
+ struct et61x251_device* cam;
+ ssize_t count;
+ int val;
+
+ if (down_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+ up(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) {
+ up(&et61x251_sysfs_lock);
+ return -ENOSYS;
+ }
+
+ if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {
+ up(&et61x251_sysfs_lock);
+ return -EIO;
+ }
+
+ count = sprintf(buf, "%d\n", val);
+
+ DBG(3, "Read bytes: %zd", count);
+
+ up(&et61x251_sysfs_lock);
+
+ return count;
+}
+
+
+static ssize_t
+et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
+{
+ struct et61x251_device* cam;
+ u8 value;
+ ssize_t count;
+ int err;
+
+ if (down_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+ up(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) {
+ up(&et61x251_sysfs_lock);
+ return -ENOSYS;
+ }
+
+ value = et61x251_strtou8(buf, len, &count);
+ if (!count) {
+ up(&et61x251_sysfs_lock);
+ return -EINVAL;
+ }
+
+ err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value);
+ if (err) {
+ up(&et61x251_sysfs_lock);
+ return -EIO;
+ }
+
+ DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
+ cam->sysfs.i2c_reg, value);
+ DBG(3, "Written bytes: %zd", count);
+
+ up(&et61x251_sysfs_lock);
+
+ return count;
+}
+
+
+static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
+ et61x251_show_reg, et61x251_store_reg);
+static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
+ et61x251_show_val, et61x251_store_val);
+static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
+ et61x251_show_i2c_reg, et61x251_store_i2c_reg);
+static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
+ et61x251_show_i2c_val, et61x251_store_i2c_val);
+
+
+static void et61x251_create_sysfs(struct et61x251_device* cam)
+{
+ struct video_device *v4ldev = cam->v4ldev;
+
+ video_device_create_file(v4ldev, &class_device_attr_reg);
+ video_device_create_file(v4ldev, &class_device_attr_val);
+ if (cam->sensor && cam->sensor->sysfs_ops) {
+ video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
+ video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+ }
+}
+#endif /* CONFIG_VIDEO_ADV_DEBUG */
+
+/*****************************************************************************/
+
+static int
+et61x251_set_pix_format(struct et61x251_device* cam,
+ struct v4l2_pix_format* pix)
+{
+ int r, err = 0;
+
+ if ((r = et61x251_read_reg(cam, 0x12)) < 0)
+ err += r;
+ if (pix->pixelformat == V4L2_PIX_FMT_ET61X251)
+ err += et61x251_write_reg(cam, r & 0xfd, 0x12);
+ else
+ err += et61x251_write_reg(cam, r | 0x02, 0x12);
+
+ return err ? -EIO : 0;
+}
+
+
+static int
+et61x251_set_compression(struct et61x251_device* cam,
+ struct v4l2_jpegcompression* compression)
+{
+ int r, err = 0;
+
+ if ((r = et61x251_read_reg(cam, 0x12)) < 0)
+ err += r;
+ if (compression->quality == 0)
+ err += et61x251_write_reg(cam, r & 0xfb, 0x12);
+ else
+ err += et61x251_write_reg(cam, r | 0x04, 0x12);
+
+ return err ? -EIO : 0;
+}
+
+
+static int et61x251_set_scale(struct et61x251_device* cam, u8 scale)
+{
+ int r = 0, err = 0;
+
+ r = et61x251_read_reg(cam, 0x12);
+ if (r < 0)
+ err += r;
+
+ if (scale == 1)
+ err += et61x251_write_reg(cam, r & ~0x01, 0x12);
+ else if (scale == 2)
+ err += et61x251_write_reg(cam, r | 0x01, 0x12);
+
+ if (err)
+ return -EIO;
+
+ PDBGG("Scaling factor: %u", scale);
+
+ return 0;
+}
+
+
+static int
+et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect)
+{
+ struct et61x251_sensor* s = cam->sensor;
+ u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left +
+ s->active_pixel.left),
+ fmw_sy = (u16)(rect->top - s->cropcap.bounds.top +
+ s->active_pixel.top),
+ fmw_length = (u16)(rect->width),
+ fmw_height = (u16)(rect->height);
+ int err = 0;
+
+ err += et61x251_write_reg(cam, fmw_sx & 0xff, 0x69);
+ err += et61x251_write_reg(cam, fmw_sy & 0xff, 0x6a);
+ err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b);
+ err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c);
+ err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6)
+ | ((fmw_length & 0x300) >> 4)
+ | ((fmw_height & 0x300) >> 2), 0x6d);
+ if (err)
+ return -EIO;
+
+ PDBGG("fmw_sx, fmw_sy, fmw_length, fmw_height: %u %u %u %u",
+ fmw_sx, fmw_sy, fmw_length, fmw_height);
+
+ return 0;
+}
+
+
+static int et61x251_init(struct et61x251_device* cam)
+{
+ struct et61x251_sensor* s = cam->sensor;
+ struct v4l2_control ctrl;
+ struct v4l2_queryctrl *qctrl;
+ struct v4l2_rect* rect;
+ u8 i = 0;
+ int err = 0;
+
+ if (!(cam->state & DEV_INITIALIZED)) {
+ init_waitqueue_head(&cam->open);
+ qctrl = s->qctrl;
+ rect = &(s->cropcap.defrect);
+ cam->compression.quality = ET61X251_COMPRESSION_QUALITY;
+ } else { /* use current values */
+ qctrl = s->_qctrl;
+ rect = &(s->_rect);
+ }
+
+ err += et61x251_set_scale(cam, rect->width / s->pix_format.width);
+ err += et61x251_set_crop(cam, rect);
+ if (err)
+ return err;
+
+ if (s->init) {
+ err = s->init(cam);
+ if (err) {
+ DBG(3, "Sensor initialization failed");
+ return err;
+ }
+ }
+
+ err += et61x251_set_compression(cam, &cam->compression);
+ err += et61x251_set_pix_format(cam, &s->pix_format);
+ if (s->set_pix_format)
+ err += s->set_pix_format(cam, &s->pix_format);
+ if (err)
+ return err;
+
+ if (s->pix_format.pixelformat == V4L2_PIX_FMT_ET61X251)
+ DBG(3, "Compressed video format is active, quality %d",
+ cam->compression.quality);
+ else
+ DBG(3, "Uncompressed video format is active");
+
+ if (s->set_crop)
+ if ((err = s->set_crop(cam, rect))) {
+ DBG(3, "set_crop() failed");
+ return err;
+ }
+
+ if (s->set_ctrl) {
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (s->qctrl[i].id != 0 &&
+ !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
+ ctrl.id = s->qctrl[i].id;
+ ctrl.value = qctrl[i].default_value;
+ err = s->set_ctrl(cam, &ctrl);
+ if (err) {
+ DBG(3, "Set %s control failed",
+ s->qctrl[i].name);
+ return err;
+ }
+ DBG(3, "Image sensor supports '%s' control",
+ s->qctrl[i].name);
+ }
+ }
+
+ if (!(cam->state & DEV_INITIALIZED)) {
+ init_MUTEX(&cam->fileop_sem);
+ spin_lock_init(&cam->queue_lock);
+ init_waitqueue_head(&cam->wait_frame);
+ init_waitqueue_head(&cam->wait_stream);
+ cam->nreadbuffers = 2;
+ memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
+ memcpy(&(s->_rect), &(s->cropcap.defrect),
+ sizeof(struct v4l2_rect));
+ cam->state |= DEV_INITIALIZED;
+ }
+
+ DBG(2, "Initialization succeeded");
+ return 0;
+}
+
+
+static void et61x251_release_resources(struct et61x251_device* cam)
+{
+ down(&et61x251_sysfs_lock);
+
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ video_set_drvdata(cam->v4ldev, NULL);
+ video_unregister_device(cam->v4ldev);
+
+ up(&et61x251_sysfs_lock);
+
+ kfree(cam->control_buffer);
+}
+
+/*****************************************************************************/
+
+static int et61x251_open(struct inode* inode, struct file* filp)
+{
+ struct et61x251_device* cam;
+ int err = 0;
+
+ /*
+ This is the only safe way to prevent race conditions with
+ disconnect
+ */
+ if (!down_read_trylock(&et61x251_disconnect))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(video_devdata(filp));
+
+ if (down_interruptible(&cam->dev_sem)) {
+ up_read(&et61x251_disconnect);
+ return -ERESTARTSYS;
+ }
+
+ if (cam->users) {
+ DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (filp->f_flags & O_NDELAY)) {
+ err = -EWOULDBLOCK;
+ goto out;
+ }
+ up(&cam->dev_sem);
+ err = wait_event_interruptible_exclusive(cam->open,
+ cam->state & DEV_DISCONNECTED
+ || !cam->users);
+ if (err) {
+ up_read(&et61x251_disconnect);
+ return err;
+ }
+ if (cam->state & DEV_DISCONNECTED) {
+ up_read(&et61x251_disconnect);
+ return -ENODEV;
+ }
+ down(&cam->dev_sem);
+ }
+
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ err = et61x251_init(cam);
+ if (err) {
+ DBG(1, "Initialization failed again. "
+ "I will retry on next open().");
+ goto out;
+ }
+ cam->state &= ~DEV_MISCONFIGURED;
+ }
+
+ if ((err = et61x251_start_transfer(cam)))
+ goto out;
+
+ filp->private_data = cam;
+ cam->users++;
+ cam->io = IO_NONE;
+ cam->stream = STREAM_OFF;
+ cam->nbuffers = 0;
+ cam->frame_count = 0;
+ et61x251_empty_framequeues(cam);
+
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+
+out:
+ up(&cam->dev_sem);
+ up_read(&et61x251_disconnect);
+ return err;
+}
+
+
+static int et61x251_release(struct inode* inode, struct file* filp)
+{
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+
+ down(&cam->dev_sem); /* prevent disconnect() to be called */
+
+ et61x251_stop_transfer(cam);
+
+ et61x251_release_buffers(cam);
+
+ if (cam->state & DEV_DISCONNECTED) {
+ et61x251_release_resources(cam);
+ up(&cam->dev_sem);
+ kfree(cam);
+ return 0;
+ }
+
+ cam->users--;
+ wake_up_interruptible_nr(&cam->open, 1);
+
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+
+ up(&cam->dev_sem);
+
+ return 0;
+}
+
+
+static ssize_t
+et61x251_read(struct file* filp, char __user * buf,
+ size_t count, loff_t* f_pos)
+{
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_frame_t* f, * i;
+ unsigned long lock_flags;
+ int err = 0;
+
+ if (down_interruptible(&cam->fileop_sem))
+ return -ERESTARTSYS;
+
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+ up(&cam->fileop_sem);
+ return -ENODEV;
+ }
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
+ up(&cam->fileop_sem);
+ return -EIO;
+ }
+
+ if (cam->io == IO_MMAP) {
+ DBG(3, "Close and open the device again to choose the read "
+ "method");
+ up(&cam->fileop_sem);
+ return -EINVAL;
+ }
+
+ if (cam->io == IO_NONE) {
+ if (!et61x251_request_buffers(cam, cam->nreadbuffers,
+ IO_READ)) {
+ DBG(1, "read() failed, not enough memory");
+ up(&cam->fileop_sem);
+ return -ENOMEM;
+ }
+ cam->io = IO_READ;
+ cam->stream = STREAM_ON;
+ }
+
+ if (list_empty(&cam->inqueue)) {
+ if (!list_empty(&cam->outqueue))
+ et61x251_empty_framequeues(cam);
+ et61x251_queue_unusedframes(cam);
+ }
+
+ if (!count) {
+ up(&cam->fileop_sem);
+ return 0;
+ }
+
+ if (list_empty(&cam->outqueue)) {
+ if (filp->f_flags & O_NONBLOCK) {
+ up(&cam->fileop_sem);
+ return -EAGAIN;
+ }
+ err = wait_event_interruptible
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED) );
+ if (err) {
+ up(&cam->fileop_sem);
+ return err;
+ }
+ if (cam->state & DEV_DISCONNECTED) {
+ up(&cam->fileop_sem);
+ return -ENODEV;
+ }
+ if (cam->state & DEV_MISCONFIGURED) {
+ up(&cam->fileop_sem);
+ return -EIO;
+ }
+ }
+
+ f = list_entry(cam->outqueue.prev, struct et61x251_frame_t, frame);
+
+ if (count > f->buf.bytesused)
+ count = f->buf.bytesused;
+
+ if (copy_to_user(buf, f->bufmem, count)) {
+ err = -EFAULT;
+ goto exit;
+ }
+ *f_pos += count;
+
+exit:
+ spin_lock_irqsave(&cam->queue_lock, lock_flags);
+ list_for_each_entry(i, &cam->outqueue, frame)
+ i->state = F_UNUSED;
+ INIT_LIST_HEAD(&cam->outqueue);
+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+ et61x251_queue_unusedframes(cam);
+
+ PDBGG("Frame #%lu, bytes read: %zu",
+ (unsigned long)f->buf.index, count);
+
+ up(&cam->fileop_sem);
+
+ return err ? err : count;
+}
+
+
+static unsigned int et61x251_poll(struct file *filp, poll_table *wait)
+{
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_frame_t* f;
+ unsigned long lock_flags;
+ unsigned int mask = 0;
+
+ if (down_interruptible(&cam->fileop_sem))
+ return POLLERR;
+
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+ goto error;
+ }
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
+ goto error;
+ }
+
+ if (cam->io == IO_NONE) {
+ if (!et61x251_request_buffers(cam, cam->nreadbuffers,
+ IO_READ)) {
+ DBG(1, "poll() failed, not enough memory");
+ goto error;
+ }
+ cam->io = IO_READ;
+ cam->stream = STREAM_ON;
+ }
+
+ if (cam->io == IO_READ) {
+ spin_lock_irqsave(&cam->queue_lock, lock_flags);
+ list_for_each_entry(f, &cam->outqueue, frame)
+ f->state = F_UNUSED;
+ INIT_LIST_HEAD(&cam->outqueue);
+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+ et61x251_queue_unusedframes(cam);
+ }
+
+ poll_wait(filp, &cam->wait_frame, wait);
+
+ if (!list_empty(&cam->outqueue))
+ mask |= POLLIN | POLLRDNORM;
+
+ up(&cam->fileop_sem);
+
+ return mask;
+
+error:
+ up(&cam->fileop_sem);
+ return POLLERR;
+}
+
+
+static void et61x251_vm_open(struct vm_area_struct* vma)
+{
+ struct et61x251_frame_t* f = vma->vm_private_data;
+ f->vma_use_count++;
+}
+
+
+static void et61x251_vm_close(struct vm_area_struct* vma)
+{
+ /* NOTE: buffers are not freed here */
+ struct et61x251_frame_t* f = vma->vm_private_data;
+ f->vma_use_count--;
+}
+
+
+static struct vm_operations_struct et61x251_vm_ops = {
+ .open = et61x251_vm_open,
+ .close = et61x251_vm_close,
+};
+
+
+static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
+{
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ unsigned long size = vma->vm_end - vma->vm_start,
+ start = vma->vm_start;
+ void *pos;
+ u32 i;
+
+ if (down_interruptible(&cam->fileop_sem))
+ return -ERESTARTSYS;
+
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+ up(&cam->fileop_sem);
+ return -ENODEV;
+ }
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
+ up(&cam->fileop_sem);
+ return -EIO;
+ }
+
+ if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
+ size != PAGE_ALIGN(cam->frame[0].buf.length)) {
+ up(&cam->fileop_sem);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cam->nbuffers; i++) {
+ if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
+ break;
+ }
+ if (i == cam->nbuffers) {
+ up(&cam->fileop_sem);
+ return -EINVAL;
+ }
+
+ vma->vm_flags |= VM_IO;
+ vma->vm_flags |= VM_RESERVED;
+
+ pos = cam->frame[i].bufmem;
+ while (size > 0) { /* size is page-aligned */
+ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+ up(&cam->fileop_sem);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ vma->vm_ops = &et61x251_vm_ops;
+ vma->vm_private_data = &cam->frame[i];
+
+ et61x251_vm_open(vma);
+
+ up(&cam->fileop_sem);
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static int
+et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_capability cap = {
+ .driver = "et61x251",
+ .version = ET61X251_MODULE_VERSION_CODE,
+ .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING,
+ };
+
+ strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
+ if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
+ strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
+ sizeof(cap.bus_info));
+
+ if (copy_to_user(arg, &cap, sizeof(cap)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_input i;
+
+ if (copy_from_user(&i, arg, sizeof(i)))
+ return -EFAULT;
+
+ if (i.index)
+ return -EINVAL;
+
+ memset(&i, 0, sizeof(i));
+ strcpy(i.name, "Camera");
+
+ if (copy_to_user(arg, &i, sizeof(i)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_gs_input(struct et61x251_device* cam, void __user * arg)
+{
+ int index;
+
+ if (copy_from_user(&index, arg, sizeof(index)))
+ return -EFAULT;
+
+ if (index != 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg)
+{
+ struct et61x251_sensor* s = cam->sensor;
+ struct v4l2_queryctrl qc;
+ u8 i;
+
+ if (copy_from_user(&qc, arg, sizeof(qc)))
+ return -EFAULT;
+
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (qc.id && qc.id == s->qctrl[i].id) {
+ memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
+ if (copy_to_user(arg, &qc, sizeof(qc)))
+ return -EFAULT;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+
+static int
+et61x251_vidioc_g_ctrl(struct et61x251_device* cam, void __user * arg)
+{
+ struct et61x251_sensor* s = cam->sensor;
+ struct v4l2_control ctrl;
+ int err = 0;
+ u8 i;
+
+ if (!s->get_ctrl && !s->set_ctrl)
+ return -EINVAL;
+
+ if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+ return -EFAULT;
+
+ if (!s->get_ctrl) {
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (ctrl.id == s->qctrl[i].id) {
+ ctrl.value = s->_qctrl[i].default_value;
+ goto exit;
+ }
+ return -EINVAL;
+ } else
+ err = s->get_ctrl(cam, &ctrl);
+
+exit:
+ if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
+ return -EFAULT;
+
+ return err;
+}
+
+
+static int
+et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg)
+{
+ struct et61x251_sensor* s = cam->sensor;
+ struct v4l2_control ctrl;
+ u8 i;
+ int err = 0;
+
+ if (!s->set_ctrl)
+ return -EINVAL;
+
+ if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+ return -EFAULT;
+
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (ctrl.id == s->qctrl[i].id) {
+ if (ctrl.value < s->qctrl[i].minimum ||
+ ctrl.value > s->qctrl[i].maximum)
+ return -ERANGE;
+ ctrl.value -= ctrl.value % s->qctrl[i].step;
+ break;
+ }
+
+ if ((err = s->set_ctrl(cam, &ctrl)))
+ return err;
+
+ s->_qctrl[i].default_value = ctrl.value;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
+
+ cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cc->pixelaspect.numerator = 1;
+ cc->pixelaspect.denominator = 1;
+
+ if (copy_to_user(arg, cc, sizeof(*cc)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg)
+{
+ struct et61x251_sensor* s = cam->sensor;
+ struct v4l2_crop crop = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ };
+
+ memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
+
+ if (copy_to_user(arg, &crop, sizeof(crop)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
+{
+ struct et61x251_sensor* s = cam->sensor;
+ struct v4l2_crop crop;
+ struct v4l2_rect* rect;
+ struct v4l2_rect* bounds = &(s->cropcap.bounds);
+ struct v4l2_pix_format* pix_format = &(s->pix_format);
+ u8 scale;
+ const enum et61x251_stream_state stream = cam->stream;
+ const u32 nbuffers = cam->nbuffers;
+ u32 i;
+ int err = 0;
+
+ if (copy_from_user(&crop, arg, sizeof(crop)))
+ return -EFAULT;
+
+ rect = &(crop.c);
+
+ if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (cam->module_param.force_munmap)
+ for (i = 0; i < cam->nbuffers; i++)
+ if (cam->frame[i].vma_use_count) {
+ DBG(3, "VIDIOC_S_CROP failed. "
+ "Unmap the buffers first.");
+ return -EINVAL;
+ }
+
+ /* Preserve R,G or B origin */
+ rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
+ rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
+
+ if (rect->width < 4)
+ rect->width = 4;
+ if (rect->height < 4)
+ rect->height = 4;
+ if (rect->width > bounds->width)
+ rect->width = bounds->width;
+ if (rect->height > bounds->height)
+ rect->height = bounds->height;
+ if (rect->left < bounds->left)
+ rect->left = bounds->left;
+ if (rect->top < bounds->top)
+ rect->top = bounds->top;
+ if (rect->left + rect->width > bounds->left + bounds->width)
+ rect->left = bounds->left+bounds->width - rect->width;
+ if (rect->top + rect->height > bounds->top + bounds->height)
+ rect->top = bounds->top+bounds->height - rect->height;
+
+ rect->width &= ~3L;
+ rect->height &= ~3L;
+
+ if (ET61X251_PRESERVE_IMGSCALE) {
+ /* Calculate the actual scaling factor */
+ u32 a, b;
+ a = rect->width * rect->height;
+ b = pix_format->width * pix_format->height;
+ scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1;
+ } else
+ scale = 1;
+
+ if (cam->stream == STREAM_ON)
+ if ((err = et61x251_stream_interrupt(cam)))
+ return err;
+
+ if (copy_to_user(arg, &crop, sizeof(crop))) {
+ cam->stream = stream;
+ return -EFAULT;
+ }
+
+ if (cam->module_param.force_munmap || cam->io == IO_READ)
+ et61x251_release_buffers(cam);
+
+ err = et61x251_set_crop(cam, rect);
+ if (s->set_crop)
+ err += s->set_crop(cam, rect);
+ err += et61x251_set_scale(cam, scale);
+
+ if (err) { /* atomic, no rollback in ioctl() */
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
+ "use the camera, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return -EIO;
+ }
+
+ s->pix_format.width = rect->width/scale;
+ s->pix_format.height = rect->height/scale;
+ memcpy(&(s->_rect), rect, sizeof(*rect));
+
+ if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
+ nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) {
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
+ "use the camera, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return -ENOMEM;
+ }
+
+ if (cam->io == IO_READ)
+ et61x251_empty_framequeues(cam);
+ else if (cam->module_param.force_munmap)
+ et61x251_requeue_outqueue(cam);
+
+ cam->stream = stream;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_fmtdesc fmtd;
+
+ if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
+ return -EFAULT;
+
+ if (fmtd.index == 0) {
+ strcpy(fmtd.description, "bayer rgb");
+ fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
+ } else if (fmtd.index == 1) {
+ strcpy(fmtd.description, "compressed");
+ fmtd.pixelformat = V4L2_PIX_FMT_ET61X251;
+ fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
+ } else
+ return -EINVAL;
+
+ fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
+
+ if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_format format;
+ struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
+
+ if (copy_from_user(&format, arg, sizeof(format)))
+ return -EFAULT;
+
+ if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251)
+ ? 0 : (pfmt->width * pfmt->priv) / 8;
+ pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
+ pfmt->field = V4L2_FIELD_NONE;
+ memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
+
+ if (copy_to_user(arg, &format, sizeof(format)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
+ void __user * arg)
+{
+ struct et61x251_sensor* s = cam->sensor;
+ struct v4l2_format format;
+ struct v4l2_pix_format* pix;
+ struct v4l2_pix_format* pfmt = &(s->pix_format);
+ struct v4l2_rect* bounds = &(s->cropcap.bounds);
+ struct v4l2_rect rect;
+ u8 scale;
+ const enum et61x251_stream_state stream = cam->stream;
+ const u32 nbuffers = cam->nbuffers;
+ u32 i;
+ int err = 0;
+
+ if (copy_from_user(&format, arg, sizeof(format)))
+ return -EFAULT;
+
+ pix = &(format.fmt.pix);
+
+ if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ memcpy(&rect, &(s->_rect), sizeof(rect));
+
+ { /* calculate the actual scaling factor */
+ u32 a, b;
+ a = rect.width * rect.height;
+ b = pix->width * pix->height;
+ scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1;
+ }
+
+ rect.width = scale * pix->width;
+ rect.height = scale * pix->height;
+
+ if (rect.width < 4)
+ rect.width = 4;
+ if (rect.height < 4)
+ rect.height = 4;
+ if (rect.width > bounds->left + bounds->width - rect.left)
+ rect.width = bounds->left + bounds->width - rect.left;
+ if (rect.height > bounds->top + bounds->height - rect.top)
+ rect.height = bounds->top + bounds->height - rect.top;
+
+ rect.width &= ~3L;
+ rect.height &= ~3L;
+
+ { /* adjust the scaling factor */
+ u32 a, b;
+ a = rect.width * rect.height;
+ b = pix->width * pix->height;
+ scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1;
+ }
+
+ pix->width = rect.width / scale;
+ pix->height = rect.height / scale;
+
+ if (pix->pixelformat != V4L2_PIX_FMT_ET61X251 &&
+ pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+ pix->pixelformat = pfmt->pixelformat;
+ pix->priv = pfmt->priv; /* bpp */
+ pix->colorspace = pfmt->colorspace;
+ pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251)
+ ? 0 : (pix->width * pix->priv) / 8;
+ pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
+ pix->field = V4L2_FIELD_NONE;
+
+ if (cmd == VIDIOC_TRY_FMT) {
+ if (copy_to_user(arg, &format, sizeof(format)))
+ return -EFAULT;
+ return 0;
+ }
+
+ if (cam->module_param.force_munmap)
+ for (i = 0; i < cam->nbuffers; i++)
+ if (cam->frame[i].vma_use_count) {
+ DBG(3, "VIDIOC_S_FMT failed. "
+ "Unmap the buffers first.");
+ return -EINVAL;
+ }
+
+ if (cam->stream == STREAM_ON)
+ if ((err = et61x251_stream_interrupt(cam)))
+ return err;
+
+ if (copy_to_user(arg, &format, sizeof(format))) {
+ cam->stream = stream;
+ return -EFAULT;
+ }
+
+ if (cam->module_param.force_munmap || cam->io == IO_READ)
+ et61x251_release_buffers(cam);
+
+ err += et61x251_set_pix_format(cam, pix);
+ err += et61x251_set_crop(cam, &rect);
+ if (s->set_pix_format)
+ err += s->set_pix_format(cam, pix);
+ if (s->set_crop)
+ err += s->set_crop(cam, &rect);
+ err += et61x251_set_scale(cam, scale);
+
+ if (err) { /* atomic, no rollback in ioctl() */
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
+ "use the camera, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return -EIO;
+ }
+
+ memcpy(pfmt, pix, sizeof(*pix));
+ memcpy(&(s->_rect), &rect, sizeof(rect));
+
+ if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
+ nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) {
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
+ "use the camera, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return -ENOMEM;
+ }
+
+ if (cam->io == IO_READ)
+ et61x251_empty_framequeues(cam);
+ else if (cam->module_param.force_munmap)
+ et61x251_requeue_outqueue(cam);
+
+ cam->stream = stream;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg)
+{
+ if (copy_to_user(arg, &cam->compression,
+ sizeof(cam->compression)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_jpegcompression jc;
+ const enum et61x251_stream_state stream = cam->stream;
+ int err = 0;
+
+ if (copy_from_user(&jc, arg, sizeof(jc)))
+ return -EFAULT;
+
+ if (jc.quality != 0 && jc.quality != 1)
+ return -EINVAL;
+
+ if (cam->stream == STREAM_ON)
+ if ((err = et61x251_stream_interrupt(cam)))
+ return err;
+
+ err += et61x251_set_compression(cam, &jc);
+ if (err) { /* atomic, no rollback in ioctl() */
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
+ "problems. To use the camera, close and open "
+ "/dev/video%d again.", cam->v4ldev->minor);
+ return -EIO;
+ }
+
+ cam->compression.quality = jc.quality;
+
+ cam->stream = stream;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_reqbufs(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_requestbuffers rb;
+ u32 i;
+ int err;
+
+ if (copy_from_user(&rb, arg, sizeof(rb)))
+ return -EFAULT;
+
+ if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ rb.memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
+
+ if (cam->io == IO_READ) {
+ DBG(3, "Close and open the device again to choose the mmap "
+ "I/O method");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cam->nbuffers; i++)
+ if (cam->frame[i].vma_use_count) {
+ DBG(3, "VIDIOC_REQBUFS failed. "
+ "Previous buffers are still mapped.");
+ return -EINVAL;
+ }
+
+ if (cam->stream == STREAM_ON)
+ if ((err = et61x251_stream_interrupt(cam)))
+ return err;
+
+ et61x251_empty_framequeues(cam);
+
+ et61x251_release_buffers(cam);
+ if (rb.count)
+ rb.count = et61x251_request_buffers(cam, rb.count, IO_MMAP);
+
+ if (copy_to_user(arg, &rb, sizeof(rb))) {
+ et61x251_release_buffers(cam);
+ cam->io = IO_NONE;
+ return -EFAULT;
+ }
+
+ cam->io = rb.count ? IO_MMAP : IO_NONE;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_querybuf(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_buffer b;
+
+ if (copy_from_user(&b, arg, sizeof(b)))
+ return -EFAULT;
+
+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ b.index >= cam->nbuffers || cam->io != IO_MMAP)
+ return -EINVAL;
+
+ memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
+
+ if (cam->frame[b.index].vma_use_count)
+ b.flags |= V4L2_BUF_FLAG_MAPPED;
+
+ if (cam->frame[b.index].state == F_DONE)
+ b.flags |= V4L2_BUF_FLAG_DONE;
+ else if (cam->frame[b.index].state != F_UNUSED)
+ b.flags |= V4L2_BUF_FLAG_QUEUED;
+
+ if (copy_to_user(arg, &b, sizeof(b)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_qbuf(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_buffer b;
+ unsigned long lock_flags;
+
+ if (copy_from_user(&b, arg, sizeof(b)))
+ return -EFAULT;
+
+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ b.index >= cam->nbuffers || cam->io != IO_MMAP)
+ return -EINVAL;
+
+ if (cam->frame[b.index].state != F_UNUSED)
+ return -EINVAL;
+
+ cam->frame[b.index].state = F_QUEUED;
+
+ spin_lock_irqsave(&cam->queue_lock, lock_flags);
+ list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+ PDBGG("Frame #%lu queued", (unsigned long)b.index);
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp,
+ void __user * arg)
+{
+ struct v4l2_buffer b;
+ struct et61x251_frame_t *f;
+ unsigned long lock_flags;
+ int err = 0;
+
+ if (copy_from_user(&b, arg, sizeof(b)))
+ return -EFAULT;
+
+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP)
+ return -EINVAL;
+
+ if (list_empty(&cam->outqueue)) {
+ if (cam->stream == STREAM_OFF)
+ return -EINVAL;
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ err = wait_event_interruptible
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED) );
+ if (err)
+ return err;
+ if (cam->state & DEV_DISCONNECTED)
+ return -ENODEV;
+ if (cam->state & DEV_MISCONFIGURED)
+ return -EIO;
+ }
+
+ spin_lock_irqsave(&cam->queue_lock, lock_flags);
+ f = list_entry(cam->outqueue.next, struct et61x251_frame_t, frame);
+ list_del(cam->outqueue.next);
+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+ f->state = F_UNUSED;
+
+ memcpy(&b, &f->buf, sizeof(b));
+ if (f->vma_use_count)
+ b.flags |= V4L2_BUF_FLAG_MAPPED;
+
+ if (copy_to_user(arg, &b, sizeof(b)))
+ return -EFAULT;
+
+ PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_streamon(struct et61x251_device* cam, void __user * arg)
+{
+ int type;
+
+ if (copy_from_user(&type, arg, sizeof(type)))
+ return -EFAULT;
+
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+ return -EINVAL;
+
+ if (list_empty(&cam->inqueue))
+ return -EINVAL;
+
+ cam->stream = STREAM_ON;
+
+ DBG(3, "Stream on");
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_streamoff(struct et61x251_device* cam, void __user * arg)
+{
+ int type, err;
+
+ if (copy_from_user(&type, arg, sizeof(type)))
+ return -EFAULT;
+
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+ return -EINVAL;
+
+ if (cam->stream == STREAM_ON)
+ if ((err = et61x251_stream_interrupt(cam)))
+ return err;
+
+ et61x251_empty_framequeues(cam);
+
+ DBG(3, "Stream off");
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_g_parm(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_streamparm sp;
+
+ if (copy_from_user(&sp, arg, sizeof(sp)))
+ return -EFAULT;
+
+ if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ sp.parm.capture.extendedmode = 0;
+ sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+ if (copy_to_user(arg, &sp, sizeof(sp)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg)
+{
+ struct v4l2_streamparm sp;
+
+ if (copy_from_user(&sp, arg, sizeof(sp)))
+ return -EFAULT;
+
+ if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ sp.parm.capture.extendedmode = 0;
+
+ if (sp.parm.capture.readbuffers == 0)
+ sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+ if (sp.parm.capture.readbuffers > ET61X251_MAX_FRAMES)
+ sp.parm.capture.readbuffers = ET61X251_MAX_FRAMES;
+
+ if (copy_to_user(arg, &sp, sizeof(sp)))
+ return -EFAULT;
+
+ cam->nreadbuffers = sp.parm.capture.readbuffers;
+
+ return 0;
+}
+
+
+static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
+ unsigned int cmd, void __user * arg)
+{
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+
+ switch (cmd) {
+
+ case VIDIOC_QUERYCAP:
+ return et61x251_vidioc_querycap(cam, arg);
+
+ case VIDIOC_ENUMINPUT:
+ return et61x251_vidioc_enuminput(cam, arg);
+
+ case VIDIOC_G_INPUT:
+ case VIDIOC_S_INPUT:
+ return et61x251_vidioc_gs_input(cam, arg);
+
+ case VIDIOC_QUERYCTRL:
+ return et61x251_vidioc_query_ctrl(cam, arg);
+
+ case VIDIOC_G_CTRL:
+ return et61x251_vidioc_g_ctrl(cam, arg);
+
+ case VIDIOC_S_CTRL_OLD:
+ case VIDIOC_S_CTRL:
+ return et61x251_vidioc_s_ctrl(cam, arg);
+
+ case VIDIOC_CROPCAP_OLD:
+ case VIDIOC_CROPCAP:
+ return et61x251_vidioc_cropcap(cam, arg);
+
+ case VIDIOC_G_CROP:
+ return et61x251_vidioc_g_crop(cam, arg);
+
+ case VIDIOC_S_CROP:
+ return et61x251_vidioc_s_crop(cam, arg);
+
+ case VIDIOC_ENUM_FMT:
+ return et61x251_vidioc_enum_fmt(cam, arg);
+
+ case VIDIOC_G_FMT:
+ return et61x251_vidioc_g_fmt(cam, arg);
+
+ case VIDIOC_TRY_FMT:
+ case VIDIOC_S_FMT:
+ return et61x251_vidioc_try_s_fmt(cam, cmd, arg);
+
+ case VIDIOC_G_JPEGCOMP:
+ return et61x251_vidioc_g_jpegcomp(cam, arg);
+
+ case VIDIOC_S_JPEGCOMP:
+ return et61x251_vidioc_s_jpegcomp(cam, arg);
+
+ case VIDIOC_REQBUFS:
+ return et61x251_vidioc_reqbufs(cam, arg);
+
+ case VIDIOC_QUERYBUF:
+ return et61x251_vidioc_querybuf(cam, arg);
+
+ case VIDIOC_QBUF:
+ return et61x251_vidioc_qbuf(cam, arg);
+
+ case VIDIOC_DQBUF:
+ return et61x251_vidioc_dqbuf(cam, filp, arg);
+
+ case VIDIOC_STREAMON:
+ return et61x251_vidioc_streamon(cam, arg);
+
+ case VIDIOC_STREAMOFF:
+ return et61x251_vidioc_streamoff(cam, arg);
+
+ case VIDIOC_G_PARM:
+ return et61x251_vidioc_g_parm(cam, arg);
+
+ case VIDIOC_S_PARM_OLD:
+ case VIDIOC_S_PARM:
+ return et61x251_vidioc_s_parm(cam, arg);
+
+ case VIDIOC_G_STD:
+ case VIDIOC_S_STD:
+ case VIDIOC_QUERYSTD:
+ case VIDIOC_ENUMSTD:
+ case VIDIOC_QUERYMENU:
+ return -EINVAL;
+
+ default:
+ return -EINVAL;
+
+ }
+}
+
+
+static int et61x251_ioctl(struct inode* inode, struct file* filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ int err = 0;
+
+ if (down_interruptible(&cam->fileop_sem))
+ return -ERESTARTSYS;
+
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+ up(&cam->fileop_sem);
+ return -ENODEV;
+ }
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
+ up(&cam->fileop_sem);
+ return -EIO;
+ }
+
+ V4LDBG(3, "et61x251", cmd);
+
+ err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+
+ up(&cam->fileop_sem);
+
+ return err;
+}
+
+
+static struct file_operations et61x251_fops = {
+ .owner = THIS_MODULE,
+ .open = et61x251_open,
+ .release = et61x251_release,
+ .ioctl = et61x251_ioctl,
+ .read = et61x251_read,
+ .poll = et61x251_poll,
+ .mmap = et61x251_mmap,
+ .llseek = no_llseek,
+};
+
+/*****************************************************************************/
+
+/* It exists a single interface only. We do not need to validate anything. */
+static int
+et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct et61x251_device* cam;
+ static unsigned int dev_nr = 0;
+ unsigned int i;
+ int err = 0;
+
+ if (!(cam = kzalloc(sizeof(struct et61x251_device), GFP_KERNEL)))
+ return -ENOMEM;
+
+ cam->usbdev = udev;
+
+ if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
+ DBG(1, "kmalloc() failed");
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ if (!(cam->v4ldev = video_device_alloc())) {
+ DBG(1, "video_device_alloc() failed");
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ init_MUTEX(&cam->dev_sem);
+
+ DBG(2, "ET61X[12]51 PC Camera Controller detected "
+ "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
+
+ for (i = 0; et61x251_sensor_table[i]; i++) {
+ err = et61x251_sensor_table[i](cam);
+ if (!err)
+ break;
+ }
+
+ if (!err && cam->sensor)
+ DBG(2, "%s image sensor detected", cam->sensor->name);
+ else {
+ DBG(1, "No supported image sensor detected");
+ err = -ENODEV;
+ goto fail;
+ }
+
+ if (et61x251_init(cam)) {
+ DBG(1, "Initialization failed. I will retry on open().");
+ cam->state |= DEV_MISCONFIGURED;
+ }
+
+ strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera");
+ cam->v4ldev->owner = THIS_MODULE;
+ cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
+ cam->v4ldev->hardware = 0;
+ cam->v4ldev->fops = &et61x251_fops;
+ cam->v4ldev->minor = video_nr[dev_nr];
+ cam->v4ldev->release = video_device_release;
+ video_set_drvdata(cam->v4ldev, cam);
+
+ down(&cam->dev_sem);
+
+ err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
+ video_nr[dev_nr]);
+ if (err) {
+ DBG(1, "V4L2 device registration failed");
+ if (err == -ENFILE && video_nr[dev_nr] == -1)
+ DBG(1, "Free /dev/videoX node not found");
+ video_nr[dev_nr] = -1;
+ dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
+ up(&cam->dev_sem);
+ goto fail;
+ }
+
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+
+ cam->module_param.force_munmap = force_munmap[dev_nr];
+
+ dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ et61x251_create_sysfs(cam);
+ DBG(2, "Optional device control through 'sysfs' interface ready");
+#endif
+
+ usb_set_intfdata(intf, cam);
+
+ up(&cam->dev_sem);
+
+ return 0;
+
+fail:
+ if (cam) {
+ kfree(cam->control_buffer);
+ if (cam->v4ldev)
+ video_device_release(cam->v4ldev);
+ kfree(cam);
+ }
+ return err;
+}
+
+
+static void et61x251_usb_disconnect(struct usb_interface* intf)
+{
+ struct et61x251_device* cam = usb_get_intfdata(intf);
+
+ if (!cam)
+ return;
+
+ down_write(&et61x251_disconnect);
+
+ down(&cam->dev_sem);
+
+ DBG(2, "Disconnecting %s...", cam->v4ldev->name);
+
+ wake_up_interruptible_all(&cam->open);
+
+ if (cam->users) {
+ DBG(2, "Device /dev/video%d is open! Deregistration and "
+ "memory deallocation are deferred on close.",
+ cam->v4ldev->minor);
+ cam->state |= DEV_MISCONFIGURED;
+ et61x251_stop_transfer(cam);
+ cam->state |= DEV_DISCONNECTED;
+ wake_up_interruptible(&cam->wait_frame);
+ wake_up_interruptible(&cam->wait_stream);
+ } else {
+ cam->state |= DEV_DISCONNECTED;
+ et61x251_release_resources(cam);
+ }
+
+ up(&cam->dev_sem);
+
+ if (!cam->users)
+ kfree(cam);
+
+ up_write(&et61x251_disconnect);
+}
+
+
+static struct usb_driver et61x251_usb_driver = {
+ .name = "et61x251",
+ .id_table = et61x251_id_table,
+ .probe = et61x251_usb_probe,
+ .disconnect = et61x251_usb_disconnect,
+};
+
+/*****************************************************************************/
+
+static int __init et61x251_module_init(void)
+{
+ int err = 0;
+
+ KDBG(2, ET61X251_MODULE_NAME " v" ET61X251_MODULE_VERSION);
+ KDBG(3, ET61X251_MODULE_AUTHOR);
+
+ if ((err = usb_register(&et61x251_usb_driver)))
+ KDBG(1, "usb_register() failed");
+
+ return err;
+}
+
+
+static void __exit et61x251_module_exit(void)
+{
+ usb_deregister(&et61x251_usb_driver);
+}
+
+
+module_init(et61x251_module_init);
+module_exit(et61x251_module_exit);
diff --git a/drivers/usb/media/et61x251_sensor.h b/drivers/usb/media/et61x251_sensor.h
new file mode 100644
index 00000000000..b9df91062fc
--- /dev/null
+++ b/drivers/usb/media/et61x251_sensor.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * API for image sensors connected to ET61X[12]51 PC Camera Controllers *
+ * *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#ifndef _ET61X251_SENSOR_H_
+#define _ET61X251_SENSOR_H_
+
+#include <linux/usb.h>
+#include <linux/videodev.h>
+#include <linux/device.h>
+#include <linux/stddef.h>
+#include <linux/errno.h>
+#include <asm/types.h>
+
+struct et61x251_device;
+struct et61x251_sensor;
+
+/*****************************************************************************/
+
+extern int et61x251_probe_tas5130d1b(struct et61x251_device* cam);
+
+#define ET61X251_SENSOR_TABLE \
+/* Weak detections must go at the end of the list */ \
+static int (*et61x251_sensor_table[])(struct et61x251_device*) = { \
+ &et61x251_probe_tas5130d1b, \
+ NULL, \
+};
+
+extern void
+et61x251_attach_sensor(struct et61x251_device* cam,
+ struct et61x251_sensor* sensor);
+
+/*****************************************************************************/
+
+extern int et61x251_write_reg(struct et61x251_device*, u8 value, u16 index);
+extern int et61x251_read_reg(struct et61x251_device*, u16 index);
+extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value);
+extern int et61x251_i2c_read(struct et61x251_device*, u8 address);
+extern int et61x251_i2c_try_write(struct et61x251_device*,
+ struct et61x251_sensor*, u8 address,
+ u8 value);
+extern int et61x251_i2c_try_read(struct et61x251_device*,
+ struct et61x251_sensor*, u8 address);
+extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1,
+ u8 data2, u8 data3, u8 data4, u8 data5,
+ u8 data6, u8 data7, u8 data8, u8 address);
+
+/*****************************************************************************/
+
+enum et61x251_i2c_sysfs_ops {
+ ET61X251_I2C_READ = 0x01,
+ ET61X251_I2C_WRITE = 0x02,
+};
+
+enum et61x251_i2c_interface {
+ ET61X251_I2C_2WIRES,
+ ET61X251_I2C_3WIRES,
+};
+
+/* Repeat start condition when RSTA is high */
+enum et61x251_i2c_rsta {
+ ET61X251_I2C_RSTA_STOP = 0x00, /* stop then start */
+ ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */
+};
+
+#define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
+
+struct et61x251_sensor {
+ char name[32];
+
+ enum et61x251_i2c_sysfs_ops sysfs_ops;
+
+ enum et61x251_i2c_interface interface;
+ u8 i2c_slave_id;
+ enum et61x251_i2c_rsta rsta;
+ struct v4l2_rect active_pixel; /* left and top define FVSX and FVSY */
+
+ struct v4l2_queryctrl qctrl[ET61X251_MAX_CTRLS];
+ struct v4l2_cropcap cropcap;
+ struct v4l2_pix_format pix_format;
+
+ int (*init)(struct et61x251_device* cam);
+ int (*get_ctrl)(struct et61x251_device* cam,
+ struct v4l2_control* ctrl);
+ int (*set_ctrl)(struct et61x251_device* cam,
+ const struct v4l2_control* ctrl);
+ int (*set_crop)(struct et61x251_device* cam,
+ const struct v4l2_rect* rect);
+ int (*set_pix_format)(struct et61x251_device* cam,
+ const struct v4l2_pix_format* pix);
+
+ const struct usb_device* usbdev;
+
+ /* Private */
+ struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS];
+ struct v4l2_rect _rect;
+};
+
+#endif /* _ET61X251_SENSOR_H_ */
diff --git a/drivers/usb/media/et61x251_tas5130d1b.c b/drivers/usb/media/et61x251_tas5130d1b.c
new file mode 100644
index 00000000000..65f1ae9cf2b
--- /dev/null
+++ b/drivers/usb/media/et61x251_tas5130d1b.c
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 *
+ * PC Camera Controllers *
+ * *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#include "et61x251_sensor.h"
+
+
+static int tas5130d1b_init(struct et61x251_device* cam)
+{
+ int err = 0;
+
+ err += et61x251_write_reg(cam, 0x14, 0x01);
+ err += et61x251_write_reg(cam, 0x1b, 0x02);
+ err += et61x251_write_reg(cam, 0x02, 0x12);
+ err += et61x251_write_reg(cam, 0x0e, 0x60);
+ err += et61x251_write_reg(cam, 0x80, 0x61);
+ err += et61x251_write_reg(cam, 0xf0, 0x62);
+ err += et61x251_write_reg(cam, 0x03, 0x63);
+ err += et61x251_write_reg(cam, 0x14, 0x64);
+ err += et61x251_write_reg(cam, 0xf4, 0x65);
+ err += et61x251_write_reg(cam, 0x01, 0x66);
+ err += et61x251_write_reg(cam, 0x05, 0x67);
+ err += et61x251_write_reg(cam, 0x8f, 0x68);
+ err += et61x251_write_reg(cam, 0x0f, 0x8d);
+ err += et61x251_write_reg(cam, 0x08, 0x8e);
+
+ return err;
+}
+
+
+static int tas5130d1b_set_ctrl(struct et61x251_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ int err = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ err += et61x251_i2c_raw_write(cam, 2, 0x20,
+ 0xf6-ctrl->value, 0, 0, 0,
+ 0, 0, 0, 0);
+ break;
+ case V4L2_CID_EXPOSURE:
+ err += et61x251_i2c_raw_write(cam, 2, 0x40,
+ 0x47-ctrl->value, 0, 0, 0,
+ 0, 0, 0, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err ? -EIO : 0;
+}
+
+
+static struct et61x251_sensor tas5130d1b = {
+ .name = "TAS5130D1B",
+ .interface = ET61X251_I2C_3WIRES,
+ .rsta = ET61X251_I2C_RSTA_STOP,
+ .active_pixel = {
+ .left = 106,
+ .top = 13,
+ },
+ .init = &tas5130d1b_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "global gain",
+ .minimum = 0x00,
+ .maximum = 0xf6,
+ .step = 0x02,
+ .default_value = 0x0d,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "exposure",
+ .minimum = 0x00,
+ .maximum = 0x47,
+ .step = 0x01,
+ .default_value = 0x23,
+ .flags = 0,
+ },
+ },
+ .set_ctrl = &tas5130d1b_set_ctrl,
+ .cropcap = {
+ .bounds = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ .defrect = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ },
+ .pix_format = {
+ .width = 640,
+ .height = 480,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .priv = 8,
+ },
+};
+
+
+int et61x251_probe_tas5130d1b(struct et61x251_device* cam)
+{
+ /* This sensor has no identifiers, so let's attach it anyway */
+ et61x251_attach_sensor(cam, &tas5130d1b);
+
+ /* Sensor detection is based on USB pid/vid */
+ if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6251)
+ return -ENODEV;
+
+ return 0;
+}
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 8af665bbe33..51e9cc06f7e 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -204,22 +204,10 @@ MODULE_LICENSE("GPL");
static struct usb_driver ov511_driver;
-static struct ov51x_decomp_ops *ov511_decomp_ops;
-static struct ov51x_decomp_ops *ov511_mmx_decomp_ops;
-static struct ov51x_decomp_ops *ov518_decomp_ops;
-static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;
-
/* Number of times to retry a failed I2C transaction. Increase this if you
* are getting "Failed to read sensor ID..." */
static const int i2c_detect_tries = 5;
-/* MMX support is present in kernel and CPU. Checked upon decomp module load. */
-#if defined(__i386__) || defined(__x86_64__)
-#define ov51x_mmx_available (cpu_has_mmx)
-#else
-#define ov51x_mmx_available (0)
-#endif
-
static struct usb_device_id device_table [] = {
{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
@@ -3012,93 +3000,18 @@ yuv420raw_to_yuv420p(struct ov511_frame *frame,
*
**********************************************************************/
-/* Chooses a decompression module, locks it, and sets ov->decomp_ops
- * accordingly. Returns -ENXIO if decompressor is not available, otherwise
- * returns 0 if no other error.
- */
static int
request_decompressor(struct usb_ov511 *ov)
{
- if (!ov)
- return -ENODEV;
-
- if (ov->decomp_ops) {
- err("ERROR: Decompressor already requested!");
- return -EINVAL;
- }
-
- lock_kernel();
-
- /* Try to get MMX, and fall back on no-MMX if necessary */
- if (ov->bclass == BCL_OV511) {
- if (ov511_mmx_decomp_ops) {
- PDEBUG(3, "Using OV511 MMX decompressor");
- ov->decomp_ops = ov511_mmx_decomp_ops;
- } else if (ov511_decomp_ops) {
- PDEBUG(3, "Using OV511 decompressor");
- ov->decomp_ops = ov511_decomp_ops;
- } else {
- err("No decompressor available");
- }
- } else if (ov->bclass == BCL_OV518) {
- if (ov518_mmx_decomp_ops) {
- PDEBUG(3, "Using OV518 MMX decompressor");
- ov->decomp_ops = ov518_mmx_decomp_ops;
- } else if (ov518_decomp_ops) {
- PDEBUG(3, "Using OV518 decompressor");
- ov->decomp_ops = ov518_decomp_ops;
- } else {
- err("No decompressor available");
- }
+ if (ov->bclass == BCL_OV511 || ov->bclass == BCL_OV518) {
+ err("No decompressor available");
} else {
err("Unknown bridge");
}
- if (!ov->decomp_ops)
- goto nosys;
-
- if (!ov->decomp_ops->owner) {
- ov->decomp_ops = NULL;
- goto nosys;
- }
-
- if (!try_module_get(ov->decomp_ops->owner))
- goto nosys;
-
- unlock_kernel();
- return 0;
-
- nosys:
- unlock_kernel();
return -ENOSYS;
}
-/* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even
- * if ov->decomp_ops is NULL.
- */
-static void
-release_decompressor(struct usb_ov511 *ov)
-{
- int released = 0; /* Did we actually do anything? */
-
- if (!ov)
- return;
-
- lock_kernel();
-
- if (ov->decomp_ops) {
- module_put(ov->decomp_ops->owner);
- released = 1;
- }
-
- ov->decomp_ops = NULL;
-
- unlock_kernel();
-
- if (released)
- PDEBUG(3, "Decompressor released");
-}
-
static void
decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
unsigned char *pIn0, unsigned char *pOut0)
@@ -3107,31 +3020,6 @@ decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
if (request_decompressor(ov))
return;
- PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd);
-
- if (frame->format == VIDEO_PALETTE_GREY
- && ov->decomp_ops->decomp_400) {
- int ret = ov->decomp_ops->decomp_400(
- pIn0,
- pOut0,
- frame->compbuf,
- frame->rawwidth,
- frame->rawheight,
- frame->bytes_recvd);
- PDEBUG(4, "DEBUG: decomp_400 returned %d", ret);
- } else if (frame->format != VIDEO_PALETTE_GREY
- && ov->decomp_ops->decomp_420) {
- int ret = ov->decomp_ops->decomp_420(
- pIn0,
- pOut0,
- frame->compbuf,
- frame->rawwidth,
- frame->rawheight,
- frame->bytes_recvd);
- PDEBUG(4, "DEBUG: decomp_420 returned %d", ret);
- } else {
- err("Decompressor does not support this format");
- }
}
/**********************************************************************
@@ -4087,8 +3975,6 @@ ov51x_v4l1_close(struct inode *inode, struct file *file)
ov->user--;
ov51x_stop_isoc(ov);
- release_decompressor(ov);
-
if (ov->led_policy == LED_AUTO)
ov51x_led_control(ov, 0);
@@ -6021,82 +5907,6 @@ static struct usb_driver ov511_driver = {
*
***************************************************************************/
-/* Returns 0 for success */
-int
-ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, int ov518,
- int mmx)
-{
- if (ver != DECOMP_INTERFACE_VER) {
- err("Decompression module has incompatible");
- err("interface version %d", ver);
- err("Interface version %d is required", DECOMP_INTERFACE_VER);
- return -EINVAL;
- }
-
- if (!ops)
- return -EFAULT;
-
- if (mmx && !ov51x_mmx_available) {
- err("MMX not available on this system or kernel");
- return -EINVAL;
- }
-
- lock_kernel();
-
- if (ov518) {
- if (mmx) {
- if (ov518_mmx_decomp_ops)
- goto err_in_use;
- else
- ov518_mmx_decomp_ops = ops;
- } else {
- if (ov518_decomp_ops)
- goto err_in_use;
- else
- ov518_decomp_ops = ops;
- }
- } else {
- if (mmx) {
- if (ov511_mmx_decomp_ops)
- goto err_in_use;
- else
- ov511_mmx_decomp_ops = ops;
- } else {
- if (ov511_decomp_ops)
- goto err_in_use;
- else
- ov511_decomp_ops = ops;
- }
- }
-
- unlock_kernel();
- return 0;
-
-err_in_use:
- unlock_kernel();
- return -EBUSY;
-}
-
-void
-ov511_deregister_decomp_module(int ov518, int mmx)
-{
- lock_kernel();
-
- if (ov518) {
- if (mmx)
- ov518_mmx_decomp_ops = NULL;
- else
- ov518_decomp_ops = NULL;
- } else {
- if (mmx)
- ov511_mmx_decomp_ops = NULL;
- else
- ov511_decomp_ops = NULL;
- }
-
- unlock_kernel();
-}
-
static int __init
usb_ov511_init(void)
{
@@ -6123,5 +5933,3 @@ usb_ov511_exit(void)
module_init(usb_ov511_init);
module_exit(usb_ov511_exit);
-EXPORT_SYMBOL(ov511_register_decomp_module);
-EXPORT_SYMBOL(ov511_deregister_decomp_module);
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 359c4b2df73..3ebb6e9cdf9 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -1152,45 +1152,6 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
/* End of Add-Ons */
/* ************************************************* */
-/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
- ioctl() calls. With 2.4, you have to do tedious copy_from_user()
- and copy_to_user() calls. With these macros we circumvent this,
- and let me maintain only one source file. The functionality is
- exactly the same otherwise.
- */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-
-/* define local variable for arg */
-#define ARG_DEF(ARG_type, ARG_name)\
- ARG_type *ARG_name = arg;
-/* copy arg to local variable */
-#define ARG_IN(ARG_name) /* nothing */
-/* argument itself (referenced) */
-#define ARGR(ARG_name) (*ARG_name)
-/* argument address */
-#define ARGA(ARG_name) ARG_name
-/* copy local variable to arg */
-#define ARG_OUT(ARG_name) /* nothing */
-
-#else
-
-#define ARG_DEF(ARG_type, ARG_name)\
- ARG_type ARG_name;
-#define ARG_IN(ARG_name)\
- if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\
- ret = -EFAULT;\
- break;\
- }
-#define ARGR(ARG_name) ARG_name
-#define ARGA(ARG_name) &ARG_name
-#define ARG_OUT(ARG_name)\
- if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\
- ret = -EFAULT;\
- break;\
- }
-
-#endif
int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
@@ -1220,243 +1181,206 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case VIDIOCPWCSCQUAL:
{
- ARG_DEF(int, qual)
+ int *qual = arg;
- ARG_IN(qual)
- if (ARGR(qual) < 0 || ARGR(qual) > 3)
+ if (*qual < 0 || *qual > 3)
ret = -EINVAL;
else
- ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
+ ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
if (ret >= 0)
- pdev->vcompression = ARGR(qual);
+ pdev->vcompression = *qual;
break;
}
case VIDIOCPWCGCQUAL:
{
- ARG_DEF(int, qual)
-
- ARGR(qual) = pdev->vcompression;
- ARG_OUT(qual)
+ int *qual = arg;
+ *qual = pdev->vcompression;
break;
}
case VIDIOCPWCPROBE:
{
- ARG_DEF(struct pwc_probe, probe)
-
- strcpy(ARGR(probe).name, pdev->vdev->name);
- ARGR(probe).type = pdev->type;
- ARG_OUT(probe)
+ struct pwc_probe *probe = arg;
+ strcpy(probe->name, pdev->vdev->name);
+ probe->type = pdev->type;
break;
}
case VIDIOCPWCGSERIAL:
{
- ARG_DEF(struct pwc_serial, serial)
-
- strcpy(ARGR(serial).serial, pdev->serial);
- ARG_OUT(serial)
+ struct pwc_serial *serial = arg;
+ strcpy(serial->serial, pdev->serial);
break;
}
case VIDIOCPWCSAGC:
{
- ARG_DEF(int, agc)
-
- ARG_IN(agc)
- if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
+ int *agc = arg;
+ if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
ret = -EINVAL;
break;
}
case VIDIOCPWCGAGC:
{
- ARG_DEF(int, agc)
+ int *agc = arg;
- if (pwc_get_agc(pdev, ARGA(agc)))
+ if (pwc_get_agc(pdev, agc))
ret = -EINVAL;
- ARG_OUT(agc)
break;
}
case VIDIOCPWCSSHUTTER:
{
- ARG_DEF(int, shutter_speed)
-
- ARG_IN(shutter_speed)
- ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
+ int *shutter_speed = arg;
+ ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
break;
}
case VIDIOCPWCSAWB:
{
- ARG_DEF(struct pwc_whitebalance, wb)
+ struct pwc_whitebalance *wb = arg;
- ARG_IN(wb)
- ret = pwc_set_awb(pdev, ARGR(wb).mode);
- if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
- pwc_set_red_gain(pdev, ARGR(wb).manual_red);
- pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
+ ret = pwc_set_awb(pdev, wb->mode);
+ if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
+ pwc_set_red_gain(pdev, wb->manual_red);
+ pwc_set_blue_gain(pdev, wb->manual_blue);
}
break;
}
case VIDIOCPWCGAWB:
{
- ARG_DEF(struct pwc_whitebalance, wb)
+ struct pwc_whitebalance *wb = arg;
- memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
- ARGR(wb).mode = pwc_get_awb(pdev);
- if (ARGR(wb).mode < 0)
+ memset(wb, 0, sizeof(struct pwc_whitebalance));
+ wb->mode = pwc_get_awb(pdev);
+ if (wb->mode < 0)
ret = -EINVAL;
else {
- if (ARGR(wb).mode == PWC_WB_MANUAL) {
- ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
+ if (wb->mode == PWC_WB_MANUAL) {
+ ret = pwc_get_red_gain(pdev, &wb->manual_red);
if (ret < 0)
break;
- ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
+ ret = pwc_get_blue_gain(pdev, &wb->manual_blue);
if (ret < 0)
break;
}
- if (ARGR(wb).mode == PWC_WB_AUTO) {
- ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
+ if (wb->mode == PWC_WB_AUTO) {
+ ret = pwc_read_red_gain(pdev, &wb->read_red);
if (ret < 0)
break;
- ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
+ ret = pwc_read_blue_gain(pdev, &wb->read_blue);
if (ret < 0)
break;
}
}
- ARG_OUT(wb)
break;
}
case VIDIOCPWCSAWBSPEED:
{
- ARG_DEF(struct pwc_wb_speed, wbs)
+ struct pwc_wb_speed *wbs = arg;
- if (ARGR(wbs).control_speed > 0) {
- ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
+ if (wbs->control_speed > 0) {
+ ret = pwc_set_wb_speed(pdev, wbs->control_speed);
}
- if (ARGR(wbs).control_delay > 0) {
- ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
+ if (wbs->control_delay > 0) {
+ ret = pwc_set_wb_delay(pdev, wbs->control_delay);
}
break;
}
case VIDIOCPWCGAWBSPEED:
{
- ARG_DEF(struct pwc_wb_speed, wbs)
+ struct pwc_wb_speed *wbs = arg;
- ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
+ ret = pwc_get_wb_speed(pdev, &wbs->control_speed);
if (ret < 0)
break;
- ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
+ ret = pwc_get_wb_delay(pdev, &wbs->control_delay);
if (ret < 0)
break;
- ARG_OUT(wbs)
break;
}
case VIDIOCPWCSLED:
{
- ARG_DEF(struct pwc_leds, leds)
-
- ARG_IN(leds)
- ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
+ struct pwc_leds *leds = arg;
+ ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
break;
}
case VIDIOCPWCGLED:
{
- ARG_DEF(struct pwc_leds, leds)
-
- ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
- ARG_OUT(leds)
+ struct pwc_leds *leds = arg;
+ ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off);
break;
}
case VIDIOCPWCSCONTOUR:
{
- ARG_DEF(int, contour)
-
- ARG_IN(contour)
- ret = pwc_set_contour(pdev, ARGR(contour));
+ int *contour = arg;
+ ret = pwc_set_contour(pdev, *contour);
break;
}
case VIDIOCPWCGCONTOUR:
{
- ARG_DEF(int, contour)
-
- ret = pwc_get_contour(pdev, ARGA(contour));
- ARG_OUT(contour)
+ int *contour = arg;
+ ret = pwc_get_contour(pdev, contour);
break;
}
case VIDIOCPWCSBACKLIGHT:
{
- ARG_DEF(int, backlight)
-
- ARG_IN(backlight)
- ret = pwc_set_backlight(pdev, ARGR(backlight));
+ int *backlight = arg;
+ ret = pwc_set_backlight(pdev, *backlight);
break;
}
case VIDIOCPWCGBACKLIGHT:
{
- ARG_DEF(int, backlight)
-
- ret = pwc_get_backlight(pdev, ARGA(backlight));
- ARG_OUT(backlight)
+ int *backlight = arg;
+ ret = pwc_get_backlight(pdev, backlight);
break;
}
case VIDIOCPWCSFLICKER:
{
- ARG_DEF(int, flicker)
-
- ARG_IN(flicker)
- ret = pwc_set_flicker(pdev, ARGR(flicker));
+ int *flicker = arg;
+ ret = pwc_set_flicker(pdev, *flicker);
break;
}
case VIDIOCPWCGFLICKER:
{
- ARG_DEF(int, flicker)
-
- ret = pwc_get_flicker(pdev, ARGA(flicker));
- ARG_OUT(flicker)
+ int *flicker = arg;
+ ret = pwc_get_flicker(pdev, flicker);
break;
}
case VIDIOCPWCSDYNNOISE:
{
- ARG_DEF(int, dynnoise)
-
- ARG_IN(dynnoise)
- ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
+ int *dynnoise = arg;
+ ret = pwc_set_dynamic_noise(pdev, *dynnoise);
break;
}
case VIDIOCPWCGDYNNOISE:
{
- ARG_DEF(int, dynnoise)
-
- ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
- ARG_OUT(dynnoise);
+ int *dynnoise = arg;
+ ret = pwc_get_dynamic_noise(pdev, dynnoise);
break;
}
case VIDIOCPWCGREALSIZE:
{
- ARG_DEF(struct pwc_imagesize, size)
-
- ARGR(size).width = pdev->image.x;
- ARGR(size).height = pdev->image.y;
- ARG_OUT(size)
+ struct pwc_imagesize *size = arg;
+ size->width = pdev->image.x;
+ size->height = pdev->image.y;
break;
}
@@ -1464,10 +1388,9 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
if (pdev->features & FEATURE_MOTOR_PANTILT)
{
- ARG_DEF(int, flags)
+ int *flags = arg;
- ARG_IN(flags)
- ret = pwc_mpt_reset(pdev, ARGR(flags));
+ ret = pwc_mpt_reset(pdev, *flags);
if (ret >= 0)
{
pdev->pan_angle = 0;
@@ -1485,10 +1408,8 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
if (pdev->features & FEATURE_MOTOR_PANTILT)
{
- ARG_DEF(struct pwc_mpt_range, range)
-
- ARGR(range) = pdev->angle_range;
- ARG_OUT(range)
+ struct pwc_mpt_range *range = arg;
+ *range = pdev->angle_range;
}
else
{
@@ -1503,21 +1424,19 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
if (pdev->features & FEATURE_MOTOR_PANTILT)
{
- ARG_DEF(struct pwc_mpt_angles, angles)
-
- ARG_IN(angles)
+ struct pwc_mpt_angles *angles = arg;
/* The camera can only set relative angles, so
do some calculations when getting an absolute angle .
*/
- if (ARGR(angles).absolute)
+ if (angles->absolute)
{
- new_pan = ARGR(angles).pan;
- new_tilt = ARGR(angles).tilt;
+ new_pan = angles->pan;
+ new_tilt = angles->tilt;
}
else
{
- new_pan = pdev->pan_angle + ARGR(angles).pan;
- new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
+ new_pan = pdev->pan_angle + angles->pan;
+ new_tilt = pdev->tilt_angle + angles->tilt;
}
/* check absolute ranges */
if (new_pan < pdev->angle_range.pan_min ||
@@ -1560,12 +1479,11 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
if (pdev->features & FEATURE_MOTOR_PANTILT)
{
- ARG_DEF(struct pwc_mpt_angles, angles)
+ struct pwc_mpt_angles *angles = arg;
- ARGR(angles).absolute = 1;
- ARGR(angles).pan = pdev->pan_angle;
- ARGR(angles).tilt = pdev->tilt_angle;
- ARG_OUT(angles)
+ angles->absolute = 1;
+ angles->pan = pdev->pan_angle;
+ angles->tilt = pdev->tilt_angle;
}
else
{
@@ -1578,10 +1496,8 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
if (pdev->features & FEATURE_MOTOR_PANTILT)
{
- ARG_DEF(struct pwc_mpt_status, status)
-
- ret = pwc_mpt_get_status(pdev, ARGA(status));
- ARG_OUT(status)
+ struct pwc_mpt_status *status = arg;
+ ret = pwc_mpt_get_status(pdev, status);
}
else
{
@@ -1592,24 +1508,22 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case VIDIOCPWCGVIDCMD:
{
- ARG_DEF(struct pwc_video_command, cmd);
+ struct pwc_video_command *cmd = arg;
- ARGR(cmd).type = pdev->type;
- ARGR(cmd).release = pdev->release;
- ARGR(cmd).command_len = pdev->cmd_len;
- memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
- ARGR(cmd).bandlength = pdev->vbandlength;
- ARGR(cmd).frame_size = pdev->frame_size;
- ARG_OUT(cmd)
+ cmd->type = pdev->type;
+ cmd->release = pdev->release;
+ cmd->command_len = pdev->cmd_len;
+ memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len);
+ cmd->bandlength = pdev->vbandlength;
+ cmd->frame_size = pdev->frame_size;
break;
}
/*
case VIDIOCPWCGVIDTABLE:
{
- ARG_DEF(struct pwc_table_init_buffer, table);
- ARGR(table).len = pdev->cmd_len;
- memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
- ARG_OUT(table)
+ struct pwc_table_init_buffer *table = arg;
+ table->len = pdev->cmd_len;
+ memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size);
break;
}
*/
diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
index e5cea0e2eb5..17d60c1eea7 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/usb/media/sn9c102.h
@@ -1,7 +1,7 @@
/***************************************************************************
* V4L2 driver for SN9C10x PC Camera Controllers *
* *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -23,7 +23,8 @@
#include <linux/version.h>
#include <linux/usb.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/spinlock.h>
@@ -52,13 +53,6 @@
/*****************************************************************************/
-#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers"
-#define SN9C102_MODULE_AUTHOR "(C) 2004-2005 Luca Risolia"
-#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
-#define SN9C102_MODULE_LICENSE "GPL"
-#define SN9C102_MODULE_VERSION "1:1.24a"
-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 24)
-
enum sn9c102_bridge {
BRIDGE_SN9C101 = 0x01,
BRIDGE_SN9C102 = 0x02,
@@ -102,12 +96,13 @@ enum sn9c102_stream_state {
STREAM_ON,
};
+typedef char sn9c103_sof_header_t[18];
typedef char sn9c102_sof_header_t[12];
typedef char sn9c102_eof_header_t[4];
struct sn9c102_sysfs_attr {
u8 reg, i2c_reg;
- sn9c102_sof_header_t frame_header;
+ sn9c103_sof_header_t frame_header;
};
struct sn9c102_module_param {
@@ -118,8 +113,6 @@ static DECLARE_MUTEX(sn9c102_sysfs_lock);
static DECLARE_RWSEM(sn9c102_disconnect);
struct sn9c102_device {
- struct device dev;
-
struct video_device* v4ldev;
enum sn9c102_bridge bridge;
@@ -140,8 +133,8 @@ struct sn9c102_device {
struct v4l2_jpegcompression compression;
struct sn9c102_sysfs_attr sysfs;
- sn9c102_sof_header_t sof_header;
- u16 reg[32];
+ sn9c103_sof_header_t sof_header;
+ u16 reg[63];
struct sn9c102_module_param module_param;
@@ -160,7 +153,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor)
{
cam->sensor = sensor;
- cam->sensor->dev = &cam->dev;
cam->sensor->usbdev = cam->usbdev;
}
@@ -170,19 +162,24 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
#undef KDBG
#ifdef SN9C102_DEBUG
# define DBG(level, fmt, args...) \
-{ \
+do { \
if (debug >= (level)) { \
if ((level) == 1) \
- dev_err(&cam->dev, fmt "\n", ## args); \
+ dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) == 2) \
- dev_info(&cam->dev, fmt "\n", ## args); \
+ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
- dev_info(&cam->dev, "[%s:%d] " fmt "\n", \
+ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
__FUNCTION__, __LINE__ , ## args); \
} \
-}
+} while (0)
+# define V4LDBG(level, name, cmd) \
+do { \
+ if (debug >= (level)) \
+ v4l_print_ioctl(name, cmd); \
+} while (0)
# define KDBG(level, fmt, args...) \
-{ \
+do { \
if (debug >= (level)) { \
if ((level) == 1 || (level) == 2) \
pr_info("sn9c102: " fmt "\n", ## args); \
@@ -190,17 +187,18 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \
__LINE__ , ## args); \
} \
-}
+} while (0)
#else
-# define KDBG(level, fmt, args...) do {;} while(0);
-# define DBG(level, fmt, args...) do {;} while(0);
+# define DBG(level, fmt, args...) do {;} while(0)
+# define V4LDBG(level, name, cmd) do {;} while(0)
+# define KDBG(level, fmt, args...) do {;} while(0)
#endif
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args);
+dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
#undef PDBGG
-#define PDBGG(fmt, args...) do {;} while(0); /* placeholder */
+#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
#endif /* _SN9C102_H_ */
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index 8d1a1c357d5..c81397e4714 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -1,7 +1,7 @@
/***************************************************************************
* V4L2 driver for SN9C10x PC Camera Controllers *
* *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -45,6 +45,15 @@
/*****************************************************************************/
+#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers"
+#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
+#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
+#define SN9C102_MODULE_LICENSE "GPL"
+#define SN9C102_MODULE_VERSION "1:1.26"
+#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 26)
+
+/*****************************************************************************/
+
MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
@@ -70,10 +79,10 @@ static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
SN9C102_FORCE_MUNMAP};
module_param_array(force_munmap, bool, NULL, 0444);
MODULE_PARM_DESC(force_munmap,
- "\n<0|1[,...]> Force the application to unmap previously "
- "\nmapped buffer memory before calling any VIDIOC_S_CROP or "
- "\nVIDIOC_S_FMT ioctl's. Not all the applications support "
- "\nthis feature. This parameter is specific for each "
+ "\n<0|1[,...]> Force the application to unmap previously"
+ "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+ "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+ "\nthis feature. This parameter is specific for each"
"\ndetected camera."
"\n 0 = do not force memory unmapping"
"\n 1 = force memory unmapping (save memory)"
@@ -102,6 +111,9 @@ static sn9c102_sof_header_t sn9c102_sof_header[] = {
{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
};
+static sn9c103_sof_header_t sn9c103_sof_header[] = {
+ {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20},
+};
static sn9c102_eof_header_t sn9c102_eof_header[] = {
{0x00, 0x00, 0x00, 0x00},
@@ -112,50 +124,6 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = {
/*****************************************************************************/
-static void* rvmalloc(size_t size)
-{
- void* mem;
- unsigned long adr;
-
- size = PAGE_ALIGN(size);
-
- mem = vmalloc_32((unsigned long)size);
- if (!mem)
- return NULL;
-
- memset(mem, 0, size);
-
- adr = (unsigned long)mem;
- while (size > 0) {
- SetPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- return mem;
-}
-
-
-static void rvfree(void* mem, size_t size)
-{
- unsigned long adr;
-
- if (!mem)
- return;
-
- size = PAGE_ALIGN(size);
-
- adr = (unsigned long)mem;
- while (size > 0) {
- ClearPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- vfree(mem);
-}
-
-
static u32
sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
enum sn9c102_io_method io)
@@ -174,7 +142,7 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
cam->nbuffers = count;
while (cam->nbuffers > 0) {
- if ((buff = rvmalloc(cam->nbuffers * PAGE_ALIGN(imagesize))))
+ if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
break;
cam->nbuffers--;
}
@@ -198,10 +166,10 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
static void sn9c102_release_buffers(struct sn9c102_device* cam)
{
if (cam->nbuffers) {
- rvfree(cam->frame[0].bufmem,
- cam->nbuffers * PAGE_ALIGN(cam->frame[0].buf.length));
+ vfree(cam->frame[0].bufmem);
cam->nbuffers = 0;
}
+ cam->frame_current = NULL;
}
@@ -219,6 +187,19 @@ static void sn9c102_empty_framequeues(struct sn9c102_device* cam)
}
+static void sn9c102_requeue_outqueue(struct sn9c102_device* cam)
+{
+ struct sn9c102_frame_t *i;
+
+ list_for_each_entry(i, &cam->outqueue, frame) {
+ i->state = F_QUEUED;
+ list_add(&i->frame, &cam->inqueue);
+ }
+
+ INIT_LIST_HEAD(&cam->outqueue);
+}
+
+
static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
{
unsigned long lock_flags;
@@ -235,19 +216,46 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
/*****************************************************************************/
+int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index)
+{
+ struct usb_device* udev = cam->usbdev;
+ int i, res;
+
+ if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg))
+ return -1;
+
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
+ index, 0, buff, sizeof(buff),
+ SN9C102_CTRL_TIMEOUT*sizeof(buff));
+ if (res < 0) {
+ DBG(3, "Failed to write registers (index 0x%02X, error %d)",
+ index, res);
+ return -1;
+ }
+
+ for (i = 0; i < sizeof(buff); i++)
+ cam->reg[index+i] = buff[i];
+
+ return 0;
+}
+
+
int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
{
struct usb_device* udev = cam->usbdev;
u8* buff = cam->control_buffer;
int res;
+ if (index >= ARRAY_SIZE(cam->reg))
+ return -1;
+
*buff = value;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
if (res < 0) {
DBG(3, "Failed to write a register (value 0x%02X, index "
- "0x%02X, error %d)", value, index, res)
+ "0x%02X, error %d)", value, index, res);
return -1;
}
@@ -268,7 +276,7 @@ static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
if (res < 0)
DBG(3, "Failed to read a register (index 0x%02X, error %d)",
- index, res)
+ index, res);
return (res >= 0) ? (int)(*buff) : -1;
}
@@ -276,8 +284,8 @@ static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
{
- if (index > 0x1f)
- return -EINVAL;
+ if (index >= ARRAY_SIZE(cam->reg))
+ return -1;
return cam->reg[index];
}
@@ -367,10 +375,10 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
err += sn9c102_i2c_detect_read_error(cam, sensor);
PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
- data[4])
+ data[4]);
if (err) {
- DBG(3, "I2C read failed for %s image sensor", sensor->name)
+ DBG(3, "I2C read failed for %s image sensor", sensor->name);
return -1;
}
@@ -410,11 +418,11 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
err += sn9c102_i2c_detect_write_error(cam, sensor);
if (err)
- DBG(3, "I2C write failed for %s image sensor", sensor->name)
+ DBG(3, "I2C write failed for %s image sensor", sensor->name);
PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
"data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
- n, data0, data1, data2, data3, data4, data5)
+ n, data0, data1, data2, data3, data4, data5);
return err ? -1 : 0;
}
@@ -461,13 +469,27 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
static void*
sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
{
- size_t soflen = sizeof(sn9c102_sof_header_t), i;
- u8 j, n = sizeof(sn9c102_sof_header) / soflen;
+ size_t soflen = 0, i;
+ u8 j, n = 0;
- for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
+ switch (cam->bridge) {
+ case BRIDGE_SN9C101:
+ case BRIDGE_SN9C102:
+ soflen = sizeof(sn9c102_sof_header_t);
+ n = sizeof(sn9c102_sof_header) / soflen;
+ break;
+ case BRIDGE_SN9C103:
+ soflen = sizeof(sn9c103_sof_header_t);
+ n = sizeof(sn9c103_sof_header) / soflen;
+ }
+
+ for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
for (j = 0; j < n; j++)
- /* It's enough to compare 7 bytes */
- if (!memcmp(mem + i, sn9c102_sof_header[j], 7)) {
+ /* The invariable part of the header is 6 bytes long */
+ if ((cam->bridge != BRIDGE_SN9C103 &&
+ !memcmp(mem + i, sn9c102_sof_header[j], 6)) ||
+ (cam->bridge == BRIDGE_SN9C103 &&
+ !memcmp(mem + i, sn9c103_sof_header[j], 6))) {
memcpy(cam->sof_header, mem + i, soflen);
/* Skip the header */
return mem + i + soflen;
@@ -499,8 +521,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
{
struct sn9c102_device* cam = urb->context;
struct sn9c102_frame_t** f;
- size_t imagesize;
- unsigned long lock_flags;
+ size_t imagesize, soflen;
u8 i;
int err = 0;
@@ -513,7 +534,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
cam->stream = STREAM_OFF;
if ((*f))
(*f)->state = F_QUEUED;
- DBG(3, "Stream interrupted")
+ DBG(3, "Stream interrupted");
wake_up_interruptible(&cam->wait_stream);
}
@@ -536,6 +557,10 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
cam->sensor->pix_format.height *
cam->sensor->pix_format.priv) / 8;
+ soflen = (cam->bridge) == BRIDGE_SN9C103 ?
+ sizeof(sn9c103_sof_header_t) :
+ sizeof(sn9c102_sof_header_t);
+
for (i = 0; i < urb->number_of_packets; i++) {
unsigned int img, len, status;
void *pos, *sof, *eof;
@@ -545,19 +570,12 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
if (status) {
- DBG(3, "Error in isochronous frame")
+ DBG(3, "Error in isochronous frame");
(*f)->state = F_ERROR;
continue;
}
- PDBGG("Isochrnous frame: length %u, #%u i", len, i)
-
- /*
- NOTE: It is probably correct to assume that SOF and EOF
- headers do not occur between two consecutive packets,
- but who knows..Whatever is the truth, this assumption
- doesn't introduce bugs.
- */
+ PDBGG("Isochrnous frame: length %u, #%u i", len, i);
redo:
sof = sn9c102_find_sof_header(cam, pos, len);
@@ -575,10 +593,10 @@ end_of_frame:
imagesize;
img = imagesize - (*f)->buf.bytesused;
DBG(3, "Expected EOF not found: "
- "video frame cut")
+ "video frame cut");
if (eof)
DBG(3, "Exceeded limit: +%u "
- "bytes", (unsigned)(b))
+ "bytes", (unsigned)(b));
}
memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
@@ -595,8 +613,7 @@ end_of_frame:
u32 b = (*f)->buf.bytesused;
(*f)->state = F_DONE;
(*f)->buf.sequence= ++cam->frame_count;
- spin_lock_irqsave(&cam->queue_lock,
- lock_flags);
+ spin_lock(&cam->queue_lock);
list_move_tail(&(*f)->frame,
&cam->outqueue);
if (!list_empty(&cam->inqueue))
@@ -606,13 +623,11 @@ end_of_frame:
frame );
else
(*f) = NULL;
- spin_unlock_irqrestore(&cam->queue_lock
- , lock_flags);
+ spin_unlock(&cam->queue_lock);
memcpy(cam->sysfs.frame_header,
- cam->sof_header,
- sizeof(sn9c102_sof_header_t));
- DBG(3, "Video frame captured: "
- "%lu bytes", (unsigned long)(b))
+ cam->sof_header, soflen);
+ DBG(3, "Video frame captured: %lu "
+ "bytes", (unsigned long)(b));
if (!(*f))
goto resubmit_urb;
@@ -621,18 +636,19 @@ end_of_frame:
(*f)->state = F_ERROR;
DBG(3, "Not expected EOF after %lu "
"bytes of image data",
- (unsigned long)((*f)->buf.bytesused))
+ (unsigned long)
+ ((*f)->buf.bytesused));
}
if (sof) /* (1) */
goto start_of_frame;
} else if (eof) {
- DBG(3, "EOF without SOF")
+ DBG(3, "EOF without SOF");
continue;
} else {
- PDBGG("Ignoring pointless isochronous frame")
+ PDBGG("Ignoring pointless isochronous frame");
continue;
}
@@ -642,7 +658,7 @@ start_of_frame:
(*f)->buf.bytesused = 0;
len -= (sof - pos);
pos = sof;
- DBG(3, "SOF detected: new video frame")
+ DBG(3, "SOF detected: new video frame");
if (len)
goto redo;
@@ -653,12 +669,13 @@ start_of_frame:
else {
if (cam->sensor->pix_format.pixelformat ==
V4L2_PIX_FMT_SN9C10X) {
- eof = sof-sizeof(sn9c102_sof_header_t);
+ eof = sof - soflen;
goto end_of_frame;
} else {
DBG(3, "SOF before expected EOF after "
"%lu bytes of image data",
- (unsigned long)((*f)->buf.bytesused))
+ (unsigned long)
+ ((*f)->buf.bytesused));
goto start_of_frame;
}
}
@@ -670,7 +687,7 @@ resubmit_urb:
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0 && err != -EPERM) {
cam->state |= DEV_MISCONFIGURED;
- DBG(1, "usb_submit_urb() failed")
+ DBG(1, "usb_submit_urb() failed");
}
wake_up_interruptible(&cam->wait_frame);
@@ -681,18 +698,22 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
{
struct usb_device *udev = cam->usbdev;
struct urb* urb;
- const unsigned int wMaxPacketSize[] = {0, 128, 256, 384, 512,
- 680, 800, 900, 1023};
- const unsigned int psz = wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
+ const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512,
+ 680, 800, 900, 1023};
+ const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512,
+ 680, 800, 900, 1003};
+ const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ?
+ sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
+ sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
s8 i, j;
int err = 0;
for (i = 0; i < SN9C102_URBS; i++) {
- cam->transfer_buffer[i] = kmalloc(SN9C102_ISO_PACKETS * psz,
+ cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
GFP_KERNEL);
if (!cam->transfer_buffer[i]) {
err = -ENOMEM;
- DBG(1, "Not enough memory")
+ DBG(1, "Not enough memory");
goto free_buffers;
}
}
@@ -702,7 +723,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
cam->urb[i] = urb;
if (!urb) {
err = -ENOMEM;
- DBG(1, "usb_alloc_urb() failed")
+ DBG(1, "usb_alloc_urb() failed");
goto free_urbs;
}
urb->dev = udev;
@@ -725,14 +746,14 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
if (err) {
err = -EIO;
- DBG(1, "I/O hardware error")
+ DBG(1, "I/O hardware error");
goto free_urbs;
}
}
err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
if (err) {
- DBG(1, "usb_set_interface() failed")
+ DBG(1, "usb_set_interface() failed");
goto free_urbs;
}
@@ -743,7 +764,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
if (err) {
for (j = i-1; j >= 0; j--)
usb_kill_urb(cam->urb[j]);
- DBG(1, "usb_submit_urb() failed, error %d", err)
+ DBG(1, "usb_submit_urb() failed, error %d", err);
goto free_urbs;
}
}
@@ -779,7 +800,7 @@ static int sn9c102_stop_transfer(struct sn9c102_device* cam)
err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
if (err)
- DBG(3, "usb_set_interface() failed")
+ DBG(3, "usb_set_interface() failed");
return err;
}
@@ -799,7 +820,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
else if (err) {
cam->state |= DEV_MISCONFIGURED;
DBG(1, "The camera is misconfigured. To use it, close and "
- "open /dev/video%d again.", cam->v4ldev->minor)
+ "open /dev/video%d again.", cam->v4ldev->minor);
return err;
}
@@ -808,6 +829,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
/*****************************************************************************/
+#ifdef CONFIG_VIDEO_ADV_DEBUG
static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
{
char str[5];
@@ -885,8 +907,8 @@ sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
cam->sysfs.reg = index;
- DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg)
- DBG(3, "Written bytes: %zd", count)
+ DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg);
+ DBG(3, "Written bytes: %zd", count);
up(&sn9c102_sysfs_lock);
@@ -916,7 +938,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
count = sprintf(buf, "%d\n", val);
- DBG(3, "Read bytes: %zd", count)
+ DBG(3, "Read bytes: %zd", count);
up(&sn9c102_sysfs_lock);
@@ -954,8 +976,8 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
}
DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X",
- cam->sysfs.reg, value)
- DBG(3, "Written bytes: %zd", count)
+ cam->sysfs.reg, value);
+ DBG(3, "Written bytes: %zd", count);
up(&sn9c102_sysfs_lock);
@@ -979,7 +1001,7 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
- DBG(3, "Read bytes: %zd", count)
+ DBG(3, "Read bytes: %zd", count);
up(&sn9c102_sysfs_lock);
@@ -1011,8 +1033,8 @@ sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
cam->sysfs.i2c_reg = index;
- DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg)
- DBG(3, "Written bytes: %zd", count)
+ DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
+ DBG(3, "Written bytes: %zd", count);
up(&sn9c102_sysfs_lock);
@@ -1047,7 +1069,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
count = sprintf(buf, "%d\n", val);
- DBG(3, "Read bytes: %zd", count)
+ DBG(3, "Read bytes: %zd", count);
up(&sn9c102_sysfs_lock);
@@ -1090,8 +1112,8 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
}
DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
- cam->sysfs.i2c_reg, value)
- DBG(3, "Written bytes: %zd", count)
+ cam->sysfs.i2c_reg, value);
+ DBG(3, "Written bytes: %zd", count);
up(&sn9c102_sysfs_lock);
@@ -1193,7 +1215,7 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
count = sizeof(cam->sysfs.frame_header);
memcpy(buf, cam->sysfs.frame_header, count);
- DBG(3, "Frame header, read bytes: %zd", count)
+ DBG(3, "Frame header, read bytes: %zd", count);
return count;
}
@@ -1227,11 +1249,12 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam)
video_device_create_file(v4ldev, &class_device_attr_blue);
video_device_create_file(v4ldev, &class_device_attr_red);
}
- if (cam->sensor->sysfs_ops) {
+ if (cam->sensor && cam->sensor->sysfs_ops) {
video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
video_device_create_file(v4ldev, &class_device_attr_i2c_val);
}
}
+#endif /* CONFIG_VIDEO_ADV_DEBUG */
/*****************************************************************************/
@@ -1281,7 +1304,7 @@ static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale)
if (err)
return -EIO;
- PDBGG("Scaling factor: %u", scale)
+ PDBGG("Scaling factor: %u", scale);
return 0;
}
@@ -1304,7 +1327,7 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
return -EIO;
PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
- "%u %u %u %u", h_start, v_start, h_size, v_size)
+ "%u %u %u %u", h_start, v_start, h_size, v_size);
return 0;
}
@@ -1336,7 +1359,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
if (s->init) {
err = s->init(cam);
if (err) {
- DBG(3, "Sensor initialization failed")
+ DBG(3, "Sensor initialization failed");
return err;
}
}
@@ -1353,13 +1376,13 @@ static int sn9c102_init(struct sn9c102_device* cam)
if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
DBG(3, "Compressed video format is active, quality %d",
- cam->compression.quality)
+ cam->compression.quality);
else
- DBG(3, "Uncompressed video format is active")
+ DBG(3, "Uncompressed video format is active");
if (s->set_crop)
if ((err = s->set_crop(cam, rect))) {
- DBG(3, "set_crop() failed")
+ DBG(3, "set_crop() failed");
return err;
}
@@ -1372,11 +1395,11 @@ static int sn9c102_init(struct sn9c102_device* cam)
err = s->set_ctrl(cam, &ctrl);
if (err) {
DBG(3, "Set %s control failed",
- s->qctrl[i].name)
+ s->qctrl[i].name);
return err;
}
DBG(3, "Image sensor supports '%s' control",
- s->qctrl[i].name)
+ s->qctrl[i].name);
}
}
@@ -1392,7 +1415,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
cam->state |= DEV_INITIALIZED;
}
- DBG(2, "Initialization succeeded")
+ DBG(2, "Initialization succeeded");
return 0;
}
@@ -1401,7 +1424,7 @@ static void sn9c102_release_resources(struct sn9c102_device* cam)
{
down(&sn9c102_sysfs_lock);
- DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor)
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
@@ -1432,7 +1455,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
}
if (cam->users) {
- DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor)
+ DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
if ((filp->f_flags & O_NONBLOCK) ||
(filp->f_flags & O_NDELAY)) {
err = -EWOULDBLOCK;
@@ -1458,7 +1481,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
err = sn9c102_init(cam);
if (err) {
DBG(1, "Initialization failed again. "
- "I will retry on next open().")
+ "I will retry on next open().");
goto out;
}
cam->state &= ~DEV_MISCONFIGURED;
@@ -1475,7 +1498,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
cam->frame_count = 0;
sn9c102_empty_framequeues(cam);
- DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor)
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
out:
up(&cam->dev_sem);
@@ -1504,7 +1527,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
cam->users--;
wake_up_interruptible_nr(&cam->open, 1);
- DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor)
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
up(&cam->dev_sem);
@@ -1524,32 +1547,38 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
return -ERESTARTSYS;
if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present")
+ DBG(1, "Device not present");
up(&cam->fileop_sem);
return -ENODEV;
}
if (cam->state & DEV_MISCONFIGURED) {
- DBG(1, "The camera is misconfigured. Close and open it again.")
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
up(&cam->fileop_sem);
return -EIO;
}
if (cam->io == IO_MMAP) {
DBG(3, "Close and open the device again to choose "
- "the read method")
+ "the read method");
up(&cam->fileop_sem);
return -EINVAL;
}
if (cam->io == IO_NONE) {
if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) {
- DBG(1, "read() failed, not enough memory")
+ DBG(1, "read() failed, not enough memory");
up(&cam->fileop_sem);
return -ENOMEM;
}
cam->io = IO_READ;
cam->stream = STREAM_ON;
+ }
+
+ if (list_empty(&cam->inqueue)) {
+ if (!list_empty(&cam->outqueue))
+ sn9c102_empty_framequeues(cam);
sn9c102_queue_unusedframes(cam);
}
@@ -1584,6 +1613,16 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
+ if (count > f->buf.bytesused)
+ count = f->buf.bytesused;
+
+ if (copy_to_user(buf, f->bufmem, count)) {
+ err = -EFAULT;
+ goto exit;
+ }
+ *f_pos += count;
+
+exit:
spin_lock_irqsave(&cam->queue_lock, lock_flags);
list_for_each_entry(i, &cam->outqueue, frame)
i->state = F_UNUSED;
@@ -1592,16 +1631,8 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
sn9c102_queue_unusedframes(cam);
- if (count > f->buf.bytesused)
- count = f->buf.bytesused;
-
- if (copy_to_user(buf, f->bufmem, count)) {
- up(&cam->fileop_sem);
- return -EFAULT;
- }
- *f_pos += count;
-
- PDBGG("Frame #%lu, bytes read: %zu", (unsigned long)f->buf.index,count)
+ PDBGG("Frame #%lu, bytes read: %zu",
+ (unsigned long)f->buf.index, count);
up(&cam->fileop_sem);
@@ -1612,33 +1643,42 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
{
struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct sn9c102_frame_t* f;
+ unsigned long lock_flags;
unsigned int mask = 0;
if (down_interruptible(&cam->fileop_sem))
return POLLERR;
if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present")
+ DBG(1, "Device not present");
goto error;
}
if (cam->state & DEV_MISCONFIGURED) {
- DBG(1, "The camera is misconfigured. Close and open it again.")
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
goto error;
}
if (cam->io == IO_NONE) {
if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
IO_READ)) {
- DBG(1, "poll() failed, not enough memory")
+ DBG(1, "poll() failed, not enough memory");
goto error;
}
cam->io = IO_READ;
cam->stream = STREAM_ON;
}
- if (cam->io == IO_READ)
+ if (cam->io == IO_READ) {
+ spin_lock_irqsave(&cam->queue_lock, lock_flags);
+ list_for_each_entry(f, &cam->outqueue, frame)
+ f->state = F_UNUSED;
+ INIT_LIST_HEAD(&cam->outqueue);
+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
sn9c102_queue_unusedframes(cam);
+ }
poll_wait(filp, &cam->wait_frame, wait);
@@ -1680,22 +1720,22 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
{
struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
unsigned long size = vma->vm_end - vma->vm_start,
- start = vma->vm_start,
- pos,
- page;
+ start = vma->vm_start;
+ void *pos;
u32 i;
if (down_interruptible(&cam->fileop_sem))
return -ERESTARTSYS;
if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present")
+ DBG(1, "Device not present");
up(&cam->fileop_sem);
return -ENODEV;
}
if (cam->state & DEV_MISCONFIGURED) {
- DBG(1, "The camera is misconfigured. Close and open it again.")
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
up(&cam->fileop_sem);
return -EIO;
}
@@ -1715,15 +1755,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
return -EINVAL;
}
- /* VM_IO is eventually going to replace PageReserved altogether */
vma->vm_flags |= VM_IO;
- vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+ vma->vm_flags |= VM_RESERVED;
- pos = (unsigned long)cam->frame[i].bufmem;
+ pos = cam->frame[i].bufmem;
while (size > 0) { /* size is page-aligned */
- page = vmalloc_to_pfn((void *)pos);
- if (remap_pfn_range(vma, start, page, PAGE_SIZE,
- vma->vm_page_prot)) {
+ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
up(&cam->fileop_sem);
return -EAGAIN;
}
@@ -1742,738 +1779,861 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
return 0;
}
+/*****************************************************************************/
-static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+static int
+sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
{
- struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct v4l2_capability cap = {
+ .driver = "sn9c102",
+ .version = SN9C102_MODULE_VERSION_CODE,
+ .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING,
+ };
+
+ strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
+ if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
+ strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
+ sizeof(cap.bus_info));
+
+ if (copy_to_user(arg, &cap, sizeof(cap)))
+ return -EFAULT;
- switch (cmd) {
+ return 0;
+}
- case VIDIOC_QUERYCAP:
- {
- struct v4l2_capability cap = {
- .driver = "sn9c102",
- .version = SN9C102_MODULE_VERSION_CODE,
- .capabilities = V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING,
- };
-
- strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
- if (usb_make_path(cam->usbdev, cap.bus_info,
- sizeof(cap.bus_info)) < 0)
- strlcpy(cap.bus_info, cam->dev.bus_id,
- sizeof(cap.bus_info));
-
- if (copy_to_user(arg, &cap, sizeof(cap)))
- return -EFAULT;
- return 0;
- }
+static int
+sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_input i;
- case VIDIOC_ENUMINPUT:
- {
- struct v4l2_input i;
+ if (copy_from_user(&i, arg, sizeof(i)))
+ return -EFAULT;
- if (copy_from_user(&i, arg, sizeof(i)))
- return -EFAULT;
+ if (i.index)
+ return -EINVAL;
- if (i.index)
- return -EINVAL;
+ memset(&i, 0, sizeof(i));
+ strcpy(i.name, "Camera");
- memset(&i, 0, sizeof(i));
- strcpy(i.name, "USB");
+ if (copy_to_user(arg, &i, sizeof(i)))
+ return -EFAULT;
- if (copy_to_user(arg, &i, sizeof(i)))
- return -EFAULT;
+ return 0;
+}
- return 0;
- }
- case VIDIOC_G_INPUT:
- case VIDIOC_S_INPUT:
- {
- int index;
+static int
+sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg)
+{
+ int index;
- if (copy_from_user(&index, arg, sizeof(index)))
- return -EFAULT;
+ if (copy_from_user(&index, arg, sizeof(index)))
+ return -EFAULT;
- if (index != 0)
- return -EINVAL;
+ if (index != 0)
+ return -EINVAL;
- return 0;
- }
+ return 0;
+}
- case VIDIOC_QUERYCTRL:
- {
- struct sn9c102_sensor* s = cam->sensor;
- struct v4l2_queryctrl qc;
- u8 i;
- if (copy_from_user(&qc, arg, sizeof(qc)))
- return -EFAULT;
+static int
+sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+ struct sn9c102_sensor* s = cam->sensor;
+ struct v4l2_queryctrl qc;
+ u8 i;
+ if (copy_from_user(&qc, arg, sizeof(qc)))
+ return -EFAULT;
+
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (qc.id && qc.id == s->qctrl[i].id) {
+ memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
+ if (copy_to_user(arg, &qc, sizeof(qc)))
+ return -EFAULT;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+
+static int
+sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+ struct sn9c102_sensor* s = cam->sensor;
+ struct v4l2_control ctrl;
+ int err = 0;
+ u8 i;
+
+ if (!s->get_ctrl && !s->set_ctrl)
+ return -EINVAL;
+
+ if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+ return -EFAULT;
+
+ if (!s->get_ctrl) {
for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
- if (qc.id && qc.id == s->qctrl[i].id) {
- memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
- if (copy_to_user(arg, &qc, sizeof(qc)))
- return -EFAULT;
- return 0;
+ if (ctrl.id && ctrl.id == s->qctrl[i].id) {
+ ctrl.value = s->_qctrl[i].default_value;
+ goto exit;
}
-
return -EINVAL;
- }
+ } else
+ err = s->get_ctrl(cam, &ctrl);
- case VIDIOC_G_CTRL:
- {
- struct sn9c102_sensor* s = cam->sensor;
- struct v4l2_control ctrl;
- int err = 0;
+exit:
+ if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
+ return -EFAULT;
- if (!s->get_ctrl)
- return -EINVAL;
+ return err;
+}
- if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
- return -EFAULT;
- err = s->get_ctrl(cam, &ctrl);
+static int
+sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+ struct sn9c102_sensor* s = cam->sensor;
+ struct v4l2_control ctrl;
+ u8 i;
+ int err = 0;
- if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
- return -EFAULT;
+ if (!s->set_ctrl)
+ return -EINVAL;
+
+ if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+ return -EFAULT;
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (ctrl.id == s->qctrl[i].id) {
+ if (ctrl.value < s->qctrl[i].minimum ||
+ ctrl.value > s->qctrl[i].maximum)
+ return -ERANGE;
+ ctrl.value -= ctrl.value % s->qctrl[i].step;
+ break;
+ }
+
+ if ((err = s->set_ctrl(cam, &ctrl)))
return err;
- }
- case VIDIOC_S_CTRL_OLD:
- case VIDIOC_S_CTRL:
- {
- struct sn9c102_sensor* s = cam->sensor;
- struct v4l2_control ctrl;
- u8 i;
- int err = 0;
+ s->_qctrl[i].default_value = ctrl.value;
- if (!s->set_ctrl)
- return -EINVAL;
+ PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
+ (unsigned long)ctrl.id, (unsigned long)ctrl.value);
- if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
- return -EFAULT;
+ return 0;
+}
- for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
- if (ctrl.id == s->qctrl[i].id) {
- if (ctrl.value < s->qctrl[i].minimum ||
- ctrl.value > s->qctrl[i].maximum)
- return -ERANGE;
- ctrl.value -= ctrl.value % s->qctrl[i].step;
- break;
+
+static int
+sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
+
+ cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cc->pixelaspect.numerator = 1;
+ cc->pixelaspect.denominator = 1;
+
+ if (copy_to_user(arg, cc, sizeof(*cc)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
+{
+ struct sn9c102_sensor* s = cam->sensor;
+ struct v4l2_crop crop = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ };
+
+ memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
+
+ if (copy_to_user(arg, &crop, sizeof(crop)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
+{
+ struct sn9c102_sensor* s = cam->sensor;
+ struct v4l2_crop crop;
+ struct v4l2_rect* rect;
+ struct v4l2_rect* bounds = &(s->cropcap.bounds);
+ struct v4l2_pix_format* pix_format = &(s->pix_format);
+ u8 scale;
+ const enum sn9c102_stream_state stream = cam->stream;
+ const u32 nbuffers = cam->nbuffers;
+ u32 i;
+ int err = 0;
+
+ if (copy_from_user(&crop, arg, sizeof(crop)))
+ return -EFAULT;
+
+ rect = &(crop.c);
+
+ if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (cam->module_param.force_munmap)
+ for (i = 0; i < cam->nbuffers; i++)
+ if (cam->frame[i].vma_use_count) {
+ DBG(3, "VIDIOC_S_CROP failed. "
+ "Unmap the buffers first.");
+ return -EINVAL;
}
- if ((err = s->set_ctrl(cam, &ctrl)))
+ /* Preserve R,G or B origin */
+ rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
+ rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
+
+ if (rect->width < 16)
+ rect->width = 16;
+ if (rect->height < 16)
+ rect->height = 16;
+ if (rect->width > bounds->width)
+ rect->width = bounds->width;
+ if (rect->height > bounds->height)
+ rect->height = bounds->height;
+ if (rect->left < bounds->left)
+ rect->left = bounds->left;
+ if (rect->top < bounds->top)
+ rect->top = bounds->top;
+ if (rect->left + rect->width > bounds->left + bounds->width)
+ rect->left = bounds->left+bounds->width - rect->width;
+ if (rect->top + rect->height > bounds->top + bounds->height)
+ rect->top = bounds->top+bounds->height - rect->height;
+
+ rect->width &= ~15L;
+ rect->height &= ~15L;
+
+ if (SN9C102_PRESERVE_IMGSCALE) {
+ /* Calculate the actual scaling factor */
+ u32 a, b;
+ a = rect->width * rect->height;
+ b = pix_format->width * pix_format->height;
+ scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
+ } else
+ scale = 1;
+
+ if (cam->stream == STREAM_ON)
+ if ((err = sn9c102_stream_interrupt(cam)))
return err;
- s->_qctrl[i].default_value = ctrl.value;
+ if (copy_to_user(arg, &crop, sizeof(crop))) {
+ cam->stream = stream;
+ return -EFAULT;
+ }
+
+ if (cam->module_param.force_munmap || cam->io == IO_READ)
+ sn9c102_release_buffers(cam);
- PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
- (unsigned long)ctrl.id, (unsigned long)ctrl.value)
+ err = sn9c102_set_crop(cam, rect);
+ if (s->set_crop)
+ err += s->set_crop(cam, rect);
+ err += sn9c102_set_scale(cam, scale);
- return 0;
+ if (err) { /* atomic, no rollback in ioctl() */
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
+ "use the camera, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return -EIO;
}
- case VIDIOC_CROPCAP:
- {
- struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
+ s->pix_format.width = rect->width/scale;
+ s->pix_format.height = rect->height/scale;
+ memcpy(&(s->_rect), rect, sizeof(*rect));
- cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- cc->pixelaspect.numerator = 1;
- cc->pixelaspect.denominator = 1;
+ if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
+ nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
+ "use the camera, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return -ENOMEM;
+ }
- if (copy_to_user(arg, cc, sizeof(*cc)))
- return -EFAULT;
+ if (cam->io == IO_READ)
+ sn9c102_empty_framequeues(cam);
+ else if (cam->module_param.force_munmap)
+ sn9c102_requeue_outqueue(cam);
- return 0;
- }
+ cam->stream = stream;
- case VIDIOC_G_CROP:
- {
- struct sn9c102_sensor* s = cam->sensor;
- struct v4l2_crop crop = {
- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- };
+ return 0;
+}
- memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
- if (copy_to_user(arg, &crop, sizeof(crop)))
- return -EFAULT;
+static int
+sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_fmtdesc fmtd;
- return 0;
- }
+ if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
+ return -EFAULT;
- case VIDIOC_S_CROP:
- {
- struct sn9c102_sensor* s = cam->sensor;
- struct v4l2_crop crop;
- struct v4l2_rect* rect;
- struct v4l2_rect* bounds = &(s->cropcap.bounds);
- struct v4l2_pix_format* pix_format = &(s->pix_format);
- u8 scale;
- const enum sn9c102_stream_state stream = cam->stream;
- const u32 nbuffers = cam->nbuffers;
- u32 i;
- int err = 0;
-
- if (copy_from_user(&crop, arg, sizeof(crop)))
- return -EFAULT;
+ if (fmtd.index == 0) {
+ strcpy(fmtd.description, "bayer rgb");
+ fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
+ } else if (fmtd.index == 1) {
+ strcpy(fmtd.description, "compressed");
+ fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
+ fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
+ } else
+ return -EINVAL;
- rect = &(crop.c);
+ fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
- if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
+ if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
+ return -EFAULT;
- if (cam->module_param.force_munmap)
- for (i = 0; i < cam->nbuffers; i++)
- if (cam->frame[i].vma_use_count) {
- DBG(3, "VIDIOC_S_CROP failed. "
- "Unmap the buffers first.")
- return -EINVAL;
- }
+ return 0;
+}
- /* Preserve R,G or B origin */
- rect->left = (s->_rect.left & 1L) ?
- rect->left | 1L : rect->left & ~1L;
- rect->top = (s->_rect.top & 1L) ?
- rect->top | 1L : rect->top & ~1L;
-
- if (rect->width < 16)
- rect->width = 16;
- if (rect->height < 16)
- rect->height = 16;
- if (rect->width > bounds->width)
- rect->width = bounds->width;
- if (rect->height > bounds->height)
- rect->height = bounds->height;
- if (rect->left < bounds->left)
- rect->left = bounds->left;
- if (rect->top < bounds->top)
- rect->top = bounds->top;
- if (rect->left + rect->width > bounds->left + bounds->width)
- rect->left = bounds->left+bounds->width - rect->width;
- if (rect->top + rect->height > bounds->top + bounds->height)
- rect->top = bounds->top+bounds->height - rect->height;
-
- rect->width &= ~15L;
- rect->height &= ~15L;
-
- if (SN9C102_PRESERVE_IMGSCALE) {
- /* Calculate the actual scaling factor */
- u32 a, b;
- a = rect->width * rect->height;
- b = pix_format->width * pix_format->height;
- scale = b ? (u8)((a / b) < 4 ? 1 :
- ((a / b) < 16 ? 2 : 4)) : 1;
- } else
- scale = 1;
-
- if (cam->stream == STREAM_ON)
- if ((err = sn9c102_stream_interrupt(cam)))
- return err;
-
- if (copy_to_user(arg, &crop, sizeof(crop))) {
- cam->stream = stream;
- return -EFAULT;
- }
- if (cam->module_param.force_munmap || cam->io == IO_READ)
- sn9c102_release_buffers(cam);
+static int
+sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_format format;
+ struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
- err = sn9c102_set_crop(cam, rect);
- if (s->set_crop)
- err += s->set_crop(cam, rect);
- err += sn9c102_set_scale(cam, scale);
+ if (copy_from_user(&format, arg, sizeof(format)))
+ return -EFAULT;
- if (err) { /* atomic, no rollback in ioctl() */
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_CROP failed because of hardware "
- "problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor)
- return -EIO;
- }
+ if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
- s->pix_format.width = rect->width/scale;
- s->pix_format.height = rect->height/scale;
- memcpy(&(s->_rect), rect, sizeof(*rect));
-
- if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
- nbuffers != sn9c102_request_buffers(cam, nbuffers,
- cam->io)) {
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_CROP failed because of not enough "
- "memory. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor)
- return -ENOMEM;
- }
+ pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
+ ? 0 : (pfmt->width * pfmt->priv) / 8;
+ pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
+ pfmt->field = V4L2_FIELD_NONE;
+ memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
- cam->stream = stream;
+ if (copy_to_user(arg, &format, sizeof(format)))
+ return -EFAULT;
- return 0;
- }
+ return 0;
+}
- case VIDIOC_ENUM_FMT:
- {
- struct v4l2_fmtdesc fmtd;
- if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
- return -EFAULT;
+static int
+sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
+ void __user * arg)
+{
+ struct sn9c102_sensor* s = cam->sensor;
+ struct v4l2_format format;
+ struct v4l2_pix_format* pix;
+ struct v4l2_pix_format* pfmt = &(s->pix_format);
+ struct v4l2_rect* bounds = &(s->cropcap.bounds);
+ struct v4l2_rect rect;
+ u8 scale;
+ const enum sn9c102_stream_state stream = cam->stream;
+ const u32 nbuffers = cam->nbuffers;
+ u32 i;
+ int err = 0;
- if (fmtd.index == 0) {
- strcpy(fmtd.description, "bayer rgb");
- fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
- } else if (fmtd.index == 1) {
- strcpy(fmtd.description, "compressed");
- fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
- fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
- } else
- return -EINVAL;
+ if (copy_from_user(&format, arg, sizeof(format)))
+ return -EFAULT;
- fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
+ pix = &(format.fmt.pix);
- if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
- return -EFAULT;
+ if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
- return 0;
+ memcpy(&rect, &(s->_rect), sizeof(rect));
+
+ { /* calculate the actual scaling factor */
+ u32 a, b;
+ a = rect.width * rect.height;
+ b = pix->width * pix->height;
+ scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
}
- case VIDIOC_G_FMT:
- {
- struct v4l2_format format;
- struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
+ rect.width = scale * pix->width;
+ rect.height = scale * pix->height;
- if (copy_from_user(&format, arg, sizeof(format)))
- return -EFAULT;
+ if (rect.width < 16)
+ rect.width = 16;
+ if (rect.height < 16)
+ rect.height = 16;
+ if (rect.width > bounds->left + bounds->width - rect.left)
+ rect.width = bounds->left + bounds->width - rect.left;
+ if (rect.height > bounds->top + bounds->height - rect.top)
+ rect.height = bounds->top + bounds->height - rect.top;
- if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
+ rect.width &= ~15L;
+ rect.height &= ~15L;
+
+ { /* adjust the scaling factor */
+ u32 a, b;
+ a = rect.width * rect.height;
+ b = pix->width * pix->height;
+ scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
+ }
- pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
- ? 0 : (pfmt->width * pfmt->priv) / 8;
- pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
- pfmt->field = V4L2_FIELD_NONE;
- memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
+ pix->width = rect.width / scale;
+ pix->height = rect.height / scale;
+ if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
+ pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+ pix->pixelformat = pfmt->pixelformat;
+ pix->priv = pfmt->priv; /* bpp */
+ pix->colorspace = pfmt->colorspace;
+ pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+ ? 0 : (pix->width * pix->priv) / 8;
+ pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
+ pix->field = V4L2_FIELD_NONE;
+
+ if (cmd == VIDIOC_TRY_FMT) {
if (copy_to_user(arg, &format, sizeof(format)))
return -EFAULT;
-
return 0;
}
- case VIDIOC_TRY_FMT:
- case VIDIOC_S_FMT:
- {
- struct sn9c102_sensor* s = cam->sensor;
- struct v4l2_format format;
- struct v4l2_pix_format* pix;
- struct v4l2_pix_format* pfmt = &(s->pix_format);
- struct v4l2_rect* bounds = &(s->cropcap.bounds);
- struct v4l2_rect rect;
- u8 scale;
- const enum sn9c102_stream_state stream = cam->stream;
- const u32 nbuffers = cam->nbuffers;
- u32 i;
- int err = 0;
-
- if (copy_from_user(&format, arg, sizeof(format)))
- return -EFAULT;
+ if (cam->module_param.force_munmap)
+ for (i = 0; i < cam->nbuffers; i++)
+ if (cam->frame[i].vma_use_count) {
+ DBG(3, "VIDIOC_S_FMT failed. Unmap the "
+ "buffers first.");
+ return -EINVAL;
+ }
- pix = &(format.fmt.pix);
+ if (cam->stream == STREAM_ON)
+ if ((err = sn9c102_stream_interrupt(cam)))
+ return err;
- if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
+ if (copy_to_user(arg, &format, sizeof(format))) {
+ cam->stream = stream;
+ return -EFAULT;
+ }
- memcpy(&rect, &(s->_rect), sizeof(rect));
+ if (cam->module_param.force_munmap || cam->io == IO_READ)
+ sn9c102_release_buffers(cam);
- { /* calculate the actual scaling factor */
- u32 a, b;
- a = rect.width * rect.height;
- b = pix->width * pix->height;
- scale = b ? (u8)((a / b) < 4 ? 1 :
- ((a / b) < 16 ? 2 : 4)) : 1;
- }
+ err += sn9c102_set_pix_format(cam, pix);
+ err += sn9c102_set_crop(cam, &rect);
+ if (s->set_pix_format)
+ err += s->set_pix_format(cam, pix);
+ if (s->set_crop)
+ err += s->set_crop(cam, &rect);
+ err += sn9c102_set_scale(cam, scale);
- rect.width = scale * pix->width;
- rect.height = scale * pix->height;
-
- if (rect.width < 16)
- rect.width = 16;
- if (rect.height < 16)
- rect.height = 16;
- if (rect.width > bounds->left + bounds->width - rect.left)
- rect.width = bounds->left + bounds->width - rect.left;
- if (rect.height > bounds->top + bounds->height - rect.top)
- rect.height = bounds->top + bounds->height - rect.top;
-
- rect.width &= ~15L;
- rect.height &= ~15L;
-
- { /* adjust the scaling factor */
- u32 a, b;
- a = rect.width * rect.height;
- b = pix->width * pix->height;
- scale = b ? (u8)((a / b) < 4 ? 1 :
- ((a / b) < 16 ? 2 : 4)) : 1;
- }
+ if (err) { /* atomic, no rollback in ioctl() */
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
+ "use the camera, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return -EIO;
+ }
- pix->width = rect.width / scale;
- pix->height = rect.height / scale;
-
- if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
- pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
- pix->pixelformat = pfmt->pixelformat;
- pix->priv = pfmt->priv; /* bpp */
- pix->colorspace = pfmt->colorspace;
- pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- ? 0 : (pix->width * pix->priv) / 8;
- pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
- pix->field = V4L2_FIELD_NONE;
-
- if (cmd == VIDIOC_TRY_FMT) {
- if (copy_to_user(arg, &format, sizeof(format)))
- return -EFAULT;
- return 0;
- }
+ memcpy(pfmt, pix, sizeof(*pix));
+ memcpy(&(s->_rect), &rect, sizeof(rect));
- if (cam->module_param.force_munmap)
- for (i = 0; i < cam->nbuffers; i++)
- if (cam->frame[i].vma_use_count) {
- DBG(3, "VIDIOC_S_FMT failed. "
- "Unmap the buffers first.")
- return -EINVAL;
- }
+ if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
+ nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
+ "use the camera, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+ return -ENOMEM;
+ }
- if (cam->stream == STREAM_ON)
- if ((err = sn9c102_stream_interrupt(cam)))
- return err;
+ if (cam->io == IO_READ)
+ sn9c102_empty_framequeues(cam);
+ else if (cam->module_param.force_munmap)
+ sn9c102_requeue_outqueue(cam);
- if (copy_to_user(arg, &format, sizeof(format))) {
- cam->stream = stream;
- return -EFAULT;
- }
+ cam->stream = stream;
- if (cam->module_param.force_munmap || cam->io == IO_READ)
- sn9c102_release_buffers(cam);
-
- err += sn9c102_set_pix_format(cam, pix);
- err += sn9c102_set_crop(cam, &rect);
- if (s->set_pix_format)
- err += s->set_pix_format(cam, pix);
- if (s->set_crop)
- err += s->set_crop(cam, &rect);
- err += sn9c102_set_scale(cam, scale);
-
- if (err) { /* atomic, no rollback in ioctl() */
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_FMT failed because of hardware "
- "problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor)
- return -EIO;
- }
+ return 0;
+}
- memcpy(pfmt, pix, sizeof(*pix));
- memcpy(&(s->_rect), &rect, sizeof(rect));
- if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
- nbuffers != sn9c102_request_buffers(cam, nbuffers,
- cam->io)) {
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_FMT failed because of not enough "
- "memory. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor)
- return -ENOMEM;
- }
+static int
+sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
+{
+ if (copy_to_user(arg, &cam->compression,
+ sizeof(cam->compression)))
+ return -EFAULT;
- cam->stream = stream;
+ return 0;
+}
- return 0;
- }
- case VIDIOC_G_JPEGCOMP:
- {
- if (copy_to_user(arg, &cam->compression,
- sizeof(cam->compression)))
- return -EFAULT;
+static int
+sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_jpegcompression jc;
+ const enum sn9c102_stream_state stream = cam->stream;
+ int err = 0;
- return 0;
- }
+ if (copy_from_user(&jc, arg, sizeof(jc)))
+ return -EFAULT;
- case VIDIOC_S_JPEGCOMP:
- {
- struct v4l2_jpegcompression jc;
- const enum sn9c102_stream_state stream = cam->stream;
- int err = 0;
+ if (jc.quality != 0 && jc.quality != 1)
+ return -EINVAL;
- if (copy_from_user(&jc, arg, sizeof(jc)))
- return -EFAULT;
+ if (cam->stream == STREAM_ON)
+ if ((err = sn9c102_stream_interrupt(cam)))
+ return err;
- if (jc.quality != 0 && jc.quality != 1)
- return -EINVAL;
+ err += sn9c102_set_compression(cam, &jc);
+ if (err) { /* atomic, no rollback in ioctl() */
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
+ "problems. To use the camera, close and open "
+ "/dev/video%d again.", cam->v4ldev->minor);
+ return -EIO;
+ }
- if (cam->stream == STREAM_ON)
- if ((err = sn9c102_stream_interrupt(cam)))
- return err;
+ cam->compression.quality = jc.quality;
- err += sn9c102_set_compression(cam, &jc);
- if (err) { /* atomic, no rollback in ioctl() */
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
- "problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor)
- return -EIO;
- }
+ cam->stream = stream;
- cam->compression.quality = jc.quality;
+ return 0;
+}
- cam->stream = stream;
- return 0;
- }
+static int
+sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_requestbuffers rb;
+ u32 i;
+ int err;
- case VIDIOC_REQBUFS:
- {
- struct v4l2_requestbuffers rb;
- u32 i;
- int err;
+ if (copy_from_user(&rb, arg, sizeof(rb)))
+ return -EFAULT;
- if (copy_from_user(&rb, arg, sizeof(rb)))
- return -EFAULT;
+ if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ rb.memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
- if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- rb.memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
+ if (cam->io == IO_READ) {
+ DBG(3, "Close and open the device again to choose the mmap "
+ "I/O method");
+ return -EINVAL;
+ }
- if (cam->io == IO_READ) {
- DBG(3, "Close and open the device again to choose "
- "the mmap I/O method")
+ for (i = 0; i < cam->nbuffers; i++)
+ if (cam->frame[i].vma_use_count) {
+ DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
+ "still mapped.");
return -EINVAL;
}
- for (i = 0; i < cam->nbuffers; i++)
- if (cam->frame[i].vma_use_count) {
- DBG(3, "VIDIOC_REQBUFS failed. "
- "Previous buffers are still mapped.")
- return -EINVAL;
- }
+ if (cam->stream == STREAM_ON)
+ if ((err = sn9c102_stream_interrupt(cam)))
+ return err;
- if (cam->stream == STREAM_ON)
- if ((err = sn9c102_stream_interrupt(cam)))
- return err;
+ sn9c102_empty_framequeues(cam);
- sn9c102_empty_framequeues(cam);
+ sn9c102_release_buffers(cam);
+ if (rb.count)
+ rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
+ if (copy_to_user(arg, &rb, sizeof(rb))) {
sn9c102_release_buffers(cam);
- if (rb.count)
- rb.count = sn9c102_request_buffers(cam, rb.count,
- IO_MMAP);
+ cam->io = IO_NONE;
+ return -EFAULT;
+ }
- if (copy_to_user(arg, &rb, sizeof(rb))) {
- sn9c102_release_buffers(cam);
- cam->io = IO_NONE;
- return -EFAULT;
- }
+ cam->io = rb.count ? IO_MMAP : IO_NONE;
- cam->io = rb.count ? IO_MMAP : IO_NONE;
+ return 0;
+}
- return 0;
- }
- case VIDIOC_QUERYBUF:
- {
- struct v4l2_buffer b;
+static int
+sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_buffer b;
- if (copy_from_user(&b, arg, sizeof(b)))
- return -EFAULT;
+ if (copy_from_user(&b, arg, sizeof(b)))
+ return -EFAULT;
- if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- b.index >= cam->nbuffers || cam->io != IO_MMAP)
- return -EINVAL;
+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ b.index >= cam->nbuffers || cam->io != IO_MMAP)
+ return -EINVAL;
- memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
+ memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
- if (cam->frame[b.index].vma_use_count)
- b.flags |= V4L2_BUF_FLAG_MAPPED;
+ if (cam->frame[b.index].vma_use_count)
+ b.flags |= V4L2_BUF_FLAG_MAPPED;
- if (cam->frame[b.index].state == F_DONE)
- b.flags |= V4L2_BUF_FLAG_DONE;
- else if (cam->frame[b.index].state != F_UNUSED)
- b.flags |= V4L2_BUF_FLAG_QUEUED;
+ if (cam->frame[b.index].state == F_DONE)
+ b.flags |= V4L2_BUF_FLAG_DONE;
+ else if (cam->frame[b.index].state != F_UNUSED)
+ b.flags |= V4L2_BUF_FLAG_QUEUED;
- if (copy_to_user(arg, &b, sizeof(b)))
- return -EFAULT;
+ if (copy_to_user(arg, &b, sizeof(b)))
+ return -EFAULT;
- return 0;
- }
+ return 0;
+}
- case VIDIOC_QBUF:
- {
- struct v4l2_buffer b;
- unsigned long lock_flags;
- if (copy_from_user(&b, arg, sizeof(b)))
- return -EFAULT;
+static int
+sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_buffer b;
+ unsigned long lock_flags;
- if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- b.index >= cam->nbuffers || cam->io != IO_MMAP)
- return -EINVAL;
+ if (copy_from_user(&b, arg, sizeof(b)))
+ return -EFAULT;
- if (cam->frame[b.index].state != F_UNUSED)
- return -EINVAL;
+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ b.index >= cam->nbuffers || cam->io != IO_MMAP)
+ return -EINVAL;
- cam->frame[b.index].state = F_QUEUED;
+ if (cam->frame[b.index].state != F_UNUSED)
+ return -EINVAL;
- spin_lock_irqsave(&cam->queue_lock, lock_flags);
- list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
- spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+ cam->frame[b.index].state = F_QUEUED;
- PDBGG("Frame #%lu queued", (unsigned long)b.index)
+ spin_lock_irqsave(&cam->queue_lock, lock_flags);
+ list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
- return 0;
- }
+ PDBGG("Frame #%lu queued", (unsigned long)b.index);
- case VIDIOC_DQBUF:
- {
- struct v4l2_buffer b;
- struct sn9c102_frame_t *f;
- unsigned long lock_flags;
- int err = 0;
+ return 0;
+}
- if (copy_from_user(&b, arg, sizeof(b)))
- return -EFAULT;
- if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP)
+static int
+sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
+ void __user * arg)
+{
+ struct v4l2_buffer b;
+ struct sn9c102_frame_t *f;
+ unsigned long lock_flags;
+ int err = 0;
+
+ if (copy_from_user(&b, arg, sizeof(b)))
+ return -EFAULT;
+
+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+ return -EINVAL;
+
+ if (list_empty(&cam->outqueue)) {
+ if (cam->stream == STREAM_OFF)
return -EINVAL;
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ err = wait_event_interruptible
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED) );
+ if (err)
+ return err;
+ if (cam->state & DEV_DISCONNECTED)
+ return -ENODEV;
+ if (cam->state & DEV_MISCONFIGURED)
+ return -EIO;
+ }
- if (list_empty(&cam->outqueue)) {
- if (cam->stream == STREAM_OFF)
- return -EINVAL;
- if (filp->f_flags & O_NONBLOCK)
- return -EAGAIN;
- err = wait_event_interruptible
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED) );
- if (err)
- return err;
- if (cam->state & DEV_DISCONNECTED)
- return -ENODEV;
- if (cam->state & DEV_MISCONFIGURED)
- return -EIO;
- }
+ spin_lock_irqsave(&cam->queue_lock, lock_flags);
+ f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
+ list_del(cam->outqueue.next);
+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
- spin_lock_irqsave(&cam->queue_lock, lock_flags);
- f = list_entry(cam->outqueue.next, struct sn9c102_frame_t,
- frame);
- list_del(cam->outqueue.next);
- spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+ f->state = F_UNUSED;
- f->state = F_UNUSED;
+ memcpy(&b, &f->buf, sizeof(b));
+ if (f->vma_use_count)
+ b.flags |= V4L2_BUF_FLAG_MAPPED;
- memcpy(&b, &f->buf, sizeof(b));
- if (f->vma_use_count)
- b.flags |= V4L2_BUF_FLAG_MAPPED;
+ if (copy_to_user(arg, &b, sizeof(b)))
+ return -EFAULT;
- if (copy_to_user(arg, &b, sizeof(b)))
- return -EFAULT;
+ PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
- PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index)
+ return 0;
+}
- return 0;
- }
- case VIDIOC_STREAMON:
- {
- int type;
+static int
+sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
+{
+ int type;
- if (copy_from_user(&type, arg, sizeof(type)))
- return -EFAULT;
+ if (copy_from_user(&type, arg, sizeof(type)))
+ return -EFAULT;
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
- return -EINVAL;
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+ return -EINVAL;
- if (list_empty(&cam->inqueue))
- return -EINVAL;
+ if (list_empty(&cam->inqueue))
+ return -EINVAL;
- cam->stream = STREAM_ON;
+ cam->stream = STREAM_ON;
- DBG(3, "Stream on")
+ DBG(3, "Stream on");
- return 0;
- }
+ return 0;
+}
- case VIDIOC_STREAMOFF:
- {
- int type, err;
- if (copy_from_user(&type, arg, sizeof(type)))
- return -EFAULT;
+static int
+sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg)
+{
+ int type, err;
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
- return -EINVAL;
+ if (copy_from_user(&type, arg, sizeof(type)))
+ return -EFAULT;
- if (cam->stream == STREAM_ON)
- if ((err = sn9c102_stream_interrupt(cam)))
- return err;
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+ return -EINVAL;
- sn9c102_empty_framequeues(cam);
+ if (cam->stream == STREAM_ON)
+ if ((err = sn9c102_stream_interrupt(cam)))
+ return err;
- DBG(3, "Stream off")
+ sn9c102_empty_framequeues(cam);
- return 0;
- }
+ DBG(3, "Stream off");
- case VIDIOC_G_PARM:
- {
- struct v4l2_streamparm sp;
+ return 0;
+}
- if (copy_from_user(&sp, arg, sizeof(sp)))
- return -EFAULT;
- if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
+static int
+sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_streamparm sp;
+
+ if (copy_from_user(&sp, arg, sizeof(sp)))
+ return -EFAULT;
+
+ if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ sp.parm.capture.extendedmode = 0;
+ sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+ if (copy_to_user(arg, &sp, sizeof(sp)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
+{
+ struct v4l2_streamparm sp;
+
+ if (copy_from_user(&sp, arg, sizeof(sp)))
+ return -EFAULT;
+
+ if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ sp.parm.capture.extendedmode = 0;
- sp.parm.capture.extendedmode = 0;
+ if (sp.parm.capture.readbuffers == 0)
sp.parm.capture.readbuffers = cam->nreadbuffers;
- if (copy_to_user(arg, &sp, sizeof(sp)))
- return -EFAULT;
+ if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
+ sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
- return 0;
- }
+ if (copy_to_user(arg, &sp, sizeof(sp)))
+ return -EFAULT;
- case VIDIOC_S_PARM_OLD:
- case VIDIOC_S_PARM:
- {
- struct v4l2_streamparm sp;
+ cam->nreadbuffers = sp.parm.capture.readbuffers;
- if (copy_from_user(&sp, arg, sizeof(sp)))
- return -EFAULT;
+ return 0;
+}
- if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- sp.parm.capture.extendedmode = 0;
+static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
+ unsigned int cmd, void __user * arg)
+{
+ struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+
+ switch (cmd) {
+
+ case VIDIOC_QUERYCAP:
+ return sn9c102_vidioc_querycap(cam, arg);
- if (sp.parm.capture.readbuffers == 0)
- sp.parm.capture.readbuffers = cam->nreadbuffers;
+ case VIDIOC_ENUMINPUT:
+ return sn9c102_vidioc_enuminput(cam, arg);
- if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
- sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
+ case VIDIOC_G_INPUT:
+ case VIDIOC_S_INPUT:
+ return sn9c102_vidioc_gs_input(cam, arg);
- if (copy_to_user(arg, &sp, sizeof(sp)))
- return -EFAULT;
+ case VIDIOC_QUERYCTRL:
+ return sn9c102_vidioc_query_ctrl(cam, arg);
- cam->nreadbuffers = sp.parm.capture.readbuffers;
+ case VIDIOC_G_CTRL:
+ return sn9c102_vidioc_g_ctrl(cam, arg);
- return 0;
- }
+ case VIDIOC_S_CTRL_OLD:
+ case VIDIOC_S_CTRL:
+ return sn9c102_vidioc_s_ctrl(cam, arg);
+
+ case VIDIOC_CROPCAP_OLD:
+ case VIDIOC_CROPCAP:
+ return sn9c102_vidioc_cropcap(cam, arg);
+
+ case VIDIOC_G_CROP:
+ return sn9c102_vidioc_g_crop(cam, arg);
+
+ case VIDIOC_S_CROP:
+ return sn9c102_vidioc_s_crop(cam, arg);
+
+ case VIDIOC_ENUM_FMT:
+ return sn9c102_vidioc_enum_fmt(cam, arg);
+
+ case VIDIOC_G_FMT:
+ return sn9c102_vidioc_g_fmt(cam, arg);
+
+ case VIDIOC_TRY_FMT:
+ case VIDIOC_S_FMT:
+ return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
+
+ case VIDIOC_G_JPEGCOMP:
+ return sn9c102_vidioc_g_jpegcomp(cam, arg);
+
+ case VIDIOC_S_JPEGCOMP:
+ return sn9c102_vidioc_s_jpegcomp(cam, arg);
+
+ case VIDIOC_REQBUFS:
+ return sn9c102_vidioc_reqbufs(cam, arg);
+
+ case VIDIOC_QUERYBUF:
+ return sn9c102_vidioc_querybuf(cam, arg);
+
+ case VIDIOC_QBUF:
+ return sn9c102_vidioc_qbuf(cam, arg);
+
+ case VIDIOC_DQBUF:
+ return sn9c102_vidioc_dqbuf(cam, filp, arg);
+
+ case VIDIOC_STREAMON:
+ return sn9c102_vidioc_streamon(cam, arg);
+
+ case VIDIOC_STREAMOFF:
+ return sn9c102_vidioc_streamoff(cam, arg);
+
+ case VIDIOC_G_PARM:
+ return sn9c102_vidioc_g_parm(cam, arg);
+
+ case VIDIOC_S_PARM_OLD:
+ case VIDIOC_S_PARM:
+ return sn9c102_vidioc_s_parm(cam, arg);
case VIDIOC_G_STD:
case VIDIOC_S_STD:
@@ -2499,17 +2659,20 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
return -ERESTARTSYS;
if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present")
+ DBG(1, "Device not present");
up(&cam->fileop_sem);
return -ENODEV;
}
if (cam->state & DEV_MISCONFIGURED) {
- DBG(1, "The camera is misconfigured. Close and open it again.")
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
up(&cam->fileop_sem);
return -EIO;
}
+ V4LDBG(3, "sn9c102", cmd);
+
err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
up(&cam->fileop_sem);
@@ -2517,9 +2680,10 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
return err;
}
+/*****************************************************************************/
static struct file_operations sn9c102_fops = {
- .owner = THIS_MODULE,
+ .owner = THIS_MODULE,
.open = sn9c102_open,
.release = sn9c102_release,
.ioctl = sn9c102_ioctl,
@@ -2538,36 +2702,22 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
struct usb_device *udev = interface_to_usbdev(intf);
struct sn9c102_device* cam;
static unsigned int dev_nr = 0;
- unsigned int i, n;
+ unsigned int i;
int err = 0, r;
- n = ARRAY_SIZE(sn9c102_id_table);
- for (i = 0; i < n-1; i++)
- if (le16_to_cpu(udev->descriptor.idVendor) ==
- sn9c102_id_table[i].idVendor &&
- le16_to_cpu(udev->descriptor.idProduct) ==
- sn9c102_id_table[i].idProduct)
- break;
- if (i == n-1)
- return -ENODEV;
-
- if (!(cam = kmalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
+ if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
return -ENOMEM;
- memset(cam, 0, sizeof(*cam));
cam->usbdev = udev;
- memcpy(&cam->dev, &udev->dev, sizeof(struct device));
-
- if (!(cam->control_buffer = kmalloc(8, GFP_KERNEL))) {
- DBG(1, "kmalloc() failed")
+ if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
+ DBG(1, "kmalloc() failed");
err = -ENOMEM;
goto fail;
}
- memset(cam->control_buffer, 0, 8);
if (!(cam->v4ldev = video_device_alloc())) {
- DBG(1, "video_device_alloc() failed")
+ DBG(1, "video_device_alloc() failed");
err = -ENOMEM;
goto fail;
}
@@ -2577,25 +2727,22 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
r = sn9c102_read_reg(cam, 0x00);
if (r < 0 || r != 0x10) {
DBG(1, "Sorry, this is not a SN9C10x based camera "
- "(vid/pid 0x%04X/0x%04X)",
- sn9c102_id_table[i].idVendor,sn9c102_id_table[i].idProduct)
+ "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
err = -ENODEV;
goto fail;
}
- cam->bridge = (sn9c102_id_table[i].idProduct & 0xffc0) == 0x6080 ?
+ cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ?
BRIDGE_SN9C103 : BRIDGE_SN9C102;
switch (cam->bridge) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
DBG(2, "SN9C10[12] PC Camera Controller detected "
- "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor,
- sn9c102_id_table[i].idProduct)
+ "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
break;
case BRIDGE_SN9C103:
DBG(2, "SN9C103 PC Camera Controller detected "
- "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor,
- sn9c102_id_table[i].idProduct)
+ "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
break;
}
@@ -2606,24 +2753,24 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
}
if (!err && cam->sensor) {
- DBG(2, "%s image sensor detected", cam->sensor->name)
+ DBG(2, "%s image sensor detected", cam->sensor->name);
DBG(3, "Support for %s maintained by %s",
- cam->sensor->name, cam->sensor->maintainer)
+ cam->sensor->name, cam->sensor->maintainer);
} else {
- DBG(1, "No supported image sensor detected")
+ DBG(1, "No supported image sensor detected");
err = -ENODEV;
goto fail;
}
if (sn9c102_init(cam)) {
- DBG(1, "Initialization failed. I will retry on open().")
+ DBG(1, "Initialization failed. I will retry on open().");
cam->state |= DEV_MISCONFIGURED;
}
strcpy(cam->v4ldev->name, "SN9C10x PC Camera");
cam->v4ldev->owner = THIS_MODULE;
cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
- cam->v4ldev->hardware = VID_HARDWARE_SN9C102;
+ cam->v4ldev->hardware = 0;
cam->v4ldev->fops = &sn9c102_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
@@ -2634,23 +2781,25 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
video_nr[dev_nr]);
if (err) {
- DBG(1, "V4L2 device registration failed")
+ DBG(1, "V4L2 device registration failed");
if (err == -ENFILE && video_nr[dev_nr] == -1)
- DBG(1, "Free /dev/videoX node not found")
+ DBG(1, "Free /dev/videoX node not found");
video_nr[dev_nr] = -1;
dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
up(&cam->dev_sem);
goto fail;
}
- DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor)
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
cam->module_param.force_munmap = force_munmap[dev_nr];
dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
sn9c102_create_sysfs(cam);
- DBG(2, "Optional device control through 'sysfs' interface ready")
+ DBG(2, "Optional device control through 'sysfs' interface ready");
+#endif
usb_set_intfdata(intf, cam);
@@ -2680,14 +2829,14 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf)
down(&cam->dev_sem);
- DBG(2, "Disconnecting %s...", cam->v4ldev->name)
+ DBG(2, "Disconnecting %s...", cam->v4ldev->name);
wake_up_interruptible_all(&cam->open);
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
"memory deallocation are deferred on close.",
- cam->v4ldev->minor)
+ cam->v4ldev->minor);
cam->state |= DEV_MISCONFIGURED;
sn9c102_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
@@ -2720,11 +2869,11 @@ static int __init sn9c102_module_init(void)
{
int err = 0;
- KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION)
- KDBG(3, SN9C102_MODULE_AUTHOR)
+ KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION);
+ KDBG(3, SN9C102_MODULE_AUTHOR);
if ((err = usb_register(&sn9c102_usb_driver)))
- KDBG(1, "usb_register() failed")
+ KDBG(1, "usb_register() failed");
return err;
}
diff --git a/drivers/usb/media/sn9c102_hv7131d.c b/drivers/usb/media/sn9c102_hv7131d.c
index 18070d5333c..46c12ec3ca6 100644
--- a/drivers/usb/media/sn9c102_hv7131d.c
+++ b/drivers/usb/media/sn9c102_hv7131d.c
@@ -2,7 +2,7 @@
* Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
diff --git a/drivers/usb/media/sn9c102_mi0343.c b/drivers/usb/media/sn9c102_mi0343.c
index 86676abf354..d9aa7a61095 100644
--- a/drivers/usb/media/sn9c102_mi0343.c
+++ b/drivers/usb/media/sn9c102_mi0343.c
@@ -2,7 +2,7 @@
* Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/usb/media/sn9c102_ov7630.c
index d27c5aedeaf..4a36519b5af 100644
--- a/drivers/usb/media/sn9c102_ov7630.c
+++ b/drivers/usb/media/sn9c102_ov7630.c
@@ -2,7 +2,7 @@
* Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
- * Copyright (C) 2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -375,8 +375,10 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
sn9c102_attach_sensor(cam, &ov7630);
- if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f &&
- le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c)
+ if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c &&
+ le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602d &&
+ le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f &&
+ le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x60b0)
return -ENODEV;
err += sn9c102_write_reg(cam, 0x01, 0x01);
diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c
index 48e3ec39d4e..b1dee78abe0 100644
--- a/drivers/usb/media/sn9c102_pas106b.c
+++ b/drivers/usb/media/sn9c102_pas106b.c
@@ -2,7 +2,7 @@
* Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
index a45166c3488..7d953b24f2f 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/usb/media/sn9c102_sensor.h
@@ -1,7 +1,7 @@
/***************************************************************************
* API for image sensors connected to the SN9C10x PC Camera Controllers *
* *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -92,7 +92,18 @@ extern void
sn9c102_attach_sensor(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor);
-/* Each SN9C10X camera has proper PID/VID identifiers. Add them here in case.*/
+/*
+ Each SN9C10x camera has proper PID/VID identifiers.
+ SN9C103 supports multiple interfaces, but we only handle the video class
+ interface.
+*/
+#define SN9C102_USB_DEVICE(vend, prod, intclass) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_INT_CLASS, \
+ .idVendor = (vend), \
+ .idProduct = (prod), \
+ .bInterfaceClass = (intclass)
+
#define SN9C102_ID_TABLE \
static const struct usb_device_id sn9c102_id_table[] = { \
{ USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \
@@ -107,33 +118,34 @@ static const struct usb_device_id sn9c102_id_table[] = { \
{ USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \
{ USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \
{ USB_DEVICE(0x0c45, 0x602d), }, \
+ { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */ \
{ USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \
- { USB_DEVICE(0x0c45, 0x6080), }, \
- { USB_DEVICE(0x0c45, 0x6082), }, /* MI0343 and MI0360 */ \
- { USB_DEVICE(0x0c45, 0x6083), }, /* HV7131[D|E1] */ \
- { USB_DEVICE(0x0c45, 0x6088), }, \
- { USB_DEVICE(0x0c45, 0x608a), }, \
- { USB_DEVICE(0x0c45, 0x608b), }, \
- { USB_DEVICE(0x0c45, 0x608c), }, /* HV7131x */ \
- { USB_DEVICE(0x0c45, 0x608e), }, /* CIS-VF10 */ \
- { USB_DEVICE(0x0c45, 0x608f), }, /* OV7630 */ \
- { USB_DEVICE(0x0c45, 0x60a0), }, \
- { USB_DEVICE(0x0c45, 0x60a2), }, \
- { USB_DEVICE(0x0c45, 0x60a3), }, \
- { USB_DEVICE(0x0c45, 0x60a8), }, /* PAS106B */ \
- { USB_DEVICE(0x0c45, 0x60aa), }, /* TAS5130D1B */ \
- { USB_DEVICE(0x0c45, 0x60ab), }, /* TAS5110C1B */ \
- { USB_DEVICE(0x0c45, 0x60ac), }, \
- { USB_DEVICE(0x0c45, 0x60ae), }, \
- { USB_DEVICE(0x0c45, 0x60af), }, /* PAS202BCB */ \
- { USB_DEVICE(0x0c45, 0x60b0), }, \
- { USB_DEVICE(0x0c45, 0x60b2), }, \
- { USB_DEVICE(0x0c45, 0x60b3), }, \
- { USB_DEVICE(0x0c45, 0x60b8), }, \
- { USB_DEVICE(0x0c45, 0x60ba), }, \
- { USB_DEVICE(0x0c45, 0x60bb), }, \
- { USB_DEVICE(0x0c45, 0x60bc), }, \
- { USB_DEVICE(0x0c45, 0x60be), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131x */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), }, \
{ } \
};
@@ -177,16 +189,18 @@ extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
/* I/O on registers in the bridge. Could be used by the sensor methods too */
+extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index);
extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
/*
NOTE: there are no exported debugging functions. To uniform the output you
must use the dev_info()/dev_warn()/dev_err() macros defined in device.h,
- already included here, the argument being the struct device 'dev' of the
- sensor structure. Do NOT use these macros before the sensor is attached or
- the kernel will crash! However, you should not need to notify the user about
- common errors or other messages, since this is done by the master module.
+ already included here, the argument being the struct device '&usbdev->dev'
+ of the sensor structure. Do NOT use these macros before the sensor is
+ attached or the kernel will crash! However, you should not need to notify
+ the user about common errors or other messages, since this is done by the
+ master module.
*/
/*****************************************************************************/
@@ -345,13 +359,6 @@ struct sn9c102_sensor {
error code without rolling back.
*/
- const struct device* dev;
- /*
- This is the argument for dev_err(), dev_info() and dev_warn(). It
- is used for debugging purposes. You must not access the struct
- before the sensor is attached.
- */
-
const struct usb_device* usbdev;
/*
Points to the usb_device struct after the sensor is attached.
diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c
index 8775999b5af..32ddf236caf 100644
--- a/drivers/usb/media/sn9c102_tas5110c1b.c
+++ b/drivers/usb/media/sn9c102_tas5110c1b.c
@@ -2,7 +2,7 @@
* Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c
index 927eafdd8c7..a0728f0ae00 100644
--- a/drivers/usb/media/sn9c102_tas5130d1b.c
+++ b/drivers/usb/media/sn9c102_tas5130d1b.c
@@ -2,7 +2,7 @@
* Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
- * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index bff9434c8e5..9937fc64c8b 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -62,7 +62,6 @@ MODULE_LICENSE(W9968CF_MODULE_LICENSE);
MODULE_SUPPORTED_DEVICE("Video");
static int ovmod_load = W9968CF_OVMOD_LOAD;
-static int vppmod_load = W9968CF_VPPMOD_LOAD;
static unsigned short simcams = W9968CF_SIMCAMS;
static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/
static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] =
@@ -107,7 +106,6 @@ static unsigned int param_nv[24]; /* number of values per parameter */
#ifdef CONFIG_KMOD
module_param(ovmod_load, bool, 0644);
-module_param(vppmod_load, bool, 0444);
#endif
module_param(simcams, ushort, 0644);
module_param_array(video_nr, short, &param_nv[0], 0444);
@@ -150,18 +148,6 @@ MODULE_PARM_DESC(ovmod_load,
"\ninto memory."
"\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"."
"\n");
-MODULE_PARM_DESC(vppmod_load,
- "\n<0|1> Automatic 'w9968cf-vpp' module loading."
- "\n0 disabled, 1 enabled."
- "\nIf enabled, every time an application attempts to open a"
- "\ncamera, 'insmod' searches for the video post-processing"
- "\nmodule in the system and loads it automatically (if"
- "\npresent). The optional 'w9968cf-vpp' module adds extra"
- "\n image manipulation functions to the 'w9968cf' module,like"
- "\nsoftware up-scaling,colour conversions and video decoding"
- "\nfor very high frame rates."
- "\nDefault value is "__MODULE_STRING(W9968CF_VPPMOD_LOAD)"."
- "\n");
#endif
MODULE_PARM_DESC(simcams,
"\n<n> Number of cameras allowed to stream simultaneously."
@@ -492,10 +478,6 @@ static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num);
static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**);
static void w9968cf_release_resources(struct w9968cf_device*);
-/* Intermodule communication */
-static int w9968cf_vppmod_detect(struct w9968cf_device*);
-static void w9968cf_vppmod_release(struct w9968cf_device*);
-
/****************************************************************************
@@ -2737,9 +2719,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
cam->streaming = 0;
cam->misconfigured = 0;
- if (!w9968cf_vpp)
- if ((err = w9968cf_vppmod_detect(cam)))
- goto out;
+ w9968cf_adjust_configuration(cam);
if ((err = w9968cf_allocate_memory(cam)))
goto deallocate_memory;
@@ -2766,7 +2746,6 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
deallocate_memory:
w9968cf_deallocate_memory(cam);
-out:
DBG(2, "Failed to open the video device")
up(&cam->dev_sem);
up_read(&w9968cf_disconnect);
@@ -2784,8 +2763,6 @@ static int w9968cf_release(struct inode* inode, struct file* filp)
w9968cf_stop_transfer(cam);
- w9968cf_vppmod_release(cam);
-
if (cam->disconnected) {
w9968cf_release_resources(cam);
up(&cam->dev_sem);
@@ -3681,106 +3658,6 @@ static struct usb_driver w9968cf_usb_driver = {
* Module init, exit and intermodule communication *
****************************************************************************/
-static int w9968cf_vppmod_detect(struct w9968cf_device* cam)
-{
- if (!w9968cf_vpp)
- if (vppmod_load)
- request_module("w9968cf-vpp");
-
- down(&w9968cf_vppmod_lock);
-
- if (!w9968cf_vpp) {
- DBG(4, "Video post-processing module not detected")
- w9968cf_adjust_configuration(cam);
- goto out;
- }
-
- if (!try_module_get(w9968cf_vpp->owner)) {
- DBG(1, "Couldn't increment the reference count of "
- "the video post-processing module")
- up(&w9968cf_vppmod_lock);
- return -ENOSYS;
- }
-
- w9968cf_vpp->busy++;
-
- DBG(5, "Video post-processing module detected")
-
-out:
- up(&w9968cf_vppmod_lock);
- return 0;
-}
-
-
-static void w9968cf_vppmod_release(struct w9968cf_device* cam)
-{
- down(&w9968cf_vppmod_lock);
-
- if (w9968cf_vpp && w9968cf_vpp->busy) {
- module_put(w9968cf_vpp->owner);
- w9968cf_vpp->busy--;
- wake_up(&w9968cf_vppmod_wait);
- DBG(5, "Video post-processing module released")
- }
-
- up(&w9968cf_vppmod_lock);
-}
-
-
-int w9968cf_vppmod_register(struct w9968cf_vpp_t* vpp)
-{
- down(&w9968cf_vppmod_lock);
-
- if (w9968cf_vpp) {
- KDBG(1, "Video post-processing module already registered")
- up(&w9968cf_vppmod_lock);
- return -EINVAL;
- }
-
- w9968cf_vpp = vpp;
- w9968cf_vpp->busy = 0;
-
- KDBG(2, "Video post-processing module registered")
- up(&w9968cf_vppmod_lock);
- return 0;
-}
-
-
-int w9968cf_vppmod_deregister(struct w9968cf_vpp_t* vpp)
-{
- down(&w9968cf_vppmod_lock);
-
- if (!w9968cf_vpp) {
- up(&w9968cf_vppmod_lock);
- return -EINVAL;
- }
-
- if (w9968cf_vpp != vpp) {
- KDBG(1, "Only the owner can unregister the video "
- "post-processing module")
- up(&w9968cf_vppmod_lock);
- return -EINVAL;
- }
-
- if (w9968cf_vpp->busy) {
- KDBG(2, "Video post-processing module busy. Wait for it to be "
- "released...")
- up(&w9968cf_vppmod_lock);
- wait_event(w9968cf_vppmod_wait, !w9968cf_vpp->busy);
- w9968cf_vpp = NULL;
- goto out;
- }
-
- w9968cf_vpp = NULL;
-
- up(&w9968cf_vppmod_lock);
-
-out:
- KDBG(2, "Video post-processing module unregistered")
- return 0;
-}
-
-
static int __init w9968cf_module_init(void)
{
int err;
@@ -3810,6 +3687,3 @@ static void __exit w9968cf_module_exit(void)
module_init(w9968cf_module_init);
module_exit(w9968cf_module_exit);
-
-EXPORT_SYMBOL(w9968cf_vppmod_register);
-EXPORT_SYMBOL(w9968cf_vppmod_deregister);
diff --git a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h
index 8acbfe205bc..47a6ff79417 100644
--- a/drivers/usb/media/w9968cf.h
+++ b/drivers/usb/media/w9968cf.h
@@ -195,7 +195,6 @@ enum w9968cf_vpp_flag {
};
static struct w9968cf_vpp_t* w9968cf_vpp;
-static DECLARE_MUTEX(w9968cf_vppmod_lock);
static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait);
static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */
diff --git a/drivers/usb/media/w9968cf_vpp.h b/drivers/usb/media/w9968cf_vpp.h
index 3f5317dc4c2..f3b91b78267 100644
--- a/drivers/usb/media/w9968cf_vpp.h
+++ b/drivers/usb/media/w9968cf_vpp.h
@@ -37,7 +37,4 @@ struct w9968cf_vpp_t {
u8 busy; /* read-only flag: module is/is not in use */
};
-extern int w9968cf_vppmod_register(struct w9968cf_vpp_t*);
-extern int w9968cf_vppmod_deregister(struct w9968cf_vpp_t*);
-
#endif /* _W9968CF_VPP_H_ */
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 6649531fa82..8ba6a701e9c 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -141,7 +141,7 @@ source "drivers/usb/misc/sisusbvga/Kconfig"
config USB_LD
tristate "USB LD driver"
- depends on USB && EXPERIMENTAL
+ depends on USB
help
This driver is for generic USB devices that use interrupt transfers,
like LD Didactic's USB devices.
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 449b2501acf..ad2f4cccd38 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -2093,6 +2093,8 @@ static void auerswald_disconnect (struct usb_interface *intf)
static struct usb_device_id auerswald_ids [] = {
{ USB_DEVICE (ID_AUERSWALD, 0x00C0) }, /* COMpact 2104 USB */
{ USB_DEVICE (ID_AUERSWALD, 0x00DB) }, /* COMpact 4410/2206 USB */
+ { USB_DEVICE (ID_AUERSWALD, 0x00DC) }, /* COMpact 4406 DSL */
+ { USB_DEVICE (ID_AUERSWALD, 0x00DD) }, /* COMpact 2204 USB */
{ USB_DEVICE (ID_AUERSWALD, 0x00F1) }, /* Comfort 2000 System Telephone */
{ USB_DEVICE (ID_AUERSWALD, 0x00F2) }, /* Comfort 1200 System Telephone */
{ } /* Terminating entry */
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 981d8a5fbfd..e2d1198623e 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -24,6 +24,7 @@
* V0.1 (mh) Initial version
* V0.11 (mh) Added raw support for HID 1.0 devices (no interrupt out endpoint)
* V0.12 (mh) Added kmalloc check for string buffer
+ * V0.13 (mh) Added support for LD X-Ray and Machine Test System
*/
#include <linux/config.h>
@@ -40,17 +41,20 @@
/* Define these values to match your devices */
#define USB_VENDOR_ID_LD 0x0f11 /* USB Vendor ID of LD Didactic GmbH */
-#define USB_DEVICE_ID_CASSY 0x1000 /* USB Product ID for all CASSY-S modules */
-#define USB_DEVICE_ID_POCKETCASSY 0x1010 /* USB Product ID for Pocket-CASSY */
-#define USB_DEVICE_ID_MOBILECASSY 0x1020 /* USB Product ID for Mobile-CASSY */
-#define USB_DEVICE_ID_JWM 0x1080 /* USB Product ID for Joule and Wattmeter */
-#define USB_DEVICE_ID_DMMP 0x1081 /* USB Product ID for Digital Multimeter P (reserved) */
-#define USB_DEVICE_ID_UMIP 0x1090 /* USB Product ID for UMI P */
-#define USB_DEVICE_ID_VIDEOCOM 0x1200 /* USB Product ID for VideoCom */
-#define USB_DEVICE_ID_COM3LAB 0x2000 /* USB Product ID for COM3LAB */
-#define USB_DEVICE_ID_TELEPORT 0x2010 /* USB Product ID for Terminal Adapter */
-#define USB_DEVICE_ID_NETWORKANALYSER 0x2020 /* USB Product ID for Network Analyser */
-#define USB_DEVICE_ID_POWERCONTROL 0x2030 /* USB Product ID for Controlling device for Power Electronics */
+#define USB_DEVICE_ID_LD_CASSY 0x1000 /* USB Product ID of CASSY-S */
+#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 /* USB Product ID of Pocket-CASSY */
+#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 /* USB Product ID of Mobile-CASSY */
+#define USB_DEVICE_ID_LD_JWM 0x1080 /* USB Product ID of Joule and Wattmeter */
+#define USB_DEVICE_ID_LD_DMMP 0x1081 /* USB Product ID of Digital Multimeter P (reserved) */
+#define USB_DEVICE_ID_LD_UMIP 0x1090 /* USB Product ID of UMI P */
+#define USB_DEVICE_ID_LD_XRAY1 0x1100 /* USB Product ID of X-Ray Apparatus */
+#define USB_DEVICE_ID_LD_XRAY2 0x1101 /* USB Product ID of X-Ray Apparatus */
+#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 /* USB Product ID of VideoCom */
+#define USB_DEVICE_ID_LD_COM3LAB 0x2000 /* USB Product ID of COM3LAB */
+#define USB_DEVICE_ID_LD_TELEPORT 0x2010 /* USB Product ID of Terminal Adapter */
+#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 /* USB Product ID of Network Analyser */
+#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 /* USB Product ID of Converter Control Unit */
+#define USB_DEVICE_ID_LD_MACHINETEST 0x2040 /* USB Product ID of Machine Test System */
#define USB_VENDOR_ID_VERNIER 0x08f7
#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
@@ -67,17 +71,20 @@
/* table of devices that work with this driver */
static struct usb_device_id ld_usb_table [] = {
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER) },
- { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) },
+ { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
@@ -85,7 +92,7 @@ static struct usb_device_id ld_usb_table [] = {
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, ld_usb_table);
-MODULE_VERSION("V0.12");
+MODULE_VERSION("V0.13");
MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>");
MODULE_DESCRIPTION("LD USB Driver");
MODULE_LICENSE("GPL");
@@ -593,7 +600,7 @@ static struct file_operations ld_usb_fops = {
/*
* usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
+ * and to have the device registered with the driver core
*/
static struct usb_class_driver ld_usb_class = {
.name = "ldusb%d",
@@ -632,8 +639,8 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
/* workaround for early firmware versions on fast computers */
if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VENDOR_ID_LD) &&
- ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_CASSY) ||
- (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_COM3LAB)) &&
+ ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_LD_CASSY) ||
+ (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_LD_COM3LAB)) &&
(le16_to_cpu(udev->descriptor.bcdDevice) <= 0x103)) {
buffer = kmalloc(256, GFP_KERNEL);
if (buffer == NULL) {
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 54118169504..3094970615c 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -916,6 +916,10 @@ static const struct usb_device_id products [] = {
// Linksys USB200M Rev 2
USB_DEVICE (0x13b1, 0x0018),
.driver_info = (unsigned long) &ax88772_info,
+}, {
+ // 0Q0 cable ethernet
+ USB_DEVICE (0x1557, 0x7720),
+ .driver_info = (unsigned long) &ax88772_info,
},
{ }, // END
};
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index da46b351e18..dc7a069503e 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -32,7 +32,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.05"
+#define DRIVER_VERSION "v0.06"
#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
/*
@@ -55,11 +55,15 @@ static int debug;
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
- { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
- { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
- { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
- { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
+ { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
+ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
+ { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
+ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
+ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
+ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
+ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
+ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ } /* Terminating Entry */
};
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 10bc1bf23b3..f2b4ca8692d 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -476,10 +476,16 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) },
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 00d45f8600d..ca40f16370f 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -31,9 +31,14 @@
#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */
#define FTDI_NF_RIC_PID 0x0001 /* Product Id */
+
/* www.irtrans.de device */
#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
+
+/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
+#define FTDI_TTUSB_PID 0xFF20 /* Product Id */
+
/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
/* they use the ftdi chipset for the USB interface and the vendor id is the same */
#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */
@@ -51,6 +56,12 @@
#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */
/*
+ * PCDJ use ftdi based dj-controllers. The following PID is for their DAC-2 device
+ * http://www.pcdjhardware.com/DAC2.asp (PID sent by Wouter Paesen)
+ * (the VID is the standard ftdi vid (FTDI_VID) */
+#define FTDI_PCDJ_DAC2_PID 0xFA88
+
+/*
* The following are the values for the Matrix Orbital LCD displays,
* which are the FT232BM ( similar to the 8U232AM )
*/
@@ -215,8 +226,10 @@
* Definitions for ATIK Instruments astronomical USB based cameras
* Check it at http://www.atik-instruments.com/
*/
-#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Camera */
-#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Camera */
+#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Grayscale Camera */
+#define FTDI_ATIK_ATK16C_PID 0xDF32 /* ATIK ATK-16C Colour Camera */
+#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Grayscale Camera */
+#define FTDI_ATIK_ATK16HRC_PID 0xDF33 /* ATIK ATK-16HRC Colour Camera */
/*
* Protego product ids
@@ -365,6 +378,12 @@
#define POSIFLEX_VID 0x0d3a /* Vendor ID */
#define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */
+/*
+ * Westrex International devices submitted by Cory Lee
+ */
+#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */
+#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 0eb883f44ad..37c81c08faa 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -73,7 +73,10 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
- { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
+ { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) },
+ { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) },
+ { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
+ { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 21d434d8181..9bc4755162a 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -64,3 +64,14 @@
/* Nokia CA-42 Cable */
#define NOKIA_CA42_VENDOR_ID 0x078b
#define NOKIA_CA42_PRODUCT_ID 0x1234
+
+/* CA-42 CLONE Cable www.ca-42.com chipset: Prolific Technology Inc */
+#define CA_42_CA42_VENDOR_ID 0x10b5
+#define CA_42_CA42_PRODUCT_ID 0xac70
+
+#define SAGEM_VENDOR_ID 0x079b
+#define SAGEM_PRODUCT_ID 0x0027
+
+/* Leadtek GPS 9531 (ID 0413:2101) */
+#define LEADTEK_VENDOR_ID 0x0413
+#define LEADTEK_9531_PRODUCT_ID 0x2101
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 5b06f9240d0..ab173b30076 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -45,6 +45,12 @@
#include "debug.h"
#include "transport.h"
+#define RIO_MSC 0x08
+#define RIOP_INIT "RIOP\x00\x01\x08"
+#define RIOP_INIT_LEN 7
+#define RIO_SEND_LEN 40
+#define RIO_RECV_LEN 0x200
+
/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
* mode */
int usb_stor_euscsi_init(struct us_data *us)
@@ -91,3 +97,70 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
return (res ? -1 : 0);
}
+
+/* Place the Rio Karma into mass storage mode.
+ *
+ * The initialization begins by sending 40 bytes starting
+ * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte
+ * packet with the high four bits set and everything else null.
+ *
+ * Next, we send RIOP\x80\x00\x08\x00. Each time, a 512 byte response
+ * must be read, but we must loop until byte 5 in the response is 0x08,
+ * indicating success. */
+int rio_karma_init(struct us_data *us)
+{
+ int result, partial;
+ char *recv;
+ unsigned long timeout;
+
+ // us->iobuf is big enough to hold cmd but not receive
+ if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL)))
+ goto die_nomem;
+
+ US_DEBUGP("Initializing Karma...\n");
+
+ memset(us->iobuf, 0, RIO_SEND_LEN);
+ memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN);
+
+ result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ us->iobuf, RIO_SEND_LEN, &partial);
+ if (result != USB_STOR_XFER_GOOD)
+ goto die;
+
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ recv, RIO_RECV_LEN, &partial);
+ if (result != USB_STOR_XFER_GOOD)
+ goto die;
+
+ us->iobuf[4] = 0x80;
+ us->iobuf[5] = 0;
+ timeout = jiffies + msecs_to_jiffies(3000);
+ for (;;) {
+ US_DEBUGP("Sending init command\n");
+ result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ us->iobuf, RIO_SEND_LEN, &partial);
+ if (result != USB_STOR_XFER_GOOD)
+ goto die;
+
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ recv, RIO_RECV_LEN, &partial);
+ if (result != USB_STOR_XFER_GOOD)
+ goto die;
+
+ if (recv[5] == RIO_MSC)
+ break;
+ if (time_after(jiffies, timeout))
+ goto die;
+ msleep(10);
+ }
+ US_DEBUGP("Karma initialized.\n");
+ kfree(recv);
+ return 0;
+
+die:
+ kfree(recv);
+die_nomem:
+ US_DEBUGP("Could not initialize karma.\n");
+ return USB_STOR_TRANSPORT_FAILED;
+}
+
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 4c1b2bd2e2e..f9907a5cf12 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -48,3 +48,4 @@ int usb_stor_euscsi_init(struct us_data *us);
/* This function is required to activate all four slots on the UCR-61S2B
* flash reader */
int usb_stor_ucr61s2b_init(struct us_data *us);
+int rio_karma_init(struct us_data *us);
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index b28151d1b60..b1ec4a71854 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(usb_usual_check_type);
static int usu_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- int type;
+ unsigned long type;
int rc;
unsigned long flags;
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index dc301e567cf..e71c5ca1a07 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -106,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Reported by Christian Leber <christian@leber.de> */
+UNUSUAL_DEV( 0x0419, 0xaaf5, 0x0100, 0x0100,
+ "TrekStor",
+ "i.Beat 115 2.0",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_NOT_LOCKABLE ),
+
/* Reported by Stefan Werner <dustbln@gmx.de> */
UNUSUAL_DEV( 0x0419, 0xaaf6, 0x0100, 0x0100,
"TrekStor",
@@ -127,6 +134,14 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
#endif
+/* Patch submitted by Daniel Drake <dsd@gentoo.org>
+ * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
+UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
+ "Neuros Audio",
+ "USB 2.0 HD 2.5",
+ US_SC_DEVICE, US_PR_BULK, NULL,
+ US_FL_NEED_OVERRIDE ),
+
/*
* Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
* The key does not actually break, but it returns zero sense which
@@ -137,13 +152,21 @@ UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100,
"USB Mass Storage Device",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
-/* Patch submitted by Daniel Drake <dsd@gentoo.org>
- * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
-UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
- "Neuros Audio",
- "USB 2.0 HD 2.5",
- US_SC_DEVICE, US_PR_BULK, NULL,
- US_FL_NEED_OVERRIDE ),
+/*
+* Bohdan Linda <bohdan.linda@gmail.com>
+* 1GB USB sticks MyFlash High Speed. I have restricted
+* the revision to my model only
+*/
+UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100,
+ "USB 2.0",
+ "Flash Disk",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_NOT_LOCKABLE ),
+
+UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101,
+ "Rio",
+ "Rio Karma",
+ US_SC_SCSI, US_PR_BULK, rio_karma_init, 0),
/* Patch submitted by Philipp Friedrich <philipp@void.at> */
UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
@@ -424,11 +447,11 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
/* This entry is needed because the device reports Sub=ff */
-UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500,
- "Sony",
- "DSC-T1",
- US_SC_8070, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN ),
+UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0600,
+ "Sony",
+ "DSC-T1/T5",
+ US_SC_8070, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
/* Reported by wim@geeks.nl */
@@ -941,6 +964,12 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_BULK32),
+/* Submitted by Jan De Luyck <lkml@kcore.org> */
+UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000,
+ "CITIZEN",
+ "X1DE-USB",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN),
/* Entry needed for flags. Moreover, all devices with this ID use
* bulk-only transport, but _some_ falsely report Control/Bulk instead.
@@ -1080,6 +1109,13 @@ UNUSUAL_DEV( 0x0dda, 0x0301, 0x0012, 0x0012,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Jim McCloskey <mcclosk@ucsc.edu> */
+UNUSUAL_DEV( 0x0e21, 0x0520, 0x0100, 0x0100,
+ "Cowon Systems",
+ "iAUDIO M5",
+ US_SC_DEVICE, US_PR_BULK, NULL,
+ 0 ),
+
/* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
"USB",
@@ -1157,6 +1193,13 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
US_FL_SINGLE_LUN),
#endif
+/* Reported by Andrew Simmons <andrew.simmons@gmail.com> */
+UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
+ "DataStor",
+ "USB4500 FW1.04",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Control/Bulk transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 5d02f16b7d0..4de9fb56ebf 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -234,7 +234,7 @@ static struct file_operations skel_fops = {
/*
* usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
+ * and to have the device registered with the driver core
*/
static struct usb_class_driver skel_class = {
.name = "skel%d",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3e153d313bb..e64ed16bd42 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -525,11 +525,6 @@ config FB_GBE_MEM
This is the amount of memory reserved for the framebuffer,
which can be any value between 1MB and 8MB.
-config BUS_I2C
- bool
- depends on (FB = y) && VISWS
- default y
-
config FB_SUN3
bool "Sun3 framebuffer support"
depends on (FB = y) && (SUN3 || SUN3X) && BROKEN
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index b2187175d03..6761b68c35e 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -116,9 +116,10 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
int ret = 0;
memset(&var->transp, 0, sizeof(var->transp));
- memset(&var->red, 0, sizeof(var->red));
- memset(&var->green, 0, sizeof(var->green));
- memset(&var->blue, 0, sizeof(var->blue));
+
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
switch (var->bits_per_pixel) {
case 1:
@@ -133,34 +134,20 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
var->blue.offset = 0;
break;
case 16:
- var->red.length = 5;
- var->green.length = 6;
- var->blue.length = 5;
- if (fb->panel->cntl & CNTL_BGR) {
- var->red.offset = 11;
- var->green.offset = 5;
- var->blue.offset = 0;
- } else {
- var->red.offset = 0;
- var->green.offset = 5;
- var->blue.offset = 11;
- }
+ var->red.length = 5;
+ var->blue.length = 5;
+ /*
+ * Green length can be 5 or 6 depending whether
+ * we're operating in RGB555 or RGB565 mode.
+ */
+ if (var->green.length != 5 && var->green.length != 6)
+ var->green.length = 6;
break;
case 32:
if (fb->panel->cntl & CNTL_LCDTFT) {
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
-
- if (fb->panel->cntl & CNTL_BGR) {
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- } else {
- var->red.offset = 0;
- var->green.offset = 8;
- var->blue.offset = 16;
- }
break;
}
default:
@@ -168,6 +155,23 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
break;
}
+ /*
+ * >= 16bpp displays have separate colour component bitfields
+ * encoded in the pixel data. Calculate their position from
+ * the bitfield length defined above.
+ */
+ if (ret == 0 && var->bits_per_pixel >= 16) {
+ if (fb->panel->cntl & CNTL_BGR) {
+ var->blue.offset = 0;
+ var->green.offset = var->blue.offset + var->blue.length;
+ var->red.offset = var->green.offset + var->green.length;
+ } else {
+ var->red.offset = 0;
+ var->green.offset = var->red.offset + var->red.length;
+ var->blue.offset = var->green.offset + var->green.length;
+ }
+ }
+
return ret;
}
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 556895e9964..1f8d805c61e 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -1321,8 +1321,6 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
mdelay( 15);
}
-#ifdef CONFIG_PPC_OF
-
static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo)
{
u32 tmp, tmp2;
@@ -1836,6 +1834,8 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
}
+#ifdef CONFIG_PPC_OF
+
static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
{
OUTREG(MC_CNTL, rinfo->save_regs[46]);
@@ -2728,13 +2728,23 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
printk("radeonfb: Dynamic Clock Power Management disabled\n");
}
+#if defined(CONFIG_PM)
/* Check if we can power manage on suspend/resume. We can do
* D2 on M6, M7 and M9, and we can resume from D3 cold a few other
* "Mac" cards, but that's all. We need more infos about what the
* BIOS does tho. Right now, all this PM stuff is pmac-only for that
* reason. --BenH
*/
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
+ /* Special case for Samsung P35 laptops
+ */
+ if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) &&
+ (rinfo->pdev->device == PCI_CHIP_RV350_NP) &&
+ (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) &&
+ (rinfo->pdev->subsystem_device == 0xc00c)) {
+ rinfo->reinit_func = radeon_reinitialize_M10;
+ rinfo->pm_mode |= radeon_pm_off;
+ }
+#if defined(CONFIG_PPC_PMAC)
if (_machine == _MACH_Pmac && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250)
@@ -2778,7 +2788,8 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
#endif
}
-#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */
+#endif /* defined(CONFIG_PPC_PMAC) */
+#endif /* defined(CONFIG_PM) */
}
void radeonfb_pm_exit(struct radeonfb_info *rinfo)
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 996d543d660..9d996f2c10d 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -50,3 +50,11 @@ config BACKLIGHT_CORGI
If you have a Sharp Zaurus SL-C7xx, say y to enable the
backlight driver.
+config BACKLIGHT_HP680
+ tristate "HP Jornada 680 Backlight Driver"
+ depends on BACKLIGHT_DEVICE && SH_HP6XX
+ default y
+ help
+ If you have a HP Jornada 680, say y to enable the
+ backlight driver.
+
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 4af321fae39..744210c38e7 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -3,4 +3,5 @@
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
+obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
obj-$(CONFIG_SHARP_LOCOMO) += locomolcd.o
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 9d5015e9937..bd39bbd88d4 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -13,7 +13,6 @@
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/fb.h>
-#include <asm/bug.h>
static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
{
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
new file mode 100644
index 00000000000..95da4c9ed1f
--- /dev/null
+++ b/drivers/video/backlight/hp680_bl.c
@@ -0,0 +1,189 @@
+/*
+ * Backlight Driver for HP Jornada 680
+ *
+ * Copyright (c) 2005 Andriy Skulysh
+ *
+ * Based on Sharp's Corgi Backlight Driver
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+
+#include <asm/cpu/dac.h>
+#include <asm/hp6xx/hp6xx.h>
+#include <asm/hd64461/hd64461.h>
+
+#define HP680_MAX_INTENSITY 255
+#define HP680_DEFAULT_INTENSITY 10
+
+static int hp680bl_powermode = FB_BLANK_UNBLANK;
+static int current_intensity = 0;
+static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+
+static void hp680bl_send_intensity(int intensity)
+{
+ unsigned long flags;
+
+ if (hp680bl_powermode != FB_BLANK_UNBLANK)
+ intensity = 0;
+
+ spin_lock_irqsave(&bl_lock, flags);
+ sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+ spin_unlock_irqrestore(&bl_lock, flags);
+}
+
+static void hp680bl_blank(int blank)
+{
+ u16 v;
+
+ switch(blank) {
+
+ case FB_BLANK_NORMAL:
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ if (hp680bl_powermode == FB_BLANK_UNBLANK) {
+ hp680bl_send_intensity(0);
+ hp680bl_powermode = blank;
+ sh_dac_disable(DAC_LCD_BRIGHTNESS);
+ v = inw(HD64461_GPBDR);
+ v |= HD64461_GPBDR_LCDOFF;
+ outw(v, HD64461_GPBDR);
+ }
+ break;
+ case FB_BLANK_UNBLANK:
+ if (hp680bl_powermode != FB_BLANK_UNBLANK) {
+ sh_dac_enable(DAC_LCD_BRIGHTNESS);
+ v = inw(HD64461_GPBDR);
+ v &= ~HD64461_GPBDR_LCDOFF;
+ outw(v, HD64461_GPBDR);
+ hp680bl_powermode = blank;
+ hp680bl_send_intensity(current_intensity);
+ }
+ break;
+ }
+}
+
+#ifdef CONFIG_PM
+static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+ if (level == SUSPEND_POWER_DOWN)
+ hp680bl_blank(FB_BLANK_POWERDOWN);
+ return 0;
+}
+
+static int hp680bl_resume(struct device *dev, u32 level)
+{
+ if (level == RESUME_POWER_ON)
+ hp680bl_blank(FB_BLANK_UNBLANK);
+ return 0;
+}
+#else
+#define hp680bl_suspend NULL
+#define hp680bl_resume NULL
+#endif
+
+
+static int hp680bl_set_power(struct backlight_device *bd, int state)
+{
+ hp680bl_blank(state);
+ return 0;
+}
+
+static int hp680bl_get_power(struct backlight_device *bd)
+{
+ return hp680bl_powermode;
+}
+
+static int hp680bl_set_intensity(struct backlight_device *bd, int intensity)
+{
+ if (intensity > HP680_MAX_INTENSITY)
+ intensity = HP680_MAX_INTENSITY;
+ hp680bl_send_intensity(intensity);
+ current_intensity = intensity;
+ return 0;
+}
+
+static int hp680bl_get_intensity(struct backlight_device *bd)
+{
+ return current_intensity;
+}
+
+static struct backlight_properties hp680bl_data = {
+ .owner = THIS_MODULE,
+ .get_power = hp680bl_get_power,
+ .set_power = hp680bl_set_power,
+ .max_brightness = HP680_MAX_INTENSITY,
+ .get_brightness = hp680bl_get_intensity,
+ .set_brightness = hp680bl_set_intensity,
+};
+
+static struct backlight_device *hp680_backlight_device;
+
+static int __init hp680bl_probe(struct device *dev)
+{
+ hp680_backlight_device = backlight_device_register ("hp680-bl",
+ NULL, &hp680bl_data);
+ if (IS_ERR (hp680_backlight_device))
+ return PTR_ERR (hp680_backlight_device);
+
+ hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY);
+
+ return 0;
+}
+
+static int hp680bl_remove(struct device *dev)
+{
+ backlight_device_unregister(hp680_backlight_device);
+
+ return 0;
+}
+
+static struct device_driver hp680bl_driver = {
+ .name = "hp680-bl",
+ .bus = &platform_bus_type,
+ .probe = hp680bl_probe,
+ .remove = hp680bl_remove,
+ .suspend = hp680bl_suspend,
+ .resume = hp680bl_resume,
+};
+
+static struct platform_device hp680bl_device = {
+ .name = "hp680-bl",
+ .id = -1,
+};
+
+static int __init hp680bl_init(void)
+{
+ int ret;
+
+ ret=driver_register(&hp680bl_driver);
+ if (!ret) {
+ ret = platform_device_register(&hp680bl_device);
+ if (ret)
+ driver_unregister(&hp680bl_driver);
+ }
+ return ret;
+}
+
+static void __exit hp680bl_exit(void)
+{
+ platform_device_unregister(&hp680bl_device);
+ driver_unregister(&hp680bl_driver);
+}
+
+module_init(hp680bl_init);
+module_exit(hp680bl_exit);
+
+MODULE_AUTHOR("Andriy Skulysh <askulysh@image.kiev.ua>");
+MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 68c690605aa..9e32485ee7b 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -13,7 +13,6 @@
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/fb.h>
-#include <asm/bug.h>
static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
{
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index a7bcd17112c..0339f5640a7 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -30,10 +30,11 @@
#define STI_DRIVERVERSION "Version 0.9a"
-struct sti_struct *default_sti;
+struct sti_struct *default_sti __read_mostly;
-static int num_sti_roms; /* # of STI ROMS found */
-static struct sti_struct *sti_roms[MAX_STI_ROMS]; /* ptr to each sti_struct */
+/* number of STI ROMS found and their ptrs to each struct */
+static int num_sti_roms __read_mostly;
+static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly;
/* The colour indices used by STI are
@@ -266,7 +267,7 @@ sti_rom_copy(unsigned long base, unsigned long count, void *dest)
-static char default_sti_path[21];
+static char default_sti_path[21] __read_mostly;
#ifndef MODULE
static int __init sti_setup(char *str)
@@ -414,10 +415,10 @@ sti_init_glob_cfg(struct sti_struct *sti,
if (!sti->sti_mem_request)
sti->sti_mem_request = 256; /* STI default */
- glob_cfg = kmalloc(sizeof(*sti->glob_cfg), GFP_KERNEL);
- glob_cfg_ext = kmalloc(sizeof(*glob_cfg_ext), GFP_KERNEL);
- save_addr = kmalloc(save_addr_size, GFP_KERNEL);
- sti_mem_addr = kmalloc(sti->sti_mem_request, GFP_KERNEL);
+ glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL);
+ glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL);
+ save_addr = kzalloc(save_addr_size, GFP_KERNEL);
+ sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL);
if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) {
kfree(glob_cfg);
@@ -427,11 +428,6 @@ sti_init_glob_cfg(struct sti_struct *sti,
return -ENOMEM;
}
- memset(glob_cfg, 0, sizeof(*glob_cfg));
- memset(glob_cfg_ext, 0, sizeof(*glob_cfg_ext));
- memset(save_addr, 0, save_addr_size);
- memset(sti_mem_addr, 0, sti->sti_mem_request);
-
glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
glob_cfg->save_addr = STI_PTR(save_addr);
for (i=0; i<8; i++) {
@@ -502,9 +498,9 @@ sti_init_glob_cfg(struct sti_struct *sti,
#ifdef CONFIG_FB
struct sti_cooked_font * __init
-sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
{
- struct font_desc *fbfont;
+ const struct font_desc *fbfont;
unsigned int size, bpc;
void *dest;
struct sti_rom_font *nf;
@@ -525,10 +521,9 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
size = bpc * 256;
size += sizeof(struct sti_rom_font);
- nf = kmalloc(size, GFP_KERNEL);
+ nf = kzalloc(size, GFP_KERNEL);
if (!nf)
return NULL;
- memset(nf, 0, size);
nf->first_char = 0;
nf->last_char = 255;
@@ -544,7 +539,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
dest += sizeof(struct sti_rom_font);
memcpy(dest, fbfont->data, bpc*256);
- cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font) {
kfree(nf);
return NULL;
@@ -559,7 +554,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
}
#else
struct sti_cooked_font * __init
-sti_select_fbfont(struct sti_cooked_rom *cooked_rom, char *fbfont_name)
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
{
return NULL;
}
@@ -617,7 +612,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
struct sti_rom_font *raw_font, *font_start;
struct sti_cooked_font *cooked_font;
- cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font)
return 0;
@@ -631,7 +626,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
while (raw_font->next_font) {
raw_font = ((void *)font_start) + (raw_font->next_font);
- cooked_font->next_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ cooked_font->next_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font->next_font)
return 1;
@@ -668,10 +663,9 @@ sti_bmode_font_raw(struct sti_cooked_font *f)
unsigned char *n, *p, *q;
int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font);
- n = kmalloc (4*size, GFP_KERNEL);
+ n = kzalloc (4*size, GFP_KERNEL);
if (!n)
return NULL;
- memset (n, 0, 4*size);
p = n + 3;
q = (unsigned char *)f->raw;
while (size--) {
@@ -816,13 +810,12 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd
return NULL;
}
- sti = kmalloc(sizeof(*sti), GFP_KERNEL);
+ sti = kzalloc(sizeof(*sti), GFP_KERNEL);
if (!sti) {
printk(KERN_ERR "Not enough memory !\n");
return NULL;
}
- memset(sti, 0, sizeof(*sti));
spin_lock_init(&sti->lock);
test_rom:
@@ -1035,7 +1028,7 @@ static struct parisc_driver pa_sti_driver = {
* sti_init_roms() - detects all STI ROMs and stores them in sti_roms[]
*/
-static int sticore_initialized;
+static int sticore_initialized __read_mostly;
static void __init sti_init_roms(void)
{
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 2b972461a03..0ae0a97b0fe 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -1665,7 +1665,6 @@ static int __devinit cyblafb_init(void)
}
#endif
output("CyblaFB version %s initializing\n", VERSION);
- return pci_module_init(&cyblafb_pci_driver);
return pci_register_driver(&cyblafb_pci_driver);
}
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index d2dede6ed3e..996c7b58564 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1550,6 +1550,7 @@ int fb_get_options(char *name, char **option)
return retval;
}
+#ifndef MODULE
/**
* video_setup - process command line options
* @options: string of options
@@ -1593,6 +1594,7 @@ static int __init video_setup(char *options)
return 0;
}
__setup("video=", video_setup);
+#endif
/*
* Visible symbols for modules
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 38d22729b12..c9a7cdf6d54 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1243,7 +1243,7 @@ static int __devexit gbefb_remove(struct platform_device* p_dev)
(void *)gbe_tiles.cpu, gbe_tiles.dma);
release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
iounmap(gbe);
- gbefb_remove_sysfs(dev);
+ gbefb_remove_sysfs(&p_dev->dev);
framebuffer_release(info);
return 0;
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index bd410e06db7..e3c8b5f1ca7 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -191,11 +191,11 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
u8 *edid = NULL;
int i;
- DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn);
- if (conn < 4) {
+ DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1);
+ if (conn < par->ddc_num) {
for (i = 0; i < 3; i++) {
/* Do the real work */
- edid = i810_do_probe_i2c_edid(&par->chan[conn-1]);
+ edid = i810_do_probe_i2c_edid(&par->chan[conn]);
if (edid)
break;
}
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 6c187d5fe95..579195c2bea 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -280,6 +280,7 @@ struct i810fb_par {
u32 blit_bpp;
u32 ovract;
u32 cur_state;
+ u32 ddc_num;
int mtrr_reg;
u16 bltcntl;
u8 interlace;
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 266d0ab9266..d8467c03b49 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -149,6 +149,7 @@ static int vyres __devinitdata;
static int sync __devinitdata;
static int extvga __devinitdata;
static int dcolor __devinitdata;
+static int ddc3 __devinitdata = 2;
/*------------------------------------------------------------*/
@@ -1763,6 +1764,8 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
if (sync)
par->dev_flags |= ALWAYS_SYNC;
+ par->ddc_num = ddc3;
+
if (bpp < 8)
bpp = 8;
@@ -1885,7 +1888,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
int found = 0;
#ifdef CONFIG_FB_I810_I2C
int i;
- int err;
+ int err = 1;
struct i810fb_par *par = info->par;
#endif
@@ -1895,8 +1898,8 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
#ifdef CONFIG_FB_I810_I2C
i810_create_i2c_busses(par);
- for (i = 0; i < 4; i++) {
- err = i810_probe_i2c_connector(info, &par->edid, i+1);
+ for (i = 0; i < par->ddc_num + 1; i++) {
+ err = i810_probe_i2c_connector(info, &par->edid, i);
if (!err)
break;
}
@@ -1983,6 +1986,8 @@ static int __devinit i810fb_setup(char *options)
vsync2 = simple_strtoul(this_opt+7, NULL, 0);
else if (!strncmp(this_opt, "dcolor", 6))
dcolor = 1;
+ else if (!strncmp(this_opt, "ddc3", 4))
+ ddc3 = 3;
else
mode_option = this_opt;
}
@@ -2190,6 +2195,8 @@ MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
module_param(dcolor, bool, 0);
MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
" (default = 0 = TrueColor)");
+module_param(ddc3, bool, 0);
+MODULE_PARM_DESC(ddc3, "Probe DDC bus 3 (default = 0 = no)");
module_param(mode_option, charp, 0);
MODULE_PARM_DESC(mode_option, "Specify initial video mode");
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 747602aa561..a2e201dc40f 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -843,6 +843,9 @@ static int neofb_set_par(struct fb_info *info)
par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */
+ /* Initialize: by default, we want display config register to be read */
+ par->PanelDispCntlRegRead = 1;
+
/* Enable any user specified display devices. */
par->PanelDispCntlReg1 = 0x00;
if (par->internal_display)
@@ -1334,6 +1337,18 @@ static int neofb_blank(int blank_mode, struct fb_info *info)
struct neofb_par *par = info->par;
int seqflags, lcdflags, dpmsflags, reg;
+
+ /*
+ * Reload the value stored in the register, if sensible. It might have
+ * been changed via FN keystroke.
+ */
+ if (par->PanelDispCntlRegRead) {
+ neoUnlock();
+ par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
+ neoLock(&par->state);
+ }
+ par->PanelDispCntlRegRead = !blank_mode;
+
switch (blank_mode) {
case FB_BLANK_POWERDOWN: /* powerdown - both sync lines down */
seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
@@ -1366,7 +1381,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info)
case FB_BLANK_NORMAL: /* just blank screen (backlight stays on) */
seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
- dpmsflags = 0; /* no hsync/vsync suppression */
+ dpmsflags = 0x00; /* no hsync/vsync suppression */
break;
case FB_BLANK_UNBLANK: /* unblank */
seqflags = 0; /* Enable sequencer */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index dbcb8962e57..a7c4e5e8ead 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -138,6 +138,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index f3927b6cda9..f5361cd8ccc 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -30,7 +30,6 @@
#include <linux/module.h>
#include <linux/types.h>
-#include <asm/bug.h>
#include <asm/io.h>
#include <asm/system.h>
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 25148de5fe6..eeeac924b50 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/types.h>
-#include <asm/bug.h>
#include <asm/io.h>
#include <asm/system.h>
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index d574dd3c9c8..9451932fbaf 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -82,7 +82,6 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
-#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
index 3a74a63dd4f..a4d7cc51ce0 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/sbuslib.c
@@ -199,8 +199,7 @@ struct fbcmap32 {
#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
-static int fbiogetputcmap(struct file *file, struct fb_info *info,
- unsigned int cmd, unsigned long arg)
+static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct fbcmap32 __user *argp = (void __user *)arg;
struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p));
@@ -216,10 +215,10 @@ static int fbiogetputcmap(struct file *file, struct fb_info *info,
ret |= put_user(compat_ptr(addr), &p->blue);
if (ret)
return -EFAULT;
- return info->fbops->fb_ioctl(file->f_dentry->d_inode, file,
+ return info->fbops->fb_ioctl(info,
(cmd == FBIOPUTCMAP32) ?
FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC,
- (unsigned long)p, info);
+ (unsigned long)p);
}
struct fbcursor32 {
@@ -236,8 +235,7 @@ struct fbcursor32 {
#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
-static int fbiogscursor(struct file *file, struct fb_info *info,
- unsigned long arg)
+static int fbiogscursor(struct fb_info *info, unsigned long arg)
{
struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
struct fbcursor32 __user *argp = (void __user *)arg;
@@ -260,12 +258,10 @@ static int fbiogscursor(struct file *file, struct fb_info *info,
ret |= put_user(compat_ptr(addr), &p->image);
if (ret)
return -EFAULT;
- return info->fbops->fb_ioctl(file->f_dentry->d_inode, file,
- FBIOSCURSOR, (unsigned long)p, info);
+ return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p);
}
-long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case FBIOGTYPE:
@@ -278,14 +274,13 @@ long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
case FBIOSCURPOS:
case FBIOGCURPOS:
case FBIOGCURMAX:
- return info->fbops->fb_ioctl(file->f_dentry->d_inode,
- file, cmd, arg, info);
+ return info->fbops->fb_ioctl(info, cmd, arg);
case FBIOPUTCMAP32:
- return fbiogetputcmap(file, info, cmd, arg);
+ return fbiogetputcmap(info, cmd, arg);
case FBIOGETCMAP32:
- return fbiogetputcmap(file, info, cmd, arg);
+ return fbiogetputcmap(info, cmd, arg);
case FBIOSCURSOR32:
- return fbiogscursor(file, info, arg);
+ return fbiogscursor(info, arg);
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h
index b470e52ce9e..492828c3fe8 100644
--- a/drivers/video/sbuslib.h
+++ b/drivers/video/sbuslib.h
@@ -20,7 +20,7 @@ extern int sbusfb_mmap_helper(struct sbus_mmap_map *map,
int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
struct fb_info *info,
int type, int fb_depth, unsigned long fb_size);
-long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info);
+int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
#endif /* _SBUSLIB_H */