Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 2 Feb 2006 06:06:15 +0000 (22:06 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 2 Feb 2006 06:06:15 +0000 (22:06 -0800)
556 files changed:
Documentation/RCU/RTFP.txt
Documentation/RCU/checklist.txt
Documentation/RCU/listRCU.txt
Documentation/RCU/rcu.txt
Documentation/RCU/rcuref.txt
Documentation/RCU/whatisRCU.txt
Documentation/feature-removal-schedule.txt
Documentation/kernel-doc-nano-HOWTO.txt
Documentation/power/interface.txt
Documentation/power/swsusp.txt
Documentation/powerpc/booting-without-of.txt [new file with mode: 0644]
Documentation/scsi/ChangeLog.megaraid_sas [new file with mode: 0644]
Documentation/scsi/aic79xx.txt
Documentation/scsi/aic7xxx.txt
Documentation/sysctl/vm.txt
Documentation/usb/et61x251.txt [new file with mode: 0644]
Documentation/usb/sn9c102.txt
Documentation/usb/w9968cf.txt
Documentation/vm/page_migration [new file with mode: 0644]
MAINTAINERS
arch/alpha/kernel/asm-offsets.c
arch/alpha/kernel/entry.S
arch/alpha/kernel/irq.c
arch/arm/configs/bast_defconfig
arch/arm/configs/collie_defconfig
arch/arm/configs/s3c2410_defconfig
arch/arm/kernel/calls.S
arch/arm/kernel/entry-common.S
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-s3c2410/cpu.h
arch/arm/mach-s3c2410/devs.c
arch/arm/mach-s3c2410/dma.c
arch/arm/mach-s3c2410/sleep.S
arch/arm/mm/ioremap.c
arch/arm/mm/mm-armv.c
arch/arm26/Kconfig
arch/arm26/kernel/fiq.c
arch/arm26/kernel/signal.c
arch/i386/Kconfig
arch/i386/kernel/cpu/centaur.c
arch/i386/kernel/cpu/cpufreq/Kconfig
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
arch/i386/kernel/cpu/intel_cacheinfo.c
arch/i386/kernel/cpu/mtrr/main.c
arch/i386/kernel/timers/timer_tsc.c
arch/i386/pci/irq.c
arch/i386/pci/mmconfig.c
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/unaligned.c
arch/ia64/sn/kernel/io_init.c
arch/ia64/sn/kernel/xpc_channel.c
arch/ia64/sn/pci/pci_dma.c
arch/mips/kernel/gdb-stub.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/platforms/powermac/pfunc_core.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/ppc/syslib/mv64x60.c
arch/s390/defconfig
arch/s390/kernel/compat_signal.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/signal.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/time.c
arch/s390/lib/Makefile
arch/sh/Kconfig
arch/sh/boards/superh/microdev/io.c
arch/sh/boards/superh/microdev/irq.c
arch/sh/boards/superh/microdev/setup.c
arch/sh/boards/unknown/Makefile
arch/sh/boards/unknown/io.c [deleted file]
arch/sh/boards/unknown/mach.c [deleted file]
arch/sh/boards/unknown/setup.c
arch/sh/cchips/voyagergx/consistent.c
arch/sh/cchips/voyagergx/irq.c
arch/sh/configs/microdev_defconfig
arch/sh/kernel/Makefile
arch/sh/kernel/cpu/Makefile
arch/sh/kernel/cpu/bus.c [deleted file]
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/irq/ipr.c
arch/sh/kernel/entry.S
arch/sh/kernel/process.c
arch/sh/kernel/setup.c
arch/sh64/kernel/time.c
arch/sparc/kernel/entry.S
arch/sparc/math-emu/math.c
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/sys32.S
arch/sparc64/kernel/systbls.S
arch/um/Makefile
arch/um/drivers/chan_kern.c
arch/um/drivers/daemon_kern.c
arch/um/drivers/line.c
arch/um/drivers/mcast_kern.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/slip_common.h
arch/um/drivers/slip_kern.c
arch/um/drivers/slirp_kern.c
arch/um/drivers/ssl.c
arch/um/include/kern_util.h
arch/um/kernel/exec_kern.c
arch/um/kernel/physmem.c
arch/um/kernel/reboot.c
arch/um/kernel/tt/syscall_kern.c
arch/um/sys-i386/ldt.c
arch/x86_64/ia32/ia32entry.S
arch/x86_64/lib/Makefile
arch/x86_64/lib/iomap_copy.S [new file with mode: 0644]
arch/x86_64/pci/mmconfig.c
block/elevator.c
block/ll_rw_blk.c
drivers/block/ub.c
drivers/char/Kconfig
drivers/char/agp/amd64-agp.c
drivers/char/agp/ati-agp.c
drivers/char/agp/frontend.c
drivers/char/agp/intel-agp.c
drivers/char/agp/isoch.c
drivers/char/hangcheck-timer.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/tpm/tpm_bios.c
drivers/char/tpm/tpm_infineon.c
drivers/char/vt.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_userspace.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/mthca/mthca_av.c
drivers/infiniband/hw/mthca/mthca_cmd.c
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_main.c
drivers/infiniband/hw/mthca/mthca_mcg.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_memfree.h
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/input/joystick/a3d.c
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/grip.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-packets.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/sidewinder.c
drivers/input/joystick/tmdc.c
drivers/input/joystick/turbografx.c
drivers/input/joystick/twidjoy.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ixp4xx-beeper.c [new file with mode: 0644]
drivers/input/mouse/psmouse-base.c
drivers/input/mousedev.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/mk712.c
drivers/macintosh/macio_asic.c
drivers/md/dm-ioctl.c
drivers/md/dm-log.c
drivers/md/dm-snap.c
drivers/md/dm-snap.h
drivers/md/dm-table.c
drivers/md/dm.c
drivers/media/video/hexium_orion.c
drivers/message/fusion/Makefile
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h
drivers/message/fusion/mptspi.c
drivers/misc/ibmasm/uart.c
drivers/mtd/maps/tsunami_flash.c
drivers/net/Kconfig
drivers/net/acenic.c
drivers/net/b44.c
drivers/net/bnx2.c
drivers/net/bnx2.h
drivers/net/bnx2_fw.h
drivers/net/bonding/bond_main.c
drivers/net/lp486e.c
drivers/net/mv643xx_eth.c
drivers/net/s2io.c
drivers/net/wireless/hostap/Kconfig
drivers/net/wireless/ipw2100.c
drivers/net/wireless/ipw2200.c
drivers/net/wireless/orinoco_cs.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/acpiphp_ibm.c
drivers/pci/hotplug/ibmphp_core.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/pci/hotplug/rpaphp.h
drivers/pci/hotplug/rpaphp_core.c
drivers/pci/hotplug/rpaphp_pci.c
drivers/pci/hotplug/rpaphp_slot.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/msi.c
drivers/pci/msi.h
drivers/pci/pci.c
drivers/pci/setup-res.c
drivers/s390/Kconfig
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3370_erp.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_9336_erp.c
drivers/s390/block/dasd_9343_erp.c
drivers/s390/block/dasd_cmb.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_diag.h
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_erp.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_fba.h
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/dasd_proc.c
drivers/s390/char/con3215.c
drivers/s390/char/con3270.c
drivers/s390/char/keyboard.c
drivers/s390/char/tape_34xx.c
drivers/s390/char/tape_class.c
drivers/s390/char/tape_class.h
drivers/s390/char/tape_core.c
drivers/s390/cio/airq.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/chsc.c
drivers/s390/cio/cio.c
drivers/s390/cio/cmf.c
drivers/s390/cio/css.c
drivers/s390/cio/device.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/qdio.c
drivers/s390/cio/qdio.h
drivers/s390/crypto/z90common.h
drivers/s390/crypto/z90crypt.h
drivers/s390/crypto/z90hardware.c
drivers/s390/crypto/z90main.c
drivers/s390/net/claw.c
drivers/s390/net/claw.h
drivers/s390/net/ctcdbug.c
drivers/s390/net/ctcdbug.h
drivers/s390/net/ctcmain.c
drivers/s390/net/ctcmain.h
drivers/s390/net/ctctty.c
drivers/s390/net/ctctty.h
drivers/s390/net/cu3088.c
drivers/s390/net/fsm.c
drivers/s390/net/fsm.h
drivers/s390/net/iucv.c
drivers/s390/net/lcs.c
drivers/s390/net/lcs.h
drivers/s390/net/netiucv.c
drivers/s390/net/qeth.h
drivers/s390/net/qeth_eddp.c
drivers/s390/net/qeth_eddp.h
drivers/s390/net/qeth_fs.h
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_mpc.c
drivers/s390/net/qeth_mpc.h
drivers/s390/net/qeth_proc.c
drivers/s390/net/qeth_sys.c
drivers/s390/net/qeth_tso.h
drivers/s390/s390_rdev.c
drivers/s390/s390mach.h
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_dbf.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs_adapter.c
drivers/s390/scsi/zfcp_sysfs_driver.c
drivers/s390/scsi/zfcp_sysfs_port.c
drivers/s390/scsi/zfcp_sysfs_unit.c
drivers/scsi/ahci.c
drivers/scsi/aic7xxx/Kconfig.aic79xx
drivers/scsi/aic7xxx/aic79xx.h
drivers/scsi/aic7xxx/aic79xx.reg
drivers/scsi/aic7xxx/aic79xx.seq
drivers/scsi/aic7xxx/aic79xx_core.c
drivers/scsi/aic7xxx/aic79xx_inline.h
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
drivers/scsi/aic7xxx/aicasm/aicasm.c
drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
drivers/scsi/dc395x.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvscsi.h
drivers/scsi/ibmvscsi/iseries_vscsi.c
drivers/scsi/ibmvscsi/rpa_vscsi.c
drivers/scsi/ide-scsi.c
drivers/scsi/ips.c
drivers/scsi/libata-scsi.c
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/sg.c
drivers/scsi/st.c
drivers/serial/21285.c
drivers/serial/8250.c
drivers/serial/Kconfig
drivers/serial/amba-pl010.c
drivers/serial/clps711x.c
drivers/serial/imx.c
drivers/serial/jsm/jsm_neo.c
drivers/serial/s3c2410.c
drivers/serial/sa1100.c
drivers/serial/serial_core.c
drivers/serial/serial_lh7a40x.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/serial/sunsu.c
drivers/sn/ioc3.c
drivers/usb/Makefile
drivers/usb/atm/cxacru.c
drivers/usb/atm/speedtch.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/atm/usbatm.c
drivers/usb/atm/usbatm.h
drivers/usb/atm/xusbatm.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/usblp.c
drivers/usb/core/message.c
drivers/usb/core/urb.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/zero.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/ohci-au1xxx.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/uhci-q.c
drivers/usb/input/hid-core.c
drivers/usb/input/hiddev.c
drivers/usb/input/touchkitusb.c
drivers/usb/input/yealink.c
drivers/usb/media/Kconfig
drivers/usb/media/Makefile
drivers/usb/media/et61x251.h [new file with mode: 0644]
drivers/usb/media/et61x251_core.c [new file with mode: 0644]
drivers/usb/media/et61x251_sensor.h [new file with mode: 0644]
drivers/usb/media/et61x251_tas5130d1b.c [new file with mode: 0644]
drivers/usb/media/ov511.c
drivers/usb/media/pwc/pwc-ctrl.c
drivers/usb/media/sn9c102.h
drivers/usb/media/sn9c102_core.c
drivers/usb/media/sn9c102_hv7131d.c
drivers/usb/media/sn9c102_mi0343.c
drivers/usb/media/sn9c102_ov7630.c
drivers/usb/media/sn9c102_pas106b.c
drivers/usb/media/sn9c102_sensor.h
drivers/usb/media/sn9c102_tas5110c1b.c
drivers/usb/media/sn9c102_tas5130d1b.c
drivers/usb/media/w9968cf.c
drivers/usb/media/w9968cf.h
drivers/usb/media/w9968cf_vpp.h
drivers/usb/misc/auerswald.c
drivers/usb/misc/ldusb.c
drivers/usb/net/asix.c
drivers/usb/serial/cp2101.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/storage/initializers.c
drivers/usb/storage/initializers.h
drivers/usb/storage/libusual.c
drivers/usb/storage/unusual_devs.h
drivers/usb/usb-skeleton.c
drivers/video/amba-clcd.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/hp680_bl.c [new file with mode: 0644]
drivers/video/cyblafb.c
drivers/video/i810/i810-i2c.c
drivers/video/i810/i810.h
drivers/video/i810/i810_main.c
fs/Kconfig
fs/bio.c
fs/buffer.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/transport.c
fs/compat.c
fs/ext2/inode.c
fs/ext3/inode.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/namei.c
fs/nfsd/nfssvc.c
fs/reiserfs/dir.c
fs/reiserfs/file.c
fs/reiserfs/fix_node.c
fs/reiserfs/inode.c
fs/reiserfs/journal.c
fs/reiserfs/namei.c
fs/reiserfs/procfs.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/smbfs/dir.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_iops.c
include/asm-alpha/dma-mapping.h
include/asm-arm/arch-s3c2410/debug-macro.S
include/asm-arm/arch-s3c2410/map.h
include/asm-arm/arch-s3c2410/regs-serial.h
include/asm-arm/arch-s3c2410/uncompress.h
include/asm-arm/mach/map.h
include/asm-arm/pgtable.h
include/asm-arm26/bitops.h
include/asm-arm26/hardirq.h
include/asm-arm26/posix_types.h
include/asm-arm26/system.h
include/asm-i386/page.h
include/asm-ia64/sn/sn_feature_sets.h
include/asm-powerpc/kexec.h
include/asm-powerpc/pmac_pfunc.h
include/asm-s390/dasd.h
include/asm-s390/qdio.h
include/asm-s390/thread_info.h
include/asm-s390/unistd.h
include/asm-sh/bus-sh.h [deleted file]
include/asm-sh/cpu-sh3/mmu_context.h
include/asm-sh/cpu-sh4/mmu_context.h
include/asm-sh/ioctls.h
include/asm-sh/irq-sh73180.h
include/asm-sh/irq-sh7780.h
include/asm-sh/irq.h
include/asm-sh/microdev.h [new file with mode: 0644]
include/asm-sh/microdev/io.h [deleted file]
include/asm-sh/microdev/irq.h [deleted file]
include/asm-sh/processor.h
include/asm-sh64/ioctls.h
include/asm-sparc64/spinlock.h
include/asm-um/ldt-x86_64.h
include/asm-um/smp.h
include/asm-x86_64/ia32_unistd.h
include/asm-xtensa/futex.h [new file with mode: 0644]
include/linux/agpgart.h
include/linux/blkdev.h
include/linux/cpufreq.h
include/linux/device-mapper.h
include/linux/fs.h
include/linux/fuse.h
include/linux/hrtimer.h
include/linux/io.h [new file with mode: 0644]
include/linux/ktime.h
include/linux/mmzone.h
include/linux/netfilter/x_tables.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/posix-timers.h
include/linux/reiserfs_fs.h
include/linux/reiserfs_fs_sb.h
include/linux/reiserfs_xattr.h
include/linux/rmap.h
include/linux/security.h
include/linux/serial_8250.h
include/linux/serial_core.h
include/linux/slab.h
include/linux/swap.h
include/linux/syscalls.h
include/linux/sysctl.h
include/linux/time.h
include/linux/types.h
include/linux/usb_ch9.h
include/linux/videodev2.h
include/net/ieee80211.h
include/net/route.h
include/scsi/scsi_device.h
include/scsi/scsi_host.h
kernel/fork.c
kernel/hrtimer.c
kernel/itimer.c
kernel/posix-timers.c
kernel/power/console.c
kernel/power/disk.c
kernel/power/power.h
kernel/power/swsusp.c
kernel/rcutorture.c
kernel/sched.c
kernel/sysctl.c
kernel/time.c
kernel/user.c
lib/Makefile
lib/iomap_copy.c [new file with mode: 0644]
mm/memory.c
mm/mempolicy.c
mm/oom_kill.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/slab.c
mm/swap_state.c
mm/swapfile.c
mm/vmscan.c
net/bridge/br_if.c
net/bridge/br_private.h
net/core/dev.c
net/core/filter.c
net/core/skbuff.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/ieee80211/ieee80211_rx.c
net/ieee80211/ieee80211_wx.c
net/ipv4/igmp.c
net/ipv4/tcp_htcp.c
net/ipv4/tcp_ipv4.c
net/ipv6/mcast.c
net/ipv6/tcp_ipv6.c
net/key/af_key.c
net/packet/af_packet.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sunrpc/sched.c
scripts/kernel-doc
security/seclvl.c
security/selinux/hooks.c
security/selinux/include/objsec.h
sound/oss/au1550_ac97.c
sound/ppc/pmac.c

index fcbcbc3..6221464 100644 (file)
@@ -90,16 +90,20 @@ at OLS.  The resulting abundance of RCU patches was presented the
 following year [McKenney02a], and use of RCU in dcache was first
 described that same year [Linder02a].
 
-Also in 2002, Michael [Michael02b,Michael02a] presented techniques
-that defer the destruction of data structures to simplify non-blocking
-synchronization (wait-free synchronization, lock-free synchronization,
-and obstruction-free synchronization are all examples of non-blocking
-synchronization).  In particular, this technique eliminates locking,
-reduces contention, reduces memory latency for readers, and parallelizes
-pipeline stalls and memory latency for writers.  However, these
-techniques still impose significant read-side overhead in the form of
-memory barriers.  Researchers at Sun worked along similar lines in the
-same timeframe [HerlihyLM02,HerlihyLMS03].
+Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer"
+techniques that defer the destruction of data structures to simplify
+non-blocking synchronization (wait-free synchronization, lock-free
+synchronization, and obstruction-free synchronization are all examples of
+non-blocking synchronization).  In particular, this technique eliminates
+locking, reduces contention, reduces memory latency for readers, and
+parallelizes pipeline stalls and memory latency for writers.  However,
+these techniques still impose significant read-side overhead in the
+form of memory barriers.  Researchers at Sun worked along similar lines
+in the same timeframe [HerlihyLM02,HerlihyLMS03].  These techniques
+can be thought of as inside-out reference counts, where the count is
+represented by the number of hazard pointers referencing a given data
+structure (rather than the more conventional counter field within the
+data structure itself).
 
 In 2003, the K42 group described how RCU could be used to create
 hot-pluggable implementations of operating-system functions.  Later that
@@ -113,7 +117,6 @@ number of operating-system kernels [PaulEdwardMcKenneyPhD], a paper
 describing how to make RCU safe for soft-realtime applications [Sarma04c],
 and a paper describing SELinux performance with RCU [JamesMorris04b].
 
-
 2005 has seen further adaptation of RCU to realtime use, permitting
 preemption of RCU realtime critical sections [PaulMcKenney05a,
 PaulMcKenney05b].
index e118a7c..49e27cc 100644 (file)
@@ -177,3 +177,9 @@ over a rather long period of time, but improvements are always welcome!
 
        If you want to wait for some of these other things, you might
        instead need to use synchronize_irq() or synchronize_sched().
+
+12.    Any lock acquired by an RCU callback must be acquired elsewhere
+       with irq disabled, e.g., via spin_lock_irqsave().  Failing to
+       disable irq on a given acquisition of that lock will result in
+       deadlock as soon as the RCU callback happens to interrupt that
+       acquisition's critical section.
index f8a54fa..1fd1753 100644 (file)
@@ -232,7 +232,7 @@ entry does not exist.  For this to be helpful, the search function must
 return holding the per-entry spinlock, as ipc_lock() does in fact do.
 
 Quick Quiz:  Why does the search function need to return holding the
-per-entry lock for this deleted-flag technique to be helpful?
+       per-entry lock for this deleted-flag technique to be helpful?
 
 If the system-call audit module were to ever need to reject stale data,
 one way to accomplish this would be to add a "deleted" flag and a "lock"
@@ -275,8 +275,8 @@ flag under the spinlock as follows:
        {
                struct audit_entry  *e;
 
-               /* Do not use the _rcu iterator here, since this is the only
-                * deletion routine. */
+               /* Do not need to use the _rcu iterator here, since this
+                * is the only deletion routine. */
                list_for_each_entry(e, list, list) {
                        if (!audit_compare_rule(rule, &e->rule)) {
                                spin_lock(&e->lock);
@@ -304,9 +304,12 @@ function to reject newly deleted data.
 
 
 Answer to Quick Quiz
-
-If the search function drops the per-entry lock before returning, then
-the caller will be processing stale data in any case.  If it is really
-OK to be processing stale data, then you don't need a "deleted" flag.
-If processing stale data really is a problem, then you need to hold the
-per-entry lock across all of the code that uses the value looked up.
+       Why does the search function need to return holding the per-entry
+       lock for this deleted-flag technique to be helpful?
+
+       If the search function drops the per-entry lock before returning,
+       then the caller will be processing stale data in any case.  If it
+       is really OK to be processing stale data, then you don't need a
+       "deleted" flag.  If processing stale data really is a problem,
+       then you need to hold the per-entry lock across all of the code
+       that uses the value that was returned.
index 6fa0922..02e27bf 100644 (file)
@@ -111,6 +111,11 @@ o  What are all these files in this directory?
 
                You are reading it!
 
+       rcuref.txt
+
+               Describes how to combine use of reference counts
+               with RCU.
+
        whatisRCU.txt
 
                Overview of how the RCU implementation works.  Along
index 3f60db4..451de2a 100644 (file)
@@ -1,7 +1,7 @@
-Refcounter design for elements of lists/arrays protected by RCU.
+Reference-count design for elements of lists/arrays protected by RCU.
 
-Refcounting on elements of  lists which are protected by traditional
-reader/writer spinlocks or semaphores are straight forward as in:
+Reference counting on elements of lists which are protected by traditional
+reader/writer spinlocks or semaphores are straightforward:
 
 1.                             2.
 add()                          search_and_reference()
@@ -28,12 +28,12 @@ release_referenced()                        delete()
                                            ...
                                        }
 
-If this list/array is made lock free using rcu as in changing the
-write_lock in add() and delete() to spin_lock and changing read_lock
+If this list/array is made lock free using RCU as in changing the
+write_lock() in add() and delete() to spin_lock and changing read_lock
 in search_and_reference to rcu_read_lock(), the atomic_get in
 search_and_reference could potentially hold reference to an element which
-has already been deleted from the list/array.  atomic_inc_not_zero takes
-care of this scenario. search_and_reference should look as;
+has already been deleted from the list/array.  Use atomic_inc_not_zero()
+in this scenario as follows:
 
 1.                                     2.
 add()                                  search_and_reference()
@@ -51,17 +51,16 @@ add()                                       search_and_reference()
 release_referenced()                   delete()
 {                                      {
     ...                                            write_lock(&list_lock);
-    atomic_dec(&el->rc, relfunc)           ...
-    ...                                            delete_element
-}                                          write_unlock(&list_lock);
-                                           ...
+    if (atomic_dec_and_test(&el->rc))       ...
+        call_rcu(&el->head, el_free);       delete_element
+    ...                                     write_unlock(&list_lock);
+}                                          ...
                                            if (atomic_dec_and_test(&el->rc))
                                                call_rcu(&el->head, el_free);
                                            ...
                                        }
 
-Sometimes, reference to the element need to be obtained in the
-update (write) stream.  In such cases, atomic_inc_not_zero might be an
-overkill since the spinlock serialising list updates are held. atomic_inc
-is to be used in such cases.
-
+Sometimes, a reference to the element needs to be obtained in the
+update (write) stream.  In such cases, atomic_inc_not_zero() might be
+overkill, since we hold the update-side spinlock.  One might instead
+use atomic_inc() in such cases.
index 15da168..5ed85af 100644 (file)
@@ -200,10 +200,11 @@ rcu_assign_pointer()
        the new value, and also executes any memory-barrier instructions
        required for a given CPU architecture.
 
-       Perhaps more important, it serves to document which pointers
-       are protected by RCU.  That said, rcu_assign_pointer() is most
-       frequently used indirectly, via the _rcu list-manipulation
-       primitives such as list_add_rcu().
+       Perhaps just as important, it serves to document (1) which
+       pointers are protected by RCU and (2) the point at which a
+       given structure becomes accessible to other CPUs.  That said,
+       rcu_assign_pointer() is most frequently used indirectly, via
+       the _rcu list-manipulation primitives such as list_add_rcu().
 
 rcu_dereference()
 
@@ -258,9 +259,11 @@ rcu_dereference()
        locking.
 
        As with rcu_assign_pointer(), an important function of
-       rcu_dereference() is to document which pointers are protected
-       by RCU.  And, again like rcu_assign_pointer(), rcu_dereference()
-       is typically used indirectly, via the _rcu list-manipulation
+       rcu_dereference() is to document which pointers are protected by
+       RCU, in particular, flagging a pointer that is subject to changing
+       at any time, including immediately after the rcu_dereference().
+       And, again like rcu_assign_pointer(), rcu_dereference() is
+       typically used indirectly, via the _rcu list-manipulation
        primitives, such as list_for_each_entry_rcu().
 
 The following diagram shows how each API communicates among the
@@ -327,7 +330,7 @@ for specialized uses, but are relatively uncommon.
 3.  WHAT ARE SOME EXAMPLE USES OF CORE RCU API?
 
 This section shows a simple use of the core RCU API to protect a
-global pointer to a dynamically allocated structure.  More typical
+global pointer to a dynamically allocated structure.  More-typical
 uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt.
 
        struct foo {
@@ -410,6 +413,8 @@ o   Use synchronize_rcu() -after- removing a data element from an
        data item.
 
 See checklist.txt for additional rules to follow when using RCU.
+And again, more-typical uses of RCU may be found in listRCU.txt,
+arrayRCU.txt, and NMI-RCU.txt.
 
 
 4.  WHAT IF MY UPDATING THREAD CANNOT BLOCK?
@@ -513,7 +518,7 @@ production-quality implementation, and see:
 
 for papers describing the Linux kernel RCU implementation.  The OLS'01
 and OLS'02 papers are a good introduction, and the dissertation provides
-more details on the current implementation.
+more details on the current implementation as of early 2004.
 
 
 5A.  "TOY" IMPLEMENTATION #1: LOCKING
@@ -768,7 +773,6 @@ RCU pointer/list traversal:
        rcu_dereference
        list_for_each_rcu               (to be deprecated in favor of
                                         list_for_each_entry_rcu)
-       list_for_each_safe_rcu          (deprecated, not used)
        list_for_each_entry_rcu
        list_for_each_continue_rcu      (to be deprecated in favor of new
                                         list_for_each_entry_continue_rcu)
@@ -807,7 +811,8 @@ Quick Quiz #1:      Why is this argument naive?  How could a deadlock
 Answer:                Consider the following sequence of events:
 
                1.      CPU 0 acquires some unrelated lock, call it
-                       "problematic_lock".
+                       "problematic_lock", disabling irq via
+                       spin_lock_irqsave().
 
                2.      CPU 1 enters synchronize_rcu(), write-acquiring
                        rcu_gp_mutex.
@@ -894,7 +899,7 @@ Answer:             Just as PREEMPT_RT permits preemption of spinlock
 ACKNOWLEDGEMENTS
 
 My thanks to the people who helped make this human-readable, including
-Jon Walpole, Josh Triplett, Serge Hallyn, and Suzanne Wood.
+Jon Walpole, Josh Triplett, Serge Hallyn, Suzanne Wood, and Alan Stern.
 
 
 For more information, see http://www.rdrop.com/users/paulmck/RCU.
index b4a1ea7..4d4897c 100644 (file)
@@ -148,3 +148,17 @@ Why:       The 8250 serial driver now has the ability to deal with the differences
        brother on Alchemy SOCs.  The loss of features is not considered an
        issue.
 Who:   Ralf Baechle <ralf@linux-mips.org>
+
+---------------------------
+
+What:  Legacy /proc/pci interface (PCI_LEGACY_PROC)
+When:  March 2006
+Why:   deprecated since 2.5.53 in favor of lspci(8)
+Who:   Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
+What:  pci_module_init(driver)
+When:  January 2007
+Why:   Is replaced by pci_register_driver(pci_driver).
+Who:   Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de>
index c406ce6..c65233d 100644 (file)
@@ -45,10 +45,10 @@ How to extract the documentation
 
 If you just want to read the ready-made books on the various
 subsystems (see Documentation/DocBook/*.tmpl), just type 'make
-psdocs', or 'make pdfdocs', or 'make htmldocs', depending on your 
-preference.  If you would rather read a different format, you can type 
-'make sgmldocs' and then use DocBook tools to convert 
-Documentation/DocBook/*.sgml to a format of your choice (for example, 
+psdocs', or 'make pdfdocs', or 'make htmldocs', depending on your
+preference.  If you would rather read a different format, you can type
+'make sgmldocs' and then use DocBook tools to convert
+Documentation/DocBook/*.sgml to a format of your choice (for example,
 'db2html ...' if 'make htmldocs' was not defined).
 
 If you want to see man pages instead, you can do this:
@@ -124,6 +124,36 @@ patterns, which are highlighted appropriately.
 Take a look around the source tree for examples.
 
 
+kernel-doc for structs, unions, enums, and typedefs
+---------------------------------------------------
+
+Beside functions you can also write documentation for structs, unions,
+enums and typedefs. Instead of the function name you must write the name
+of the declaration;  the struct/union/enum/typedef must always precede
+the name. Nesting of declarations is not supported.
+Use the argument mechanism to document members or constants.
+
+Inside a struct description, you can use the "private:" and "public:"
+comment tags.  Structure fields that are inside a "private:" area
+are not listed in the generated output documentation.
+
+Example:
+
+/**
+ * struct my_struct - short description
+ * @a: first member
+ * @b: second member
+ *
+ * Longer description
+ */
+struct my_struct {
+    int a;
+    int b;
+/* private: */
+    int c;
+};
+
+
 How to make new SGML template files
 -----------------------------------
 
@@ -147,4 +177,3 @@ documentation, in <filename>, for the functions listed.
 
 Tim.
 */ <twaugh@redhat.com>
-
index bd4ffb5..4117802 100644 (file)
@@ -44,7 +44,7 @@ it.
 /sys/power/image_size controls the size of the image created by
 the suspend-to-disk mechanism.  It can be written a string
 representing a non-negative integer that will be used as an upper
-limit of the image size, in megabytes.  The suspend-to-disk mechanism will
+limit of the image size, in bytes.  The suspend-to-disk mechanism will
 do its best to ensure the image size will not exceed that number.  However,
 if this turns out to be impossible, it will try to suspend anyway using the
 smallest image possible.  In particular, if "0" is written to this file, the
index 08c79d4..b28b7f0 100644 (file)
@@ -27,7 +27,7 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
 
 echo platform > /sys/power/disk; echo disk > /sys/power/state
 
-If you want to limit the suspend image size to N megabytes, do
+If you want to limit the suspend image size to N bytes, do
 
 echo N > /sys/power/image_size
 
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
new file mode 100644 (file)
index 0000000..1284498
--- /dev/null
@@ -0,0 +1,1420 @@
+           Booting the Linux/ppc kernel without Open Firmware
+           --------------------------------------------------
+
+
+(c) 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>,
+    IBM Corp.
+(c) 2005 Becky Bruce <becky.bruce at freescale.com>,
+    Freescale Semiconductor, FSL SOC and 32-bit additions
+
+   May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.
+
+   May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or
+                           clarifies the fact that a lot of things are
+                           optional, the kernel only requires a very
+                           small device tree, though it is encouraged
+                           to provide an as complete one as possible.
+
+   May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM
+                        - Misc fixes
+                        - Define version 3 and new format version 16
+                          for the DT block (version 16 needs kernel
+                          patches, will be fwd separately).
+                          String block now has a size, and full path
+                          is replaced by unit name for more
+                          compactness.
+                          linux,phandle is made optional, only nodes
+                          that are referenced by other nodes need it.
+                          "name" property is now automatically
+                          deduced from the unit name
+
+   June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and
+                           OF_DT_END_NODE in structure definition.
+                         - Change version 16 format to always align
+                           property data to 4 bytes. Since tokens are
+                           already aligned, that means no specific
+                           required alignement between property size
+                           and property data. The old style variable
+                           alignment would make it impossible to do
+                           "simple" insertion of properties using
+                           memove (thanks Milton for
+                           noticing). Updated kernel patch as well
+                        - Correct a few more alignement constraints
+                        - Add a chapter about the device-tree
+                           compiler and the textural representation of
+                           the tree that can be "compiled" by dtc.
+
+
+   November 21, 2005: Rev 0.5
+                        - Additions/generalizations for 32-bit
+                        - Changed to reflect the new arch/powerpc
+                          structure
+                        - Added chapter VI
+
+
+ ToDo:
+       - Add some definitions of interrupt tree (simple/complex)
+       - Add some definitions for pci host bridges
+       - Add some common address format examples
+       - Add definitions for standard properties and "compatible"
+         names for cells that are not already defined by the existing
+         OF spec.
+       - Compare FSL SOC use of PCI to standard and make sure no new
+         node definition required.
+       - Add more information about node definitions for SOC devices
+         that currently have no standard, like the FSL CPM.
+
+
+I - Introduction
+================
+
+During the recent development of the Linux/ppc64 kernel, and more
+specifically, the addition of new platform types outside of the old
+IBM pSeries/iSeries pair, it was decided to enforce some strict rules
+regarding the kernel entry and bootloader <-> kernel interfaces, in
+order to avoid the degeneration that had become the ppc32 kernel entry
+point and the way a new platform should be added to the kernel. The
+legacy iSeries platform breaks those rules as it predates this scheme,
+but no new board support will be accepted in the main tree that
+doesn't follows them properly.  In addition, since the advent of the
+arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit
+platforms and 32-bit platforms which move into arch/powerpc will be
+required to use these rules as well.
+
+The main requirement that will be defined in more detail below is
+the presence of a device-tree whose format is defined after Open
+Firmware specification. However, in order to make life easier
+to embedded board vendors, the kernel doesn't require the device-tree
+to represent every device in the system and only requires some nodes
+and properties to be present. This will be described in detail in
+section III, but, for example, the kernel does not require you to
+create a node for every PCI device in the system. It is a requirement
+to have a node for PCI host bridges in order to provide interrupt
+routing informations and memory/IO ranges, among others. It is also
+recommended to define nodes for on chip devices and other busses that
+don't specifically fit in an existing OF specification. This creates a
+great flexibility in the way the kernel can then probe those and match
+drivers to device, without having to hard code all sorts of tables. It
+also makes it more flexible for board vendors to do minor hardware
+upgrades without significantly impacting the kernel code or cluttering
+it with special cases.
+
+
+1) Entry point for arch/powerpc
+-------------------------------
+
+   There is one and one single entry point to the kernel, at the start
+   of the kernel image. That entry point supports two calling
+   conventions:
+
+        a) Boot from Open Firmware. If your firmware is compatible
+        with Open Firmware (IEEE 1275) or provides an OF compatible
+        client interface API (support for "interpret" callback of
+        forth words isn't required), you can enter the kernel with:
+
+              r5 : OF callback pointer as defined by IEEE 1275
+              bindings to powerpc. Only the 32 bit client interface
+              is currently supported
+
+              r3, r4 : address & length of an initrd if any or 0
+
+              The MMU is either on or off; the kernel will run the
+              trampoline located in arch/powerpc/kernel/prom_init.c to
+              extract the device-tree and other information from open
+              firmware and build a flattened device-tree as described
+              in b). prom_init() will then re-enter the kernel using
+              the second method. This trampoline code runs in the
+              context of the firmware, which is supposed to handle all
+              exceptions during that time.
+
+        b) Direct entry with a flattened device-tree block. This entry
+        point is called by a) after the OF trampoline and can also be
+        called directly by a bootloader that does not support the Open
+        Firmware client interface. It is also used by "kexec" to
+        implement "hot" booting of a new kernel from a previous
+        running one. This method is what I will describe in more
+        details in this document, as method a) is simply standard Open
+        Firmware, and thus should be implemented according to the
+        various standard documents defining it and its binding to the
+        PowerPC platform. The entry point definition then becomes:
+
+                r3 : physical pointer to the device-tree block
+                (defined in chapter II) in RAM
+
+                r4 : physical pointer to the kernel itself. This is
+                used by the assembly code to properly disable the MMU
+                in case you are entering the kernel with MMU enabled
+                and a non-1:1 mapping.
+
+                r5 : NULL (as to differenciate with method a)
+
+        Note about SMP entry: Either your firmware puts your other
+        CPUs in some sleep loop or spin loop in ROM where you can get
+        them out via a soft reset or some other means, in which case
+        you don't need to care, or you'll have to enter the kernel
+        with all CPUs. The way to do that with method b) will be
+        described in a later revision of this document.
+
+
+2) Board support
+----------------
+
+64-bit kernels:
+
+   Board supports (platforms) are not exclusive config options. An
+   arbitrary set of board supports can be built in a single kernel
+   image. The kernel will "know" what set of functions to use for a
+   given platform based on the content of the device-tree. Thus, you
+   should:
+
+        a) add your platform support as a _boolean_ option in
+        arch/powerpc/Kconfig, following the example of PPC_PSERIES,
+        PPC_PMAC and PPC_MAPLE. The later is probably a good
+        example of a board support to start from.
+
+        b) create your main platform file as
+        "arch/powerpc/platforms/myplatform/myboard_setup.c" and add it
+        to the Makefile under the condition of your CONFIG_
+        option. This file will define a structure of type "ppc_md"
+        containing the various callbacks that the generic code will
+        use to get to your platform specific code
+
+        c) Add a reference to your "ppc_md" structure in the
+        "machines" table in arch/powerpc/kernel/setup_64.c if you are
+        a 64-bit platform.
+
+        d) request and get assigned a platform number (see PLATFORM_*
+        constants in include/asm-powerpc/processor.h
+
+32-bit embedded kernels:
+
+  Currently, board support is essentially an exclusive config option.
+  The kernel is configured for a single platform.  Part of the reason
+  for this is to keep kernels on embedded systems small and efficient;
+  part of this is due to the fact the code is already that way. In the
+  future, a kernel may support multiple platforms, but only if the
+  platforms feature the same core architectire.  A single kernel build
+  cannot support both configurations with Book E and configurations
+  with classic Powerpc architectures.
+
+  32-bit embedded platforms that are moved into arch/powerpc using a
+  flattened device tree should adopt the merged tree practice of
+  setting ppc_md up dynamically, even though the kernel is currently
+  built with support for only a single platform at a time.  This allows
+  unification of the setup code, and will make it easier to go to a
+  multiple-platform-support model in the future.
+
+NOTE: I believe the above will be true once Ben's done with the merge
+of the boot sequences.... someone speak up if this is wrong!
+
+  To add a 32-bit embedded platform support, follow the instructions
+  for 64-bit platforms above, with the exception that the Kconfig
+  option should be set up such that the kernel builds exclusively for
+  the platform selected.  The processor type for the platform should
+  enable another config option to select the specific board
+  supported.
+
+NOTE: If ben doesn't merge the setup files, may need to change this to
+point to setup_32.c
+
+
+   I will describe later the boot process and various callbacks that
+   your platform should implement.
+
+
+II - The DT block format
+========================
+
+
+This chapter defines the actual format of the flattened device-tree
+passed to the kernel. The actual content of it and kernel requirements
+are described later. You can find example of code manipulating that
+format in various places, including arch/powerpc/kernel/prom_init.c
+which will generate a flattened device-tree from the Open Firmware
+representation, or the fs2dt utility which is part of the kexec tools
+which will generate one from a filesystem representation. It is
+expected that a bootloader like uboot provides a bit more support,
+that will be discussed later as well.
+
+Note: The block has to be in main memory. It has to be accessible in
+both real mode and virtual mode with no mapping other than main
+memory. If you are writing a simple flash bootloader, it should copy
+the block to RAM before passing it to the kernel.
+
+
+1) Header
+---------
+
+   The kernel is entered with r3 pointing to an area of memory that is
+   roughtly described in include/asm-powerpc/prom.h by the structure
+   boot_param_header:
+
+struct boot_param_header {
+        u32     magic;                  /* magic word OF_DT_HEADER */
+        u32     totalsize;              /* total size of DT block */
+        u32     off_dt_struct;          /* offset to structure */
+        u32     off_dt_strings;         /* offset to strings */
+        u32     off_mem_rsvmap;         /* offset to memory reserve map
+*/
+        u32     version;                /* format version */
+        u32     last_comp_version;      /* last compatible version */
+
+        /* version 2 fields below */
+        u32     boot_cpuid_phys;        /* Which physical CPU id we're
+                                           booting on */
+        /* version 3 fields below */
+        u32     size_dt_strings;        /* size of the strings block */
+};
+
+   Along with the constants:
+
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER            0xd00dfeed      /* 4: version,
+                                                  4: total size */
+#define OF_DT_BEGIN_NODE        0x1             /* Start node: full name
+*/
+#define OF_DT_END_NODE          0x2             /* End node */
+#define OF_DT_PROP              0x3             /* Property: name off,
+                                                   size, content */
+#define OF_DT_END               0x9
+
+   All values in this header are in big endian format, the various
+   fields in this header are defined more precisely below. All
+   "offset" values are in bytes from the start of the header; that is
+   from the value of r3.
+
+   - magic
+
+     This is a magic value that "marks" the beginning of the
+     device-tree block header. It contains the value 0xd00dfeed and is
+     defined by the constant OF_DT_HEADER
+
+   - totalsize
+
+     This is the total size of the DT block including the header. The
+     "DT" block should enclose all data structures defined in this
+     chapter (who are pointed to by offsets in this header). That is,
+     the device-tree structure, strings, and the memory reserve map.
+
+   - off_dt_struct
+
+     This is an offset from the beginning of the header to the start
+     of the "structure" part the device tree. (see 2) device tree)
+
+   - off_dt_strings
+
+     This is an offset from the beginning of the header to the start
+     of the "strings" part of the device-tree
+
+   - off_mem_rsvmap
+
+     This is an offset from the beginning of the header to the start
+     of the reserved memory map. This map is a list of pairs of 64
+     bit integers. Each pair is a physical address and a size. The
+
+     list is terminated by an entry of size 0. This map provides the
+     kernel with a list of physical memory areas that are "reserved"
+     and thus not to be used for memory allocations, especially during
+     early initialization. The kernel needs to allocate memory during
+     boot for things like un-flattening the device-tree, allocating an
+     MMU hash table, etc... Those allocations must be done in such a
+     way to avoid overriding critical things like, on Open Firmware
+     capable machines, the RTAS instance, or on some pSeries, the TCE
+     tables used for the iommu. Typically, the reserve map should
+     contain _at least_ this DT block itself (header,total_size). If
+     you are passing an initrd to the kernel, you should reserve it as
+     well. You do not need to reserve the kernel image itself. The map
+     should be 64 bit aligned.
+
+   - version
+
+     This is the version of this structure. Version 1 stops
+     here. Version 2 adds an additional field boot_cpuid_phys.
+     Version 3 adds the size of the strings block, allowing the kernel
+     to reallocate it easily at boot and free up the unused flattened
+     structure after expansion. Version 16 introduces a new more
+     "compact" format for the tree itself that is however not backward
+     compatible. You should always generate a structure of the highest
+     version defined at the time of your implementation. Currently
+     that is version 16, unless you explicitely aim at being backward
+     compatible.
+
+   - last_comp_version
+
+     Last compatible version. This indicates down to what version of
+     the DT block you are backward compatible. For example, version 2
+     is backward compatible with version 1 (that is, a kernel build
+     for version 1 will be able to boot with a version 2 format). You
+     should put a 1 in this field if you generate a device tree of
+     version 1 to 3, or 0x10 if you generate a tree of version 0x10
+     using the new unit name format.
+
+   - boot_cpuid_phys
+
+     This field only exist on version 2 headers. It indicate which
+     physical CPU ID is calling the kernel entry point. This is used,
+     among others, by kexec. If you are on an SMP system, this value
+     should match the content of the "reg" property of the CPU node in
+     the device-tree corresponding to the CPU calling the kernel entry
+     point (see further chapters for more informations on the required
+     device-tree contents)
+
+
+   So the typical layout of a DT block (though the various parts don't
+   need to be in that order) looks like this (addresses go from top to
+   bottom):
+
+
+             ------------------------------
+       r3 -> |  struct boot_param_header  |
+             ------------------------------
+             |      (alignment gap) (*)   |
+             ------------------------------
+             |      memory reserve map    |
+             ------------------------------
+             |      (alignment gap)       |
+             ------------------------------
+             |                            |
+             |    device-tree structure   |
+             |                            |
+             ------------------------------
+             |      (alignment gap)       |
+             ------------------------------
+             |                            |
+             |     device-tree strings    |
+             |                            |
+      -----> ------------------------------
+      |
+      |
+      --- (r3 + totalsize)
+
+  (*) The alignment gaps are not necessarily present; their presence
+      and size are dependent on the various alignment requirements of
+      the individual data blocks.
+
+
+2) Device tree generalities
+---------------------------
+
+This device-tree itself is separated in two different blocks, a
+structure block and a strings block. Both need to be aligned to a 4
+byte boundary.
+
+First, let's quickly describe the device-tree concept before detailing
+the storage format. This chapter does _not_ describe the detail of the
+required types of nodes & properties for the kernel, this is done
+later in chapter III.
+
+The device-tree layout is strongly inherited from the definition of
+the Open Firmware IEEE 1275 device-tree. It's basically a tree of
+nodes, each node having two or more named properties. A property can
+have a value or not.
+
+It is a tree, so each node has one and only one parent except for the
+root node who has no parent.
+
+A node has 2 names. The actual node name is generally contained in a
+property of type "name" in the node property list whose value is a
+zero terminated string and is mandatory for version 1 to 3 of the
+format definition (as it is in Open Firmware). Version 0x10 makes it
+optional as it can generate it from the unit name defined below.
+
+There is also a "unit name" that is used to differenciate nodes with
+the same name at the same level, it is usually made of the node
+name's, the "@" sign, and a "unit address", which definition is
+specific to the bus type the node sits on.
+
+The unit name doesn't exist as a property per-se but is included in
+the device-tree structure. It is typically used to represent "path" in
+the device-tree. More details about the actual format of these will be
+below.
+
+The kernel powerpc generic code does not make any formal use of the
+unit address (though some board support code may do) so the only real
+requirement here for the unit address is to ensure uniqueness of
+the node unit name at a given level of the tree. Nodes with no notion
+of address and no possible sibling of the same name (like /memory or
+/cpus) may omit the unit address in the context of this specification,
+or use the "@0" default unit address. The unit name is used to define
+a node "full path", which is the concatenation of all parent node
+unit names separated with "/".
+
+The root node doesn't have a defined name, and isn't required to have
+a name property either if you are using version 3 or earlier of the
+format. It also has no unit address (no @ symbol followed by a unit
+address). The root node unit name is thus an empty string. The full
+path to the root node is "/".
+
+Every node which actually represents an actual device (that is, a node
+which isn't only a virtual "container" for more nodes, like "/cpus"
+is) is also required to have a "device_type" property indicating the
+type of node .
+
+Finally, every node that can be referenced from a property in another
+node is required to have a "linux,phandle" property. Real open
+firmware implementations provide a unique "phandle" value for every
+node that the "prom_init()" trampoline code turns into
+"linux,phandle" properties. However, this is made optional if the
+flattened device tree is used directly. An example of a node
+referencing another node via "phandle" is when laying out the
+interrupt tree which will be described in a further version of this
+document.
+
+This "linux, phandle" property is a 32 bit value that uniquely
+identifies a node. You are free to use whatever values or system of
+values, internal pointers, or whatever to generate these, the only
+requirement is that every node for which you provide that property has
+a unique value for it.
+
+Here is an example of a simple device-tree. In this example, an "o"
+designates a node followed by the node unit name. Properties are
+presented with their name followed by their content. "content"
+represents an ASCII string (zero terminated) value, while <content>
+represents a 32 bit hexadecimal value. The various nodes in this
+example will be discussed in a later chapter. At this point, it is
+only meant to give you a idea of what a device-tree looks like. I have
+purposefully kept the "name" and "linux,phandle" properties which
+aren't necessary in order to give you a better idea of what the tree
+looks like in practice.
+
+  / o device-tree
+      |- name = "device-tree"
+      |- model = "MyBoardName"
+      |- compatible = "MyBoardFamilyName"
+      |- #address-cells = <2>
+      |- #size-cells = <2>
+      |- linux,phandle = <0>
+      |
+      o cpus
+      | | - name = "cpus"
+      | | - linux,phandle = <1>
+      | | - #address-cells = <1>
+      | | - #size-cells = <0>
+      | |
+      | o PowerPC,970@0
+      |   |- name = "PowerPC,970"
+      |   |- device_type = "cpu"
+      |   |- reg = <0>
+      |   |- clock-frequency = <5f5e1000>
+      |   |- linux,boot-cpu
+      |   |- linux,phandle = <2>
+      |
+      o memory@0
+      | |- name = "memory"
+      | |- device_type = "memory"
+      | |- reg = <00000000 00000000 00000000 20000000>
+      | |- linux,phandle = <3>
+      |
+      o chosen
+        |- name = "chosen"
+        |- bootargs = "root=/dev/sda2"
+        |- linux,platform = <00000600>
+        |- linux,phandle = <4>
+
+This tree is almost a minimal tree. It pretty much contains the
+minimal set of required nodes and properties to boot a linux kernel;
+that is, some basic model informations at the root, the CPUs, and the
+physical memory layout.  It also includes misc information passed
+through /chosen, like in this example, the platform type (mandatory)
+and the kernel command line arguments (optional).
+
+The /cpus/PowerPC,970@0/linux,boot-cpu property is an example of a
+property without a value. All other properties have a value. The
+significance of the #address-cells and #size-cells properties will be
+explained in chapter IV which defines precisely the required nodes and
+properties and their content.
+
+
+3) Device tree "structure" block
+
+The structure of the device tree is a linearized tree structure. The
+"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE"
+ends that node definition. Child nodes are simply defined before
+"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32
+bit value. The tree has to be "finished" with a OF_DT_END token
+
+Here's the basic structure of a single node:
+
+     * token OF_DT_BEGIN_NODE (that is 0x00000001)
+     * for version 1 to 3, this is the node full path as a zero
+       terminated string, starting with "/". For version 16 and later,
+       this is the node unit name only (or an empty string for the
+       root node)
+     * [align gap to next 4 bytes boundary]
+     * for each property:
+        * token OF_DT_PROP (that is 0x00000003)
+        * 32 bit value of property value size in bytes (or 0 of no
+     * value)
+        * 32 bit value of offset in string block of property name
+        * property value data if any
+        * [align gap to next 4 bytes boundary]
+     * [child nodes if any]
+     * token OF_DT_END_NODE (that is 0x00000002)
+
+So the node content can be summmarised as a start token, a full path,
+a list of properties, a list of child node and an end token. Every
+child node is a full node structure itself as defined above.
+
+4) Device tree 'strings" block
+
+In order to save space, property names, which are generally redundant,
+are stored separately in the "strings" block. This block is simply the
+whole bunch of zero terminated strings for all property names
+concatenated together. The device-tree property definitions in the
+structure block will contain offset values from the beginning of the
+strings block.
+
+
+III - Required content of the device tree
+=========================================
+
+WARNING: All "linux,*" properties defined in this document apply only
+to a flattened device-tree. If your platform uses a real
+implementation of Open Firmware or an implementation compatible with
+the Open Firmware client interface, those properties will be created
+by the trampoline code in the kernel's prom_init() file. For example,
+that's where you'll have to add code to detect your board model and
+set the platform number. However, when using the flatenned device-tree
+entry point, there is no prom_init() pass, and thus you have to
+provide those properties yourself.
+
+
+1) Note about cells and address representation
+----------------------------------------------
+
+The general rule is documented in the various Open Firmware
+documentations. If you chose to describe a bus with the device-tree
+and there exist an OF bus binding, then you should follow the
+specification. However, the kernel does not require every single
+device or bus to be described by the device tree.
+
+In general, the format of an address for a device is defined by the
+parent bus type, based on the #address-cells and #size-cells
+property. In the absence of such a property, the parent's parent
+values are used, etc... The kernel requires the root node to have
+those properties defining addresses format for devices directly mapped
+on the processor bus.
+
+Those 2 properties define 'cells' for representing an address and a
+size. A "cell" is a 32 bit number. For example, if both contain 2
+like the example tree given above, then an address and a size are both
+composed of 2 cells, and each is a 64 bit number (cells are
+concatenated and expected to be in big endian format). Another example
+is the way Apple firmware defines them, with 2 cells for an address
+and one cell for a size.  Most 32-bit implementations should define
+#address-cells and #size-cells to 1, which represents a 32-bit value.
+Some 32-bit processors allow for physical addresses greater than 32
+bits; these processors should define #address-cells as 2.
+
+"reg" properties are always a tuple of the type "address size" where
+the number of cells of address and size is specified by the bus
+#address-cells and #size-cells. When a bus supports various address
+spaces and other flags relative to a given address allocation (like
+prefetchable, etc...) those flags are usually added to the top level
+bits of the physical address. For example, a PCI physical address is
+made of 3 cells, the bottom two containing the actual address itself
+while the top cell contains address space indication, flags, and pci
+bus & device numbers.
+
+For busses that support dynamic allocation, it's the accepted practice
+to then not provide the address in "reg" (keep it 0) though while
+providing a flag indicating the address is dynamically allocated, and
+then, to provide a separate "assigned-addresses" property that
+contains the fully allocated addresses. See the PCI OF bindings for
+details.
+
+In general, a simple bus with no address space bits and no dynamic
+allocation is preferred if it reflects your hardware, as the existing
+kernel address parsing functions will work out of the box. If you
+define a bus type with a more complex address format, including things
+like address space bits, you'll have to add a bus translator to the
+prom_parse.c file of the recent kernels for your bus type.
+
+The "reg" property only defines addresses and sizes (if #size-cells
+is
+non-0) within a given bus. In order to translate addresses upward
+(that is into parent bus addresses, and possibly into cpu physical
+addresses), all busses must contain a "ranges" property. If the
+"ranges" property is missing at a given level, it's assumed that
+translation isn't possible. The format of the "ranges" proprety for a
+bus is a list of:
+
+       bus address, parent bus address, size
+
+"bus address" is in the format of the bus this bus node is defining,
+that is, for a PCI bridge, it would be a PCI address. Thus, (bus
+address, size) defines a range of addresses for child devices. "parent
+bus address" is in the format of the parent bus of this bus. For
+example, for a PCI host controller, that would be a CPU address. For a
+PCI<->ISA bridge, that would be a PCI address. It defines the base
+address in the parent bus where the beginning of that range is mapped.
+
+For a new 64 bit powerpc board, I recommend either the 2/2 format or
+Apple's 2/1 format which is slightly more compact since sizes usually
+fit in a single 32 bit word.   New 32 bit powerpc boards should use a
+1/1 format, unless the processor supports physical addresses greater
+than 32-bits, in which case a 2/1 format is recommended.
+
+
+2) Note about "compatible" properties
+-------------------------------------
+
+These properties are optional, but recommended in devices and the root
+node. The format of a "compatible" property is a list of concatenated
+zero terminated strings. They allow a device to express its
+compatibility with a family of similar devices, in some cases,
+allowing a single driver to match against several devices regardless
+of their actual names.
+
+3) Note about "name" properties
+-------------------------------
+
+While earlier users of Open Firmware like OldWorld macintoshes tended
+to use the actual device name for the "name" property, it's nowadays
+considered a good practice to use a name that is closer to the device
+class (often equal to device_type). For example, nowadays, ethernet
+controllers are named "ethernet", an additional "model" property
+defining precisely the chip type/model, and "compatible" property
+defining the family in case a single driver can driver more than one
+of these chips. However, the kernel doesn't generally put any
+restriction on the "name" property; it is simply considered good
+practice to follow the standard and its evolutions as closely as
+possible.
+
+Note also that the new format version 16 makes the "name" property
+optional. If it's absent for a node, then the node's unit name is then
+used to reconstruct the name. That is, the part of the unit name
+before the "@" sign is used (or the entire unit name if no "@" sign
+is present).
+
+4) Note about node and property names and character set
+-------------------------------------------------------
+
+While open firmware provides more flexibe usage of 8859-1, this
+specification enforces more strict rules. Nodes and properties should
+be comprised only of ASCII characters 'a' to 'z', '0' to
+'9', ',', '.', '_', '+', '#', '?', and '-'. Node names additionally
+allow uppercase characters 'A' to 'Z' (property names should be
+lowercase. The fact that vendors like Apple don't respect this rule is
+irrelevant here). Additionally, node and property names should always
+begin with a character in the range 'a' to 'z' (or 'A' to 'Z' for node
+names).
+
+The maximum number of characters for both nodes and property names
+is 31. In the case of node names, this is only the leftmost part of
+a unit name (the pure "name" property), it doesn't include the unit
+address which can extend beyond that limit.
+
+
+5) Required nodes and properties
+--------------------------------
+  These are all that are currently required. However, it is strongly
+  recommended that you expose PCI host bridges as documented in the
+  PCI binding to open firmware, and your interrupt tree as documented
+  in OF interrupt tree specification.
+
+  a) The root node
+
+  The root node requires some properties to be present:
+
+    - model : this is your board name/model
+    - #address-cells : address representation for "root" devices
+    - #size-cells: the size representation for "root" devices
+
+  Additionally, some recommended properties are:
+
+    - compatible : the board "family" generally finds its way here,
+      for example, if you have 2 board models with a similar layout,
+      that typically get driven by the same platform code in the
+      kernel, you would use a different "model" property but put a
+      value in "compatible". The kernel doesn't directly use that
+      value (see /chosen/linux,platform for how the kernel choses a
+      platform type) but it is generally useful.
+
+  The root node is also generally where you add additional properties
+  specific to your board like the serial number if any, that sort of
+  thing. it is recommended that if you add any "custom" property whose
+  name may clash with standard defined ones, you prefix them with your
+  vendor name and a comma.
+
+  b) The /cpus node
+
+  This node is the parent of all individual CPU nodes. It doesn't
+  have any specific requirements, though it's generally good practice
+  to have at least:
+
+               #address-cells = <00000001>
+               #size-cells    = <00000000>
+
+  This defines that the "address" for a CPU is a single cell, and has
+  no meaningful size. This is not necessary but the kernel will assume
+  that format when reading the "reg" properties of a CPU node, see
+  below
+
+  c) The /cpus/* nodes
+
+  So under /cpus, you are supposed to create a node for every CPU on
+  the machine. There is no specific restriction on the name of the
+  CPU, though It's common practice to call it PowerPC,<name>. For
+  example, Apple uses PowerPC,G5 while IBM uses PowerPC,970FX.
+
+  Required properties:
+
+    - device_type : has to be "cpu"
+    - reg : This is the physical cpu number, it's a single 32 bit cell
+      and is also used as-is as the unit number for constructing the
+      unit name in the full path. For example, with 2 CPUs, you would
+      have the full path:
+        /cpus/PowerPC,970FX@0
+        /cpus/PowerPC,970FX@1
+      (unit addresses do not require leading zeroes)
+    - d-cache-line-size : one cell, L1 data cache line size in bytes
+    - i-cache-line-size : one cell, L1 instruction cache line size in
+      bytes
+    - d-cache-size : one cell, size of L1 data cache in bytes
+    - i-cache-size : one cell, size of L1 instruction cache in bytes
+    - linux, boot-cpu : Should be defined if this cpu is the boot cpu.
+
+  Recommended properties:
+
+    - timebase-frequency : a cell indicating the frequency of the
+      timebase in Hz. This is not directly used by the generic code,
+      but you are welcome to copy/paste the pSeries code for setting
+      the kernel timebase/decrementer calibration based on this
+      value.
+    - clock-frequency : a cell indicating the CPU core clock frequency
+      in Hz. A new property will be defined for 64 bit values, but if
+      your frequency is < 4Ghz, one cell is enough. Here as well as
+      for the above, the common code doesn't use that property, but
+      you are welcome to re-use the pSeries or Maple one. A future
+      kernel version might provide a common function for this.
+
+  You are welcome to add any property you find relevant to your board,
+  like some information about the mechanism used to soft-reset the
+  CPUs. For example, Apple puts the GPIO number for CPU soft reset
+  lines in there as a "soft-reset" property since they start secondary
+  CPUs by soft-resetting them.
+
+
+  d) the /memory node(s)
+
+  To define the physical memory layout of your board, you should
+  create one or more memory node(s). You can either create a single
+  node with all memory ranges in its reg property, or you can create
+  several nodes, as you wish. The unit address (@ part) used for the
+  full path is the address of the first range of memory defined by a
+  given node. If you use a single memory node, this will typically be
+  @0.
+
+  Required properties:
+
+    - device_type : has to be "memory"
+    - reg : This property contains all the physical memory ranges of
+      your board. It's a list of addresses/sizes concatenated
+      together, with the number of cells of each defined by the
+      #address-cells and #size-cells of the root node. For example,
+      with both of these properties beeing 2 like in the example given
+      earlier, a 970 based machine with 6Gb of RAM could typically
+      have a "reg" property here that looks like:
+
+      00000000 00000000 00000000 80000000
+      00000001 00000000 00000001 00000000
+
+      That is a range starting at 0 of 0x80000000 bytes and a range
+      starting at 0x100000000 and of 0x100000000 bytes. You can see
+      that there is no memory covering the IO hole between 2Gb and
+      4Gb. Some vendors prefer splitting those ranges into smaller
+      segments, but the kernel doesn't care.
+
+  e) The /chosen node
+
+  This node is a bit "special". Normally, that's where open firmware
+  puts some variable environment information, like the arguments, or
+  phandle pointers to nodes like the main interrupt controller, or the
+  default input/output devices.
+
+  This specification makes a few of these mandatory, but also defines
+  some linux-specific properties that would be normally constructed by
+  the prom_init() trampoline when booting with an OF client interface,
+  but that you have to provide yourself when using the flattened format.
+
+  Required properties:
+
+    - linux,platform : This is your platform number as assigned by the
+      architecture maintainers
+
+  Recommended properties:
+
+    - bootargs : This zero-terminated string is passed as the kernel
+      command line
+    - linux,stdout-path : This is the full path to your standard
+      console device if any. Typically, if you have serial devices on
+      your board, you may want to put the full path to the one set as
+      the default console in the firmware here, for the kernel to pick
+      it up as it's own default console. If you look at the funciton
+      set_preferred_console() in arch/ppc64/kernel/setup.c, you'll see
+      that the kernel tries to find out the default console and has
+      knowledge of various types like 8250 serial ports. You may want
+      to extend this function to add your own.
+    - interrupt-controller : This is one cell containing a phandle
+      value that matches the "linux,phandle" property of your main
+      interrupt controller node. May be used for interrupt routing.
+
+
+  Note that u-boot creates and fills in the chosen node for platforms
+  that use it.
+
+  f) the /soc<SOCname> node
+
+  This node is used to represent a system-on-a-chip (SOC) and must be
+  present if the processor is a SOC. The top-level soc node contains
+  information that is global to all devices on the SOC. The node name
+  should contain a unit address for the SOC, which is the base address
+  of the memory-mapped register set for the SOC. The name of an soc
+  node should start with "soc", and the remainder of the name should
+  represent the part number for the soc.  For example, the MPC8540's
+  soc node would be called "soc8540".
+
+  Required properties:
+
+    - device_type : Should be "soc"
+    - ranges : Should be defined as specified in 1) to describe the
+      translation of SOC addresses for memory mapped SOC registers.
+
+  Recommended properties:
+
+    - reg : This property defines the address and size of the
+      memory-mapped registers that are used for the SOC node itself.
+      It does not include the child device registers - these will be
+      defined inside each child node.  The address specified in the
+      "reg" property should match the unit address of the SOC node.
+    - #address-cells : Address representation for "soc" devices.  The
+      format of this field may vary depending on whether or not the
+      device registers are memory mapped.  For memory mapped
+      registers, this field represents the number of cells needed to
+      represent the address of the registers.  For SOCs that do not
+      use MMIO, a special address format should be defined that
+      contains enough cells to represent the required information.
+      See 1) above for more details on defining #address-cells.
+    - #size-cells : Size representation for "soc" devices
+    - #interrupt-cells : Defines the width of cells used to represent
+       interrupts.  Typically this value is <2>, which includes a
+       32-bit number that represents the interrupt number, and a
+       32-bit number that represents the interrupt sense and level.
+       This field is only needed if the SOC contains an interrupt
+       controller.
+
+  The SOC node may contain child nodes for each SOC device that the
+  platform uses.  Nodes should not be created for devices which exist
+  on the SOC but are not used by a particular platform. See chapter VI
+  for more information on how to specify devices that are part of an
+SOC.
+
+  Example SOC node for the MPC8540:
+
+       soc8540@e0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <00000000 e0000000 00100000>
+               reg = <e0000000 00003000>;
+       }
+
+
+
+IV - "dtc", the device tree compiler
+====================================
+
+
+dtc source code can be found at
+<http://ozlabs.org/~dgibson/dtc/dtc.tar.gz>
+
+WARNING: This version is still in early development stage; the
+resulting device-tree "blobs" have not yet been validated with the
+kernel. The current generated bloc lacks a useful reserve map (it will
+be fixed to generate an empty one, it's up to the bootloader to fill
+it up) among others. The error handling needs work, bugs are lurking,
+etc...
+
+dtc basically takes a device-tree in a given format and outputs a
+device-tree in another format. The currently supported formats are:
+
+  Input formats:
+  -------------
+
+     - "dtb": "blob" format, that is a flattened device-tree block
+       with
+        header all in a binary blob.
+     - "dts": "source" format. This is a text file containing a
+       "source" for a device-tree. The format is defined later in this
+        chapter.
+     - "fs" format. This is a representation equivalent to the
+        output of /proc/device-tree, that is nodes are directories and
+       properties are files
+
+ Output formats:
+ ---------------
+
+     - "dtb": "blob" format
+     - "dts": "source" format
+     - "asm": assembly language file. This is a file that can be
+       sourced by gas to generate a device-tree "blob". That file can
+       then simply be added to your Makefile. Additionally, the
+       assembly file exports some symbols that can be use
+
+
+The syntax of the dtc tool is
+
+    dtc [-I <input-format>] [-O <output-format>]
+        [-o output-filename] [-V output_version] input_filename
+
+
+The "output_version" defines what versio of the "blob" format will be
+generated. Supported versions are 1,2,3 and 16. The default is
+currently version 3 but that may change in the future to version 16.
+
+Additionally, dtc performs various sanity checks on the tree, like the
+uniqueness of linux,phandle properties, validity of strings, etc...
+
+The format of the .dts "source" file is "C" like, supports C and C++
+style commments.
+
+/ {
+}
+
+The above is the "device-tree" definition. It's the only statement
+supported currently at the toplevel.
+
+/ {
+  property1 = "string_value";  /* define a property containing a 0
+                                 * terminated string
+                                */
+
+  property2 = <1234abcd>;      /* define a property containing a
+                                 * numerical 32 bits value (hexadecimal)
+                                */
+
+  property3 = <12345678 12345678 deadbeef>;
+                                /* define a property containing 3
+                                 * numerical 32 bits values (cells) in
+                                 * hexadecimal
+                                */
+  property4 = [0a 0b 0c 0d de ea ad be ef];
+                                /* define a property whose content is
+                                 * an arbitrary array of bytes
+                                 */
+
+  childnode@addresss { /* define a child node named "childnode"
+                                 * whose unit name is "childnode at
+                                * address"
+                                 */
+
+    childprop = "hello\n";      /* define a property "childprop" of
+                                 * childnode (in this case, a string)
+                                 */
+  };
+};
+
+Nodes can contain other nodes etc... thus defining the hierarchical
+structure of the tree.
+
+Strings support common escape sequences from C: "\n", "\t", "\r",
+"\(octal value)", "\x(hex value)".
+
+It is also suggested that you pipe your source file through cpp (gcc
+preprocessor) so you can use #include's, #define for constants, etc...
+
+Finally, various options are planned but not yet implemented, like
+automatic generation of phandles, labels (exported to the asm file so
+you can point to a property content and change it easily from whatever
+you link the device-tree with), label or path instead of numeric value
+in some cells to "point" to a node (replaced by a phandle at compile
+time), export of reserve map address to the asm file, ability to
+specify reserve map content at compile time, etc...
+
+We may provide a .h include file with common definitions of that
+proves useful for some properties (like building PCI properties or
+interrupt maps) though it may be better to add a notion of struct
+definitions to the compiler...
+
+
+V - Recommendations for a bootloader
+====================================
+
+
+Here are some various ideas/recommendations that have been proposed
+while all this has been defined and implemented.
+
+  - The bootloader may want to be able to use the device-tree itself
+    and may want to manipulate it (to add/edit some properties,
+    like physical memory size or kernel arguments). At this point, 2
+    choices can be made. Either the bootloader works directly on the
+    flattened format, or the bootloader has its own internal tree
+    representation with pointers (similar to the kernel one) and
+    re-flattens the tree when booting the kernel. The former is a bit
+    more difficult to edit/modify, the later requires probably a bit
+    more code to handle the tree structure. Note that the structure
+    format has been designed so it's relatively easy to "insert"
+    properties or nodes or delete them by just memmoving things
+    around. It contains no internal offsets or pointers for this
+    purpose.
+
+  - An example of code for iterating nodes & retreiving properties
+    directly from the flattened tree format can be found in the kernel
+    file arch/ppc64/kernel/prom.c, look at scan_flat_dt() function,
+    it's usage in early_init_devtree(), and the corresponding various
+    early_init_dt_scan_*() callbacks. That code can be re-used in a
+    GPL bootloader, and as the author of that code, I would be happy
+    do discuss possible free licencing to any vendor who wishes to
+    integrate all or part of this code into a non-GPL bootloader.
+
+
+
+VI - System-on-a-chip devices and nodes
+=======================================
+
+Many companies are now starting to develop system-on-a-chip
+processors, where the processor core (cpu) and many peripheral devices
+exist on a single piece of silicon.  For these SOCs, an SOC node
+should be used that defines child nodes for the devices that make
+up the SOC. While platforms are not required to use this model in
+order to boot the kernel, it is highly encouraged that all SOC
+implementations define as complete a flat-device-tree as possible to
+describe the devices on the SOC.  This will allow for the
+genericization of much of the kernel code.
+
+
+1) Defining child nodes of an SOC
+---------------------------------
+
+Each device that is part of an SOC may have its own node entry inside
+the SOC node.  For each device that is included in the SOC, the unit
+address property represents the address offset for this device's
+memory-mapped registers in the parent's address space.  The parent's
+address space is defined by the "ranges" property in the top-level soc
+node. The "reg" property for each node that exists directly under the
+SOC node should contain the address mapping from the child address space
+to the parent SOC address space and the size of the device's
+memory-mapped register file.
+
+For many devices that may exist inside an SOC, there are predefined
+specifications for the format of the device tree node.  All SOC child
+nodes should follow these specifications, except where noted in this
+document.
+
+See appendix A for an example partial SOC node definition for the
+MPC8540.
+
+
+2) Specifying interrupt information for SOC devices
+---------------------------------------------------
+
+Each device that is part of an SOC and which generates interrupts
+should have the following properties:
+
+       - interrupt-parent : contains the phandle of the interrupt
+          controller which handles interrupts for this device
+       - interrupts : a list of tuples representing the interrupt
+          number and the interrupt sense and level for each interupt
+          for this device.
+
+This information is used by the kernel to build the interrupt table
+for the interrupt controllers in the system.
+
+Sense and level information should be encoded as follows:
+
+   Devices connected to openPIC-compatible controllers should encode
+   sense and polarity as follows:
+
+       0 = high to low edge sensitive type enabled
+       1 = active low level sensitive type enabled
+       2 = low to high edge sensitive type enabled
+       3 = active high level sensitive type enabled
+
+   ISA PIC interrupt controllers should adhere to the ISA PIC
+   encodings listed below:
+
+       0 =  active low level sensitive type enabled
+       1 =  active high level sensitive type enabled
+       2 =  high to low edge sensitive type enabled
+       3 =  low to high edge sensitive type enabled
+
+
+
+3) Representing devices without a current OF specification
+----------------------------------------------------------
+
+Currently, there are many devices on SOCs that do not have a standard
+representation pre-defined as part of the open firmware
+specifications, mainly because the boards that contain these SOCs are
+not currently booted using open firmware.   This section contains
+descriptions for the SOC devices for which new nodes have been
+defined; this list will expand as more and more SOC-containing
+platforms are moved over to use the flattened-device-tree model.
+
+  a) MDIO IO device
+
+  The MDIO is a bus to which the PHY devices are connected.  For each
+  device that exists on this bus, a child node should be created.  See
+  the definition of the PHY node below for an example of how to define
+  a PHY.
+
+  Required properties:
+    - reg : Offset and length of the register set for the device
+    - device_type : Should be "mdio"
+    - compatible : Should define the compatible device type for the
+      mdio.  Currently, this is most likely to be "gianfar"
+
+  Example:
+
+       mdio@24520 {
+               reg = <24520 20>;
+
+               ethernet-phy@0 {
+                       ......
+               };
+       };
+
+
+  b) Gianfar-compatible ethernet nodes
+
+  Required properties:
+
+    - device_type : Should be "network"
+    - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
+    - compatible : Should be "gianfar"
+    - reg : Offset and length of the register set for the device
+    - address : List of bytes representing the ethernet address of
+      this controller
+    - interrupts : <a b> where a is the interrupt number and b is a
+      field that represents an encoding of the sense and level
+      information for the interrupt.  This should be encoded based on
+      the information in section 2) depending on the type of interrupt
+      controller you have.
+    - interrupt-parent : the phandle for the interrupt controller that
+      services interrupts for this device.
+    - phy-handle : The phandle for the PHY connected to this ethernet
+      controller.
+
+  Example:
+
+       ethernet@24000 {
+               #size-cells = <0>;
+               device_type = "network";
+               model = "TSEC";
+               compatible = "gianfar";
+               reg = <24000 1000>;
+               address = [ 00 E0 0C 00 73 00 ];
+               interrupts = <d 3 e 3 12 3>;
+               interrupt-parent = <40000>;
+               phy-handle = <2452000>
+       };
+
+
+
+   c) PHY nodes
+
+   Required properties:
+
+    - device_type : Should be "ethernet-phy"
+    - interrupts : <a b> where a is the interrupt number and b is a
+      field that represents an encoding of the sense and level
+      information for the interrupt.  This should be encoded based on
+      the information in section 2) depending on the type of interrupt
+      controller you have.
+    - interrupt-parent : the phandle for the interrupt controller that
+      services interrupts for this device.
+    - reg : The ID number for the phy, usually a small integer
+    - linux,phandle :  phandle for this node; likely referenced by an
+      ethernet controller node.
+
+
+   Example:
+
+       ethernet-phy@0 {
+               linux,phandle = <2452000>
+               interrupt-parent = <40000>;
+               interrupts = <35 1>;
+               reg = <0>;
+               device_type = "ethernet-phy";
+       };
+
+
+   d) Interrupt controllers
+
+   Some SOC devices contain interrupt controllers that are different
+   from the standard Open PIC specification.  The SOC device nodes for
+   these types of controllers should be specified just like a standard
+   OpenPIC controller.  Sense and level information should be encoded
+   as specified in section 2) of this chapter for each device that
+   specifies an interrupt.
+
+   Example :
+
+       pic@40000 {
+               linux,phandle = <40000>;
+               clock-frequency = <0>;
+               interrupt-controller;
+               #address-cells = <0>;
+               reg = <40000 40000>;
+               built-in;
+               compatible = "chrp,open-pic";
+               device_type = "open-pic";
+               big-endian;
+       };
+
+
+   e) I2C
+
+   Required properties :
+
+    - device_type : Should be "i2c"
+    - reg : Offset and length of the register set for the device
+
+   Recommended properties :
+
+    - compatible : Should be "fsl-i2c" for parts compatible with
+      Freescale I2C specifications.
+    - interrupts : <a b> where a is the interrupt number and b is a
+      field that represents an encoding of the sense and level
+      information for the interrupt.  This should be encoded based on
+      the information in section 2) depending on the type of interrupt
+      controller you have.
+    - interrupt-parent : the phandle for the interrupt controller that
+      services interrupts for this device.
+    - dfsrr : boolean; if defined, indicates that this I2C device has
+      a digital filter sampling rate register
+    - fsl5200-clocking : boolean; if defined, indicated that this device
+      uses the FSL 5200 clocking mechanism.
+
+   Example :
+
+       i2c@3000 {
+               interrupt-parent = <40000>;
+               interrupts = <1b 3>;
+               reg = <3000 18>;
+               device_type = "i2c";
+               compatible  = "fsl-i2c";
+               dfsrr;
+       };
+
+
+   More devices will be defined as this spec matures.
+
+
+Appendix A - Sample SOC node for MPC8540
+========================================
+
+Note that the #address-cells and #size-cells for the SoC node
+in this example have been explicitly listed; these are likely
+not necessary as they are usually the same as the root node.
+
+       soc8540@e0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <00000000 e0000000 00100000>
+               reg = <e0000000 00003000>;
+
+               mdio@24520 {
+                       reg = <24520 20>;
+                       device_type = "mdio";
+                       compatible = "gianfar";
+
+                       ethernet-phy@0 {
+                               linux,phandle = <2452000>
+                               interrupt-parent = <40000>;
+                               interrupts = <35 1>;
+                               reg = <0>;
+                               device_type = "ethernet-phy";
+                       };
+
+                       ethernet-phy@1 {
+                               linux,phandle = <2452001>
+                               interrupt-parent = <40000>;
+                               interrupts = <35 1>;
+                               reg = <1>;
+                               device_type = "ethernet-phy";
+                       };
+
+                       ethernet-phy@3 {
+                               linux,phandle = <2452002>
+                               interrupt-parent = <40000>;
+                               interrupts = <35 1>;
+                               reg = <3>;
+                               device_type = "ethernet-phy";
+                       };
+
+               };
+
+               ethernet@24000 {
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <24000 1000>;
+                       address = [ 00 E0 0C 00 73 00 ];
+                       interrupts = <d 3 e 3 12 3>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452000>;
+               };
+
+               ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <25000 1000>;
+                       address = [ 00 E0 0C 00 73 01 ];
+                       interrupts = <13 3 14 3 18 3>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+
+               ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "FEC";
+                       compatible = "gianfar";
+                       reg = <26000 1000>;
+                       address = [ 00 E0 0C 00 73 02 ];
+                       interrupts = <19 3>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452002>;
+               };
+
+               serial@4500 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4500 100>;
+                       clock-frequency = <0>;
+                       interrupts = <1a 3>;
+                       interrupt-parent = <40000>;
+               };
+
+               pic@40000 {
+                       linux,phandle = <40000>;
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       reg = <40000 40000>;
+                       built-in;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                        big-endian;
+               };
+
+               i2c@3000 {
+                       interrupt-parent = <40000>;
+                       interrupts = <1b 3>;
+                       reg = <3000 18>;
+                       device_type = "i2c";
+                       compatible  = "fsl-i2c";
+                       dfsrr;
+               };
+
+       };
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
new file mode 100644 (file)
index 0000000..f8c16cb
--- /dev/null
@@ -0,0 +1,24 @@
+1 Release Date    : Mon Jan 23 14:09:01 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.02.02
+3 Older Version   : 00.00.02.01 
+
+i.     New template defined to represent each family of controllers (identified by processor used). 
+       The template will have defintions that will be initialised to appropritae values for a specific family of controllers. The template definition has four function pointers. During driver initialisation the function pointers will be set based on the controller family type. This change is done to support new controllers that has different processors and thus different register set.
+
+               -Sumant Patro <Sumant.Patro@lsil.com>
+
+1 Release Date    : Mon Dec 19 14:36:26 PST 2005 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.02.00-rc4 
+3 Older Version   : 00.00.02.01 
+
+i.     Code reorganized to remove code duplication in megasas_build_cmd. 
+
+       "There's a lot of duplicate code megasas_build_cmd.  Move that out of the different codepathes and merge the reminder of megasas_build_cmd into megasas_queue_command"
+
+               - Christoph Hellwig <hch@lst.de>
+
+ii.    Defined MEGASAS_IOC_FIRMWARE32 for code paths that handles 32 bit applications in 64 bit systems.
+
+       "MEGASAS_IOC_FIRMWARE can't be redefined if CONFIG_COMPAT is set, we need to define a MEGASAS_IOC_FIRMWARE32 define so native binaries continue to work"
+
+               - Christoph Hellwig <hch@lst.de>
index 0aeef74..382b439 100644 (file)
@@ -1,5 +1,5 @@
 ====================================================================
-=             Adaptec Ultra320 Family Manager Set v1.3.11          =
+=             Adaptec Ultra320 Family Manager Set                  =
 =                                                                  =
 =                            README for                            =
 =                    The Linux Operating System                    =
@@ -63,6 +63,11 @@ The following information is available in this file:
                               68-pin)
 2. Version History
 
+   3.0   (December 1st, 2005)
+       - Updated driver to use SCSI transport class infrastructure
+       - Upported sequencer and core fixes from adaptec released
+         version 2.0.15 of the driver.
+
    1.3.11 (July 11, 2003)
         - Fix several deadlock issues.
         - Add 29320ALP and 39320B Id's.
@@ -194,7 +199,7 @@ The following information is available in this file:
           supported)
         - Support for the PCI-X standard up to 133MHz
         - Support for the PCI v2.2 standard
-       - Domain Validation
+        - Domain Validation
 
    2.2. Operating System Support:
         - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1
@@ -411,77 +416,53 @@ The following information is available in this file:
           http://www.adaptec.com.
 
 
-5. Contacting Adaptec
+5. Adaptec Customer Support
 
    A Technical Support Identification (TSID) Number is required for 
    Adaptec technical support.
     - The 12-digit TSID can be found on the white barcode-type label
-      included inside the box with your product. The TSID helps us 
+      included inside the box with your product.  The TSID helps us 
       provide more efficient service by accurately identifying your 
       product and support status.
+
    Support Options
     - Search the Adaptec Support Knowledgebase (ASK) at
       http://ask.adaptec.com for articles, troubleshooting tips, and
-      frequently asked questions for your product.
+      frequently asked questions about your product.
     - For support via Email, submit your question to Adaptec's 
-      Technical Support Specialists at http://ask.adaptec.com.
+      Technical Support Specialists at http://ask.adaptec.com/.
      
    North America
-    - Visit our Web site at http://www.adaptec.com.
-    - To speak with a Fibre Channel/RAID/External Storage Technical
-      Support Specialist, call 1-321-207-2000,
-      Hours: Monday-Friday, 3:00 A.M. to 5:00 P.M., PST.
-      (Not open on holidays)
-    - For Technical Support in all other technologies including 
-      SCSI, call 1-408-934-7274,
-      Hours: Monday-Friday, 6:00 A.M. to 5:00 P.M., PST.
-      (Not open on holidays)
-    - For after hours support, call 1-800-416-8066 ($99/call, 
-      $149/call on holidays)
-    - To order Adaptec products including software and cables, call
-      1-800-442-7274 or 1-408-957-7274. You can also visit our 
-      online store at http://www.adaptecstore.com
+    - Visit our Web site at http://www.adaptec.com/.
+    - For information about Adaptec's support options, call
+      408-957-2550, 24 hours a day, 7 days a week.
+    - To speak with a Technical Support Specialist,
+      * For hardware products, call 408-934-7274,
+        Monday to Friday, 3:00 am to 5:00 pm, PDT.
+      * For RAID and Fibre Channel products, call 321-207-2000,
+        Monday to Friday, 3:00 am to 5:00 pm, PDT.
+      To expedite your service, have your computer with you.
+    - To order Adaptec products, including accessories and cables,
+      call 408-957-7274.  To order cables online go to
+      http://www.adaptec.com/buy-cables/.
 
    Europe
-    - Visit our Web site at http://www.adaptec-europe.com.
-    - English and French: To speak with a Technical Support 
-      Specialist, call one of the following numbers:
-        - English: +32-2-352-3470
-        - French:  +32-2-352-3460
-      Hours: Monday-Thursday, 10:00 to 12:30, 13:30 to 17:30 CET 
-             Friday, 10:00 to 12:30, 13:30 to 16:30 CET
-    - German: To speak with a Technical Support Specialist,
-      call +49-89-456-40660
-      Hours: Monday-Thursday, 09:30 to 12:30, 13:30 to 16:30 CET
-             Friday, 09:30 to 12:30, 13:30 to 15:00 CET
-    - To order Adaptec products, including accessories and cables:
-        - UK: +0800-96-65-26 or fax +0800-731-02-95
-        - Other European countries: +32-11-300-379
-
-   Australia and New Zealand
-    - Visit our Web site at http://www.adaptec.com.au.
-    - To speak with a Technical Support Specialist, call 
-      +612-9416-0698
-      Hours: Monday-Friday, 10:00 A.M. to 4:30 P.M., EAT
-      (Not open on holidays)
+    - Visit our Web site at http://www.adaptec-europe.com/.
+    - To speak with a Technical Support Specialist, call, or email,
+      * German:  +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET,
+        http://ask-de.adaptec.com/.
+      * French:  +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET,
+       http://ask-fr.adaptec.com/.
+      * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT,
+       http://ask.adaptec.com/.
+    - You can order Adaptec cables online at
+      http://www.adaptec.com/buy-cables/.
 
    Japan
+    - Visit our web site at http://www.adaptec.co.jp/.
     - To speak with a Technical Support Specialist, call 
-      +81-3-5308-6120 
-      Hours: Monday-Friday, 9:00 a.m. to 12:00 p.m., 1:00 p.m. to
-      6:00 p.m. TSC
-
-   Hong Kong and China
-    - To speak with a Technical Support Specialist, call 
-      +852-2869-7200
-      Hours: Monday-Friday, 10:00 to 17:00.
-    - Fax Technical Support at +852-2869-7100.
-
-   Singapore
-    - To speak with a Technical Support Specialist, call 
-      +65-245-7470
-      Hours: Monday-Friday, 10:00 to 17:00.
-    - Fax Technical Support at +852-2869-7100
+      +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m.,
+      1:00 p.m. to 6:00 p.m.
 
 -------------------------------------------------------------------
 /*
index 47e74dd..3481fcd 100644 (file)
@@ -309,81 +309,57 @@ The following information is available in this file:
    -----------------------------------------------------------------
 
    Example:
-   'options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1"
+   'options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1'
         enables verbose logging, Disable EISA/VLB probing,
         and set tag depth on Controller 1/Target 2 to 10 tags.
 
-3. Contacting Adaptec
+4. Adaptec Customer Support
 
    A Technical Support Identification (TSID) Number is required for 
    Adaptec technical support.
     - The 12-digit TSID can be found on the white barcode-type label
-      included inside the box with your product. The TSID helps us 
+      included inside the box with your product.  The TSID helps us 
       provide more efficient service by accurately identifying your 
       product and support status.
+
    Support Options
     - Search the Adaptec Support Knowledgebase (ASK) at
       http://ask.adaptec.com for articles, troubleshooting tips, and
-      frequently asked questions for your product.
+      frequently asked questions about your product.
     - For support via Email, submit your question to Adaptec's 
-      Technical Support Specialists at http://ask.adaptec.com.
+      Technical Support Specialists at http://ask.adaptec.com/.
      
    North America
-    - Visit our Web site at http://www.adaptec.com.
-    - To speak with a Fibre Channel/RAID/External Storage Technical
-      Support Specialist, call 1-321-207-2000,
-      Hours: Monday-Friday, 3:00 A.M. to 5:00 P.M., PST.
-      (Not open on holidays)
-    - For Technical Support in all other technologies including 
-      SCSI, call 1-408-934-7274,
-      Hours: Monday-Friday, 6:00 A.M. to 5:00 P.M., PST.
-      (Not open on holidays)
-    - For after hours support, call 1-800-416-8066 ($99/call, 
-      $149/call on holidays)
-    - To order Adaptec products including software and cables, call
-      1-800-442-7274 or 1-408-957-7274. You can also visit our 
-      online store at http://www.adaptecstore.com
+    - Visit our Web site at http://www.adaptec.com/.
+    - For information about Adaptec's support options, call
+      408-957-2550, 24 hours a day, 7 days a week.
+    - To speak with a Technical Support Specialist,
+      * For hardware products, call 408-934-7274,
+        Monday to Friday, 3:00 am to 5:00 pm, PDT.
+      * For RAID and Fibre Channel products, call 321-207-2000,
+        Monday to Friday, 3:00 am to 5:00 pm, PDT.
+      To expedite your service, have your computer with you.
+    - To order Adaptec products, including accessories and cables,
+      call 408-957-7274.  To order cables online go to
+      http://www.adaptec.com/buy-cables/.
 
    Europe
-    - Visit our Web site at http://www.adaptec-europe.com.
-    - English and French: To speak with a Technical Support 
-      Specialist, call one of the following numbers:
-        - English: +32-2-352-3470
-        - French:  +32-2-352-3460
-      Hours: Monday-Thursday, 10:00 to 12:30, 13:30 to 17:30 CET 
-             Friday, 10:00 to 12:30, 13:30 to 16:30 CET
-    - German: To speak with a Technical Support Specialist,
-      call +49-89-456-40660
-      Hours: Monday-Thursday, 09:30 to 12:30, 13:30 to 16:30 CET
-             Friday, 09:30 to 12:30, 13:30 to 15:00 CET
-    - To order Adaptec products, including accessories and cables:
-        - UK: +0800-96-65-26 or fax +0800-731-02-95
-        - Other European countries: +32-11-300-379
-
-   Australia and New Zealand
-    - Visit our Web site at http://www.adaptec.com.au.
-    - To speak with a Technical Support Specialist, call 
-      +612-9416-0698
-      Hours: Monday-Friday, 10:00 A.M. to 4:30 P.M., EAT
-      (Not open on holidays)
+    - Visit our Web site at http://www.adaptec-europe.com/.
+    - To speak with a Technical Support Specialist, call, or email,
+      * German:  +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET,
+        http://ask-de.adaptec.com/.
+      * French:  +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET,
+       http://ask-fr.adaptec.com/.
+      * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT,
+       http://ask.adaptec.com/.
+    - You can order Adaptec cables online at
+      http://www.adaptec.com/buy-cables/.
 
    Japan
+    - Visit our web site at http://www.adaptec.co.jp/.
     - To speak with a Technical Support Specialist, call 
-      +81-3-5308-6120 
-      Hours: Monday-Friday, 9:00 a.m. to 12:00 p.m., 1:00 p.m. to
-      6:00 p.m. TSC
-
-   Hong Kong and China
-    - To speak with a Technical Support Specialist, call 
-      +852-2869-7200
-      Hours: Monday-Friday, 10:00 to 17:00.
-    - Fax Technical Support at +852-2869-7100.
-
-   Singapore
-    - To speak with a Technical Support Specialist, call 
-      +65-245-7470
-      Hours: Monday-Friday, 10:00 to 17:00.
-    - Fax Technical Support at +852-2869-7100
+      +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m.,
+      1:00 p.m. to 6:00 p.m.
 
 -------------------------------------------------------------------
 /*
index 391dd64..a46c10f 100644 (file)
@@ -28,6 +28,7 @@ Currently, these files are in /proc/sys/vm:
 - block_dump
 - drop-caches
 - zone_reclaim_mode
+- zone_reclaim_interval
 
 ==============================================================
 
@@ -126,15 +127,54 @@ the high water marks for each per cpu page list.
 
 zone_reclaim_mode:
 
-This is set during bootup to 1 if it is determined that pages from
-remote zones will cause a significant performance reduction. The
+Zone_reclaim_mode allows to set more or less agressive approaches to
+reclaim memory when a zone runs out of memory. If it is set to zero then no
+zone reclaim occurs. Allocations will be satisfied from other zones / nodes
+in the system.
+
+This is value ORed together of
+
+1      = Zone reclaim on
+2      = Zone reclaim writes dirty pages out
+4      = Zone reclaim swaps pages
+8      = Also do a global slab reclaim pass
+
+zone_reclaim_mode is set during bootup to 1 if it is determined that pages
+from remote zones will cause a measurable performance reduction. The
 page allocator will then reclaim easily reusable pages (those page
-cache pages that are currently not used) before going off node.
+cache pages that are currently not used) before allocating off node pages.
+
+It may be beneficial to switch off zone reclaim if the system is
+used for a file server and all of memory should be used for caching files
+from disk. In that case the caching effect is more important than
+data locality.
+
+Allowing zone reclaim to write out pages stops processes that are
+writing large amounts of data from dirtying pages on other nodes. Zone
+reclaim will write out dirty pages if a zone fills up and so effectively
+throttle the process. This may decrease the performance of a single process
+since it cannot use all of system memory to buffer the outgoing writes
+anymore but it preserve the memory on other nodes so that the performance
+of other processes running on other nodes will not be affected.
+
+Allowing regular swap effectively restricts allocations to the local
+node unless explicitly overridden by memory policies or cpuset
+configurations.
+
+It may be advisable to allow slab reclaim if the system makes heavy
+use of files and builds up large slab caches. However, the slab
+shrink operation is global, may take a long time and free slabs
+in all nodes of the system.
+
+================================================================
+
+zone_reclaim_interval:
+
+The time allowed for off node allocations after zone reclaim
+has failed to reclaim enough pages to allow a local allocation.
 
-The user can override this setting. It may be beneficial to switch
-off zone reclaim if the system is used for a file server and all
-of memory should be used for caching files from disk.
+Time is set in seconds and set by default to 30 seconds.
 
-It may be beneficial to switch this on if one wants to do zone
-reclaim regardless of the numa distances in the system.
+Reduce the interval if undesired off node allocations occur. However, too
+frequent scans will have a negative impact onoff node allocation performance.
 
diff --git a/Documentation/usb/et61x251.txt b/Documentation/usb/et61x251.txt
new file mode 100644 (file)
index 0000000..b44dda4
--- /dev/null
@@ -0,0 +1,306 @@
+
+                       ET61X[12]51 PC Camera Controllers
+                                Driver for Linux
+                       =================================
+
+                               - Documentation -
+
+
+Index
+=====
+1.  Copyright
+2.  Disclaimer
+3.  License
+4.  Overview and features
+5.  Module dependencies
+6.  Module loading
+7.  Module parameters
+8.  Optional device control through "sysfs"
+9.  Supported devices
+10. Notes for V4L2 application developers
+11. Contact information
+
+
+1. Copyright
+============
+Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>
+
+
+2. Disclaimer
+=============
+Etoms is a trademark of Etoms Electronics Corp.
+This software is not developed or sponsored by Etoms Electronics.
+
+
+3. License
+==========
+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.
+
+
+4. Overview and features
+========================
+This driver supports the video interface of the devices mounting the ET61X151
+or ET61X251 PC Camera Controllers.
+
+It's worth to note that Etoms Electronics has never collaborated with the
+author during the development of this project; despite several requests,
+Etoms Electronics also refused to release enough detailed specifications of
+the video compression engine.
+
+The driver relies on the Video4Linux2 and USB core modules. It has been
+designed to run properly on SMP systems as well.
+
+The latest version of the ET61X[12]51 driver can be found at the following URL:
+http://www.linux-projects.org/
+
+Some of the features of the driver are:
+
+- full compliance with the Video4Linux2 API (see also "Notes for V4L2
+  application developers" paragraph);
+- available mmap or read/poll methods for video streaming through isochronous
+  data transfers;
+- automatic detection of image sensor;
+- support for any window resolutions and optional panning within the maximum
+  pixel area of image sensor;
+- image downscaling with arbitrary scaling factors from 1 and 2 in both
+  directions (see "Notes for V4L2 application developers" paragraph);
+- two different video formats for uncompressed or compressed data in low or
+  high compression quality (see also "Notes for V4L2 application developers"
+  paragraph);
+- full support for the capabilities of every possible image sensors that can
+  be connected to the ET61X[12]51 bridges, including, for istance, red, green,
+  blue and global gain adjustments and exposure control (see "Supported
+  devices" paragraph for details);
+- use of default color settings for sunlight conditions;
+- dynamic I/O interface for both ET61X[12]51 and image sensor control (see
+  "Optional device control through 'sysfs'" paragraph);
+- dynamic driver control thanks to various module parameters (see "Module
+  parameters" paragraph);
+- up to 64 cameras can be handled at the same time; they can be connected and
+  disconnected from the host many times without turning off the computer, if
+  the system supports hotplugging;
+- no known bugs.
+
+
+5. Module dependencies
+======================
+For it to work properly, the driver needs kernel support for Video4Linux and
+USB.
+
+The following options of the kernel configuration file must be enabled and
+corresponding modules must be compiled:
+
+       # Multimedia devices
+       #
+       CONFIG_VIDEO_DEV=m
+
+To enable advanced debugging functionality on the device through /sysfs:
+
+       # Multimedia devices
+       #
+       CONFIG_VIDEO_ADV_DEBUG=y
+
+       # USB support
+       #
+       CONFIG_USB=m
+
+In addition, depending on the hardware being used, the modules below are
+necessary:
+
+       # USB Host Controller Drivers
+       #
+       CONFIG_USB_EHCI_HCD=m
+       CONFIG_USB_UHCI_HCD=m
+       CONFIG_USB_OHCI_HCD=m
+
+And finally:
+
+       # USB Multimedia devices
+       #
+       CONFIG_USB_ET61X251=m
+
+
+6. Module loading
+=================
+To use the driver, it is necessary to load the "et61x251" module into memory
+after every other module required: "videodev", "usbcore" and, depending on
+the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
+
+Loading can be done as shown below:
+
+       [root@localhost home]# modprobe et61x251
+
+At this point the devices should be recognized. You can invoke "dmesg" to
+analyze kernel messages and verify that the loading process has gone well:
+
+       [user@localhost home]$ dmesg
+
+
+7. Module parameters
+====================
+Module parameters are listed below:
+-------------------------------------------------------------------------------
+Name:           video_nr
+Type:           short array (min = 0, max = 64)
+Syntax:         <-1|n[,...]>
+Description:    Specify V4L2 minor mode number:
+                -1 = use next available
+                 n = use minor number n
+                You can specify up to 64 cameras this way.
+                For example:
+                video_nr=-1,2,-1 would assign minor number 2 to the second
+                registered camera and use auto for the first one and for every
+                other camera.
+Default:        -1
+-------------------------------------------------------------------------------
+Name:           force_munmap
+Type:           bool array (min = 0, max = 64)
+Syntax:         <0|1[,...]>
+Description:    Force the application to unmap previously mapped buffer memory
+                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+                all the applications support this feature. This parameter is
+                specific for each detected camera.
+                0 = do not force memory unmapping
+                1 = force memory unmapping (save memory)
+Default:        0
+-------------------------------------------------------------------------------
+Name:           debug
+Type:           ushort
+Syntax:         <n>
+Description:    Debugging information level, from 0 to 3:
+                0 = none (use carefully)
+                1 = critical errors
+                2 = significant informations
+                3 = more verbose messages
+                Level 3 is useful for testing only, when only one device
+                is used at the same time. It also shows some more informations
+                about the hardware being detected. This module parameter can be
+                changed at runtime thanks to the /sys filesystem interface.
+Default:        2
+-------------------------------------------------------------------------------
+
+
+8. Optional device control through "sysfs"
+==========================================
+If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
+it is possible to read and write both the ET61X[12]51 and the image sensor
+registers by using the "sysfs" filesystem interface.
+
+There are four files in the /sys/class/video4linux/videoX directory for each
+registered camera: "reg", "val", "i2c_reg" and "i2c_val". The first two files
+control the ET61X[12]51 bridge, while the other two control the sensor chip.
+"reg" and "i2c_reg" hold the values of the current register index where the
+following reading/writing operations are addressed at through "val" and
+"i2c_val". Their use is not intended for end-users, unless you know what you
+are doing. Remember that you must be logged in as root before writing to them.
+
+As an example, suppose we were to want to read the value contained in the
+register number 1 of the sensor register table - which is usually the product
+identifier - of the camera registered as "/dev/video0":
+
+       [root@localhost #] cd /sys/class/video4linux/video0
+       [root@localhost #] echo 1 > i2c_reg
+       [root@localhost #] cat i2c_val
+
+Note that if the sensor registers can not be read, "cat" will fail.
+To avoid race conditions, all the I/O accesses to the files are serialized.
+
+
+9. Supported devices
+====================
+None of the names of the companies as well as their products will be mentioned
+here. They have never collaborated with the author, so no advertising.
+
+From the point of view of a driver, what unambiguously identify a device are
+its vendor and product USB identifiers. Below is a list of known identifiers of
+devices mounting the ET61X[12]51 PC camera controllers:
+
+Vendor ID  Product ID
+---------  ----------
+0x102c     0x6151
+0x102c     0x6251
+0x102c     0x6253
+0x102c     0x6254
+0x102c     0x6255
+0x102c     0x6256
+0x102c     0x6257
+0x102c     0x6258
+0x102c     0x6259
+0x102c     0x625a
+0x102c     0x625b
+0x102c     0x625c
+0x102c     0x625d
+0x102c     0x625e
+0x102c     0x625f
+0x102c     0x6260
+0x102c     0x6261
+0x102c     0x6262
+0x102c     0x6263
+0x102c     0x6264
+0x102c     0x6265
+0x102c     0x6266
+0x102c     0x6267
+0x102c     0x6268
+0x102c     0x6269
+
+The following image sensors are supported:
+
+Model       Manufacturer
+-----       ------------
+TAS5130D1B  Taiwan Advanced Sensor Corporation
+
+All the available control settings of each image sensor are supported through
+the V4L2 interface.
+
+
+10. Notes for V4L2 application developers
+========================================
+This driver follows the V4L2 API specifications. In particular, it enforces two
+rules:
+
+- exactly one I/O method, either "mmap" or "read", is associated with each
+file descriptor. Once it is selected, the application must close and reopen the
+device to switch to the other I/O method;
+
+- although it is not mandatory, previously mapped buffer memory should always
+be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's.
+The same number of buffers as before will be allocated again to match the size
+of the new video frames, so you have to map the buffers again before any I/O
+attempts on them.
+
+Consistently with the hardware limits, this driver also supports image
+downscaling with arbitrary scaling factors from 1 and 2 in both directions.
+However, the V4L2 API specifications don't correctly define how the scaling
+factor can be chosen arbitrarily by the "negotiation" of the "source" and
+"target" rectangles. To work around this flaw, we have added the convention
+that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
+scaling factor is restored to 1.
+
+This driver supports two different video formats: the first one is the "8-bit
+Sequential Bayer" format and can be used to obtain uncompressed video data
+from the device through the current I/O method, while the second one provides
+"raw" compressed video data (without frame headers not related to the
+compressed data). The current compression quality may vary from 0 to 1 and can
+be selected or queried thanks to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP
+V4L2 ioctl's.
+
+
+11. Contact information
+=======================
+The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
+
+GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is
+'FCE635A4'; the public 1024-bit key should be available at any keyserver;
+the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
index 3f8a119..c6b7641 100644 (file)
@@ -17,16 +17,15 @@ Index
 7.  Module parameters
 8.  Optional device control through "sysfs"
 9.  Supported devices
-10. How to add plug-in's for new image sensors
-11. Notes for V4L2 application developers
-12. Video frame formats
-13. Contact information
-14. Credits
+10. Notes for V4L2 application developers
+11. Video frame formats
+12. Contact information
+13. Credits
 
 
 1. Copyright
 ============
-Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it>
+Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>
 
 
 2. Disclaimer
@@ -54,9 +53,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 4. Overview and features
 ========================
-This driver attempts to support the video and audio streaming capabilities of
-the devices mounting the SONiX SN9C101, SN9C102 and SN9C103 PC Camera
-Controllers.
+This driver attempts to support the video interface of the devices mounting the
+SONiX SN9C101, SN9C102 and SN9C103 PC Camera Controllers.
 
 It's worth to note that SONiX has never collaborated with the author during the
 development of this project, despite several requests for enough detailed
@@ -78,6 +76,7 @@ Some of the features of the driver are:
 - available mmap or read/poll methods for video streaming through isochronous
   data transfers;
 - automatic detection of image sensor;
+- support for built-in microphone interface;
 - support for any window resolutions and optional panning within the maximum
   pixel area of image sensor;
 - image downscaling with arbitrary scaling factors from 1, 2 and 4 in both
@@ -96,7 +95,7 @@ Some of the features of the driver are:
   parameters" paragraph);
 - up to 64 cameras can be handled at the same time; they can be connected and
   disconnected from the host many times without turning off the computer, if
-  your system supports hotplugging;
+  the system supports hotplugging;
 - no known bugs.
 
 
@@ -112,6 +111,12 @@ corresponding modules must be compiled:
        #
        CONFIG_VIDEO_DEV=m
 
+To enable advanced debugging functionality on the device through /sysfs:
+
+       # Multimedia devices
+       #
+       CONFIG_VIDEO_ADV_DEBUG=y
+
        # USB support
        #
        CONFIG_USB=m
@@ -125,6 +130,21 @@ necessary:
        CONFIG_USB_UHCI_HCD=m
        CONFIG_USB_OHCI_HCD=m
 
+The SN9C103 controller also provides a built-in microphone interface. It is
+supported by the USB Audio driver thanks to the ALSA API:
+
+       # Sound
+       #
+       CONFIG_SOUND=y
+
+       # Advanced Linux Sound Architecture
+       #
+       CONFIG_SND=m
+
+       # USB devices
+       #
+       CONFIG_SND_USB_AUDIO=m
+
 And finally:
 
        # USB Multimedia devices
@@ -153,7 +173,7 @@ analyze kernel messages and verify that the loading process has gone well:
 Module parameters are listed below:
 -------------------------------------------------------------------------------
 Name:           video_nr
-Type:           int array (min = 0, max = 64)
+Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]> 
 Description:    Specify V4L2 minor mode number:
                 -1 = use next available
@@ -165,19 +185,19 @@ Description:    Specify V4L2 minor mode number:
                 other camera.
 Default:        -1
 -------------------------------------------------------------------------------
-Name:           force_munmap;
+Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]> 
 Description:    Force the application to unmap previously mapped buffer memory
                 before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
                 all the applications support this feature. This parameter is
                 specific for each detected camera.
-                0 = do not force memory unmapping"
-                1 = force memory unmapping (save memory)"
+                0 = do not force memory unmapping
+                1 = force memory unmapping (save memory)
 Default:        0
 -------------------------------------------------------------------------------
 Name:           debug
-Type:           int
+Type:           ushort
 Syntax:         <n> 
 Description:    Debugging information level, from 0 to 3:
                 0 = none (use carefully)
@@ -187,14 +207,15 @@ Description:    Debugging information level, from 0 to 3:
                 Level 3 is useful for testing only, when only one device
                 is used. It also shows some more informations about the
                 hardware being detected. This parameter can be changed at
-                runtime thanks to the /sys filesystem.
+                runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 
 
 8. Optional device control through "sysfs" [1]
 ==========================================
-It is possible to read and write both the SN9C10x and the image sensor
+If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
+it is possible to read and write both the SN9C10x and the image sensor
 registers by using the "sysfs" filesystem interface.
 
 Every time a supported device is recognized, a write-only file named "green" is
@@ -236,7 +257,7 @@ serialized.
 
 The sysfs interface also provides the "frame_header" entry, which exports the
 frame header of the most recent requested and captured video frame. The header
-is 12-bytes long and is appended to every video frame by the SN9C10x
+is always 18-bytes long and is appended to every video frame by the SN9C10x
 controllers. As an example, this additional information can be used by the user
 application for implementing auto-exposure features via software. 
 
@@ -250,7 +271,8 @@ Byte #  Value         Description
 0x03    0xC4          Frame synchronisation pattern.
 0x04    0xC4          Frame synchronisation pattern.
 0x05    0x96          Frame synchronisation pattern.
-0x06    0x00 or 0x01  Unknown meaning. The exact value depends on the chip.
+0x06    0xXX          Unknown meaning. The exact value depends on the chip;
+                      possible values are 0x00, 0x01 and 0x20.
 0x07    0xXX          Variable value, whose bits are ff00uzzc, where ff is a
                       frame counter, u is unknown, zz is a size indicator
                       (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
@@ -267,12 +289,23 @@ Byte #  Value         Description
                       times the area outside of the specified AE area. For
                       images that are not pure white, the value scales down
                       according to relative whiteness.
+                      according to relative whiteness.
+
+The following bytes are used by the SN9C103 bridge only:
+
+0x0C    0xXX          Unknown meaning
+0x0D    0xXX          Unknown meaning
+0x0E    0xXX          Unknown meaning
+0x0F    0xXX          Unknown meaning
+0x10    0xXX          Unknown meaning
+0x11    0xXX          Unknown meaning
 
 The AE area (sx, sy, ex, ey) in the active window can be set by programming the
 registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C10x controllers, where one unit
 corresponds to 32 pixels.
 
-[1] The frame header has been documented by Bertrik Sikken.
+[1] Part of the meaning of the frame header has been documented by Bertrik
+    Sikken.
 
 
 9. Supported devices
@@ -298,6 +331,7 @@ Vendor ID  Product ID
 0x0c45     0x602b
 0x0c45     0x602c
 0x0c45     0x602d
+0x0c45     0x602e
 0x0c45     0x6030
 0x0c45     0x6080
 0x0c45     0x6082
@@ -348,18 +382,7 @@ appreciated. Non-available hardware will not be supported by the author of this
 driver.
 
 
-10. How to add plug-in's for new image sensors
-==============================================
-It should be easy to write plug-in's for new sensors by using the small API
-that has been created for this purpose, which is present in "sn9c102_sensor.h"
-(documentation is included there). As an example, have a look at the code in
-"sn9c102_pas106b.c", which uses the mentioned interface.
-
-At the moment, possible unsupported image sensors are: CIS-VF10 (VGA),
-OV7620 (VGA), OV7630 (VGA).
-
-
-11. Notes for V4L2 application developers
+10. Notes for V4L2 application developers
 =========================================
 This driver follows the V4L2 API specifications. In particular, it enforces two
 rules:
@@ -394,7 +417,7 @@ initialized (as described in the documentation of the API for the image sensors
 supplied by this driver).
 
 
-12. Video frame formats [1]
+11. Video frame formats [1]
 =======================
 The SN9C10x PC Camera Controllers can send images in two possible video
 formats over the USB: either native "Sequential RGB Bayer" or Huffman
@@ -455,7 +478,7 @@ The following Huffman codes have been found:
     documented by Bertrik Sikken.
 
 
-13. Contact information
+12. Contact information
 =======================
 The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
 
@@ -464,7 +487,7 @@ GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is
 the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
 
 
-14. Credits
+13. Credits
 ===========
 Many thanks to following persons for their contribute (listed in alphabetical
 order):
@@ -480,5 +503,5 @@ order):
 - Bertrik Sikken, who reverse-engineered and documented the Huffman compression
   algorithm used in the SN9C10x controllers and implemented the first decoder;
 - Mizuno Takafumi for the donation of a webcam;
-- An "anonymous" donator (who didn't want his name to be revealed) for the
+- an "anonymous" donator (who didn't want his name to be revealed) for the
   donation of a webcam.
index 18a4773..9d46cd0 100644 (file)
@@ -57,16 +57,12 @@ based cameras should be supported as well.
 The driver is divided into two modules: the basic one, "w9968cf", is needed for
 the supported devices to work; the second one, "w9968cf-vpp", is an optional
 module, which provides some useful video post-processing functions like video
-decoding, up-scaling and colour conversions. Once the driver is installed,
-every time an application tries to open a recognized device, "w9968cf" checks
-the presence of the "w9968cf-vpp" module and loads it automatically by default.
+decoding, up-scaling and colour conversions.
 
-Please keep in mind that official kernels do not include the second module for
-performance purposes. However it is always recommended to download and install
-the latest and complete release of the driver, replacing the existing one, if
-present: it will be still even possible not to load the "w9968cf-vpp" module at
-all, if you ever want to. Another important missing feature of the version in
-the official Linux 2.4 kernels is the writeable /proc filesystem interface.
+Note that the official kernels do neither include nor support the second
+module for performance purposes. Therefore, it is always recommended to
+download and install the latest and complete release of the driver,
+replacing the existing one, if present.
 
 The latest and full-featured version of the W996[87]CF driver can be found at:
 http://www.linux-projects.org. Please refer to the documentation included in
@@ -201,22 +197,6 @@ Note:            The kernel must be compiled with the CONFIG_KMOD option
                  enabled for the 'ovcamchip' module to be loaded and for
                  this parameter to be present.
 -------------------------------------------------------------------------------
-Name:           vppmod_load
-Type:           bool
-Syntax:         <0|1>
-Description:    Automatic 'w9968cf-vpp' module loading: 0 disabled, 1 enabled.
-                If enabled, every time an application attempts to open a
-                camera, 'insmod' searches for the video post-processing module
-                in the system and loads it automatically (if present).
-                The optional 'w9968cf-vpp' module adds extra image manipulation
-                capabilities to the 'w9968cf' module,like software up-scaling,
-                colour conversions and video decompression for very high frame
-                rates.
-Default:        1
-Note:           The kernel must be compiled with the CONFIG_KMOD option
-                enabled for the 'w9968cf-vpp' module to be loaded and for
-                this parameter to be present.
--------------------------------------------------------------------------------
 Name:           simcams 
 Type:           int 
 Syntax:         <n> 
diff --git a/Documentation/vm/page_migration b/Documentation/vm/page_migration
new file mode 100644 (file)
index 0000000..c52820f
--- /dev/null
@@ -0,0 +1,129 @@
+Page migration
+--------------
+
+Page migration allows the moving of the physical location of pages between
+nodes in a numa system while the process is running. This means that the
+virtual addresses that the process sees do not change. However, the
+system rearranges the physical location of those pages.
+
+The main intend of page migration is to reduce the latency of memory access
+by moving pages near to the processor where the process accessing that memory
+is running.
+
+Page migration allows a process to manually relocate the node on which its
+pages are located through the MF_MOVE and MF_MOVE_ALL options while setting
+a new memory policy. The pages of process can also be relocated
+from another process using the sys_migrate_pages() function call. The
+migrate_pages function call takes two sets of nodes and moves pages of a
+process that are located on the from nodes to the destination nodes.
+
+Manual migration is very useful if for example the scheduler has relocated
+a process to a processor on a distant node. A batch scheduler or an
+administrator may detect the situation and move the pages of the process
+nearer to the new processor. At some point in the future we may have
+some mechanism in the scheduler that will automatically move the pages.
+
+Larger installations usually partition the system using cpusets into
+sections of nodes. Paul Jackson has equipped cpusets with the ability to
+move pages when a task is moved to another cpuset. This allows automatic
+control over locality of a process. If a task is moved to a new cpuset
+then also all its pages are moved with it so that the performance of the
+process does not sink dramatically (as is the case today).
+
+Page migration allows the preservation of the relative location of pages
+within a group of nodes for all migration techniques which will preserve a
+particular memory allocation pattern generated even after migrating a
+process. This is necessary in order to preserve the memory latencies.
+Processes will run with similar performance after migration.
+
+Page migration occurs in several steps. First a high level
+description for those trying to use migrate_pages() and then
+a low level description of how the low level details work.
+
+A. Use of migrate_pages()
+-------------------------
+
+1. Remove pages from the LRU.
+
+   Lists of pages to be migrated are generated by scanning over
+   pages and moving them into lists. This is done by
+   calling isolate_lru_page() or __isolate_lru_page().
+   Calling isolate_lru_page increases the references to the page
+   so that it cannot vanish under us.
+
+2. Generate a list of newly allocates page to move the contents
+   of the first list to.
+
+3. The migrate_pages() function is called which attempts
+   to do the migration. It returns the moved pages in the
+   list specified as the third parameter and the failed
+   migrations in the fourth parameter. The first parameter
+   will contain the pages that could still be retried.
+
+4. The leftover pages of various types are returned
+   to the LRU using putback_to_lru_pages() or otherwise
+   disposed of. The pages will still have the refcount as
+   increased by isolate_lru_pages()!
+
+B. Operation of migrate_pages()
+--------------------------------
+
+migrate_pages does several passes over its list of pages. A page is moved
+if all references to a page are removable at the time.
+
+Steps:
+
+1. Lock the page to be migrated
+
+2. Insure that writeback is complete.
+
+3. Make sure that the page has assigned swap cache entry if
+   it is an anonyous page. The swap cache reference is necessary
+   to preserve the information contain in the page table maps.
+
+4. Prep the new page that we want to move to. It is locked
+   and set to not being uptodate so that all accesses to the new
+   page immediately lock while we are moving references.
+
+5. All the page table references to the page are either dropped (file backed)
+   or converted to swap references (anonymous pages). This should decrease the
+   reference count.
+
+6. The radix tree lock is taken
+
+7. The refcount of the page is examined and we back out if references remain
+   otherwise we know that we are the only one referencing this page.
+
+8. The radix tree is checked and if it does not contain the pointer to this
+   page then we back out.
+
+9. The mapping is checked. If the mapping is gone then a truncate action may
+   be in progress and we back out.
+
+10. The new page is prepped with some settings from the old page so that accesses
+   to the new page will be discovered to have the correct settings.
+
+11. The radix tree is changed to point to the new page.
+
+12. The reference count of the old page is dropped because the reference has now
+    been removed.
+
+13. The radix tree lock is dropped.
+
+14. The page contents are copied to the new page.
+
+15. The remaining page flags are copied to the new page.
+
+16. The old page flags are cleared to indicate that the page does
+    not use any information anymore.
+
+17. Queued up writeback on the new page is triggered.
+
+18. If swap pte's were generated for the page then remove them again.
+
+19. The locks are dropped from the old and new page.
+
+20. The new page is moved to the LRU.
+
+Christoph Lameter, December 19, 2005.
+
index 3f8a90a..42955fe 100644 (file)
@@ -1176,8 +1176,8 @@ T:        git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
 S:     Maintained
 
 SN-IA64 (Itanium) SUB-PLATFORM
-P:     Greg Edwards
-M:     edwardsg@sgi.com
+P:     Jes Sorensen
+M:     jes@sgi.com
 L:     linux-altix@sgi.com
 L:     linux-ia64@vger.kernel.org
 W:     http://www.sgi.com/altix
@@ -2673,6 +2673,14 @@ M:       dbrownell@users.sourceforge.net
 L:     linux-usb-devel@lists.sourceforge.net
 S:     Maintained
 
+USB ET61X[12]51 DRIVER
+P:     Luca Risolia
+M:     luca.risolia@studio.unibo.it
+L:     linux-usb-devel@lists.sourceforge.net
+L:     video4linux-list@redhat.com
+W:     http://www.linux-projects.org
+S:     Maintained
+
 USB HID/HIDBP DRIVERS
 P:     Vojtech Pavlik
 M:     vojtech@suse.cz
@@ -2836,6 +2844,7 @@ USB SN9C10x DRIVER
 P:     Luca Risolia
 M:     luca.risolia@studio.unibo.it
 L:     linux-usb-devel@lists.sourceforge.net
+L:     video4linux-list@redhat.com
 W:     http://www.linux-projects.org
 S:     Maintained
 
@@ -2865,6 +2874,7 @@ USB W996[87]CF DRIVER
 P:     Luca Risolia
 M:     luca.risolia@studio.unibo.it
 L:     linux-usb-devel@lists.sourceforge.net
+L:     video4linux-list@redhat.com
 W:     http://www.linux-projects.org
 S:     Maintained
 
index 8f2e5c7..6c56c75 100644 (file)
@@ -28,6 +28,7 @@ void foo(void)
         DEFINE(TASK_GID, offsetof(struct task_struct, gid));
         DEFINE(TASK_EGID, offsetof(struct task_struct, egid));
         DEFINE(TASK_REAL_PARENT, offsetof(struct task_struct, real_parent));
+        DEFINE(TASK_GROUP_LEADER, offsetof(struct task_struct, group_leader));
         DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
         BLANK();
 
index e38671c..7af15bf 100644 (file)
@@ -879,17 +879,19 @@ sys_getxpid:
 
        /* See linux/kernel/timer.c sys_getppid for discussion
           about this loop.  */
-       ldq     $3, TASK_REAL_PARENT($2)
-1:     ldl     $1, TASK_TGID($3)
+       ldq     $3, TASK_GROUP_LEADER($2)
+       ldq     $4, TASK_REAL_PARENT($3)
+       ldl     $0, TASK_TGID($2)
+1:     ldl     $1, TASK_TGID($4)
 #ifdef CONFIG_SMP
-       mov     $3, $4
+       mov     $4, $5
        mb
-       ldq     $3, TASK_REAL_PARENT($2)
-       cmpeq   $3, $4, $4
-       beq     $4, 1b
+       ldq     $3, TASK_GROUP_LEADER($2)
+       ldq     $4, TASK_REAL_PARENT($3)
+       cmpeq   $4, $5, $5
+       beq     $5, 1b
 #endif
        stq     $1, 80($sp)
-       ldl     $0, TASK_TGID($2)
        ret
 .end sys_getxpid
 
index 76be5cf..9006063 100644 (file)
@@ -68,34 +68,32 @@ show_interrupts(struct seq_file *p, void *v)
 #ifdef CONFIG_SMP
        int j;
 #endif
-       int i = *(loff_t *) v;
+       int irq = *(loff_t *) v;
        struct irqaction * action;
        unsigned long flags;
 
 #ifdef CONFIG_SMP
-       if (i == 0) {
+       if (irq == 0) {
                seq_puts(p, "           ");
-               for (i = 0; i < NR_CPUS; i++)
-                       if (cpu_online(i))
-                               seq_printf(p, "CPU%d       ", i);
+               for_each_online_cpu(j)
+                       seq_printf(p, "CPU%d       ", j);
                seq_putc(p, '\n');
        }
 #endif
 
-       if (i < ACTUAL_NR_IRQS) {
-               spin_lock_irqsave(&irq_desc[i].lock, flags);
-               action = irq_desc[i].action;
+       if (irq < ACTUAL_NR_IRQS) {
+               spin_lock_irqsave(&irq_desc[irq].lock, flags);
+               action = irq_desc[irq].action;
                if (!action) 
                        goto unlock;
-               seq_printf(p, "%3d: ",i);
+               seq_printf(p, "%3d: ", irq);
 #ifndef CONFIG_SMP
-               seq_printf(p, "%10u ", kstat_irqs(i));
+               seq_printf(p, "%10u ", kstat_irqs(irq));
 #else
-               for (j = 0; j < NR_CPUS; j++)
-                       if (cpu_online(j))
-                               seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+               for_each_online_cpu(j)
+                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[irq]);
 #endif
-               seq_printf(p, " %14s", irq_desc[i].handler->typename);
+               seq_printf(p, " %14s", irq_desc[irq].handler->typename);
                seq_printf(p, "  %c%s",
                        (action->flags & SA_INTERRUPT)?'+':' ',
                        action->name);
@@ -108,13 +106,12 @@ show_interrupts(struct seq_file *p, void *v)
 
                seq_putc(p, '\n');
 unlock:
-               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       } else if (i == ACTUAL_NR_IRQS) {
+               spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+       } else if (irq == ACTUAL_NR_IRQS) {
 #ifdef CONFIG_SMP
                seq_puts(p, "IPI: ");
-               for (i = 0; i < NR_CPUS; i++)
-                       if (cpu_online(i))
-                               seq_printf(p, "%10lu ", cpu_data[i].ipi_count);
+               for_each_online_cpu(j)
+                       seq_printf(p, "%10lu ", cpu_data[j].ipi_count);
                seq_putc(p, '\n');
 #endif
                seq_printf(p, "ERR: %10lu\n", irq_err_count);
@@ -122,7 +119,6 @@ unlock:
        return 0;
 }
 
-
 /*
  * handle_irq handles all normal device IRQ's (the special
  * SMP cross-CPU interrupts have their own specific
index 6886001..4a8564f 100644 (file)
@@ -14,8 +14,7 @@ CONFIG_GENERIC_IOMAP=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
+CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
@@ -360,7 +359,6 @@ CONFIG_BLK_DEV_IDE_BAST=y
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -781,7 +779,6 @@ CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
index 15468a0..c9aa878 100644 (file)
@@ -13,8 +13,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
+CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -308,9 +307,7 @@ CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
 CONFIG_MTD_OBSOLETE_CHIPS=y
-# CONFIG_MTD_AMDSTD is not set
 CONFIG_MTD_SHARP=y
-# CONFIG_MTD_JEDEC is not set
 
 #
 # Mapping drivers for chip access
@@ -396,7 +393,6 @@ CONFIG_ATA_OVER_ETH=m
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -741,7 +737,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
index 33f3108..1964ccd 100644 (file)
@@ -13,8 +13,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
+CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -473,7 +472,6 @@ CONFIG_BLK_DEV_IDE_BAST=y
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -896,7 +894,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
index 75e6f9a..d058e7c 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- *  This file is included twice in entry-common.S
+ *  This file is included thrice in entry-common.S
  */
-#ifndef NR_syscalls
-#define NR_syscalls 328
-#else
-
-100:
-/* 0 */                .long   sys_restart_syscall
-               .long   sys_exit
-               .long   sys_fork_wrapper
-               .long   sys_read
-               .long   sys_write
-/* 5 */                .long   sys_open
-               .long   sys_close
-               .long   sys_ni_syscall          /* was sys_waitpid */
-               .long   sys_creat
-               .long   sys_link
-/* 10 */       .long   sys_unlink
-               .long   sys_execve_wrapper
-               .long   sys_chdir
-               .long   OBSOLETE(sys_time)      /* used by libc4 */
-               .long   sys_mknod
-/* 15 */       .long   sys_chmod
-               .long   sys_lchown16
-               .long   sys_ni_syscall          /* was sys_break */
-               .long   sys_ni_syscall          /* was sys_stat */
-               .long   sys_lseek
-/* 20 */       .long   sys_getpid
-               .long   sys_mount
-               .long   OBSOLETE(sys_oldumount) /* used by libc4 */
-               .long   sys_setuid16
-               .long   sys_getuid16
-/* 25 */       .long   OBSOLETE(sys_stime)
-               .long   sys_ptrace
-               .long   OBSOLETE(sys_alarm)     /* used by libc4 */
-               .long   sys_ni_syscall          /* was sys_fstat */
-               .long   sys_pause
-/* 30 */       .long   OBSOLETE(sys_utime)     /* used by libc4 */
-               .long   sys_ni_syscall          /* was sys_stty */
-               .long   sys_ni_syscall          /* was sys_getty */
-               .long   sys_access
-               .long   sys_nice
-/* 35 */       .long   sys_ni_syscall          /* was sys_ftime */
-               .long   sys_sync
-               .long   sys_kill
-               .long   sys_rename
-               .long   sys_mkdir
-/* 40 */       .long   sys_rmdir
-               .long   sys_dup
-               .long   sys_pipe
-               .long   sys_times
-               .long   sys_ni_syscall          /* was sys_prof */
-/* 45 */       .long   sys_brk
-               .long   sys_setgid16
-               .long   sys_getgid16
-               .long   sys_ni_syscall          /* was sys_signal */
-               .long   sys_geteuid16
-/* 50 */       .long   sys_getegid16
-               .long   sys_acct
-               .long   sys_umount
-               .long   sys_ni_syscall          /* was sys_lock */
-               .long   sys_ioctl
-/* 55 */       .long   sys_fcntl
-               .long   sys_ni_syscall          /* was sys_mpx */
-               .long   sys_setpgid
-               .long   sys_ni_syscall          /* was sys_ulimit */
-               .long   sys_ni_syscall          /* was sys_olduname */
-/* 60 */       .long   sys_umask
-               .long   sys_chroot
-               .long   sys_ustat
-               .long   sys_dup2
-               .long   sys_getppid
-/* 65 */       .long   sys_getpgrp
-               .long   sys_setsid
-               .long   sys_sigaction
-               .long   sys_ni_syscall          /* was sys_sgetmask */
-               .long   sys_ni_syscall          /* was sys_ssetmask */
-/* 70 */       .long   sys_setreuid16
-               .long   sys_setregid16
-               .long   sys_sigsuspend_wrapper
-               .long   sys_sigpending
-               .long   sys_sethostname
-/* 75 */       .long   sys_setrlimit
-               .long   OBSOLETE(sys_old_getrlimit) /* used by libc4 */
-               .long   sys_getrusage
-               .long   sys_gettimeofday
-               .long   sys_settimeofday
-/* 80 */       .long   sys_getgroups16
-               .long   sys_setgroups16
-               .long   OBSOLETE(old_select)    /* used by libc4 */
-               .long   sys_symlink
-               .long   sys_ni_syscall          /* was sys_lstat */
-/* 85 */       .long   sys_readlink
-               .long   sys_uselib
-               .long   sys_swapon
-               .long   sys_reboot
-               .long   OBSOLETE(old_readdir)   /* used by libc4 */
-/* 90 */       .long   OBSOLETE(old_mmap)      /* used by libc4 */
-               .long   sys_munmap
-               .long   sys_truncate
-               .long   sys_ftruncate
-               .long   sys_fchmod
-/* 95 */       .long   sys_fchown16
-               .long   sys_getpriority
-               .long   sys_setpriority
-               .long   sys_ni_syscall          /* was sys_profil */
-               .long   sys_statfs
-/* 100 */      .long   sys_fstatfs
-               .long   sys_ni_syscall
-               .long   OBSOLETE(sys_socketcall)
-               .long   sys_syslog
-               .long   sys_setitimer
-/* 105 */      .long   sys_getitimer
-               .long   sys_newstat
-               .long   sys_newlstat
-               .long   sys_newfstat
-               .long   sys_ni_syscall          /* was sys_uname */
-/* 110 */      .long   sys_ni_syscall          /* was sys_iopl */
-               .long   sys_vhangup
-               .long   sys_ni_syscall
-               .long   OBSOLETE(sys_syscall)   /* call a syscall */
-               .long   sys_wait4
-/* 115 */      .long   sys_swapoff
-               .long   sys_sysinfo
-               .long   OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))
-               .long   sys_fsync
-               .long   sys_sigreturn_wrapper
-/* 120 */      .long   sys_clone_wrapper
-               .long   sys_setdomainname
-               .long   sys_newuname
-               .long   sys_ni_syscall
-               .long   sys_adjtimex
-/* 125 */      .long   sys_mprotect
-               .long   sys_sigprocmask
-               .long   sys_ni_syscall          /* was sys_create_module */
-               .long   sys_init_module
-               .long   sys_delete_module
-/* 130 */      .long   sys_ni_syscall          /* was sys_get_kernel_syms */
-               .long   sys_quotactl
-               .long   sys_getpgid
-               .long   sys_fchdir
-               .long   sys_bdflush
-/* 135 */      .long   sys_sysfs
-               .long   sys_personality
-               .long   sys_ni_syscall          /* .long        _sys_afs_syscall */
-               .long   sys_setfsuid16
-               .long   sys_setfsgid16
-/* 140 */      .long   sys_llseek
-               .long   sys_getdents
-               .long   sys_select
-               .long   sys_flock
-               .long   sys_msync
-/* 145 */      .long   sys_readv
-               .long   sys_writev
-               .long   sys_getsid
-               .long   sys_fdatasync
-               .long   sys_sysctl
-/* 150 */      .long   sys_mlock
-               .long   sys_munlock
-               .long   sys_mlockall
-               .long   sys_munlockall
-               .long   sys_sched_setparam
-/* 155 */      .long   sys_sched_getparam
-               .long   sys_sched_setscheduler
-               .long   sys_sched_getscheduler
-               .long   sys_sched_yield
-               .long   sys_sched_get_priority_max
-/* 160 */      .long   sys_sched_get_priority_min
-               .long   sys_sched_rr_get_interval
-               .long   sys_nanosleep
-               .long   sys_arm_mremap
-               .long   sys_setresuid16
-/* 165 */      .long   sys_getresuid16
-               .long   sys_ni_syscall
-               .long   sys_ni_syscall          /* was sys_query_module */
-               .long   sys_poll
-               .long   sys_nfsservctl
-/* 170 */      .long   sys_setresgid16
-               .long   sys_getresgid16
-               .long   sys_prctl
-               .long   sys_rt_sigreturn_wrapper
-               .long   sys_rt_sigaction
-/* 175 */      .long   sys_rt_sigprocmask
-               .long   sys_rt_sigpending
-               .long   sys_rt_sigtimedwait
-               .long   sys_rt_sigqueueinfo
-               .long   sys_rt_sigsuspend_wrapper
-/* 180 */      .long   ABI(sys_pread64, sys_oabi_pread64)
-               .long   ABI(sys_pwrite64, sys_oabi_pwrite64)
-               .long   sys_chown16
-               .long   sys_getcwd
-               .long   sys_capget
-/* 185 */      .long   sys_capset
-               .long   sys_sigaltstack_wrapper
-               .long   sys_sendfile
-               .long   sys_ni_syscall
-               .long   sys_ni_syscall
-/* 190 */      .long   sys_vfork_wrapper
-               .long   sys_getrlimit
-               .long   sys_mmap2
-               .long   ABI(sys_truncate64, sys_oabi_truncate64)
-               .long   ABI(sys_ftruncate64, sys_oabi_ftruncate64)
-/* 195 */      .long   ABI(sys_stat64, sys_oabi_stat64)
-               .long   ABI(sys_lstat64, sys_oabi_lstat64)
-               .long   ABI(sys_fstat64, sys_oabi_fstat64)
-               .long   sys_lchown
-               .long   sys_getuid
-/* 200 */      .long   sys_getgid
-               .long   sys_geteuid
-               .long   sys_getegid
-               .long   sys_setreuid
-               .long   sys_setregid
-/* 205 */      .long   sys_getgroups
-               .long   sys_setgroups
-               .long   sys_fchown
-               .long   sys_setresuid
-               .long   sys_getresuid
-/* 210 */      .long   sys_setresgid
-               .long   sys_getresgid
-               .long   sys_chown
-               .long   sys_setuid
-               .long   sys_setgid
-/* 215 */      .long   sys_setfsuid
-               .long   sys_setfsgid
-               .long   sys_getdents64
-               .long   sys_pivot_root
-               .long   sys_mincore
-/* 220 */      .long   sys_madvise
-               .long   ABI(sys_fcntl64, sys_oabi_fcntl64)
-               .long   sys_ni_syscall /* TUX */
-               .long   sys_ni_syscall
-               .long   sys_gettid
-/* 225 */      .long   ABI(sys_readahead, sys_oabi_readahead)
-               .long   sys_setxattr
-               .long   sys_lsetxattr
-               .long   sys_fsetxattr
-               .long   sys_getxattr
-/* 230 */      .long   sys_lgetxattr
-               .long   sys_fgetxattr
-               .long   sys_listxattr
-               .long   sys_llistxattr
-               .long   sys_flistxattr
-/* 235 */      .long   sys_removexattr
-               .long   sys_lremovexattr
-               .long   sys_fremovexattr
-               .long   sys_tkill
-               .long   sys_sendfile64
-/* 240 */      .long   sys_futex
-               .long   sys_sched_setaffinity
-               .long   sys_sched_getaffinity
-               .long   sys_io_setup
-               .long   sys_io_destroy
-/* 245 */      .long   sys_io_getevents
-               .long   sys_io_submit
-               .long   sys_io_cancel
-               .long   sys_exit_group
-               .long   sys_lookup_dcookie
-/* 250 */      .long   sys_epoll_create
-               .long   ABI(sys_epoll_ctl, sys_oabi_epoll_ctl)
-               .long   ABI(sys_epoll_wait, sys_oabi_epoll_wait)
-               .long   sys_remap_file_pages
-               .long   sys_ni_syscall  /* sys_set_thread_area */
-/* 255 */      .long   sys_ni_syscall  /* sys_get_thread_area */
-               .long   sys_set_tid_address
-               .long   sys_timer_create
-               .long   sys_timer_settime
-               .long   sys_timer_gettime
-/* 260 */      .long   sys_timer_getoverrun
-               .long   sys_timer_delete
-               .long   sys_clock_settime
-               .long   sys_clock_gettime
-               .long   sys_clock_getres
-/* 265 */      .long   sys_clock_nanosleep
-               .long   sys_statfs64_wrapper
-               .long   sys_fstatfs64_wrapper
-               .long   sys_tgkill
-               .long   sys_utimes
-/* 270 */      .long   sys_arm_fadvise64_64
-               .long   sys_pciconfig_iobase
-               .long   sys_pciconfig_read
-               .long   sys_pciconfig_write
-               .long   sys_mq_open
-/* 275 */      .long   sys_mq_unlink
-               .long   sys_mq_timedsend
-               .long   sys_mq_timedreceive
-               .long   sys_mq_notify
-               .long   sys_mq_getsetattr
-/* 280 */      .long   sys_waitid
-               .long   sys_socket
-               .long   sys_bind
-               .long   sys_connect
-               .long   sys_listen
-/* 285 */      .long   sys_accept
-               .long   sys_getsockname
-               .long   sys_getpeername
-               .long   sys_socketpair
-               .long   sys_send
-/* 290 */      .long   sys_sendto
-               .long   sys_recv
-               .long   sys_recvfrom
-               .long   sys_shutdown
-               .long   sys_setsockopt
-/* 295 */      .long   sys_getsockopt
-               .long   sys_sendmsg
-               .long   sys_recvmsg
-               .long   ABI(sys_semop, sys_oabi_semop)
-               .long   sys_semget
-/* 300 */      .long   sys_semctl
-               .long   sys_msgsnd
-               .long   sys_msgrcv
-               .long   sys_msgget
-               .long   sys_msgctl
-/* 305 */      .long   sys_shmat
-               .long   sys_shmdt
-               .long   sys_shmget
-               .long   sys_shmctl
-               .long   sys_add_key
-/* 310 */      .long   sys_request_key
-               .long   sys_keyctl
-               .long   ABI(sys_semtimedop, sys_oabi_semtimedop)
-/* vserver */  .long   sys_ni_syscall
-               .long   sys_ioprio_set
-/* 315 */      .long   sys_ioprio_get
-               .long   sys_inotify_init
-               .long   sys_inotify_add_watch
-               .long   sys_inotify_rm_watch
-               .long   sys_mbind
-/* 320 */      .long   sys_get_mempolicy
-               .long   sys_set_mempolicy
-
-               .rept   NR_syscalls - (. - 100b) / 4
-                       .long   sys_ni_syscall
-               .endr
+/* 0 */                CALL(sys_restart_syscall)
+               CALL(sys_exit)
+               CALL(sys_fork_wrapper)
+               CALL(sys_read)
+               CALL(sys_write)
+/* 5 */                CALL(sys_open)
+               CALL(sys_close)
+               CALL(sys_ni_syscall)            /* was sys_waitpid */
+               CALL(sys_creat)
+               CALL(sys_link)
+/* 10 */       CALL(sys_unlink)
+               CALL(sys_execve_wrapper)
+               CALL(sys_chdir)
+               CALL(OBSOLETE(sys_time))        /* used by libc4 */
+               CALL(sys_mknod)
+/* 15 */       CALL(sys_chmod)
+               CALL(sys_lchown16)
+               CALL(sys_ni_syscall)            /* was sys_break */
+               CALL(sys_ni_syscall)            /* was sys_stat */
+               CALL(sys_lseek)
+/* 20 */       CALL(sys_getpid)
+               CALL(sys_mount)
+               CALL(OBSOLETE(sys_oldumount))   /* used by libc4 */
+               CALL(sys_setuid16)
+               CALL(sys_getuid16)
+/* 25 */       CALL(OBSOLETE(sys_stime))
+               CALL(sys_ptrace)
+               CALL(OBSOLETE(sys_alarm))       /* used by libc4 */
+               CALL(sys_ni_syscall)            /* was sys_fstat */
+               CALL(sys_pause)
+/* 30 */       CALL(OBSOLETE(sys_utime))       /* used by libc4 */
+               CALL(sys_ni_syscall)            /* was sys_stty */
+               CALL(sys_ni_syscall)            /* was sys_getty */
+               CALL(sys_access)
+               CALL(sys_nice)
+/* 35 */       CALL(sys_ni_syscall)            /* was sys_ftime */
+               CALL(sys_sync)
+               CALL(sys_kill)
+               CALL(sys_rename)
+               CALL(sys_mkdir)
+/* 40 */       CALL(sys_rmdir)
+               CALL(sys_dup)
+               CALL(sys_pipe)
+               CALL(sys_times)
+               CALL(sys_ni_syscall)            /* was sys_prof */
+/* 45 */       CALL(sys_brk)
+               CALL(sys_setgid16)
+               CALL(sys_getgid16)
+               CALL(sys_ni_syscall)            /* was sys_signal */
+               CALL(sys_geteuid16)
+/* 50 */       CALL(sys_getegid16)
+               CALL(sys_acct)
+               CALL(sys_umount)
+               CALL(sys_ni_syscall)            /* was sys_lock */
+               CALL(sys_ioctl)
+/* 55 */       CALL(sys_fcntl)
+               CALL(sys_ni_syscall)            /* was sys_mpx */
+               CALL(sys_setpgid)
+               CALL(sys_ni_syscall)            /* was sys_ulimit */
+               CALL(sys_ni_syscall)            /* was sys_olduname */
+/* 60 */       CALL(sys_umask)
+               CALL(sys_chroot)
+               CALL(sys_ustat)
+               CALL(sys_dup2)
+               CALL(sys_getppid)
+/* 65 */       CALL(sys_getpgrp)
+               CALL(sys_setsid)
+               CALL(sys_sigaction)
+               CALL(sys_ni_syscall)            /* was sys_sgetmask */
+               CALL(sys_ni_syscall)            /* was sys_ssetmask */
+/* 70 */       CALL(sys_setreuid16)
+               CALL(sys_setregid16)
+               CALL(sys_sigsuspend_wrapper)
+               CALL(sys_sigpending)
+               CALL(sys_sethostname)
+/* 75 */       CALL(sys_setrlimit)
+               CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */
+               CALL(sys_getrusage)
+               CALL(sys_gettimeofday)
+               CALL(sys_settimeofday)
+/* 80 */       CALL(sys_getgroups16)
+               CALL(sys_setgroups16)
+               CALL(OBSOLETE(old_select))      /* used by libc4 */
+               CALL(sys_symlink)
+               CALL(sys_ni_syscall)            /* was sys_lstat */
+/* 85 */       CALL(sys_readlink)
+               CALL(sys_uselib)
+               CALL(sys_swapon)
+               CALL(sys_reboot)
+               CALL(OBSOLETE(old_readdir))     /* used by libc4 */
+/* 90 */       CALL(OBSOLETE(old_mmap))        /* used by libc4 */
+               CALL(sys_munmap)
+               CALL(sys_truncate)
+               CALL(sys_ftruncate)
+               CALL(sys_fchmod)
+/* 95 */       CALL(sys_fchown16)
+               CALL(sys_getpriority)
+               CALL(sys_setpriority)
+               CALL(sys_ni_syscall)            /* was sys_profil */
+               CALL(sys_statfs)
+/* 100 */      CALL(sys_fstatfs)
+               CALL(sys_ni_syscall)
+               CALL(OBSOLETE(sys_socketcall))
+               CALL(sys_syslog)
+               CALL(sys_setitimer)
+/* 105 */      CALL(sys_getitimer)
+               CALL(sys_newstat)
+               CALL(sys_newlstat)
+               CALL(sys_newfstat)
+               CALL(sys_ni_syscall)            /* was sys_uname */
+/* 110 */      CALL(sys_ni_syscall)            /* was sys_iopl */
+               CALL(sys_vhangup)
+               CALL(sys_ni_syscall)
+               CALL(OBSOLETE(sys_syscall))     /* call a syscall */
+               CALL(sys_wait4)
+/* 115 */      CALL(sys_swapoff)
+               CALL(sys_sysinfo)
+               CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
+               CALL(sys_fsync)
+               CALL(sys_sigreturn_wrapper)
+/* 120 */      CALL(sys_clone_wrapper)
+               CALL(sys_setdomainname)
+               CALL(sys_newuname)
+               CALL(sys_ni_syscall)
+               CALL(sys_adjtimex)
+/* 125 */      CALL(sys_mprotect)
+               CALL(sys_sigprocmask)
+               CALL(sys_ni_syscall)            /* was sys_create_module */
+               CALL(sys_init_module)
+               CALL(sys_delete_module)
+/* 130 */      CALL(sys_ni_syscall)            /* was sys_get_kernel_syms */
+               CALL(sys_quotactl)
+               CALL(sys_getpgid)
+               CALL(sys_fchdir)
+               CALL(sys_bdflush)
+/* 135 */      CALL(sys_sysfs)
+               CALL(sys_personality)
+               CALL(sys_ni_syscall)            /* CALL(_sys_afs_syscall) */
+               CALL(sys_setfsuid16)
+               CALL(sys_setfsgid16)
+/* 140 */      CALL(sys_llseek)
+               CALL(sys_getdents)
+               CALL(sys_select)
+               CALL(sys_flock)
+               CALL(sys_msync)
+/* 145 */      CALL(sys_readv)
+               CALL(sys_writev)
+               CALL(sys_getsid)
+               CALL(sys_fdatasync)
+               CALL(sys_sysctl)
+/* 150 */      CALL(sys_mlock)
+               CALL(sys_munlock)
+               CALL(sys_mlockall)
+               CALL(sys_munlockall)
+               CALL(sys_sched_setparam)
+/* 155 */      CALL(sys_sched_getparam)
+               CALL(sys_sched_setscheduler)
+               CALL(sys_sched_getscheduler)
+               CALL(sys_sched_yield)
+               CALL(sys_sched_get_priority_max)
+/* 160 */      CALL(sys_sched_get_priority_min)
+               CALL(sys_sched_rr_get_interval)
+               CALL(sys_nanosleep)
+               CALL(sys_arm_mremap)
+               CALL(sys_setresuid16)
+/* 165 */      CALL(sys_getresuid16)
+               CALL(sys_ni_syscall)
+               CALL(sys_ni_syscall)            /* was sys_query_module */
+               CALL(sys_poll)
+               CALL(sys_nfsservctl)
+/* 170 */      CALL(sys_setresgid16)
+               CALL(sys_getresgid16)
+               CALL(sys_prctl)
+               CALL(sys_rt_sigreturn_wrapper)
+               CALL(sys_rt_sigaction)
+/* 175 */      CALL(sys_rt_sigprocmask)
+               CALL(sys_rt_sigpending)
+               CALL(sys_rt_sigtimedwait)
+               CALL(sys_rt_sigqueueinfo)
+               CALL(sys_rt_sigsuspend_wrapper)
+/* 180 */      CALL(ABI(sys_pread64, sys_oabi_pread64))
+               CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
+               CALL(sys_chown16)
+               CALL(sys_getcwd)
+               CALL(sys_capget)
+/* 185 */      CALL(sys_capset)
+               CALL(sys_sigaltstack_wrapper)
+               CALL(sys_sendfile)
+               CALL(sys_ni_syscall)
+               CALL(sys_ni_syscall)
+/* 190 */      CALL(sys_vfork_wrapper)
+               CALL(sys_getrlimit)
+               CALL(sys_mmap2)
+               CALL(ABI(sys_truncate64, sys_oabi_truncate64))
+               CALL(ABI(sys_ftruncate64, sys_oabi_ftruncate64))
+/* 195 */      CALL(ABI(sys_stat64, sys_oabi_stat64))
+               CALL(ABI(sys_lstat64, sys_oabi_lstat64))
+               CALL(ABI(sys_fstat64, sys_oabi_fstat64))
+               CALL(sys_lchown)
+               CALL(sys_getuid)
+/* 200 */      CALL(sys_getgid)
+               CALL(sys_geteuid)
+               CALL(sys_getegid)
+               CALL(sys_setreuid)
+               CALL(sys_setregid)
+/* 205 */      CALL(sys_getgroups)
+               CALL(sys_setgroups)
+               CALL(sys_fchown)
+               CALL(sys_setresuid)
+               CALL(sys_getresuid)
+/* 210 */      CALL(sys_setresgid)
+               CALL(sys_getresgid)
+               CALL(sys_chown)
+               CALL(sys_setuid)
+               CALL(sys_setgid)
+/* 215 */      CALL(sys_setfsuid)
+               CALL(sys_setfsgid)
+               CALL(sys_getdents64)
+               CALL(sys_pivot_root)
+               CALL(sys_mincore)
+/* 220 */      CALL(sys_madvise)
+               CALL(ABI(sys_fcntl64, sys_oabi_fcntl64))
+               CALL(sys_ni_syscall) /* TUX */
+               CALL(sys_ni_syscall)
+               CALL(sys_gettid)
+/* 225 */      CALL(ABI(sys_readahead, sys_oabi_readahead))
+               CALL(sys_setxattr)
+               CALL(sys_lsetxattr)
+               CALL(sys_fsetxattr)
+               CALL(sys_getxattr)
+/* 230 */      CALL(sys_lgetxattr)
+               CALL(sys_fgetxattr)
+               CALL(sys_listxattr)
+               CALL(sys_llistxattr)
+               CALL(sys_flistxattr)
+/* 235 */      CALL(sys_removexattr)
+               CALL(sys_lremovexattr)
+               CALL(sys_fremovexattr)
+               CALL(sys_tkill)
+               CALL(sys_sendfile64)
+/* 240 */      CALL(sys_futex)
+               CALL(sys_sched_setaffinity)
+               CALL(sys_sched_getaffinity)
+               CALL(sys_io_setup)
+               CALL(sys_io_destroy)
+/* 245 */      CALL(sys_io_getevents)
+               CALL(sys_io_submit)
+               CALL(sys_io_cancel)
+               CALL(sys_exit_group)
+               CALL(sys_lookup_dcookie)
+/* 250 */      CALL(sys_epoll_create)
+               CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl))
+               CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait))
+               CALL(sys_remap_file_pages)
+               CALL(sys_ni_syscall)    /* sys_set_thread_area */
+/* 255 */      CALL(sys_ni_syscall)    /* sys_get_thread_area */
+               CALL(sys_set_tid_address)
+               CALL(sys_timer_create)
+               CALL(sys_timer_settime)
+               CALL(sys_timer_gettime)
+/* 260 */      CALL(sys_timer_getoverrun)
+               CALL(sys_timer_delete)
+               CALL(sys_clock_settime)
+               CALL(sys_clock_gettime)
+               CALL(sys_clock_getres)
+/* 265 */      CALL(sys_clock_nanosleep)
+               CALL(sys_statfs64_wrapper)
+               CALL(sys_fstatfs64_wrapper)
+               CALL(sys_tgkill)
+               CALL(sys_utimes)
+/* 270 */      CALL(sys_arm_fadvise64_64)
+               CALL(sys_pciconfig_iobase)
+               CALL(sys_pciconfig_read)
+               CALL(sys_pciconfig_write)
+               CALL(sys_mq_open)
+/* 275 */      CALL(sys_mq_unlink)
+               CALL(sys_mq_timedsend)
+               CALL(sys_mq_timedreceive)
+               CALL(sys_mq_notify)
+               CALL(sys_mq_getsetattr)
+/* 280 */      CALL(sys_waitid)
+               CALL(sys_socket)
+               CALL(sys_bind)
+               CALL(sys_connect)
+               CALL(sys_listen)
+/* 285 */      CALL(sys_accept)
+               CALL(sys_getsockname)
+               CALL(sys_getpeername)
+               CALL(sys_socketpair)
+               CALL(sys_send)
+/* 290 */      CALL(sys_sendto)
+               CALL(sys_recv)
+               CALL(sys_recvfrom)
+               CALL(sys_shutdown)
+               CALL(sys_setsockopt)
+/* 295 */      CALL(sys_getsockopt)
+               CALL(sys_sendmsg)
+               CALL(sys_recvmsg)
+               CALL(ABI(sys_semop, sys_oabi_semop))
+               CALL(sys_semget)
+/* 300 */      CALL(sys_semctl)
+               CALL(sys_msgsnd)
+               CALL(sys_msgrcv)
+               CALL(sys_msgget)
+               CALL(sys_msgctl)
+/* 305 */      CALL(sys_shmat)
+               CALL(sys_shmdt)
+               CALL(sys_shmget)
+               CALL(sys_shmctl)
+               CALL(sys_add_key)
+/* 310 */      CALL(sys_request_key)
+               CALL(sys_keyctl)
+               CALL(ABI(sys_semtimedop, sys_oabi_semtimedop))
+/* vserver */  CALL(sys_ni_syscall)
+               CALL(sys_ioprio_set)
+/* 315 */      CALL(sys_ioprio_get)
+               CALL(sys_inotify_init)
+               CALL(sys_inotify_add_watch)
+               CALL(sys_inotify_rm_watch)
+               CALL(sys_mbind)
+/* 320 */      CALL(sys_get_mempolicy)
+               CALL(sys_set_mempolicy)
+#ifndef syscalls_counted
+.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
+#define syscalls_counted
 #endif
+.rept syscalls_padding
+               CALL(sys_ni_syscall)
+.endr
index 2b92ce8..dbcb11a 100644 (file)
@@ -87,7 +87,11 @@ ENTRY(ret_from_fork)
        b       ret_slow_syscall
        
 
+       .equ NR_syscalls,0
+#define CALL(x) .equ NR_syscalls,NR_syscalls+1
 #include "calls.S"
+#undef CALL
+#define CALL(x) .long x
 
 /*=============================================================================
  * SWI handler
index 3182017..a0724f2 100644 (file)
@@ -469,7 +469,9 @@ static void cp_clcd_enable(struct clcd_fb *fb)
        if (fb->fb.var.bits_per_pixel <= 8)
                val = CM_CTRL_LCDMUXSEL_VGA_8421BPP;
        else if (fb->fb.var.bits_per_pixel <= 16)
-               val = CM_CTRL_LCDMUXSEL_VGA_16BPP;
+               val = CM_CTRL_LCDMUXSEL_VGA_16BPP
+                       | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1
+                       | CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
        else
                val = 0; /* no idea for this, don't trust the docs */
 
index 9cbe5ee..fc10677 100644 (file)
  *     14-Jan-2005 BJD  Added s3c24xx_init_clocks() call
  *     10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} & IODESC_ENT
  *     14-Mar-2005 BJD  Updated for __iomem
+ *     15-Jan-2006 LCVR Updated S3C2410_PA_##x to new S3C24XX_PA_##x macro
 */
 
 /* todo - fix when rmk changes iodescs to use `void __iomem *` */
 
-#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C2410_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
+#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef MHZ
 #define MHZ (1000*1000)
index f58406e..b8d994a 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     15-Jan-2006 LCVR Using S3C24XX_PA_##x macro for common S3C24XX devices
  *     10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
  *     10-Feb-2005 BJD  Added camera from guillaume.gourat@nexvision.tv
  *     29-Aug-2004 BJD  Added timers 0 through 3
@@ -46,8 +47,8 @@ struct platform_device *s3c24xx_uart_devs[3];
 
 static struct resource s3c_usb_resource[] = {
        [0] = {
-               .start = S3C2410_PA_USBHOST,
-               .end   = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
+               .start = S3C24XX_PA_USBHOST,
+               .end   = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -76,8 +77,8 @@ EXPORT_SYMBOL(s3c_device_usb);
 
 static struct resource s3c_lcd_resource[] = {
        [0] = {
-               .start = S3C2410_PA_LCD,
-               .end   = S3C2410_PA_LCD + S3C24XX_SZ_LCD - 1,
+               .start = S3C24XX_PA_LCD,
+               .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -139,8 +140,8 @@ EXPORT_SYMBOL(s3c_device_nand);
 
 static struct resource s3c_usbgadget_resource[] = {
        [0] = {
-               .start = S3C2410_PA_USBDEV,
-               .end   = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
+               .start = S3C24XX_PA_USBDEV,
+               .end   = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -164,8 +165,8 @@ EXPORT_SYMBOL(s3c_device_usbgadget);
 
 static struct resource s3c_wdt_resource[] = {
        [0] = {
-               .start = S3C2410_PA_WATCHDOG,
-               .end   = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
+               .start = S3C24XX_PA_WATCHDOG,
+               .end   = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -189,8 +190,8 @@ EXPORT_SYMBOL(s3c_device_wdt);
 
 static struct resource s3c_i2c_resource[] = {
        [0] = {
-               .start = S3C2410_PA_IIC,
-               .end   = S3C2410_PA_IIC + S3C24XX_SZ_IIC - 1,
+               .start = S3C24XX_PA_IIC,
+               .end   = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -214,8 +215,8 @@ EXPORT_SYMBOL(s3c_device_i2c);
 
 static struct resource s3c_iis_resource[] = {
        [0] = {
-               .start = S3C2410_PA_IIS,
-               .end   = S3C2410_PA_IIS + S3C24XX_SZ_IIS -1,
+               .start = S3C24XX_PA_IIS,
+               .end   = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1,
                .flags = IORESOURCE_MEM,
        }
 };
@@ -239,8 +240,8 @@ EXPORT_SYMBOL(s3c_device_iis);
 
 static struct resource s3c_rtc_resource[] = {
        [0] = {
-               .start = S3C2410_PA_RTC,
-               .end   = S3C2410_PA_RTC + 0xff,
+               .start = S3C24XX_PA_RTC,
+               .end   = S3C24XX_PA_RTC + 0xff,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -268,8 +269,8 @@ EXPORT_SYMBOL(s3c_device_rtc);
 
 static struct resource s3c_adc_resource[] = {
        [0] = {
-               .start = S3C2410_PA_ADC,
-               .end   = S3C2410_PA_ADC + S3C24XX_SZ_ADC - 1,
+               .start = S3C24XX_PA_ADC,
+               .end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -316,8 +317,8 @@ EXPORT_SYMBOL(s3c_device_sdi);
 
 static struct resource s3c_spi0_resource[] = {
        [0] = {
-               .start = S3C2410_PA_SPI,
-               .end   = S3C2410_PA_SPI + 0x1f,
+               .start = S3C24XX_PA_SPI,
+               .end   = S3C24XX_PA_SPI + 0x1f,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -341,8 +342,8 @@ EXPORT_SYMBOL(s3c_device_spi0);
 
 static struct resource s3c_spi1_resource[] = {
        [0] = {
-               .start = S3C2410_PA_SPI + 0x20,
-               .end   = S3C2410_PA_SPI + 0x20 + 0x1f,
+               .start = S3C24XX_PA_SPI + 0x20,
+               .end   = S3C24XX_PA_SPI + 0x20 + 0x1f,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -366,8 +367,8 @@ EXPORT_SYMBOL(s3c_device_spi1);
 
 static struct resource s3c_timer0_resource[] = {
        [0] = {
-               .start = S3C2410_PA_TIMER + 0x0C,
-               .end   = S3C2410_PA_TIMER + 0x0C + 0xB,
+               .start = S3C24XX_PA_TIMER + 0x0C,
+               .end   = S3C24XX_PA_TIMER + 0x0C + 0xB,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -391,8 +392,8 @@ EXPORT_SYMBOL(s3c_device_timer0);
 
 static struct resource s3c_timer1_resource[] = {
        [0] = {
-               .start = S3C2410_PA_TIMER + 0x18,
-               .end   = S3C2410_PA_TIMER + 0x23,
+               .start = S3C24XX_PA_TIMER + 0x18,
+               .end   = S3C24XX_PA_TIMER + 0x23,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -416,8 +417,8 @@ EXPORT_SYMBOL(s3c_device_timer1);
 
 static struct resource s3c_timer2_resource[] = {
        [0] = {
-               .start = S3C2410_PA_TIMER + 0x24,
-               .end   = S3C2410_PA_TIMER + 0x2F,
+               .start = S3C24XX_PA_TIMER + 0x24,
+               .end   = S3C24XX_PA_TIMER + 0x2F,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
@@ -441,8 +442,8 @@ EXPORT_SYMBOL(s3c_device_timer2);
 
 static struct resource s3c_timer3_resource[] = {
        [0] = {
-               .start = S3C2410_PA_TIMER + 0x30,
-               .end   = S3C2410_PA_TIMER + 0x3B,
+               .start = S3C24XX_PA_TIMER + 0x30,
+               .end   = S3C24XX_PA_TIMER + 0x3B,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
index 65feaf2..4dbd8e7 100644 (file)
@@ -1152,7 +1152,7 @@ static int __init s3c2410_init_dma(void)
 
        printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
 
-       dma_base = ioremap(S3C2410_PA_DMA, 0x200);
+       dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
        if (dma_base == NULL) {
                printk(KERN_ERR "dma failed to remap register block\n");
                return -ENOMEM;
index 61768da..e9a055b 100644 (file)
@@ -133,12 +133,12 @@ ENTRY(s3c2410_cpu_resume)
        @@ load UART to allow us to print the two characters for
        @@ resume debug
 
-       mov     r2, #S3C2410_PA_UART & 0xff000000
-       orr     r2, r2, #S3C2410_PA_UART & 0xff000
+       mov     r2, #S3C24XX_PA_UART & 0xff000000
+       orr     r2, r2, #S3C24XX_PA_UART & 0xff000
 
 #if 0
        /* SMDK2440 LED set */
-       mov     r14, #S3C2410_PA_GPIO
+       mov     r14, #S3C24XX_PA_GPIO
        ldr     r12, [ r14, #0x54 ]
        bic     r12, r12, #3<<4
        orr     r12, r12, #1<<7
index de3ce1e..da9b359 100644 (file)
@@ -142,7 +142,7 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
                return NULL;
        addr = (unsigned long)area->addr;
        if (remap_area_pages(addr, pfn, size, flags)) {
-               vfree(addr);
+               vfree((void *)addr);
                return NULL;
        }
        return (void __iomem *) (offset + (char *)addr);
index d0245a3..ef8d30a 100644 (file)
@@ -343,6 +343,12 @@ static struct mem_types mem_types[] __initdata = {
                                PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE |
                                PMD_SECT_TEX(1),
                .domain    = DOMAIN_IO,
+       },
+       [MT_NONSHARED_DEVICE] = {
+               .prot_l1   = PMD_TYPE_TABLE,
+               .prot_sect = PMD_TYPE_SECT | PMD_SECT_NONSHARED_DEV |
+                               PMD_SECT_AP_WRITE,
+               .domain    = DOMAIN_IO,
        }
 };
 
index 274e070..dee23d8 100644 (file)
@@ -53,14 +53,14 @@ config GENERIC_ISA_DMA
 
 config ARCH_MAY_HAVE_PC_FDC
        bool
-       default y
 
 source "init/Kconfig"
 
 
 menu "System Type"
 
-comment "Archimedes/A5000 Implementations (select only ONE)"
+choice
+       prompt "Archimedes/A5000 Implementations"
 
 config ARCH_ARC
         bool "Archimedes"
@@ -73,6 +73,7 @@ config ARCH_ARC
 
 config ARCH_A5K
         bool "A5000"
+       select ARCH_MAY_HAVE_PC_FDC
         help
           Say Y here to to support the Acorn A5000.
 
@@ -87,6 +88,7 @@ config PAGESIZE_16
           Say Y here if your Archimedes or A5000 system has only 2MB of
           memory, otherwise say N.  The resulting kernel will not run on a
           machine with 4MB of memory.
+endchoice
 endmenu
 
 config ISA_DMA_API
index 08a97c9..a24272b 100644 (file)
@@ -104,14 +104,14 @@ void set_fiq_regs(struct pt_regs *regs)
 {
        register unsigned long tmp, tmp2;
        __asm__ volatile (
-       "mov    %0, pc
-       bic     %1, %0, #0x3
-       orr     %1, %1, %3
-       teqp    %1, #0          @ select FIQ mode
-       mov     r0, r0
-       ldmia   %2, {r8 - r14}
-       teqp    %0, #0          @ return to SVC mode
-       mov     r0, r0"
+       "mov    %0, pc                                  \n"
+       "bic    %1, %0, #0x3                            \n"
+       "orr    %1, %1, %3                              \n"
+       "teqp   %1, #0          @ select FIQ mode       \n"
+       "mov    r0, r0                                  \n"
+       "ldmia  %2, {r8 - r14}                          \n"
+       "teqp   %0, #0          @ return to SVC mode    \n"
+       "mov    r0, r0                                  "
        : "=&r" (tmp), "=&r" (tmp2)
        : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | MODE_FIQ26)
        /* These registers aren't modified by the above code in a way
@@ -125,14 +125,14 @@ void get_fiq_regs(struct pt_regs *regs)
 {
        register unsigned long tmp, tmp2;
        __asm__ volatile (
-       "mov    %0, pc
-       bic     %1, %0, #0x3
-       orr     %1, %1, %3
-       teqp    %1, #0          @ select FIQ mode
-       mov     r0, r0
-       stmia   %2, {r8 - r14}
-       teqp    %0, #0          @ return to SVC mode
-       mov     r0, r0"
+       "mov    %0, pc                                  \n"
+       "bic    %1, %0, #0x3                            \n"
+       "orr    %1, %1, %3                              \n"
+       "teqp   %1, #0          @ select FIQ mode       \n"
+       "mov    r0, r0                                  \n"
+       "stmia  %2, {r8 - r14}                          \n"
+       "teqp   %0, #0          @ return to SVC mode    \n"
+       "mov    r0, r0                                  "
        : "=&r" (tmp), "=&r" (tmp2)
        : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | MODE_FIQ26)
        /* These registers aren't modified by the above code in a way
index ce2055b..2a48c12 100644 (file)
@@ -480,6 +480,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 {
        siginfo_t info;
        int signr;
+       struct k_sigaction ka;
 
        /*
         * We want the common case to go fast, which
@@ -493,7 +494,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
         if (current->ptrace & PT_SINGLESTEP)
                 ptrace_cancel_bpt(current);
        
-        signr = get_signal_to_deliver(&info, regs, NULL);
+        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
         if (signr > 0) {
                 handle_signal(signr, &info, oldset, regs, syscall);
                 if (current->ptrace & PT_SINGLESTEP)
index cbde675..d86c865 100644 (file)
@@ -47,15 +47,6 @@ config DMI
 
 source "init/Kconfig"
 
-config DOUBLEFAULT
-       default y
-       bool "Enable doublefault exception handler" if EMBEDDED
-       help
-          This option allows trapping of rare doublefault exceptions that
-          would otherwise cause a system to silently reboot. Disabling this
-          option saves about 4k and might cause you much additional grey
-          hair.
-
 menu "Processor type and features"
 
 choice
@@ -457,6 +448,43 @@ config HIGHMEM64G
 
 endchoice
 
+choice
+       depends on EXPERIMENTAL && !X86_PAE
+       prompt "Memory split"
+       default VMSPLIT_3G
+       help
+         Select the desired split between kernel and user memory.
+
+         If the address range available to the kernel is less than the
+         physical memory installed, the remaining memory will be available
+         as "high memory". Accessing high memory is a little more costly
+         than low memory, as it needs to be mapped into the kernel first.
+         Note that increasing the kernel address space limits the range
+         available to user programs, making the address space there
+         tighter.  Selecting anything other than the default 3G/1G split
+         will also likely make your kernel incompatible with binary-only
+         kernel modules.
+
+         If you are not absolutely sure what you are doing, leave this
+         option alone!
+
+       config VMSPLIT_3G
+               bool "3G/1G user/kernel split"
+       config VMSPLIT_3G_OPT
+               bool "3G/1G user/kernel split (for full 1G low memory)"
+       config VMSPLIT_2G
+               bool "2G/2G user/kernel split"
+       config VMSPLIT_1G
+               bool "1G/3G user/kernel split"
+endchoice
+
+config PAGE_OFFSET
+       hex
+       default 0xB0000000 if VMSPLIT_3G_OPT
+       default 0x78000000 if VMSPLIT_2G
+       default 0x40000000 if VMSPLIT_1G
+       default 0xC0000000
+
 config HIGHMEM
        bool
        depends on HIGHMEM64G || HIGHMEM4G
@@ -711,6 +739,15 @@ config HOTPLUG_CPU
 
          Say N.
 
+config DOUBLEFAULT
+       default y
+       bool "Enable doublefault exception handler" if EMBEDDED
+       help
+          This option allows trapping of rare doublefault exceptions that
+          would otherwise cause a system to silently reboot. Disabling this
+          option saves about 4k and might cause you much additional grey
+          hair.
+
 endmenu
 
 
index 394814e..0dd92a2 100644 (file)
@@ -405,10 +405,6 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
                                winchip2_protect_mcr();
 #endif
                                break;
-                       case 10:
-                               name="4";
-                               /* no info on the WC4 yet */
-                               break;
                        default:
                                name="??";
                        }
index 0f1eb50..26892d2 100644 (file)
@@ -96,6 +96,7 @@ config X86_POWERNOW_K8_ACPI
 
 config X86_GX_SUSPMOD
        tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
+       depends on PCI
        help
         This add the CPUFreq driver for NatSemi Geode processors which
         support suspend modulation.
index 270f218..cc73a7a 100644 (file)
@@ -52,6 +52,7 @@ enum {
 
 
 static int has_N44_O17_errata[NR_CPUS];
+static int has_N60_errata[NR_CPUS];
 static unsigned int stock_freq;
 static struct cpufreq_driver p4clockmod_driver;
 static unsigned int cpufreq_p4_get(unsigned int cpu);
@@ -226,6 +227,12 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
        case 0x0f12:
                has_N44_O17_errata[policy->cpu] = 1;
                dprintk("has errata -- disabling low frequencies\n");
+               break;
+
+       case 0x0f29:
+               has_N60_errata[policy->cpu] = 1;
+               dprintk("has errata -- disabling frequencies lower than 2ghz\n");
+               break;
        }
        
        /* get max frequency */
@@ -237,6 +244,8 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
        for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
                if ((i<2) && (has_N44_O17_errata[policy->cpu]))
                        p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+               else if (has_N60_errata[policy->cpu] && p4clockmod_table[i].frequency < 2000000)
+                       p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
                else
                        p4clockmod_table[i].frequency = (stock_freq * i)/8;
        }
index fbfd374..af591c7 100644 (file)
@@ -43,13 +43,23 @@ static struct _cache_table cache_table[] __cpuinitdata =
        { 0x2c, LVL_1_DATA, 32 },       /* 8-way set assoc, 64 byte line size */
        { 0x30, LVL_1_INST, 32 },       /* 8-way set assoc, 64 byte line size */
        { 0x39, LVL_2,      128 },      /* 4-way set assoc, sectored cache, 64 byte line size */
+       { 0x3a, LVL_2,      192 },      /* 6-way set assoc, sectored cache, 64 byte line size */
        { 0x3b, LVL_2,      128 },      /* 2-way set assoc, sectored cache, 64 byte line size */
        { 0x3c, LVL_2,      256 },      /* 4-way set assoc, sectored cache, 64 byte line size */
+       { 0x3d, LVL_2,      384 },      /* 6-way set assoc, sectored cache, 64 byte line size */
+       { 0x3e, LVL_2,      512 },      /* 4-way set assoc, sectored cache, 64 byte line size */
        { 0x41, LVL_2,      128 },      /* 4-way set assoc, 32 byte line size */
        { 0x42, LVL_2,      256 },      /* 4-way set assoc, 32 byte line size */
        { 0x43, LVL_2,      512 },      /* 4-way set assoc, 32 byte line size */
        { 0x44, LVL_2,      1024 },     /* 4-way set assoc, 32 byte line size */
        { 0x45, LVL_2,      2048 },     /* 4-way set assoc, 32 byte line size */
+       { 0x46, LVL_3,      4096 },     /* 4-way set assoc, 64 byte line size */
+       { 0x47, LVL_3,      8192 },     /* 8-way set assoc, 64 byte line size */
+       { 0x49, LVL_3,      4096 },     /* 16-way set assoc, 64 byte line size */
+       { 0x4a, LVL_3,      6144 },     /* 12-way set assoc, 64 byte line size */
+       { 0x4b, LVL_3,      8192 },     /* 16-way set assoc, 64 byte line size */
+       { 0x4c, LVL_3,     12288 },     /* 12-way set assoc, 64 byte line size */
+       { 0x4d, LVL_3,     16384 },     /* 16-way set assoc, 64 byte line size */
        { 0x60, LVL_1_DATA, 16 },       /* 8-way set assoc, sectored cache, 64 byte line size */
        { 0x66, LVL_1_DATA, 8 },        /* 4-way set assoc, sectored cache, 64 byte line size */
        { 0x67, LVL_1_DATA, 16 },       /* 4-way set assoc, sectored cache, 64 byte line size */
@@ -57,6 +67,7 @@ static struct _cache_table cache_table[] __cpuinitdata =
        { 0x70, LVL_TRACE,  12 },       /* 8-way set assoc */
        { 0x71, LVL_TRACE,  16 },       /* 8-way set assoc */
        { 0x72, LVL_TRACE,  32 },       /* 8-way set assoc */
+       { 0x73, LVL_TRACE,  64 },       /* 8-way set assoc */
        { 0x78, LVL_2,    1024 },       /* 4-way set assoc, 64 byte line size */
        { 0x79, LVL_2,     128 },       /* 8-way set assoc, sectored cache, 64 byte line size */
        { 0x7a, LVL_2,     256 },       /* 8-way set assoc, sectored cache, 64 byte line size */
index 1e9db19..3b4618b 100644 (file)
 #include <asm/msr.h>
 #include "mtrr.h"
 
-#define MTRR_VERSION            "2.0 (20020519)"
-
 u32 num_var_ranges = 0;
 
 unsigned int *usage_table;
-static DECLARE_MUTEX(main_lock);
+static DECLARE_MUTEX(mtrr_sem);
 
 u32 size_or_mask, size_and_mask;
 
@@ -335,7 +333,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
        /* No CPU hotplug when we change MTRR entries */
        lock_cpu_hotplug();
        /*  Search for existing MTRR  */
-       down(&main_lock);
+       down(&mtrr_sem);
        for (i = 0; i < num_var_ranges; ++i) {
                mtrr_if->get(i, &lbase, &lsize, &ltype);
                if (base >= lbase + lsize)
@@ -373,7 +371,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
                printk(KERN_INFO "mtrr: no more MTRRs available\n");
        error = i;
  out:
-       up(&main_lock);
+       up(&mtrr_sem);
        unlock_cpu_hotplug();
        return error;
 }
@@ -466,7 +464,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
        max = num_var_ranges;
        /* No CPU hotplug when we change MTRR entries */
        lock_cpu_hotplug();
-       down(&main_lock);
+       down(&mtrr_sem);
        if (reg < 0) {
                /*  Search for existing MTRR  */
                for (i = 0; i < max; ++i) {
@@ -505,7 +503,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
                set_mtrr(reg, 0, 0, 0);
        error = reg;
  out:
-       up(&main_lock);
+       up(&mtrr_sem);
        unlock_cpu_hotplug();
        return error;
 }
@@ -671,7 +669,6 @@ void __init mtrr_bp_init(void)
                        break;
                }
        }
-       printk(KERN_INFO "mtrr: v%s\n",MTRR_VERSION);
 
        if (mtrr_if) {
                set_num_var_ranges();
@@ -688,7 +685,7 @@ void mtrr_ap_init(void)
        if (!mtrr_if || !use_intel())
                return;
        /*
-        * Ideally we should hold main_lock here to avoid mtrr entries changed,
+        * Ideally we should hold mtrr_sem here to avoid mtrr entries changed,
         * but this routine will be called in cpu boot time, holding the lock
         * breaks it. This routine is called in two cases: 1.very earily time
         * of software resume, when there absolutely isn't mtrr entry changes;
index 47675bb..7c86e3c 100644 (file)
@@ -45,6 +45,15 @@ static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */
 static unsigned long long monotonic_base;
 static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
 
+/* Avoid compensating for lost ticks before TSCs are synched */
+static int detect_lost_ticks;
+static int __init start_lost_tick_compensation(void)
+{
+       detect_lost_ticks = 1;
+       return 0;
+}
+late_initcall(start_lost_tick_compensation);
+
 /* convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
  *             ns = cycles / (freq / ns_per_sec)
@@ -196,7 +205,8 @@ static void mark_offset_tsc_hpet(void)
 
        /* lost tick compensation */
        offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
-       if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) {
+       if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))
+                                       && detect_lost_ticks) {
                int lost_ticks = (offset - hpet_last) / hpet_tick;
                jiffies_64 += lost_ticks;
        }
@@ -421,7 +431,7 @@ static void mark_offset_tsc(void)
        delta += delay_at_last_interrupt;
        lost = delta/(1000000/HZ);
        delay = delta%(1000000/HZ);
-       if (lost >= 2) {
+       if (lost >= 2 && detect_lost_ticks) {
                jiffies_64 += lost-1;
 
                /* sanity check to ensure we're not always losing ticks */
index e715aa9..3ca59ca 100644 (file)
@@ -539,6 +539,11 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
                case PCI_DEVICE_ID_INTEL_ICH7_30:
                case PCI_DEVICE_ID_INTEL_ICH7_31:
                case PCI_DEVICE_ID_INTEL_ESB2_0:
+               case PCI_DEVICE_ID_INTEL_ICH8_0:
+               case PCI_DEVICE_ID_INTEL_ICH8_1:
+               case PCI_DEVICE_ID_INTEL_ICH8_2:
+               case PCI_DEVICE_ID_INTEL_ICH8_3:
+               case PCI_DEVICE_ID_INTEL_ICH8_4:
                        r->name = "PIIX/ICH";
                        r->get = pirq_piix_get;
                        r->set = pirq_piix_set;
index 4bb4d4b..0ee8a98 100644 (file)
@@ -36,8 +36,7 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
        while (1) {
                ++cfg_num;
                if (cfg_num >= pci_mmcfg_config_num) {
-                       /* Not found - fallback to type 1 */
-                       return 0;
+                       break;
                }
                cfg = &pci_mmcfg_config[cfg_num];
                if (cfg->pci_segment_group_number != seg)
@@ -46,6 +45,18 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
                    (cfg->end_bus_number >= bus))
                        return cfg->base_address;
        }
+
+       /* Handle more broken MCFG tables on Asus etc.
+          They only contain a single entry for bus 0-0. Assume
+          this applies to all busses. */
+       cfg = &pci_mmcfg_config[0];
+       if (pci_mmcfg_config_num == 1 &&
+               cfg->pci_segment_group_number == 0 &&
+               (cfg->start_bus_number | cfg->end_bus_number) == 0)
+               return cfg->base_address;
+
+       /* Fall back to type 0 */
+       return 0;
 }
 
 static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
index 403a80a..60a464b 100644 (file)
@@ -512,7 +512,7 @@ ia64_state_save:
        st8 [temp1]=r12         // os_status, default is cold boot
        mov r6=IA64_MCA_SAME_CONTEXT
        ;;
-       st8 [temp1]=r6          // context, default is same context
+       st8 [temp2]=r6          // context, default is same context
 
        // Save the pt_regs data that is not in minstate.  The previous code
        // left regs at sos.
index 43b45b6..f9e0ae9 100644 (file)
@@ -1283,8 +1283,9 @@ within_logging_rate_limit (void)
 
        if (jiffies - last_time > 5*HZ)
                count = 0;
-       if (++count < 5) {
+       if (count < 5) {
                last_time = jiffies;
+               count++;
                return 1;
        }
        return 0;
index 00700f7..a4c7815 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/nodemask.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/sn_feature_sets.h>
 #include <asm/sn/geo.h>
 #include <asm/sn/io.h>
 #include <asm/sn/pcibr_provider.h>
@@ -173,8 +174,8 @@ sn_pcidev_info_get(struct pci_dev *dev)
  */
 static u8 war_implemented = 0;
 
-static void sn_device_fixup_war(u64 nasid, u64 widget, int device,
-                               struct sn_flush_device_common *common)
+static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
+                              struct sn_flush_device_common *common)
 {
        struct sn_flush_device_war *war_list;
        struct sn_flush_device_war *dev_entry;
@@ -198,8 +199,9 @@ static void sn_device_fixup_war(u64 nasid, u64 widget, int device,
 
        dev_entry = war_list + device;
        memcpy(common,dev_entry, sizeof(*common));
-
        kfree(war_list);
+
+       return isrv.status;
 }
 
 /*
@@ -279,23 +281,21 @@ static void sn_fixup_ionodes(void)
                                memset(dev_entry->common, 0x0, sizeof(struct
                                                       sn_flush_device_common));
 
-                               status = sal_get_device_dmaflush_list(nasid,
-                                                                       widget,
-                                                                       device,
+                               if (sn_prom_feature_available(
+                                                      PRF_DEVICE_FLUSH_LIST))
+                                       status = sal_get_device_dmaflush_list(
+                                                                         nasid,
+                                                                        widget,
+                                                                        device,
                                                      (u64)(dev_entry->common));
-                               if (status) {
-                                       if (sn_sal_rev() < 0x0450) {
-                                               /* shortlived WAR for older
-                                                * PROM images
-                                                */
-                                               sn_device_fixup_war(nasid,
-                                                                   widget,
-                                                                   device,
+                               else
+                                       status = sn_device_fixup_war(nasid,
+                                                                    widget,
+                                                                    device,
                                                             dev_entry->common);
-                                       }
-                                       else
-                                               BUG();
-                               }
+                               if (status != SALRET_OK)
+                                       panic("SAL call failed: %s\n",
+                                             ia64_sal_strerror(status));
 
                                spin_lock_init(&dev_entry->sfdl_flush_lock);
                        }
index 8d950c7..36e5437 100644 (file)
@@ -447,7 +447,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch)
 
                nbytes = nentries * ch->msg_size;
                ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
-                                               (GFP_KERNEL | GFP_DMA),
+                                               GFP_KERNEL,
                                                &ch->local_msgqueue_base);
                if (ch->local_msgqueue == NULL) {
                        continue;
@@ -455,7 +455,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch)
                memset(ch->local_msgqueue, 0, nbytes);
 
                nbytes = nentries * sizeof(struct xpc_notify);
-               ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA));
+               ch->notify_queue = kmalloc(nbytes, GFP_KERNEL);
                if (ch->notify_queue == NULL) {
                        kfree(ch->local_msgqueue_base);
                        ch->local_msgqueue = NULL;
@@ -502,7 +502,7 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
 
                nbytes = nentries * ch->msg_size;
                ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
-                                               (GFP_KERNEL | GFP_DMA),
+                                               GFP_KERNEL,
                                                &ch->remote_msgqueue_base);
                if (ch->remote_msgqueue == NULL) {
                        continue;
index 9bf9f23..5a36292 100644 (file)
@@ -90,14 +90,14 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size,
         */
        node = pcibus_to_node(pdev->bus);
        if (likely(node >=0)) {
-               struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size));
+               struct page *p = alloc_pages_node(node, flags, get_order(size));
 
                if (likely(p))
                        cpuaddr = page_address(p);
                else
                        return NULL;
        } else
-               cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
+               cpuaddr = (void *)__get_free_pages(flags, get_order(size));
 
        if (unlikely(!cpuaddr))
                return NULL;
index 96d18c4..d4f88e0 100644 (file)
@@ -178,7 +178,7 @@ int kgdb_enabled;
  */
 static DEFINE_SPINLOCK(kgdb_lock);
 static raw_spinlock_t kgdb_cpulock[NR_CPUS] = {
-       [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED;
+       [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED,
 };
 
 /*
index f970ace..c7a799a 100644 (file)
@@ -134,7 +134,6 @@ static int __init add_legacy_soc_port(struct device_node *np,
        return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags);
 }
 
-#ifdef CONFIG_ISA
 static int __init add_legacy_isa_port(struct device_node *np,
                                      struct device_node *isa_brg)
 {
@@ -168,7 +167,6 @@ static int __init add_legacy_isa_port(struct device_node *np,
        return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, NO_IRQ, UPF_BOOT_AUTOCONF);
 
 }
-#endif
 
 #ifdef CONFIG_PCI
 static int __init add_legacy_pci_port(struct device_node *np,
@@ -276,7 +274,6 @@ void __init find_legacy_serial_ports(void)
                of_node_put(soc);
        }
 
-#ifdef CONFIG_ISA
        /* First fill our array with ISA ports */
        for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
                struct device_node *isa = of_get_parent(np);
@@ -287,7 +284,6 @@ void __init find_legacy_serial_ports(void)
                }
                of_node_put(isa);
        }
-#endif
 
 #ifdef CONFIG_PCI
        /* Next, try to locate PCI ports */
index 3747ab0..c6d0595 100644 (file)
@@ -254,11 +254,9 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs);
  */
 long sys_sigsuspend(old_sigset_t mask)
 {
-       sigset_t saveset;
-
        mask &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        siginitset(&current->blocked, mask);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
index c32c623..356a739 100644 (file)
@@ -862,21 +862,28 @@ int pmf_register_irq_client(struct device_node *target,
                spin_unlock_irqrestore(&pmf_lock, flags);
                return -ENODEV;
        }
+       if (list_empty(&func->irq_clients))
+               func->dev->handlers->irq_enable(func);
        list_add(&client->link, &func->irq_clients);
+       client->func = func;
        spin_unlock_irqrestore(&pmf_lock, flags);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(pmf_register_irq_client);
 
-void pmf_unregister_irq_client(struct device_node *np,
-                             const char *name,
-                             struct pmf_irq_client *client)
+void pmf_unregister_irq_client(struct pmf_irq_client *client)
 {
+       struct pmf_function *func = client->func;
        unsigned long flags;
 
+       BUG_ON(func == NULL);
+
        spin_lock_irqsave(&pmf_lock, flags);
+       client->func = NULL;
        list_del(&client->link);
+       if (list_empty(&func->irq_clients))
+               func->dev->handlers->irq_disable(func);
        spin_unlock_irqrestore(&pmf_lock, flags);
 }
 EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);
index 2193478..bdaa8aa 100644 (file)
@@ -58,6 +58,7 @@ pcibios_find_pci_bus(struct device_node *dn)
 
        return find_bus_among_children(pdn->phb->bus, dn);
 }
+EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
 
 /**
  * pcibios_remove_pci_devices - remove all devices under this bus
@@ -106,6 +107,7 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
                }
        }
 }
+EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
 
 static int
 pcibios_pci_config_bridge(struct pci_dev *dev)
@@ -172,3 +174,4 @@ pcibios_add_pci_devices(struct pci_bus * bus)
                        pcibios_pci_config_bridge(dev);
        }
 }
+EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
index 94ea346..1f01b7e 100644 (file)
@@ -313,7 +313,7 @@ static struct platform_device mpsc1_device = {
 };
 #endif
 
-#ifdef CONFIG_MV643XX_ETH
+#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
 static struct resource mv64x60_eth_shared_resources[] = {
        [0] = {
                .name   = "ethernet shared base",
@@ -456,7 +456,7 @@ static struct platform_device *mv64x60_pd_devs[] __initdata = {
        &mpsc0_device,
        &mpsc1_device,
 #endif
-#ifdef CONFIG_MV643XX_ETH
+#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
        &mv64x60_eth_shared_device,
 #endif
 #ifdef CONFIG_MV643XX_ETH_0
index 7d23edc..3525c91 100644 (file)
@@ -1,13 +1,12 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc2
-# Mon Nov 21 13:51:30 2005
+# Linux kernel version: 2.6.16-rc1
+# Thu Jan 19 10:58:53 2006
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_S390=y
-CONFIG_UID16=y
 
 #
 # Code maturity level options
@@ -29,18 +28,20 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_SYSCTL=y
 CONFIG_AUDIT=y
 # CONFIG_AUDITSYSCALL is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -49,8 +50,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -76,11 +79,11 @@ CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_DEFAULT_IOSCHED="deadline"
 
 #
 # Base setup
@@ -193,6 +196,11 @@ CONFIG_IPV6=y
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -362,6 +370,7 @@ CONFIG_DM_MULTIPATH=y
 #
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=2048
+# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # Watchdog Cards
@@ -488,6 +497,7 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -520,6 +530,7 @@ CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -584,6 +595,7 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -592,7 +604,7 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_NLS is not set
 
 #
-# Profiling support
+# Instrumentation Support
 #
 # CONFIG_PROFILING is not set
 
@@ -600,19 +612,21 @@ CONFIG_MSDOS_PARTITION=y
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
-CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 
 #
index fa2b3bc..ef70669 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  arch/s390/kernel/signal32.c
+ *  arch/s390/kernel/compat_signal.c
  *
- *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 2000,2006
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *               Gerhard Tonn (ton@de.ibm.com)                  
  *
@@ -52,8 +51,6 @@ typedef struct
        struct ucontext32 uc;
 } rt_sigframe32;
 
-asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
-
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
        int err;
@@ -161,66 +158,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
        return err;
 }
 
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys32_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
-{
-       sigset_t saveset;
-
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-       regs->gprs[2] = -EINTR;
-
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
-}
-
-asmlinkage int
-sys32_rt_sigsuspend(struct pt_regs * regs, compat_sigset_t __user *unewset,
-                                                               size_t sigsetsize)
-{
-       sigset_t saveset, newset;
-       compat_sigset_t set32;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&set32, unewset, sizeof(set32)))
-               return -EFAULT;
-       switch (_NSIG_WORDS) {
-       case 4: newset.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
-       case 3: newset.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
-       case 2: newset.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
-       case 1: newset.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
-       }
-        sigdelsetmask(&newset, ~_BLOCKABLE);
-
-        spin_lock_irq(&current->sighand->siglock);
-        saveset = current->blocked;
-        current->blocked = newset;
-        recalc_sigpending();
-        spin_unlock_irq(&current->sighand->siglock);
-        regs->gprs[2] = -EINTR;
-
-        while (1) {
-                set_current_state(TASK_INTERRUPTIBLE);
-                schedule();
-                if (do_signal(regs, &saveset))
-                        return -EINTR;
-        }
-}
-
 asmlinkage long
 sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
                 struct old_sigaction32 __user *oact)
@@ -520,7 +457,7 @@ static inline int map_signal(int sig)
                return sig;
 }
 
-static void setup_frame32(int sig, struct k_sigaction *ka,
+static int setup_frame32(int sig, struct k_sigaction *ka,
                        sigset_t *set, struct pt_regs * regs)
 {
        sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
@@ -565,13 +502,14 @@ static void setup_frame32(int sig, struct k_sigaction *ka,
        /* Place signal number on stack to allow backtrace from handler.  */
        if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
                goto give_sigsegv;
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
-static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
                           sigset_t *set, struct pt_regs * regs)
 {
        int err = 0;
@@ -615,31 +553,37 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->gprs[2] = map_signal(sig);
        regs->gprs[3] = (__u64) &frame->info;
        regs->gprs[4] = (__u64) &frame->uc;
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */    
 
-void
+int
 handle_signal32(unsigned long sig, struct k_sigaction *ka,
                siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
+       int ret;
+
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame32(sig, ka, info, oldset, regs);
+               ret = setup_rt_frame32(sig, ka, info, oldset, regs);
        else
-               setup_frame32(sig, ka, oldset, regs);
-
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked,sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+               ret = setup_frame32(sig, ka, oldset, regs);
+
+       if (ret == 0) {
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+       }
+       return ret;
 }
 
index cfde190..6e27ac6 100644 (file)
@@ -1,9 +1,8 @@
 /*
-*  arch/s390/kernel/sys_wrapper31.S
+*  arch/s390/kernel/compat_wrapper.S
 *    wrapper for 31 bit compatible system calls.
 *
-*  S390 version
-*    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+*    Copyright (C) IBM Corp. 2000,2006
 *    Author(s): Gerhard Tonn (ton@de.ibm.com),
 *               Thomas Spatzier (tspat@de.ibm.com)
 */ 
@@ -288,7 +287,12 @@ sys32_setregid16_wrapper:
        llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t 
        jg      sys32_setregid16        # branch to system call
 
-#sys32_sigsuspend_wrapper              # done in sigsuspend_glue 
+       .globl sys_sigsuspend_wrapper
+sys_sigsuspend_wrapper:
+       lgfr    %r2,%r2                 # int
+       lgfr    %r3,%r3                 # int
+       llgfr   %r4,%r4                 # old_sigset_t
+       jg      sys_sigsuspend
 
        .globl  compat_sys_sigpending_wrapper 
 compat_sys_sigpending_wrapper:
@@ -855,7 +859,11 @@ sys32_rt_sigqueueinfo_wrapper:
        llgtr   %r4,%r4                 # siginfo_emu31_t *
        jg      sys32_rt_sigqueueinfo   # branch to system call
 
-#sys32_rt_sigsuspend_wrapper           # done in rt_sigsuspend_glue 
+       .globl compat_sys_rt_sigsuspend_wrapper
+compat_sys_rt_sigsuspend_wrapper:
+       llgtr   %r2,%r2                 # compat_sigset_t *
+       llgfr   %r3,%r3                 # compat_size_t
+       jg      compat_sys_rt_sigsuspend
 
        .globl  sys32_pread64_wrapper 
 sys32_pread64_wrapper:
@@ -1475,3 +1483,122 @@ sys_inotify_rm_watch_wrapper:
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # u32
        jg      sys_inotify_rm_watch
+
+       .globl compat_sys_openat_wrapper
+compat_sys_openat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       lgfr    %r4,%r4                 # int
+       lgfr    %r5,%r5                 # int
+       jg      compat_sys_openat
+
+       .globl sys_mkdirat_wrapper
+sys_mkdirat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       lgfr    %r4,%r4                 # int
+       jg      sys_mkdirat
+
+       .globl sys_mknodat_wrapper
+sys_mknodat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       lgfr    %r4,%r4                 # int
+       llgfr   %r5,%r5                 # unsigned int
+       jg      sys_mknodat
+
+       .globl sys_fchownat_wrapper
+sys_fchownat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       llgfr   %r4,%r4                 # uid_t
+       llgfr   %r5,%r5                 # gid_t
+       lgfr    %r6,%r6                 # int
+       jg      sys_fchownat
+
+       .globl compat_sys_futimesat_wrapper
+compat_sys_futimesat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # char *
+       llgtr   %r4,%r4                 # struct timeval *
+       jg      compat_sys_futimesat
+
+       .globl compat_sys_newfstatat_wrapper
+compat_sys_newfstatat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # char *
+       llgtr   %r4,%r4                 # struct stat *
+       lgfr    %r5,%r5                 # int
+       jg      compat_sys_newfstatat
+
+       .globl sys_unlinkat_wrapper
+sys_unlinkat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       lgfr    %r4,%r4                 # int
+       jg      sys_unlinkat
+
+       .globl sys_renameat_wrapper
+sys_renameat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       lgfr    %r4,%r4                 # int
+       llgtr   %r5,%r5                 # const char *
+       jg      sys_renameat
+
+       .globl sys_linkat_wrapper
+sys_linkat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       lgfr    %r4,%r4                 # int
+       llgtr   %r5,%r5                 # const char *
+       jg      sys_linkat
+
+       .globl sys_symlinkat_wrapper
+sys_symlinkat_wrapper:
+       llgtr   %r2,%r2                 # const char *
+       lgfr    %r3,%r3                 # int
+       llgtr   %r4,%r4                 # const char *
+       jg      sys_symlinkat
+
+       .globl sys_readlinkat_wrapper
+sys_readlinkat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       llgtr   %r4,%r4                 # char *
+       lgfr    %r5,%r5                 # int
+       jg      sys_readlinkat
+
+       .globl sys_fchmodat_wrapper
+sys_fchmodat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       llgfr   %r4,%r4                 # mode_t
+       jg      sys_fchmodat
+
+       .globl sys_faccessat_wrapper
+sys_faccessat_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char *
+       lgfr    %r4,%r4                 # int
+       jg      sys_faccessat
+
+       .globl compat_sys_pselect6_wrapper
+compat_sys_pselect6_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # fd_set *
+       llgtr   %r4,%r4                 # fd_set *
+       llgtr   %r5,%r5                 # fd_set *
+       llgtr   %r6,%r6                 # struct timespec *
+       llgt    %r0,164(%r15)           # void *
+       stg     %r0,160(%r15)
+       jg      compat_sys_pselect6
+
+       .globl compat_sys_ppoll_wrapper
+compat_sys_ppoll_wrapper:
+       llgtr   %r2,%r2                 # struct pollfd *
+       llgfr   %r3,%r3                 # unsigned int
+       llgtr   %r4,%r4                 # struct timespec *
+       llgtr   %r5,%r5                 # const sigset_t *
+       llgfr   %r6,%r6                 # size_t
+       jg      compat_sys_ppoll
index 27b0773..b244848 100644 (file)
@@ -2,8 +2,7 @@
  *  arch/s390/kernel/entry.S
  *    S390 low-level entry points.
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -50,9 +49,10 @@ SP_ILC       =  STACK_FRAME_OVERHEAD + __PT_ILC
 SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
 SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
-                _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+                _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+                _TIF_MCCK_PENDING)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -251,8 +251,8 @@ sysc_work:
        bo      BASED(sysc_mcck_pending)
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bo      BASED(sysc_reschedule)
-       tm      __TI_flags+3(%r9),_TIF_SIGPENDING
-       b     BASED(sysc_sigpending)
+       tm      __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       bnz     BASED(sysc_sigpending)
        tm      __TI_flags+3(%r9),_TIF_RESTART_SVC
        bo      BASED(sysc_restart)
        tm      __TI_flags+3(%r9),_TIF_SINGLE_STEP
@@ -276,12 +276,11 @@ sysc_mcck_pending:
        br      %r1                     # TIF bit will be cleared by handler
 
 #
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
 sysc_sigpending:     
        ni      __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        sr      %r3,%r3                # clear *oldset
         l       %r1,BASED(.Ldo_signal)
        basr    %r14,%r1               # call do_signal
        tm      __TI_flags+3(%r9),_TIF_RESTART_SVC
@@ -397,30 +396,6 @@ sys_rt_sigreturn_glue:
         l       %r1,BASED(.Lrt_sigreturn)
         br      %r1                   # branch to sys_sigreturn
 
-#
-# sigsuspend and rt_sigsuspend need pt_regs as an additional
-# parameter and they have to skip the store of %r2 into the
-# user register %r2 because the return value was set in 
-# sigsuspend and rt_sigsuspend already and must not be overwritten!
-#
-
-sys_sigsuspend_glue:    
-        lr      %r5,%r4               # move mask back
-        lr      %r4,%r3               # move history1 parameter
-        lr      %r3,%r2               # move history0 parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-        l       %r1,BASED(.Lsigsuspend)
-       la      %r14,4(%r14)          # skip store of return value
-        br      %r1                   # branch to sys_sigsuspend
-
-sys_rt_sigsuspend_glue: 
-        lr      %r4,%r3               # move sigsetsize parameter
-        lr      %r3,%r2               # move unewset parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-        l       %r1,BASED(.Lrt_sigsuspend)
-       la      %r14,4(%r14)          # skip store of return value
-        br      %r1                   # branch to sys_rt_sigsuspend
-
 sys_sigaltstack_glue:
         la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
         l       %r1,BASED(.Lsigaltstack)
@@ -604,15 +579,16 @@ io_work:
        lr      %r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
+# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED
+#              and _TIF_MCCK_PENDING
 #
 io_work_loop:
        tm      __TI_flags+3(%r9),_TIF_MCCK_PENDING
        bo      BASED(io_mcck_pending)
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bo      BASED(io_reschedule)
-       tm      __TI_flags+3(%r9),_TIF_SIGPENDING
-       b     BASED(io_sigpending)
+       tm      __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       bnz     BASED(io_sigpending)
        b       BASED(io_leave)
 
 #
@@ -636,12 +612,11 @@ io_reschedule:
        b       BASED(io_work_loop)
 
 #
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
 io_sigpending:     
         stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        sr      %r3,%r3                # clear *oldset
         l       %r1,BASED(.Ldo_signal)
        basr    %r14,%r1               # call do_signal
         stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
index 369ab44..2ac095b 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  arch/s390/kernel/entry.S
+ *  arch/s390/kernel/entry64.S
  *    S390 low-level entry points.
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -53,9 +52,10 @@ SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
-                _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+                _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+                _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -249,8 +249,8 @@ sysc_work:
        jo      sysc_mcck_pending
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jo      sysc_reschedule
-       tm      __TI_flags+7(%r9),_TIF_SIGPENDING
-       j     sysc_sigpending
+       tm      __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       jnz     sysc_sigpending
        tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
        jo      sysc_restart
        tm      __TI_flags+7(%r9),_TIF_SINGLE_STEP
@@ -272,12 +272,11 @@ sysc_mcck_pending:
        jg      s390_handle_mcck    # TIF bit will be cleared by handler
 
 #
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
 sysc_sigpending:     
        ni      __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
         la      %r2,SP_PTREGS(%r15) # load pt_regs
-        sgr     %r3,%r3           # clear *oldset
        brasl   %r14,do_signal    # call do_signal
        tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
        jo      sysc_restart
@@ -414,52 +413,6 @@ sys32_rt_sigreturn_glue:
         jg      sys32_rt_sigreturn    # branch to sys32_sigreturn
 #endif
 
-#
-# sigsuspend and rt_sigsuspend need pt_regs as an additional
-# parameter and they have to skip the store of %r2 into the
-# user register %r2 because the return value was set in 
-# sigsuspend and rt_sigsuspend already and must not be overwritten!
-#
-
-sys_sigsuspend_glue:    
-        lgr     %r5,%r4               # move mask back
-        lgr     %r4,%r3               # move history1 parameter
-        lgr     %r3,%r2               # move history0 parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-       la      %r14,6(%r14)          # skip store of return value
-        jg      sys_sigsuspend        # branch to sys_sigsuspend
-
-#ifdef CONFIG_COMPAT
-sys32_sigsuspend_glue:    
-       llgfr   %r4,%r4               # unsigned long                   
-        lgr     %r5,%r4               # move mask back
-       lgfr    %r3,%r3               # int                     
-        lgr     %r4,%r3               # move history1 parameter
-       lgfr    %r2,%r2               # int                     
-        lgr     %r3,%r2               # move history0 parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-       la      %r14,6(%r14)          # skip store of return value
-        jg      sys32_sigsuspend      # branch to sys32_sigsuspend
-#endif
-
-sys_rt_sigsuspend_glue: 
-        lgr     %r4,%r3               # move sigsetsize parameter
-        lgr     %r3,%r2               # move unewset parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-       la      %r14,6(%r14)          # skip store of return value
-        jg      sys_rt_sigsuspend     # branch to sys_rt_sigsuspend
-
-#ifdef CONFIG_COMPAT
-sys32_rt_sigsuspend_glue: 
-       llgfr   %r3,%r3               # size_t                  
-        lgr     %r4,%r3               # move sigsetsize parameter
-       llgtr   %r2,%r2               # sigset_emu31_t *
-        lgr     %r3,%r2               # move unewset parameter
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-       la      %r14,6(%r14)          # skip store of return value
-        jg      sys32_rt_sigsuspend   # branch to sys32_rt_sigsuspend
-#endif
-
 sys_sigaltstack_glue:
         la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
         jg      sys_sigaltstack       # branch to sys_sigreturn
@@ -646,15 +599,16 @@ io_work:
        lgr     %r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
+# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGPENDING, _TIF_NEED_RESCHED
+#             and _TIF_MCCK_PENDING
 #
 io_work_loop:
        tm      __TI_flags+7(%r9),_TIF_MCCK_PENDING
        jo      io_mcck_pending
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jo      io_reschedule
-       tm      __TI_flags+7(%r9),_TIF_SIGPENDING
-       j     io_sigpending
+       tm      __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       jnz     io_sigpending
        j       io_leave
 
 #
@@ -676,12 +630,11 @@ io_reschedule:
        j       io_work_loop
 
 #
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
 io_sigpending:     
        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        la      %r2,SP_PTREGS(%r15)     # load pt_regs
-       slgr    %r3,%r3                 # clear *oldset
        brasl   %r14,do_signal          # call do_signal
        stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
        j       io_work_loop
index 6ae4a77..ae1927e 100644 (file)
@@ -1,8 +1,7 @@
 /*
  *  arch/s390/kernel/signal.c
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *
  *    Based on Intel version
@@ -51,60 +50,24 @@ typedef struct
        struct ucontext uc;
 } rt_sigframe;
 
-int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int
-sys_sigsuspend(struct pt_regs * regs, int history0, int history1,
-              old_sigset_t mask)
+sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-       sigset_t saveset;
-
        mask &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        siginitset(&current->blocked, mask);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
-       regs->gprs[2] = -EINTR;
-
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
-}
-
-asmlinkage long
-sys_rt_sigsuspend(struct pt_regs *regs, sigset_t __user *unewset,
-                                               size_t sigsetsize)
-{
-       sigset_t saveset, newset;
 
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
 
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-       regs->gprs[2] = -EINTR;
-
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
+       return -ERESTARTNOHAND;
 }
 
 asmlinkage long
@@ -306,8 +269,8 @@ static inline int map_signal(int sig)
                return sig;
 }
 
-static void setup_frame(int sig, struct k_sigaction *ka,
-                       sigset_t *set, struct pt_regs * regs)
+static int setup_frame(int sig, struct k_sigaction *ka,
+                      sigset_t *set, struct pt_regs * regs)
 {
        sigframe __user *frame;
 
@@ -355,13 +318,14 @@ static void setup_frame(int sig, struct k_sigaction *ka,
        /* Place signal number on stack to allow backtrace from handler.  */
        if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
                goto give_sigsegv;
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                           sigset_t *set, struct pt_regs * regs)
 {
        int err = 0;
@@ -409,32 +373,39 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->gprs[2] = map_signal(sig);
        regs->gprs[3] = (unsigned long) &frame->info;
        regs->gprs[4] = (unsigned long) &frame->uc;
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */    
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka,
              siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
+       int ret;
+
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame(sig, ka, info, oldset, regs);
+               ret = setup_rt_frame(sig, ka, info, oldset, regs);
        else
-               setup_frame(sig, ka, oldset, regs);
+               ret = setup_frame(sig, ka, oldset, regs);
+
+       if (ret == 0) {
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+       }
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked,sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       return ret;
 }
 
 /*
@@ -446,12 +417,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+void do_signal(struct pt_regs *regs)
 {
        unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -460,9 +432,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
         * if so.
         */
        if (!user_mode(regs))
-               return 1;
+               return;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        /* Are we from a system call? */
@@ -473,12 +447,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
 
                /* Prepare for system call restart.  We do this here so that a
                   debugger will see the already changed PSW. */
-               if (retval == -ERESTARTNOHAND ||
-                   retval == -ERESTARTSYS ||
-                   retval == -ERESTARTNOINTR) {
+               switch (retval) {
+               case -ERESTARTNOHAND:
+               case -ERESTARTSYS:
+               case -ERESTARTNOINTR:
                        regs->gprs[2] = regs->orig_gpr2;
                        regs->psw.addr = restart_addr;
-               } else if (retval == -ERESTART_RESTARTBLOCK) {
+                       break;
+               case -ERESTART_RESTARTBLOCK:
                        regs->gprs[2] = -EINTR;
                }
        }
@@ -503,17 +479,38 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                /* Whee!  Actually deliver the signal.  */
 #ifdef CONFIG_COMPAT
                if (test_thread_flag(TIF_31BIT)) {
-                       extern void handle_signal32(unsigned long sig,
-                                                   struct k_sigaction *ka,
-                                                   siginfo_t *info,
-                                                   sigset_t *oldset,
-                                                   struct pt_regs *regs);
-                       handle_signal32(signr, &ka, &info, oldset, regs);
-                       return 1;
+                       extern int handle_signal32(unsigned long sig,
+                                                  struct k_sigaction *ka,
+                                                  siginfo_t *info,
+                                                  sigset_t *oldset,
+                                                  struct pt_regs *regs);
+                       if (handle_signal32(
+                                   signr, &ka, &info, oldset, regs) == 0) {
+                               if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+                       }
+                       return;
                }
 #endif
-               handle_signal(signr, &ka, &info, oldset, regs);
-               return 1;
+               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+                       /*
+                        * A signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag.
+                        */
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               }
+               return;
+       }
+
+       /*
+        * If there's no signal to deliver, we just put the saved sigmask back.
+        */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 
        /* Restart a different system call. */
@@ -522,5 +519,4 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                regs->gprs[2] = __NR_restart_syscall;
                set_thread_flag(TIF_RESTART_SVC);
        }
-       return 0;
 }
index 426d7ca..3280345 100644 (file)
@@ -80,7 +80,7 @@ NI_SYSCALL                                                    /* old sgetmask syscall*/
 NI_SYSCALL                                                     /* old ssetmask syscall*/
 SYSCALL(sys_setreuid16,sys_ni_syscall,sys32_setreuid16_wrapper)        /* old setreuid16 syscall */
 SYSCALL(sys_setregid16,sys_ni_syscall,sys32_setregid16_wrapper)        /* old setregid16 syscall */
-SYSCALL(sys_sigsuspend_glue,sys_sigsuspend_glue,sys32_sigsuspend_glue)
+SYSCALL(sys_sigsuspend,sys_sigsuspend,sys_sigsuspend_wrapper)
 SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending_wrapper)
 SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
 SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper)      /* 75 */
@@ -187,7 +187,7 @@ SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 1
 SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper)
 SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_sys_rt_sigtimedwait_wrapper)
 SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
-SYSCALL(sys_rt_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
+SYSCALL(sys_rt_sigsuspend,sys_rt_sigsuspend,compat_sys_rt_sigsuspend_wrapper)
 SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper)         /* 180 */
 SYSCALL(sys_pwrite64,sys_pwrite64,sys32_pwrite64_wrapper)
 SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper)      /* old chown16 syscall */
@@ -293,5 +293,21 @@ SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid_wrapper)
 SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper)
 SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper)
 SYSCALL(sys_inotify_init,sys_inotify_init,sys_inotify_init)
-SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper)
+SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper)     /* 285 */
 SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper)
+NI_SYSCALL                                                     /* 287 sys_migrate_pages */
+SYSCALL(sys_openat,sys_openat,compat_sys_openat_wrapper)
+SYSCALL(sys_mkdirat,sys_mkdirat,sys_mkdirat_wrapper)
+SYSCALL(sys_mknodat,sys_mknodat,sys_mknodat_wrapper)   /* 290 */
+SYSCALL(sys_fchownat,sys_fchownat,sys_fchownat_wrapper)
+SYSCALL(sys_futimesat,sys_futimesat,compat_sys_futimesat_wrapper)
+SYSCALL(sys_newfstatat,sys_newfstatat,compat_sys_newfstatat_wrapper)
+SYSCALL(sys_unlinkat,sys_unlinkat,sys_unlinkat_wrapper)
+SYSCALL(sys_renameat,sys_renameat,sys_renameat_wrapper)        /* 295 */
+SYSCALL(sys_linkat,sys_linkat,sys_linkat_wrapper)
+SYSCALL(sys_symlinkat,sys_symlinkat,sys_symlinkat_wrapper)
+SYSCALL(sys_readlinkat,sys_readlinkat,sys_readlinkat_wrapper)
+SYSCALL(sys_fchmodat,sys_fchmodat,sys_fchmodat_wrapper)
+SYSCALL(sys_faccessat,sys_faccessat,sys_faccessat_wrapper)     /* 300 */
+SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper)
+SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper)
index 7c0fe15..fea043b 100644 (file)
@@ -61,9 +61,18 @@ extern unsigned long wall_jiffies;
  */
 unsigned long long sched_clock(void)
 {
-       return ((get_clock() - jiffies_timer_cc) * 1000) >> 12;
+       return ((get_clock() - jiffies_timer_cc) * 125) >> 9;
 }
 
+/*
+ * Monotonic_clock - returns # of nanoseconds passed since time_init()
+ */
+unsigned long long monotonic_clock(void)
+{
+       return sched_clock();
+}
+EXPORT_SYMBOL(monotonic_clock);
+
 void tod_to_timeval(__u64 todval, struct timespec *xtime)
 {
        unsigned long long sec;
index f20b51f..e05d087 100644 (file)
@@ -6,4 +6,4 @@ EXTRA_AFLAGS := -traditional
 
 lib-y += delay.o string.o
 lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o)
-lib-$(CONFIG_SMP) += spinlock.o
\ No newline at end of file
+lib-$(CONFIG_SMP) += spinlock.o
index 01bc7d5..504d56f 100644 (file)
@@ -396,14 +396,8 @@ source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
 
 source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
 
-config SH_PCLK_FREQ_BOOL
-       bool "Set default pclk frequency"
-       default y if !SH_RTC
-       default n
-
 config SH_PCLK_FREQ
        int "Peripheral clock frequency (in Hz)"
-       depends on SH_PCLK_FREQ_BOOL
        default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
        default "60000000" if CPU_SUBTYPE_SH7751
        default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760
index fe83b2c..1ed7f88 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/pci.h>
 #include <linux/wait.h>
 #include <asm/io.h>
-#include <asm/mach/io.h>
+#include <asm/microdev.h>
 
        /*
         *      we need to have a 'safe' address to re-direct all I/O requests
 #define        IO_ISP1161_PHYS         0xa7700000ul    /* Physical address of Philips ISP1161x USB chip */
 #define        IO_SUPERIO_PHYS         0xa7800000ul    /* Physical address of SMSC FDC37C93xAPM SuperIO chip */
 
-#define PORT2ADDR(x) (microdev_isa_port2addr(x))
+/*
+ * map I/O ports to memory-mapped addresses
+ */
+static unsigned long microdev_isa_port2addr(unsigned long offset)
+{
+       unsigned long result;
+
+       if ((offset >= IO_LAN91C111_BASE) &&
+           (offset <  IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
+                       /*
+                        *      SMSC LAN91C111 Ethernet chip
+                        */
+               result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE;
+       } else if ((offset >= IO_SUPERIO_BASE) &&
+                  (offset <  IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) {
+                       /*
+                        *      SMSC FDC37C93xAPM SuperIO chip
+                        *
+                        *      Configuration Registers
+                        */
+               result = IO_SUPERIO_PHYS + (offset << 1);
+#if 0
+       } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG ||
+                  offset == KBD_STATUS_REG) {
+                       /*
+                        *      SMSC FDC37C93xAPM SuperIO chip
+                        *
+                        *      PS/2 Keyboard + Mouse (ports 0x60 and 0x64).
+                        */
+               result = IO_SUPERIO_PHYS + (offset << 1);
+#endif
+       } else if (((offset >= IO_IDE1_BASE) &&
+                   (offset <  IO_IDE1_BASE + IO_IDE_EXTENT)) ||
+                   (offset == IO_IDE1_MISC)) {
+                       /*
+                        *      SMSC FDC37C93xAPM SuperIO chip
+                        *
+                        *      IDE #1
+                        */
+               result = IO_SUPERIO_PHYS + (offset << 1);
+       } else if (((offset >= IO_IDE2_BASE) &&
+                   (offset <  IO_IDE2_BASE + IO_IDE_EXTENT)) ||
+                   (offset == IO_IDE2_MISC)) {
+                       /*
+                        *      SMSC FDC37C93xAPM SuperIO chip
+                        *
+                        *      IDE #2
+                        */
+               result = IO_SUPERIO_PHYS + (offset << 1);
+       } else if ((offset >= IO_SERIAL1_BASE) &&
+                  (offset <  IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) {
+                       /*
+                        *      SMSC FDC37C93xAPM SuperIO chip
+                        *
+                        *      Serial #1
+                        */
+               result = IO_SUPERIO_PHYS + (offset << 1);
+       } else if ((offset >= IO_SERIAL2_BASE) &&
+                  (offset <  IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) {
+                       /*
+                        *      SMSC FDC37C93xAPM SuperIO chip
+                        *
+                        *      Serial #2
+                        */
+               result = IO_SUPERIO_PHYS + (offset << 1);
+       } else if ((offset >= IO_ISP1161_BASE) &&
+                  (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) {
+                       /*
+                        *      Philips USB ISP1161x chip
+                        */
+               result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE;
+       } else {
+                       /*
+                        *      safe default.
+                        */
+               printk("Warning: unexpected port in %s( offset = 0x%lx )\n",
+                      __FUNCTION__, offset);
+               result = PVR;
+       }
+
+       return result;
+}
 
+#define PORT2ADDR(x) (microdev_isa_port2addr(x))
 
 static inline void delay(void)
 {
@@ -94,6 +176,17 @@ unsigned int microdev_inl(unsigned long port)
        return *(volatile unsigned int*)PORT2ADDR(port);
 }
 
+void microdev_outw(unsigned short b, unsigned long port)
+{
+#ifdef CONFIG_PCI
+       if (port >= PCIBIOS_MIN_IO) {
+               microdev_pci_outw(b, port);
+               return;
+       }
+#endif
+       *(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
 void microdev_outb(unsigned char b, unsigned long port)
 {
 #ifdef CONFIG_PCI
@@ -158,17 +251,6 @@ void microdev_outb(unsigned char b, unsigned long port)
        }
 }
 
-void microdev_outw(unsigned short b, unsigned long port)
-{
-#ifdef CONFIG_PCI
-       if (port >= PCIBIOS_MIN_IO) {
-               microdev_pci_outw(b, port);
-               return;
-       }
-#endif
-       *(volatile unsigned short*)PORT2ADDR(port) = b;
-}
-
 void microdev_outl(unsigned int b, unsigned long port)
 {
 #ifdef CONFIG_PCI
@@ -284,87 +366,3 @@ void microdev_outsl(unsigned long port, const void *buffer, unsigned long count)
        while (count--)
                *port_addr = *buf++;
 }
-
-/*
- * map I/O ports to memory-mapped addresses
- */
-unsigned long microdev_isa_port2addr(unsigned long offset)
-{
-       unsigned long result;
-
-       if ((offset >= IO_LAN91C111_BASE) &&
-           (offset <  IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
-                       /*
-                        *      SMSC LAN91C111 Ethernet chip
-                        */
-               result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE;
-       } else if ((offset >= IO_SUPERIO_BASE) &&
-                  (offset <  IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) {
-                       /*
-                        *      SMSC FDC37C93xAPM SuperIO chip
-                        *
-                        *      Configuration Registers
-                        */
-               result = IO_SUPERIO_PHYS + (offset << 1);
-#if 0
-       } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG ||
-                  offset == KBD_STATUS_REG) {
-                       /*
-                        *      SMSC FDC37C93xAPM SuperIO chip
-                        *
-                        *      PS/2 Keyboard + Mouse (ports 0x60 and 0x64).
-                        */
-               result = IO_SUPERIO_PHYS + (offset << 1);
-#endif
-       } else if (((offset >= IO_IDE1_BASE) &&
-                   (offset <  IO_IDE1_BASE + IO_IDE_EXTENT)) ||
-                   (offset == IO_IDE1_MISC)) {
-                       /*
-                        *      SMSC FDC37C93xAPM SuperIO chip
-                        *
-                        *      IDE #1
-                        */
-               result = IO_SUPERIO_PHYS + (offset << 1);
-       } else if (((offset >= IO_IDE2_BASE) &&
-                   (offset <  IO_IDE2_BASE + IO_IDE_EXTENT)) ||
-                   (offset == IO_IDE2_MISC)) {
-                       /*
-                        *      SMSC FDC37C93xAPM SuperIO chip
-                        *
-                        *      IDE #2
-                        */
-               result = IO_SUPERIO_PHYS + (offset << 1);
-       } else if ((offset >= IO_SERIAL1_BASE) &&
-                  (offset <  IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) {
-                       /*
-                        *      SMSC FDC37C93xAPM SuperIO chip
-                        *
-                        *      Serial #1
-                        */
-               result = IO_SUPERIO_PHYS + (offset << 1);
-       } else if ((offset >= IO_SERIAL2_BASE) &&
-                  (offset <  IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) {
-                       /*
-                        *      SMSC FDC37C93xAPM SuperIO chip
-                        *
-                        *      Serial #2
-                        */
-               result = IO_SUPERIO_PHYS + (offset << 1);
-       } else if ((offset >= IO_ISP1161_BASE) &&
-                  (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) {
-                       /*
-                        *      Philips USB ISP1161x chip
-                        */
-               result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE;
-       } else {
-                       /*
-                        *      safe default.
-                        */
-               printk("Warning: unexpected port in %s( offset = 0x%lx )\n",
-                      __FUNCTION__, offset);
-               result = PVR;
-       }
-
-       return result;
-}
-
index 1395c1e..efcbd86 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/mach/irq.h>
+#include <asm/microdev.h>
 
 #define NUM_EXTERNAL_IRQS 16   /* IRL0 .. IRL15 */
 
index 1c1d65f..892b14d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
  * Copyright (C) 2003, 2004 SuperH, Inc.
- * Copyright (C) 2004 Paul Mundt
+ * Copyright (C) 2004, 2005 Paul Mundt
  *
  * SuperH SH4-202 MicroDev board support.
  *
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
+#include <video/s1d13xxxfb.h>
+#include <asm/microdev.h>
 #include <asm/io.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/io.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
 
 extern void microdev_heartbeat(void);
 
@@ -51,8 +50,6 @@ struct sh_machine_vector mv_sh4202_microdev __initmv = {
        .mv_outsw               = microdev_outsw,
        .mv_outsl               = microdev_outsl,
 
-       .mv_isa_port2addr       = microdev_isa_port2addr,
-
        .mv_init_irq            = init_microdev_irq,
 
 #ifdef CONFIG_HEARTBEAT
@@ -142,16 +139,161 @@ static struct platform_device smc91x_device = {
        .resource       = smc91x_resources,
 };
 
-static int __init smc91x_setup(void)
+#ifdef CONFIG_FB_S1D13XXX
+static struct s1d13xxxfb_regval s1d13806_initregs[] = {
+       { S1DREG_MISC,                  0x00 },
+       { S1DREG_COM_DISP_MODE,         0x00 },
+       { S1DREG_GPIO_CNF0,             0x00 },
+       { S1DREG_GPIO_CNF1,             0x00 },
+       { S1DREG_GPIO_CTL0,             0x00 },
+       { S1DREG_GPIO_CTL1,             0x00 },
+       { S1DREG_CLK_CNF,               0x02 },
+       { S1DREG_LCD_CLK_CNF,           0x01 },
+       { S1DREG_CRT_CLK_CNF,           0x03 },
+       { S1DREG_MPLUG_CLK_CNF,         0x03 },
+       { S1DREG_CPU2MEM_WST_SEL,       0x02 },
+       { S1DREG_SDRAM_REF_RATE,        0x03 },
+       { S1DREG_SDRAM_TC0,             0x00 },
+       { S1DREG_SDRAM_TC1,             0x01 },
+       { S1DREG_MEM_CNF,               0x80 },
+       { S1DREG_PANEL_TYPE,            0x25 },
+       { S1DREG_MOD_RATE,              0x00 },
+       { S1DREG_LCD_DISP_HWIDTH,       0x63 },
+       { S1DREG_LCD_NDISP_HPER,        0x1e },
+       { S1DREG_TFT_FPLINE_START,      0x06 },
+       { S1DREG_TFT_FPLINE_PWIDTH,     0x03 },
+       { S1DREG_LCD_DISP_VHEIGHT0,     0x57 },
+       { S1DREG_LCD_DISP_VHEIGHT1,     0x02 },
+       { S1DREG_LCD_NDISP_VPER,        0x00 },
+       { S1DREG_TFT_FPFRAME_START,     0x0a },
+       { S1DREG_TFT_FPFRAME_PWIDTH,    0x81 },
+       { S1DREG_LCD_DISP_MODE,         0x03 },
+       { S1DREG_LCD_MISC,              0x00 },
+       { S1DREG_LCD_DISP_START0,       0x00 },
+       { S1DREG_LCD_DISP_START1,       0x00 },
+       { S1DREG_LCD_DISP_START2,       0x00 },
+       { S1DREG_LCD_MEM_OFF0,          0x90 },
+       { S1DREG_LCD_MEM_OFF1,          0x01 },
+       { S1DREG_LCD_PIX_PAN,           0x00 },
+       { S1DREG_LCD_DISP_FIFO_HTC,     0x00 },
+       { S1DREG_LCD_DISP_FIFO_LTC,     0x00 },
+       { S1DREG_CRT_DISP_HWIDTH,       0x63 },
+       { S1DREG_CRT_NDISP_HPER,        0x1f },
+       { S1DREG_CRT_HRTC_START,        0x04 },
+       { S1DREG_CRT_HRTC_PWIDTH,       0x8f },
+       { S1DREG_CRT_DISP_VHEIGHT0,     0x57 },
+       { S1DREG_CRT_DISP_VHEIGHT1,     0x02 },
+       { S1DREG_CRT_NDISP_VPER,        0x1b },
+       { S1DREG_CRT_VRTC_START,        0x00 },
+       { S1DREG_CRT_VRTC_PWIDTH,       0x83 },
+       { S1DREG_TV_OUT_CTL,            0x10 },
+       { S1DREG_CRT_DISP_MODE,         0x05 },
+       { S1DREG_CRT_DISP_START0,       0x00 },
+       { S1DREG_CRT_DISP_START1,       0x00 },
+       { S1DREG_CRT_DISP_START2,       0x00 },
+       { S1DREG_CRT_MEM_OFF0,          0x20 },
+       { S1DREG_CRT_MEM_OFF1,          0x03 },
+       { S1DREG_CRT_PIX_PAN,           0x00 },
+       { S1DREG_CRT_DISP_FIFO_HTC,     0x00 },
+       { S1DREG_CRT_DISP_FIFO_LTC,     0x00 },
+       { S1DREG_LCD_CUR_CTL,           0x00 },
+       { S1DREG_LCD_CUR_START,         0x01 },
+       { S1DREG_LCD_CUR_XPOS0,         0x00 },
+       { S1DREG_LCD_CUR_XPOS1,         0x00 },
+       { S1DREG_LCD_CUR_YPOS0,         0x00 },
+       { S1DREG_LCD_CUR_YPOS1,         0x00 },
+       { S1DREG_LCD_CUR_BCTL0,         0x00 },
+       { S1DREG_LCD_CUR_GCTL0,         0x00 },
+       { S1DREG_LCD_CUR_RCTL0,         0x00 },
+       { S1DREG_LCD_CUR_BCTL1,         0x1f },
+       { S1DREG_LCD_CUR_GCTL1,         0x3f },
+       { S1DREG_LCD_CUR_RCTL1,         0x1f },
+       { S1DREG_LCD_CUR_FIFO_HTC,      0x00 },
+       { S1DREG_CRT_CUR_CTL,           0x00 },
+       { S1DREG_CRT_CUR_START,         0x01 },
+       { S1DREG_CRT_CUR_XPOS0,         0x00 },
+       { S1DREG_CRT_CUR_XPOS1,         0x00 },
+       { S1DREG_CRT_CUR_YPOS0,         0x00 },
+       { S1DREG_CRT_CUR_YPOS1,         0x00 },
+       { S1DREG_CRT_CUR_BCTL0,         0x00 },
+       { S1DREG_CRT_CUR_GCTL0,         0x00 },
+       { S1DREG_CRT_CUR_RCTL0,         0x00 },
+       { S1DREG_CRT_CUR_BCTL1,         0x1f },
+       { S1DREG_CRT_CUR_GCTL1,         0x3f },
+       { S1DREG_CRT_CUR_RCTL1,         0x1f },
+       { S1DREG_CRT_CUR_FIFO_HTC,      0x00 },
+       { S1DREG_BBLT_CTL0,             0x00 },
+       { S1DREG_BBLT_CTL1,             0x00 },
+       { S1DREG_BBLT_CC_EXP,           0x00 },
+       { S1DREG_BBLT_OP,               0x00 },
+       { S1DREG_BBLT_SRC_START0,       0x00 },
+       { S1DREG_BBLT_SRC_START1,       0x00 },
+       { S1DREG_BBLT_SRC_START2,       0x00 },
+       { S1DREG_BBLT_DST_START0,       0x00 },
+       { S1DREG_BBLT_DST_START1,       0x00 },
+       { S1DREG_BBLT_DST_START2,       0x00 },
+       { S1DREG_BBLT_MEM_OFF0,         0x00 },
+       { S1DREG_BBLT_MEM_OFF1,         0x00 },
+       { S1DREG_BBLT_WIDTH0,           0x00 },
+       { S1DREG_BBLT_WIDTH1,           0x00 },
+       { S1DREG_BBLT_HEIGHT0,          0x00 },
+       { S1DREG_BBLT_HEIGHT1,          0x00 },
+       { S1DREG_BBLT_BGC0,             0x00 },
+       { S1DREG_BBLT_BGC1,             0x00 },
+       { S1DREG_BBLT_FGC0,             0x00 },
+       { S1DREG_BBLT_FGC1,             0x00 },
+       { S1DREG_LKUP_MODE,             0x00 },
+       { S1DREG_LKUP_ADDR,             0x00 },
+       { S1DREG_PS_CNF,                0x10 },
+       { S1DREG_PS_STATUS,             0x00 },
+       { S1DREG_CPU2MEM_WDOGT,         0x00 },
+       { S1DREG_COM_DISP_MODE,         0x02 },
+};
+
+static struct s1d13xxxfb_pdata s1d13806_platform_data = {
+       .initregs       = s1d13806_initregs,
+       .initregssize   = ARRAY_SIZE(s1d13806_initregs),
+};
+
+static struct resource s1d13806_resources[] = {
+       [0] = {
+               .start          = 0x07200000,
+               .end            = 0x07200000 + 0x00200000 - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start          = 0x07000000,
+               .end            = 0x07000000 + 0x00200000 - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device s1d13806_device = {
+       .name           = "s1d13806fb",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s1d13806_resources),
+       .resource       = s1d13806_resources,
+
+       .dev = {
+               .platform_data  = &s1d13806_platform_data,
+       },
+};
+#endif
+
+static struct platform_device *microdev_devices[] __initdata = {
+       &smc91x_device,
+#ifdef CONFIG_FB_S1D13XXX
+       &s1d13806_device,
+#endif
+};
+
+static int __init microdev_devices_setup(void)
 {
-       return platform_device_register(&smc91x_device);
+       return platform_add_devices(microdev_devices, ARRAY_SIZE(microdev_devices));
 }
 
-__initcall(smc91x_setup);
+__initcall(microdev_devices_setup);
 
-       /*
-        * Initialize the board
-        */
 void __init platform_setup(void)
 {
        int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
index cffc210..7d18f40 100644 (file)
@@ -2,5 +2,5 @@
 # Makefile for unknown SH boards 
 #
 
-obj-y   := mach.o io.o setup.o
+obj-y   := setup.o
 
diff --git a/arch/sh/boards/unknown/io.c b/arch/sh/boards/unknown/io.c
deleted file mode 100644 (file)
index 8f3f172..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/arch/sh/kernel/io_unknown.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * I/O routine for unknown hardware.
- */
-
-static unsigned int unknown_handler(void)
-{
-       return 0;
-}
-
-#define UNKNOWN_ALIAS(fn) \
-       void unknown_##fn(void) __attribute__ ((alias ("unknown_handler")));
-
-UNKNOWN_ALIAS(inb)
-UNKNOWN_ALIAS(inw)
-UNKNOWN_ALIAS(inl)
-UNKNOWN_ALIAS(outb)
-UNKNOWN_ALIAS(outw)
-UNKNOWN_ALIAS(outl)
-UNKNOWN_ALIAS(inb_p)
-UNKNOWN_ALIAS(inw_p)
-UNKNOWN_ALIAS(inl_p)
-UNKNOWN_ALIAS(outb_p)
-UNKNOWN_ALIAS(outw_p)
-UNKNOWN_ALIAS(outl_p)
-UNKNOWN_ALIAS(insb)
-UNKNOWN_ALIAS(insw)
-UNKNOWN_ALIAS(insl)
-UNKNOWN_ALIAS(outsb)
-UNKNOWN_ALIAS(outsw)
-UNKNOWN_ALIAS(outsl)
-UNKNOWN_ALIAS(readb)
-UNKNOWN_ALIAS(readw)
-UNKNOWN_ALIAS(readl)
-UNKNOWN_ALIAS(writeb)
-UNKNOWN_ALIAS(writew)
-UNKNOWN_ALIAS(writel)
-UNKNOWN_ALIAS(isa_port2addr)
-UNKNOWN_ALIAS(ioremap)
-UNKNOWN_ALIAS(iounmap)
diff --git a/arch/sh/boards/unknown/mach.c b/arch/sh/boards/unknown/mach.c
deleted file mode 100644 (file)
index ad0bcc6..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_unknown.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine specific code for an unknown machine (internal peripherials only)
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io_unknown.h>
-
-#include <asm/rtc.h>
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_unknown __initmv = {
-#if defined(CONFIG_CPU_SH4)
-       .mv_nr_irqs             = 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
-       .mv_nr_irqs             = 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
-       .mv_nr_irqs             = 61,
-#endif
-
-       .mv_inb                 = unknown_inb,
-       .mv_inw                 = unknown_inw,
-       .mv_inl                 = unknown_inl,
-       .mv_outb                = unknown_outb,
-       .mv_outw                = unknown_outw,
-       .mv_outl                = unknown_outl,
-
-       .mv_inb_p               = unknown_inb_p,
-       .mv_inw_p               = unknown_inw_p,
-       .mv_inl_p               = unknown_inl_p,
-       .mv_outb_p              = unknown_outb_p,
-       .mv_outw_p              = unknown_outw_p,
-       .mv_outl_p              = unknown_outl_p,
-
-       .mv_insb                = unknown_insb,
-       .mv_insw                = unknown_insw,
-       .mv_insl                = unknown_insl,
-       .mv_outsb               = unknown_outsb,
-       .mv_outsw               = unknown_outsw,
-       .mv_outsl               = unknown_outsl,
-
-       .mv_readb               = unknown_readb,
-       .mv_readw               = unknown_readw,
-       .mv_readl               = unknown_readl,
-       .mv_writeb              = unknown_writeb,
-       .mv_writew              = unknown_writew,
-       .mv_writel              = unknown_writel,
-
-       .mv_ioremap             = unknown_ioremap,
-       .mv_iounmap             = unknown_iounmap,
-
-       .mv_isa_port2addr       = unknown_isa_port2addr,
-};
-ALIAS_MV(unknown)
index 7d772a6..02e84f0 100644 (file)
@@ -7,10 +7,20 @@
  * License.  See linux/COPYING for more information.
  *
  * Setup code for an unknown machine (internal peripherials only)
+ *
+ * This is the simplest of all boards, and serves only as a quick and dirty
+ * method to start debugging a new board during bring-up until proper board
+ * setup code is written.
  */
-
 #include <linux/config.h>
 #include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/irq.h>
+
+struct sh_machine_vector mv_unknown __initmv = {
+       .mv_nr_irqs             = NR_IRQS,
+};
+ALIAS_MV(unknown)
 
 const char *get_system_type(void)
 {
index 3d9a02c..07e8b9c 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <asm/io.h>
-#include <asm/bus-sh.h>
+
 
 struct voya_alloc_entry {
        struct list_head list;
@@ -30,12 +30,13 @@ static LIST_HEAD(voya_alloc_list);
 #define OHCI_HCCA_SIZE 0x100
 #define OHCI_SRAM_SIZE 0x10000
 
+#define VOYAGER_OHCI_NAME      "voyager-ohci"
+
 void *voyagergx_consistent_alloc(struct device *dev, size_t size,
                                 dma_addr_t *handle, gfp_t flag)
 {
        struct list_head *list = &voya_alloc_list;
        struct voya_alloc_entry *entry;
-       struct sh_dev *shdev = to_sh_dev(dev);
        unsigned long start, end;
        unsigned long flags;
 
@@ -46,9 +47,7 @@ void *voyagergx_consistent_alloc(struct device *dev, size_t size,
         *
         * Everything else goes through consistent_alloc().
         */
-       if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
-                  (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
-                   shdev->dev_id != SH_DEV_ID_USB_OHCI))
+       if (!dev || strcmp(dev->driver->name, VOYAGER_OHCI_NAME))
                return NULL;
 
        start = OHCI_SRAM_START + OHCI_HCCA_SIZE;
@@ -98,12 +97,9 @@ int voyagergx_consistent_free(struct device *dev, size_t size,
                              void *vaddr, dma_addr_t handle)
 {
        struct voya_alloc_entry *entry;
-       struct sh_dev *shdev = to_sh_dev(dev);
        unsigned long flags;
 
-       if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
-                  (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
-                   shdev->dev_id != SH_DEV_ID_USB_OHCI))
+       if (!dev || strcmp(dev->driver->name, VOYAGER_OHCI_NAME))
                return -EINVAL;
 
        spin_lock_irqsave(&voya_list_lock, flags);
@@ -123,4 +119,3 @@ int voyagergx_consistent_free(struct device *dev, size_t size,
 
 EXPORT_SYMBOL(voyagergx_consistent_alloc);
 EXPORT_SYMBOL(voyagergx_consistent_free);
-
index 1b6ac52..2ee330b 100644 (file)
@@ -163,7 +163,12 @@ int voyagergx_irq_demux(int irq)
        return irq;
 }
 
-static struct irqaction irq0  = { voyagergx_interrupt, SA_INTERRUPT, 0, "VOYAGERGX", NULL, NULL};
+static struct irqaction irq0  = {
+       .name           = "voyagergx",
+       .handler        = voyagergx_interrupt,
+       .flags          = SA_INTERRUPT,
+       .mask           = CPU_MASK_NONE,
+};
 
 void __init setup_voyagergx_irq(void)
 {
index a3bd280..ab3db76 100644 (file)
@@ -1,10 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-sh
-# Wed Mar  2 15:09:41 2005
+# Linux kernel version: 2.6.16-rc1
+# Fri Jan 27 19:43:20 2006
 #
 CONFIG_SUPERH=y
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -17,11 +16,13 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
@@ -29,28 +30,53 @@ CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
 #
 # CONFIG_MODULES is not set
 
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
 #
 # System type
 #
@@ -61,9 +87,7 @@ CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
-# CONFIG_SH_HP620 is not set
-# CONFIG_SH_HP680 is not set
-# CONFIG_SH_HP690 is not set
+# CONFIG_SH_HP6XX is not set
 # CONFIG_SH_CQREEK is not set
 # CONFIG_SH_DMIDA is not set
 # CONFIG_SH_EC3104 is not set
@@ -78,45 +102,94 @@ CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
 # CONFIG_SH_EDOSK7705 is not set
 CONFIG_SH_SH4202_MICRODEV=y
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
 # CONFIG_SH_UNKNOWN is not set
-# CONFIG_CPU_SH2 is not set
-# CONFIG_CPU_SH3 is not set
+
+#
+# Processor selection
+#
 CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
 # CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
-# CONFIG_CPU_SUBTYPE_SH73180 is not set
+CONFIG_CPU_SUBTYPE_SH4_202=y
+
+#
+# ST40 Processor Support
+#
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-CONFIG_CPU_SUBTYPE_SH4_202=y
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
 CONFIG_MMU=y
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttySC0,115200"
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x04000000
-CONFIG_MEMORY_SET=y
-# CONFIG_MEMORY_OVERRIDE is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SH_RTC=y
 CONFIG_SH_FPU=y
-CONFIG_ZERO_PAGE_OFFSET=0x00001000
-CONFIG_BOOT_LINK_OFFSET=0x00800000
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_PREEMPT=y
-# CONFIG_UBC_WAKEUP is not set
-# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
 # CONFIG_SH_STORE_QUEUES is not set
-# CONFIG_SMP is not set
-CONFIG_SH_PCLK_CALC=y
-CONFIG_SH_PCLK_FREQ=65986048
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=66000000
 
 #
 # CPU Frequency scaling
@@ -137,20 +210,31 @@ CONFIG_NR_ONCHIP_DMA_CHANNELS=4
 CONFIG_HEARTBEAT=y
 
 #
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+# Kernel features
 #
-CONFIG_ISA=y
-# CONFIG_PCI is not set
+# CONFIG_KEXEC is not set
+CONFIG_PREEMPT=y
+# CONFIG_SMP is not set
 
 #
-# PCCARD (PCMCIA/CardBus) support
+# Boot options
 #
-# CONFIG_PCCARD is not set
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200"
 
 #
-# PC-card bridges
+# Bus options
 #
-CONFIG_PCMCIA_PROBE=y
+# CONFIG_SUPERHYWAY is not set
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -164,9 +248,79 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 
 #
-# SH initrd options
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_UNIX is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
 #
-# CONFIG_EMBEDDED_RAMDISK is not set
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -179,6 +333,11 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -192,13 +351,10 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -206,17 +362,7 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -241,9 +387,7 @@ CONFIG_BLK_DEV_IDECD=y
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-CONFIG_IDE_SH=y
 # CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -251,13 +395,9 @@ CONFIG_IDE_SH=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
 #
 # Multi-device support (RAID and LVM)
 #
@@ -266,6 +406,7 @@ CONFIG_IDE_SH=y
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -276,69 +417,8 @@ CONFIG_IDE_SH=y
 #
 
 #
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_UNIX is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
 #
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -346,9 +426,9 @@ CONFIG_NETDEVICES=y
 # CONFIG_TUN is not set
 
 #
-# ARCnet devices
+# PHY device support
 #
-# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -356,17 +436,7 @@ CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 # CONFIG_STNIC is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
 CONFIG_SMC91X=y
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -379,7 +449,6 @@ CONFIG_SMC91X=y
 #
 # Token Ring devices
 #
-# CONFIG_TR is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -394,6 +463,8 @@ CONFIG_SMC91X=y
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -411,20 +482,10 @@ CONFIG_SMC91X=y
 # CONFIG_INPUT is not set
 
 #
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
+# Hardware I/O ports
 #
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
-# Input Device Drivers
-#
+# CONFIG_GAMEPORT is not set
 
 #
 # Character devices
@@ -464,23 +525,45 @@ CONFIG_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
 #
 # I2C support
 #
 # CONFIG_I2C is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
 
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
 #
 # Misc devices
 #
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -508,7 +591,7 @@ CONFIG_RTC=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
 #
 
 #
@@ -524,13 +607,21 @@ CONFIG_RTC=y
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# EDAC - error detection and reporting (RAS)
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -540,17 +631,17 @@ CONFIG_JBD=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -574,16 +665,12 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -607,12 +694,14 @@ CONFIG_RAMFS=y
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
@@ -622,6 +711,7 @@ CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -681,8 +771,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
@@ -706,6 +798,7 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -730,5 +823,6 @@ CONFIG_CRYPTO_DES=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
index 7a86eeb..f05cd96 100644 (file)
@@ -8,7 +8,7 @@ obj-y   := process.o signal.o entry.o traps.o irq.o \
        ptrace.o setup.o time.o sys_sh.o semaphore.o \
        io.o io_generic.o sh_ksyms.o
 
-obj-y                          += cpu/
+obj-y                          += cpu/ timers/
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_CF_ENABLER)       += cf-enabler.o
index 5bfc33b..59d5b74 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the Linux/SuperH CPU-specifc backends.
 #
 
-obj-y  += irq/ init.o bus.o clock.o
+obj-y  += irq/ init.o clock.o
 
 obj-$(CONFIG_CPU_SH2)          += sh2/
 obj-$(CONFIG_CPU_SH3)          += sh3/
diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c
deleted file mode 100644 (file)
index fc6c4bd..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * arch/sh/kernel/cpu/bus.c
- *
- * Virtual bus for SuperH.
- *
- * Copyright (C) 2004 Paul Mundt
- *
- * Shamelessly cloned from arch/arm/mach-omap/bus.c, which was written
- * by:
- *
- *     Copyright (C) 2003 - 2004 Nokia Corporation
- *     Written by Tony Lindgren <tony@atomide.com>
- *     Portions of code based on sa1111.c.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <asm/bus-sh.h>
-
-static int sh_bus_match(struct device *dev, struct device_driver *drv)
-{
-       struct sh_driver *shdrv = to_sh_driver(drv);
-       struct sh_dev *shdev = to_sh_dev(dev);
-
-       return shdev->dev_id == shdrv->dev_id;
-}
-
-static int sh_bus_suspend(struct device *dev, pm_message_t state)
-{
-       struct sh_dev *shdev = to_sh_dev(dev);
-       struct sh_driver *shdrv = to_sh_driver(dev->driver);
-
-       if (shdrv && shdrv->suspend)
-               return shdrv->suspend(shdev, state);
-
-       return 0;
-}
-
-static int sh_bus_resume(struct device *dev)
-{
-       struct sh_dev *shdev = to_sh_dev(dev);
-       struct sh_driver *shdrv = to_sh_driver(dev->driver);
-
-       if (shdrv && shdrv->resume)
-               return shdrv->resume(shdev);
-
-       return 0;
-}
-
-static int sh_device_probe(struct device *dev)
-{
-       struct sh_dev *shdev = to_sh_dev(dev);
-       struct sh_driver *shdrv = to_sh_driver(dev->driver);
-
-       if (shdrv && shdrv->probe)
-               return shdrv->probe(shdev);
-
-       return -ENODEV;
-}
-
-static int sh_device_remove(struct device *dev)
-{
-       struct sh_dev *shdev = to_sh_dev(dev);
-       struct sh_driver *shdrv = to_sh_driver(dev->driver);
-
-       if (shdrv && shdrv->remove)
-               return shdrv->remove(shdev);
-
-       return 0;
-}
-
-static struct device sh_bus_devices[SH_NR_BUSES] = {
-       {
-               .bus_id         = SH_BUS_NAME_VIRT,
-       },
-};
-
-struct bus_type sh_bus_types[SH_NR_BUSES] = {
-       {
-               .name           = SH_BUS_NAME_VIRT,
-               .match          = sh_bus_match,
-               .probe          = sh_bus_probe,
-               .remove         = sh_bus_remove,
-               .suspend        = sh_bus_suspend,
-               .resume         = sh_bus_resume,
-       },
-};
-
-int sh_device_register(struct sh_dev *dev)
-{
-       if (!dev)
-               return -EINVAL;
-
-       if (dev->bus_id < 0 || dev->bus_id >= SH_NR_BUSES) {
-               printk(KERN_ERR "%s: bus_id invalid: %s bus: %d\n",
-                      __FUNCTION__, dev->name, dev->bus_id);
-               return -EINVAL;
-       }
-
-       dev->dev.parent = &sh_bus_devices[dev->bus_id];
-       dev->dev.bus    = &sh_bus_types[dev->bus_id];
-
-       /* This is needed for USB OHCI to work */
-       if (dev->dma_mask)
-               dev->dev.dma_mask = dev->dma_mask;
-       if (dev->coherent_dma_mask)
-               dev->dev.coherent_dma_mask = dev->coherent_dma_mask;
-
-       snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u",
-                dev->name, dev->dev_id);
-
-       printk(KERN_INFO "Registering SH device '%s'. Parent at %s\n",
-              dev->dev.bus_id, dev->dev.parent->bus_id);
-
-       return device_register(&dev->dev);
-}
-
-void sh_device_unregister(struct sh_dev *dev)
-{
-       device_unregister(&dev->dev);
-}
-
-int sh_driver_register(struct sh_driver *drv)
-{
-       if (!drv)
-               return -EINVAL;
-
-       if (drv->bus_id < 0 || drv->bus_id >= SH_NR_BUSES) {
-               printk(KERN_ERR "%s: bus_id invalid: bus: %d device %d\n",
-                      __FUNCTION__, drv->bus_id, drv->dev_id);
-               return -EINVAL;
-       }
-
-       drv->drv.bus    = &sh_bus_types[drv->bus_id];
-
-       return driver_register(&drv->drv);
-}
-
-void sh_driver_unregister(struct sh_driver *drv)
-{
-       driver_unregister(&drv->drv);
-}
-
-static int __init sh_bus_init(void)
-{
-       int i, ret = 0;
-
-       for (i = 0; i < SH_NR_BUSES; i++) {
-               ret = device_register(&sh_bus_devices[i]);
-               if (ret != 0) {
-                       printk(KERN_ERR "Unable to register bus device %s\n",
-                              sh_bus_devices[i].bus_id);
-                       continue;
-               }
-
-               ret = bus_register(&sh_bus_types[i]);
-               if (ret != 0) {
-                       printk(KERN_ERR "Unable to register bus %s\n",
-                              sh_bus_types[i].name);
-                       device_unregister(&sh_bus_devices[i]);
-               }
-       }
-
-       printk(KERN_INFO "SH Virtual Bus initialized\n");
-
-       return ret;
-}
-
-static void __exit sh_bus_exit(void)
-{
-       int i;
-
-       for (i = 0; i < SH_NR_BUSES; i++) {
-               bus_unregister(&sh_bus_types[i]);
-               device_unregister(&sh_bus_devices[i]);
-       }
-}
-
-module_init(sh_bus_init);
-module_exit(sh_bus_exit);
-
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
-MODULE_DESCRIPTION("SH Virtual Bus");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(sh_bus_types);
-EXPORT_SYMBOL(sh_device_register);
-EXPORT_SYMBOL(sh_device_unregister);
-EXPORT_SYMBOL(sh_driver_register);
-EXPORT_SYMBOL(sh_driver_unregister);
-
index 989e7fd..97fa37f 100644 (file)
@@ -38,9 +38,7 @@ static DECLARE_MUTEX(clock_list_sem);
 static struct clk master_clk = {
        .name           = "master_clk",
        .flags          = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
-#ifdef CONFIG_SH_PCLK_FREQ_BOOL
        .rate           = CONFIG_SH_PCLK_FREQ,
-#endif
 };
 
 static struct clk module_clk = {
@@ -227,16 +225,7 @@ int __init clk_init(void)
 {
        int i, ret = 0;
 
-       if (unlikely(!master_clk.rate))
-               /*
-                * NOTE: This will break if the default divisor has been
-                * changed.
-                *
-                * No one should be changing the default on us however,
-                * expect that a sane value for CONFIG_SH_PCLK_FREQ will
-                * be defined in the event of a different divisor.
-                */
-               master_clk.rate = get_timer_frequency() * 4;
+       BUG_ON(unlikely(!master_clk.rate));
 
        for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
                struct clk *clk = onchip_clocks[i];
index fdbd718..e55150e 100644 (file)
@@ -108,8 +108,7 @@ static void end_ipr_irq(unsigned int irq)
                enable_ipr_irq(irq);
 }
 
-void make_ipr_irq(unsigned int irq, unsigned int addr, int pos,
-                 int priority, int maskpos)
+void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
 {
        disable_irq_nosync(irq);
        ipr_data[irq].addr = addr;
@@ -123,44 +122,44 @@ void make_ipr_irq(unsigned int irq, unsigned int addr, int pos,
 void __init init_IRQ(void)
 {
 #ifndef CONFIG_CPU_SUBTYPE_SH7780
-       make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY, 0);
-       make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY, 0);
+       make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+       make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
 #if defined(CONFIG_SH_RTC)
-       make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY, 0);
+       make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
 #endif
 
 #ifdef SCI_ERI_IRQ
-       make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
-       make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
-       make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
+       make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+       make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+       make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
 #endif
 
 #ifdef SCIF1_ERI_IRQ
-       make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
-       make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
-       make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
-       make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
+       make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+       make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+       make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+       make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7300)
-       make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY, 0);
-       make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0);
-       make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0);
-       make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY, 0);
+       make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY);
+       make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
 #endif
 
 #ifdef SCIF_ERI_IRQ
-       make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
-       make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
-       make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
-       make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
+       make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+       make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+       make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+       make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
 #endif
 
 #ifdef IRDA_ERI_IRQ
-       make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
-       make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
-       make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
-       make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
+       make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+       make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+       make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+       make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
@@ -175,12 +174,12 @@ void __init init_IRQ(void)
         * You should set corresponding bits of PFC to "00"
         * to enable these interrupts.
         */
-       make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY, 0);
-       make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY, 0);
-       make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY, 0);
-       make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY, 0);
-       make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY, 0);
-       make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY, 0);
+       make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY);
+       make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
+       make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
+       make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY);
+       make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY);
+       make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY);
 #endif
 #endif
 
index fb63681..a440d36 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/config.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
+#include <asm/cpu/mmu_context.h>
 #include <asm/unistd.h>
 
 #if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
 ENOSYS = 38
 EINVAL = 22
 
-#if defined(CONFIG_CPU_SH3)
-TRA     = 0xffffffd0
-EXPEVT  = 0xffffffd4
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
-INTEVT  = 0xa4000000           ! INTEVTE2(0xa4000000)
-#else
-INTEVT  = 0xffffffd8
-#endif
-MMU_TEA = 0xfffffffc           ! TLB Exception Address Register
-#elif defined(CONFIG_CPU_SH4)
-TRA     = 0xff000020
-EXPEVT  = 0xff000024
-INTEVT  = 0xff000028
-MMU_TEA = 0xff00000c           ! TLB Exception Address Register
-#endif
-
 #if defined(CONFIG_KGDB_NMI)
 NMI_VEC = 0x1c0                        ! Must catch early for debounce
 #endif
index a4dc2b5..9fd1723 100644 (file)
 #include <linux/unistd.h>
 #include <linux/mm.h>
 #include <linux/elfcore.h>
-#include <linux/slab.h>
 #include <linux/a.out.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
 #include <linux/ptrace.h>
 #include <linux/platform.h>
 #include <linux/kallsyms.h>
+#include <linux/kexec.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/elf.h>
-#if defined(CONFIG_SH_HS7751RVOIP)
-#include <asm/hs7751rvoip/hs7751rvoip.h>
-#elif defined(CONFIG_SH_RTS7751R2D)
-#include <asm/rts7751r2d/rts7751r2d.h>
-#endif
 
 static int hlt_counter=0;
 
@@ -37,6 +34,11 @@ int ubc_usercnt = 0;
 
 #define HARD_IDLE_TIMEOUT (HZ / 3)
 
+void (*pm_idle)(void);
+
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
 void disable_hlt(void)
 {
        hlt_counter++;
@@ -51,17 +53,25 @@ void enable_hlt(void)
 
 EXPORT_SYMBOL(enable_hlt);
 
+void default_idle(void)
+{
+       if (!hlt_counter)
+               cpu_sleep();
+       else
+               cpu_relax();
+}
+
 void cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
        while (1) {
-               if (hlt_counter) {
-                       while (!need_resched())
-                               cpu_relax();
-               } else {
-                       while (!need_resched())
-                               cpu_sleep();
-               }
+               void (*idle)(void) = pm_idle;
+
+               if (!idle)
+                       idle = default_idle;
+
+               while (!need_resched())
+                       idle();
 
                preempt_enable_no_resched();
                schedule();
@@ -88,28 +98,16 @@ void machine_restart(char * __unused)
 
 void machine_halt(void)
 {
-#if defined(CONFIG_SH_HS7751RVOIP)
-       unsigned short value;
+       local_irq_disable();
 
-       value = ctrl_inw(PA_OUTPORTR);
-       ctrl_outw((value & 0xffdf), PA_OUTPORTR);
-#elif defined(CONFIG_SH_RTS7751R2D)
-       ctrl_outw(0x0001, PA_POWOFF);
-#endif
        while (1)
                cpu_sleep();
 }
 
 void machine_power_off(void)
 {
-#if defined(CONFIG_SH_HS7751RVOIP)
-       unsigned short value;
-
-       value = ctrl_inw(PA_OUTPORTR);
-       ctrl_outw((value & 0xffdf), PA_OUTPORTR);
-#elif defined(CONFIG_SH_RTS7751R2D)
-       ctrl_outw(0x0001, PA_POWOFF);
-#endif
+       if (pm_power_off)
+               pm_power_off();
 }
 
 void show_regs(struct pt_regs * regs)
index 036050b..a067a34 100644 (file)
 #include <linux/cpu.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/io_generic.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
+#include <asm/clock.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -41,7 +41,7 @@ extern void * __rd_start, * __rd_end;
  * This value will be used at the very early stage of serial setup.
  * The bigger value means no problem.
  */
-struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, };
+struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
 struct screen_info screen_info;
 
 #if defined(CONFIG_SH_UNKNOWN)
@@ -186,7 +186,7 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
 
 static int __init sh_mv_setup(char **cmdline_p)
 {
-#if defined(CONFIG_SH_UNKNOWN)
+#ifdef CONFIG_SH_UNKNOWN
        extern struct sh_machine_vector mv_unknown;
 #endif
        struct sh_machine_vector *mv = NULL;
@@ -196,7 +196,7 @@ static int __init sh_mv_setup(char **cmdline_p)
 
        parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
 
-#ifdef CONFIG_SH_GENERIC
+#ifdef CONFIG_SH_UNKNOWN
        if (mv == NULL) {
                mv = &mv_unknown;
                if (*mv_name != '\0') {
@@ -206,9 +206,6 @@ static int __init sh_mv_setup(char **cmdline_p)
        }
        sh_mv = *mv;
 #endif
-#ifdef CONFIG_SH_UNKNOWN
-       sh_mv = mv_unknown;
-#endif
 
        /*
         * Manually walk the vec, fill in anything that the board hasn't yet
@@ -231,10 +228,8 @@ static int __init sh_mv_setup(char **cmdline_p)
        mv_set(readb);  mv_set(readw);  mv_set(readl);
        mv_set(writeb); mv_set(writew); mv_set(writel);
 
-       mv_set(ioremap);
-       mv_set(iounmap);
-
-       mv_set(isa_port2addr);
+       mv_set(ioport_map);
+       mv_set(ioport_unmap);
        mv_set(irq_demux);
 
 #ifdef CONFIG_SH_UNKNOWN
@@ -273,10 +268,10 @@ void __init setup_arch(char **cmdline_p)
        init_mm.end_data = (unsigned long) _edata;
        init_mm.brk = (unsigned long) _end;
 
-       code_resource.start = virt_to_bus(_text);
-       code_resource.end = virt_to_bus(_etext)-1;
-       data_resource.start = virt_to_bus(_etext);
-       data_resource.end = virt_to_bus(_edata)-1;
+       code_resource.start = (unsigned long)virt_to_phys(_text);
+       code_resource.end = (unsigned long)virt_to_phys(_etext)-1;
+       data_resource.start = (unsigned long)virt_to_phys(_etext);
+       data_resource.end = (unsigned long)virt_to_phys(_edata)-1;
 
        sh_mv_setup(cmdline_p);
 
@@ -435,6 +430,9 @@ static const char *cpu_name[] = {
        [CPU_ST40GX1]   = "ST40GX1",
        [CPU_SH4_202]   = "SH4-202",
        [CPU_SH4_501]   = "SH4-501",
+       [CPU_SH7770]    = "SH7770",
+       [CPU_SH7780]    = "SH7780",
+       [CPU_SH7781]    = "SH7781",
        [CPU_SH_NONE]   = "Unknown"
 };
 
@@ -445,7 +443,7 @@ const char *get_cpu_subtype(void)
 
 #ifdef CONFIG_PROC_FS
 static const char *cpu_flags[] = {
-       "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
+       "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", "ptea", NULL
 };
 
 static void show_cpuflags(struct seq_file *m)
@@ -459,7 +457,7 @@ static void show_cpuflags(struct seq_file *m)
                return;
        }
 
-       for (i = 0; i < cpu_data->flags; i++)
+       for (i = 0; cpu_flags[i]; i++)
                if ((cpu_data->flags & (1 << i)))
                        seq_printf(m, " %s", cpu_flags[i+1]);
 
@@ -472,7 +470,8 @@ static void show_cacheinfo(struct seq_file *m, const char *type, struct cache_in
 
        cache_size = info.ways * info.sets * info.linesz;
 
-       seq_printf(m, "%s size\t: %dKiB\n", type, cache_size >> 10);
+       seq_printf(m, "%s size\t: %2dKiB (%d-way)\n",
+                  type, cache_size >> 10, info.ways);
 }
 
 /*
@@ -511,21 +510,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                     boot_cpu_data.loops_per_jiffy/(500000/HZ),
                     (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100);
 
-#define PRINT_CLOCK(name, value) \
-       seq_printf(m, name " clock\t: %d.%02dMHz\n", \
-                    ((value) / 1000000), ((value) % 1000000)/10000)
-       
-       PRINT_CLOCK("cpu", boot_cpu_data.cpu_clock);
-       PRINT_CLOCK("bus", boot_cpu_data.bus_clock);
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-       PRINT_CLOCK("memory", boot_cpu_data.memory_clock);
-#endif
-       PRINT_CLOCK("module", boot_cpu_data.module_clock);
-
-       return 0;
+       return show_clocks(m);
 }
 
-
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
        return *pos < NR_CPUS ? cpu_data + *pos : NULL;
@@ -596,7 +583,7 @@ static int __init kgdb_parse_options(char *options)
                options += map->namelen + 1;
 
                options = (*options == ',') ? options+1 : options;
-               
+
                /* Read optional parameters (baud/parity/bits) */
                baud = simple_strtoul(options, &options, 10);
                if (baud != 0) {
index 1195af3..0773c9f 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/profile.h>
 #include <linux/smp.h>
+#include <linux/module.h>
 
 #include <asm/registers.h>      /* required by inline __asm__ stmt. */
 
index c51d08d..267ec8f 100644 (file)
@@ -38,7 +38,7 @@
 
 #define curptr      g6
 
-#define NR_SYSCALLS 284      /* Each OS is different... */
+#define NR_SYSCALLS 299      /* Each OS is different... */
 
 /* These are just handy. */
 #define _SV    save    %sp, -STACKFRAME_SZ, %sp
index be2c809..8613b3e 100644 (file)
@@ -323,11 +323,6 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs)
                case FMOVS:
                case FABSS:
                case FNEGS: TYPE(2,1,0,1,0,0,0); break;
-               default:
-#ifdef DEBUG_MATHEMU
-                       printk("unknown FPop1: %03lx\n",(insn>>5)&0x1ff);
-#endif
-                       break;
                }
        } else if ((insn & 0xc1f80000) == 0x81a80000)   /* FPOP2 */ {
                switch ((insn >> 5) & 0x1ff) {
@@ -337,11 +332,6 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs)
                case FCMPED: TYPE(3,0,0,2,1,2,1); break;
                case FCMPQ: TYPE(3,0,0,3,1,3,1); break;
                case FCMPEQ: TYPE(3,0,0,3,1,3,1); break;
-               default:
-#ifdef DEBUG_MATHEMU
-                       printk("unknown FPop2: %03lx\n",(insn>>5)&0x1ff);
-#endif
-                       break;
                }
        }
 
index e50e56e..12911e7 100644 (file)
@@ -25,7 +25,7 @@
 
 #define curptr      g6
 
-#define NR_SYSCALLS 284      /* Each OS is different... */
+#define NR_SYSCALLS 299      /* Each OS is different... */
 
        .text
        .align          32
index 9cd272a..60b5937 100644 (file)
@@ -84,7 +84,6 @@ SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5)
 SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1)
 SIGN1(sys32_mlockall, sys_mlockall, %o0)
 SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0)
-SIGN1(sys32_clock_settime, compat_sys_clock_settime, %o1)
 SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1)
 SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1)
 SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
index bf0fc5b..2881faf 100644 (file)
@@ -71,7 +71,7 @@ sys_call_table32:
 /*240*/        .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
        .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
 /*250*/        .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
-       .word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
+       .word sys_ni_syscall, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
 /*260*/        .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
        .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/        .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
index 6430a63..c58b657 100644 (file)
@@ -47,13 +47,16 @@ ARCH_INCLUDE        += -I$(srctree)/$(ARCH_DIR)/include
 endif
 SYS_DIR                := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
 
-# -Dvmap=kernel_vmap affects everything, and prevents anything from
-# referencing the libpcap.o symbol so named.
+# -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so
+# named - it's a common symbol in libpcap, so we get a binary which crashes.
 #
-# Same things for in6addr_loopback - found in libc.
+# Same things for in6addr_loopback and mktime - found in libc. For these two we
+# only get link-time error, luckily.
+#
+# These apply to USER_CFLAGS to.
 
-CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
-       $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
+CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\"   \
+       $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap      \
        -Din6addr_loopback=kernel_in6addr_loopback
 
 AFLAGS += $(ARCH_INCLUDE)
@@ -66,6 +69,7 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
 # in CFLAGS.  Otherwise, it would cause ld to complain about the two different
 # errnos.
+# These apply to kernelspace only.
 
 CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
        -Dmktime=kernel_mktime
@@ -168,10 +172,13 @@ else
        $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
 endif
 
-$(ARCH_DIR)/include/sysdep:
+$(objtree)/$(ARCH_DIR)/include:
+       @echo '  MKDIR $@'
+       $(Q)mkdir -p $@
+
+$(ARCH_DIR)/include/sysdep: $(objtree)/$(ARCH_DIR)/include
        @echo '  SYMLINK $@'
 ifneq ($(KBUILD_SRC),)
-       $(Q)mkdir -p $(ARCH_DIR)/include
        $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep
 else
        $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
@@ -214,7 +221,7 @@ $(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s
 
 CLEAN_FILES += $(ARCH_DIR)/user-offsets.s
 
-$(ARCH_DIR)/include/kern_constants.h:
+$(ARCH_DIR)/include/kern_constants.h: $(objtree)/$(ARCH_DIR)/include
        @echo '  SYMLINK $@'
        $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@
 
index ab0d0b1..7218c75 100644 (file)
@@ -403,7 +403,7 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
        return 0;
 }
 
-void free_one_chan(struct chan *chan, int delay_free_irq)
+static void free_one_chan(struct chan *chan, int delay_free_irq)
 {
        list_del(&chan->list);
 
@@ -416,7 +416,7 @@ void free_one_chan(struct chan *chan, int delay_free_irq)
        kfree(chan);
 }
 
-void free_chan(struct list_head *chans, int delay_free_irq)
+static void free_chan(struct list_head *chans, int delay_free_irq)
 {
        struct list_head *ele, *next;
        struct chan *chan;
@@ -497,7 +497,7 @@ struct chan_type {
        struct chan_ops *ops;
 };
 
-struct chan_type chan_table[] = {
+static struct chan_type chan_table[] = {
        { "fd", &fd_ops },
 
 #ifdef CONFIG_NULL_CHAN
index 507e3cb..a61b7b4 100644 (file)
@@ -18,7 +18,7 @@ struct daemon_init {
        char *ctl_sock;
 };
 
-void daemon_init(struct net_device *dev, void *data)
+static void daemon_init(struct net_device *dev, void *data)
 {
        struct uml_net_private *pri;
        struct daemon_data *dpri;
@@ -64,7 +64,7 @@ static struct net_kern_info daemon_kern_info = {
        .write                  = daemon_write,
 };
 
-int daemon_setup(char *str, char **mac_out, void *data)
+static int daemon_setup(char *str, char **mac_out, void *data)
 {
        struct daemon_init *init = data;
        char *remain;
index 46ceb25..6c2d4cc 100644 (file)
@@ -714,7 +714,7 @@ struct winch {
        struct tty_struct *tty;
 };
 
-irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
 {
        struct winch *winch = data;
        struct tty_struct *tty;
index 217438c..c9b078f 100644 (file)
@@ -26,7 +26,7 @@ struct mcast_init {
        int ttl;
 };
 
-void mcast_init(struct net_device *dev, void *data)
+static void mcast_init(struct net_device *dev, void *data)
 {
        struct uml_net_private *pri;
        struct mcast_data *dpri;
@@ -40,7 +40,7 @@ void mcast_init(struct net_device *dev, void *data)
        dpri->dev = dev;
 
        printk("mcast backend ");
-       printk("multicast adddress: %s:%u, TTL:%u ",
+       printk("multicast address: %s:%u, TTL:%u ",
               dpri->addr, dpri->port, dpri->ttl);
 
        printk("\n");
index e3d5765..54388d1 100644 (file)
@@ -273,7 +273,7 @@ void mconsole_proc(struct mc_request *req)
     config <dev> - Query the configuration of a device \n\
     remove <dev> - Remove a device from UML \n\
     sysrq <letter> - Performs the SysRq action controlled by the letter \n\
-    cad - invoke the Ctl-Alt-Del handler \n\
+    cad - invoke the Ctrl-Alt-Del handler \n\
     stop - pause the UML; it will do nothing until it receives a 'go' \n\
     go - continue the UML after a 'stop' \n\
     log <string> - make UML enter <string> into the kernel log\n\
@@ -327,7 +327,7 @@ void mconsole_stop(struct mc_request *req)
 
 /* This list is populated by __initcall routines. */
 
-LIST_HEAD(mconsole_devices);
+static LIST_HEAD(mconsole_devices);
 
 void mconsole_register_dev(struct mc_device *new)
 {
@@ -561,6 +561,8 @@ void mconsole_sysrq(struct mc_request *req)
 }
 #endif
 
+#ifdef CONFIG_MODE_SKAS
+
 static void stack_proc(void *arg)
 {
        struct task_struct *from = current, *to = arg;
@@ -574,7 +576,7 @@ static void stack_proc(void *arg)
  *  Dumps a stacks registers to the linux console.
  *  Usage stack <pid>.
  */
-void do_stack(struct mc_request *req)
+static void do_stack_trace(struct mc_request *req)
 {
        char *ptr = req->request.data;
        int pid_requested= -1;
@@ -605,6 +607,7 @@ void do_stack(struct mc_request *req)
        }
        with_console(req, stack_proc, to);
 }
+#endif /* CONFIG_MODE_SKAS */
 
 void mconsole_stack(struct mc_request *req)
 {
@@ -613,7 +616,7 @@ void mconsole_stack(struct mc_request *req)
         */
        CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode",
                                   1, 0),
-                   do_stack(req));
+                   do_stack_trace(req));
 }
 
 /* Changed by mconsole_setup, which is __setup, and called before SMP is
index 2ae76d8..d574e0a 100644 (file)
@@ -88,12 +88,13 @@ struct slip_proto {
        int esc;
 };
 
-#define SLIP_PROTO_INIT { \
-       .ibuf   = { '\0' }, \
-       .obuf   = { '\0' }, \
-        .more  = 0, \
-       .pos    = 0, \
-       .esc    = 0 \
+static inline void slip_proto_init(struct slip_proto * slip)
+{
+       memset(slip->ibuf, 0, sizeof(slip->ibuf));
+       memset(slip->obuf, 0, sizeof(slip->obuf));
+       slip->more = 0;
+       slip->pos = 0;
+       slip->esc = 0;
 }
 
 extern int slip_proto_read(int fd, void *buf, int len,
index 9a6f5c8..a62f5ef 100644 (file)
@@ -21,13 +21,14 @@ void slip_init(struct net_device *dev, void *data)
 
        private = dev->priv;
        spri = (struct slip_data *) private->user;
-       *spri = ((struct slip_data)
-               { .name         = { '\0' },
-                 .addr         = NULL,
-                 .gate_addr    = init->gate_addr,
-                 .slave        = -1,
-                 .slip         = SLIP_PROTO_INIT,
-                 .dev          = dev });
+
+       memset(spri->name, 0, sizeof(spri->name));
+       spri->addr = NULL;
+       spri->gate_addr = init->gate_addr;
+       spri->slave = -1;
+       spri->dev = dev;
+
+       slip_proto_init(&spri->slip);
 
        dev->init = NULL;
        dev->header_cache_update = NULL;
index 9864d27..33d7982 100644 (file)
@@ -21,12 +21,13 @@ void slirp_init(struct net_device *dev, void *data)
 
        private = dev->priv;
        spri = (struct slirp_data *) private->user;
-       *spri = ((struct slirp_data)
-               { .argw         = init->argw,
-                 .pid          = -1,
-                 .slave        = -1,
-                 .slip         = SLIP_PROTO_INIT,
-                 .dev          = dev });
+
+       spri->argw = init->argw;
+       spri->pid = -1;
+       spri->slave = -1;
+       spri->dev = dev;
+
+       slip_proto_init(&spri->slip);
 
        dev->init = NULL;
        dev->hard_header_len = 0;
index a32ef55..a4d6415 100644 (file)
@@ -33,7 +33,7 @@ static struct tty_driver *ssl_driver;
 
 #define NR_PORTS 64
 
-void ssl_announce(char *dev_name, int dev)
+static void ssl_announce(char *dev_name, int dev)
 {
        printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev,
               dev_name);
@@ -98,7 +98,7 @@ static int ssl_remove(int n)
        return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n);
 }
 
-int ssl_open(struct tty_struct *tty, struct file *filp)
+static int ssl_open(struct tty_struct *tty, struct file *filp)
 {
        return line_open(serial_lines, tty);
 }
@@ -182,7 +182,7 @@ static struct console ssl_cons = {
        .index          = -1,
 };
 
-int ssl_init(void)
+static int ssl_init(void)
 {
        char *new_title;
 
index c649108..07176d9 100644 (file)
@@ -31,8 +31,6 @@ extern int timer_irq_inited;
 extern int jail;
 extern int nsyscalls;
 
-extern struct task_struct *idle_threads[NR_CPUS];
-
 #define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
 #define UML_ROUND_UP(addr) \
        UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
index 569fe8b..c264e1c 100644 (file)
@@ -33,7 +33,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 extern void log_exec(char **argv, void *tty);
 
 static long execve1(char *file, char __user * __user *argv,
-                   char *__user __user *env)
+                   char __user *__user *env)
 {
         long error;
 
index f3b583a..544665e 100644 (file)
@@ -265,7 +265,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
        highmem_len = highmem_pages * sizeof(struct page);
 
        total_pages = phys_pages + iomem_pages + highmem_pages;
-       total_len = phys_len + iomem_pages + highmem_len;
+       total_len = phys_len + iomem_len + highmem_len;
 
        if(kmalloc_ok){
                map = kmalloc(total_len, GFP_KERNEL);
index 6f1a3a2..3ef73bf 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "linux/module.h"
 #include "linux/sched.h"
+#include "asm/smp.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
index 3d29c90..3fda9a0 100644 (file)
@@ -23,16 +23,20 @@ void syscall_handler_tt(int sig, struct pt_regs *regs)
        int syscall;
 #ifdef CONFIG_SYSCALL_DEBUG
        int index;
-       index = record_syscall_start(syscall);
 #endif
        sc = UPT_SC(&regs->regs);
        SC_START_SYSCALL(sc);
 
+       syscall = UPT_SYSCALL_NR(&regs->regs);
+
+#ifdef CONFIG_SYSCALL_DEBUG
+       index = record_syscall_start(syscall);
+#endif
+
        syscall_trace(&regs->regs, 0);
 
        current->thread.nsyscalls++;
        nsyscalls++;
-       syscall = UPT_SYSCALL_NR(&regs->regs);
 
        if((syscall >= NR_syscalls) || (syscall < 0))
                result = -ENOSYS;
index 0cdfd44..1fa09a7 100644 (file)
@@ -16,7 +16,6 @@
 #include "choose-mode.h"
 #include "kern.h"
 #include "mode_kern.h"
-#include "proc_mm.h"
 #include "os.h"
 
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
@@ -90,6 +89,7 @@ out:
 #include "skas.h"
 #include "skas_ptrace.h"
 #include "asm/mmu_context.h"
+#include "proc_mm.h"
 
 long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
                     void **addr, int done)
index f05c2a8..067c0f4 100644 (file)
@@ -676,7 +676,7 @@ ia32_sys_call_table:
        .quad sys_mkdirat
        .quad sys_mknodat
        .quad sys_fchownat
-       .quad sys_futimesat
+       .quad compat_sys_futimesat
        .quad compat_sys_newfstatat     /* 300 */
        .quad sys_unlinkat
        .quad sys_renameat
index bba5db6..ccef6ae 100644 (file)
@@ -4,7 +4,7 @@
 
 CFLAGS_csum-partial.o := -funroll-loops
 
-obj-y := io.o
+obj-y := io.o iomap_copy.o
 
 lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
        usercopy.o getuser.o putuser.o  \
diff --git a/arch/x86_64/lib/iomap_copy.S b/arch/x86_64/lib/iomap_copy.S
new file mode 100644 (file)
index 0000000..8bbade5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 PathScale, Inc.  All Rights Reserved.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * override generic version in lib/iomap_copy.c
+ */
+       .globl __iowrite32_copy
+       .p2align 4
+__iowrite32_copy:
+       movl %edx,%ecx
+       rep movsd
+       ret
index f16c0d5..00d4ddb 100644 (file)
@@ -29,11 +29,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
 
        while (1) {
                ++cfg_num;
-               if (cfg_num >= pci_mmcfg_config_num) {
-                       /* Not found - fall back to type 1. This happens
-                          e.g. on the internal devices of a K8 northbridge. */
-                       return NULL;
-               }
+               if (cfg_num >= pci_mmcfg_config_num)
+                       break;
                cfg = pci_mmcfg_virt[cfg_num].cfg;
                if (cfg->pci_segment_group_number != seg)
                        continue;
@@ -41,6 +38,18 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
                    (cfg->end_bus_number >= bus))
                        return pci_mmcfg_virt[cfg_num].virt;
        }
+
+       /* Handle more broken MCFG tables on Asus etc.
+          They only contain a single entry for bus 0-0. Assume
+          this applies to all busses. */
+       cfg = &pci_mmcfg_config[0];
+       if (pci_mmcfg_config_num == 1 &&
+               cfg->pci_segment_group_number == 0 &&
+               (cfg->start_bus_number | cfg->end_bus_number) == 0)
+               return cfg->base_address;
+
+       /* Fall back to type 0 */
+       return 0;
 }
 
 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
index c9f424d..96a61e0 100644 (file)
@@ -139,35 +139,16 @@ static int elevator_attach(request_queue_t *q, struct elevator_type *e,
 
 static char chosen_elevator[16];
 
-static void elevator_setup_default(void)
+static int __init elevator_setup(char *str)
 {
-       struct elevator_type *e;
-
-       /*
-        * If default has not been set, use the compiled-in selection.
-        */
-       if (!chosen_elevator[0])
-               strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
-
        /*
         * Be backwards-compatible with previous kernels, so users
         * won't get the wrong elevator.
         */
-       if (!strcmp(chosen_elevator, "as"))
+       if (!strcmp(str, "as"))
                strcpy(chosen_elevator, "anticipatory");
-
-       /*
-        * If the given scheduler is not available, fall back to the default
-        */
-       if ((e = elevator_find(chosen_elevator)))
-               elevator_put(e);
        else
-               strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
-}
-
-static int __init elevator_setup(char *str)
-{
-       strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1);
+               strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1);
        return 0;
 }
 
@@ -184,14 +165,16 @@ int elevator_init(request_queue_t *q, char *name)
        q->end_sector = 0;
        q->boundary_rq = NULL;
 
-       elevator_setup_default();
+       if (name && !(e = elevator_get(name)))
+               return -EINVAL;
 
-       if (!name)
-               name = chosen_elevator;
+       if (!e && *chosen_elevator && !(e = elevator_get(chosen_elevator)))
+               printk("I/O scheduler %s not found\n", chosen_elevator);
 
-       e = elevator_get(name);
-       if (!e)
-               return -EINVAL;
+       if (!e && !(e = elevator_get(CONFIG_DEFAULT_IOSCHED))) {
+               printk("Default I/O scheduler not found, using no-op\n");
+               e = elevator_get("noop");
+       }
 
        eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL);
        if (!eq) {
@@ -669,8 +652,10 @@ int elv_register(struct elevator_type *e)
        spin_unlock_irq(&elv_list_lock);
 
        printk(KERN_INFO "io scheduler %s registered", e->elevator_name);
-       if (!strcmp(e->elevator_name, chosen_elevator))
-               printk(" (default)");
+       if (!strcmp(e->elevator_name, chosen_elevator) ||
+                       (!*chosen_elevator &&
+                        !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED)))
+                               printk(" (default)");
        printk("\n");
        return 0;
 }
index 8e27d0a..f9fc07e 100644 (file)
@@ -304,6 +304,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
  * blk_queue_ordered - does this queue support ordered writes
  * @q:        the request queue
  * @ordered:  one of QUEUE_ORDERED_*
+ * @prepare_flush_fn: rq setup helper for cache flush ordered writes
  *
  * Description:
  *   For journalled file systems, doing ordered writes on a commit
@@ -332,6 +333,7 @@ int blk_queue_ordered(request_queue_t *q, unsigned ordered,
                return -EINVAL;
        }
 
+       q->ordered = ordered;
        q->next_ordered = ordered;
        q->prepare_flush_fn = prepare_flush_fn;
 
@@ -662,7 +664,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
  *    Enables a low level driver to set an upper limit on the size of
  *    received requests.
  **/
-void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors)
+void blk_queue_max_sectors(request_queue_t *q, unsigned int max_sectors)
 {
        if ((max_sectors << 9) < PAGE_CACHE_SIZE) {
                max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
@@ -2577,6 +2579,8 @@ void disk_round_stats(struct gendisk *disk)
        disk->stamp = now;
 }
 
+EXPORT_SYMBOL_GPL(disk_round_stats);
+
 /*
  * queue lock must be held
  */
@@ -2632,6 +2636,7 @@ EXPORT_SYMBOL(blk_put_request);
 /**
  * blk_end_sync_rq - executes a completion event on a request
  * @rq: request to complete
+ * @error: end io status of the request
  */
 void blk_end_sync_rq(struct request *rq, int error)
 {
@@ -3153,7 +3158,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
        if (blk_fs_request(req) && req->rq_disk) {
                const int rw = rq_data_dir(req);
 
-               __disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
+               disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
        }
 
        total_bytes = bio_nbytes = 0;
index a05fe58..f04d864 100644 (file)
@@ -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;
 }
 
@@ -626,6 +631,24 @@ static void ub_id_put(int id)
        spin_unlock_irqrestore(&ub_lock, flags);
 }
 
+/*
+ * 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
@@ -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 */
@@ -2117,6 +2146,52 @@ static void ub_probe_timeout(unsigned long arg)
        complete(cop);
 }
 
+/*
+ * 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.
  */
@@ -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;
index 4135d8c..4c67727 100644 (file)
@@ -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
index 810679d..9964c50 100644 (file)
@@ -600,6 +600,26 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev)
        agp_put_bridge(bridge);
 }
 
+#ifdef CONFIG_PM
+
+static int agp_amd64_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       pci_save_state(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int agp_amd64_resume(struct pci_dev *pdev)
+{
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+
+       return amd_8151_configure();
+}
+
+#endif /* CONFIG_PM */
+
 static struct pci_device_id agp_amd64_pci_table[] = {
        {
        .class          = (PCI_CLASS_BRIDGE_HOST << 8),
@@ -718,6 +738,10 @@ static struct pci_driver agp_amd64_pci_driver = {
        .id_table       = agp_amd64_pci_table,
        .probe          = agp_amd64_probe,
        .remove         = agp_amd64_remove,
+#ifdef CONFIG_PM
+       .suspend        = agp_amd64_suspend,
+       .resume         = agp_amd64_resume,
+#endif
 };
 
 
index 53372a8..5b74c36 100644 (file)
@@ -244,6 +244,22 @@ static int ati_configure(void)
 }
 
 
+#ifdef CONFIG_PM
+static int agp_ati_resume(struct pci_dev *dev)
+{
+       pci_restore_state(dev);
+
+       return ati_configure();
+}
+
+static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       pci_save_state(dev);
+
+       return 0;
+}
+#endif
+
 /*
  *Since we don't need contigious memory we just try
  * to get the gatt table once
@@ -525,6 +541,10 @@ static struct pci_driver agp_ati_pci_driver = {
        .id_table       = agp_ati_pci_table,
        .probe          = agp_ati_probe,
        .remove         = agp_ati_remove,
+#ifdef CONFIG_PM
+       .resume         = agp_ati_resume,
+       .suspend        = agp_ati_suspend,
+#endif
 };
 
 static int __init agp_ati_init(void)
index 17f520c..97eeb23 100644 (file)
@@ -592,7 +592,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
        struct agp_file_private *priv = file->private_data;
        struct agp_kern_info kerninfo;
 
-       down(&(agp_fe.agp_mutex));
+       mutex_lock(&(agp_fe.agp_mutex));
 
        if (agp_fe.backend_acquired != TRUE)
                goto out_eperm;
@@ -627,7 +627,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
                                            size, vma->vm_page_prot)) {
                        goto out_again;
                }
-               up(&(agp_fe.agp_mutex));
+               mutex_unlock(&(agp_fe.agp_mutex));
                return 0;
        }
 
@@ -643,20 +643,20 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
                                            size, vma->vm_page_prot)) {
                        goto out_again;
                }
-               up(&(agp_fe.agp_mutex));
+               mutex_unlock(&(agp_fe.agp_mutex));
                return 0;
        }
 
 out_eperm:
-       up(&(agp_fe.agp_mutex));
+       mutex_unlock(&(agp_fe.agp_mutex));
        return -EPERM;
 
 out_inval:
-       up(&(agp_fe.agp_mutex));
+       mutex_unlock(&(agp_fe.agp_mutex));
        return -EINVAL;
 
 out_again:
-       up(&(agp_fe.agp_mutex));
+       mutex_unlock(&(agp_fe.agp_mutex));
        return -EAGAIN;
 }
 
@@ -664,7 +664,7 @@ static int agp_release(struct inode *inode, struct file *file)
 {
        struct agp_file_private *priv = file->private_data;
 
-       down(&(agp_fe.agp_mutex));
+       mutex_lock(&(agp_fe.agp_mutex));
 
        DBG("priv=%p", priv);
 
@@ -687,7 +687,7 @@ static int agp_release(struct inode *inode, struct file *file)
        agp_remove_file_private(priv);
        kfree(priv);
        file->private_data = NULL;
-       up(&(agp_fe.agp_mutex));
+       mutex_unlock(&(agp_fe.agp_mutex));
        return 0;
 }
 
@@ -698,7 +698,7 @@ static int agp_open(struct inode *inode, struct file *file)
        struct agp_client *client;
        int rc = -ENXIO;
 
-       down(&(agp_fe.agp_mutex));
+       mutex_lock(&(agp_fe.agp_mutex));
 
        if (minor != AGPGART_MINOR)
                goto err_out;
@@ -723,13 +723,13 @@ static int agp_open(struct inode *inode, struct file *file)
        file->private_data = (void *) priv;
        agp_insert_file_private(priv);
        DBG("private=%p, client=%p", priv, client);
-       up(&(agp_fe.agp_mutex));
+       mutex_unlock(&(agp_fe.agp_mutex));
        return 0;
 
 err_out_nomem:
        rc = -ENOMEM;
 err_out:
-       up(&(agp_fe.agp_mutex));
+       mutex_unlock(&(agp_fe.agp_mutex));
        return rc;
 }
 
@@ -985,7 +985,7 @@ static int agp_ioctl(struct inode *inode, struct file *file,
        int ret_val = -ENOTTY;
 
        DBG("priv=%p, cmd=%x", curr_priv, cmd);
-       down(&(agp_fe.agp_mutex));
+       mutex_lock(&(agp_fe.agp_mutex));
 
        if ((agp_fe.current_controller == NULL) &&
            (cmd != AGPIOC_ACQUIRE)) {
@@ -1055,7 +1055,7 @@ static int agp_ioctl(struct inode *inode, struct file *file,
 
 ioctl_out:
        DBG("ioctl returns %d\n", ret_val);
-       up(&(agp_fe.agp_mutex));
+       mutex_unlock(&(agp_fe.agp_mutex));
        return ret_val;
 }
 
@@ -1081,7 +1081,7 @@ static struct miscdevice agp_miscdev =
 int agp_frontend_initialize(void)
 {
        memset(&agp_fe, 0, sizeof(struct agp_front_data));
-       sema_init(&(agp_fe.agp_mutex), 1);
+       mutex_init(&(agp_fe.agp_mutex));
 
        if (misc_register(&agp_miscdev)) {
                printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
index e7bed50..631531f 100644 (file)
@@ -422,7 +422,8 @@ static void intel_i830_init_gtt_entries(void)
                        /* Check it's really I915G */
                        if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
                            agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
-                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB)
                                gtt_entries = MB(48) - KB(size);
                        else
                                gtt_entries = 0;
@@ -431,7 +432,8 @@ static void intel_i830_init_gtt_entries(void)
                        /* Check it's really I915G */
                        if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
                            agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
-                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB)
                                gtt_entries = MB(64) - KB(size);
                        else
                                gtt_entries = 0;
@@ -1681,6 +1683,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
                }
                name = "945G";
                break;
+       case PCI_DEVICE_ID_INTEL_82945GM_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG)) {
+                       bridge->driver = &intel_915_driver;
+               } else {
+                       bridge->driver = &intel_845_driver;
+               }
+               name = "945GM";
+               break;
        case PCI_DEVICE_ID_INTEL_7505_0:
                bridge->driver = &intel_7505_driver;
                name = "E7505";
@@ -1821,6 +1831,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
        ID(PCI_DEVICE_ID_INTEL_82915G_HB),
        ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
        ID(PCI_DEVICE_ID_INTEL_82945G_HB),
+       ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
        { }
 };
 
index 4008324..7c14a09 100644 (file)
@@ -218,10 +218,8 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
                        master[cdev].rq *= (1 << (master[cdev].y - 1));
 
                tot_rq += master[cdev].rq;
-
-               if (cdev == ndevs-1)
-                       master[cdev].n += rem;
        }
+       master[ndevs-1].n += rem;
 
        /* Figure the number of isochronous and asynchronous RQ slots the
         * target is providing. */
index 40a67c8..ac62641 100644 (file)
@@ -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 */
index c67ef3e..6ed213b 100644 (file)
@@ -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;
        }
index aedf7a8..537aa45 100644 (file)
@@ -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");
index 8198dbb..ec75909 100644 (file)
@@ -441,7 +441,7 @@ 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;
index f1d9cb7..0900d1d 100644 (file)
@@ -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);
 }
index 277a843..7a51147 100644 (file)
@@ -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)
 
@@ -55,7 +56,7 @@ 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)
 {
@@ -297,18 +298,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);
+               mutex_unlock(&cpufreq_governor_mutex);
        }
        return -EINVAL;
 }
@@ -600,7 +601,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 +612,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 +624,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 +645,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 +766,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);
 
@@ -834,9 +838,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,7 +866,7 @@ 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);
 
@@ -875,7 +879,7 @@ unsigned int cpufreq_get(unsigned int cpu)
                }
        }
 
-       up(&policy->lock);
+       mutex_unlock(&policy->lock);
 
  out:
        cpufreq_cpu_put(policy);
@@ -1158,11 +1162,11 @@ 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);
 
@@ -1199,9 +1203,9 @@ 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);
 
@@ -1217,17 +1221,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;
 }
@@ -1239,9 +1243,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,9 +1272,9 @@ 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);
 
@@ -1382,7 +1386,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 +1394,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,7 +1418,7 @@ 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, 
@@ -1425,9 +1429,17 @@ int cpufreq_update_policy(unsigned int cpu)
        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 != 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;
index 39543a2..ac38766 100644 (file)
@@ -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;
index e69fd8d..9ee9411 100644 (file)
@@ -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;
index d32bf35..92a0be2 100644 (file)
@@ -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;
index acda7d6..501cc05 100644 (file)
@@ -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);
index 96ea79b..903f85a 100644 (file)
@@ -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);
index a14eed0..a19e0ed 100644 (file)
@@ -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);
index be1791b..f9b9b93 100644 (file)
@@ -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;
 
index a104ab0..2a165fd 100644 (file)
@@ -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"
@@ -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;
index 8b00d9a..9c849d2 100644 (file)
@@ -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;
index 77bc6c7..321f11e 100644 (file)
@@ -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;
 }
index 9fb985a..d709cb1 100644 (file)
@@ -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;
index 4fdca26..36f1141 100644 (file)
@@ -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 {
index 484a7e6..e88e39a 100644 (file)
@@ -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)
index fd3f5c8..c3b5f79 100644 (file)
@@ -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));
 
index 98039da..ccaa0c3 100644 (file)
@@ -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);
@@ -687,6 +703,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 +717,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, "
index 31207e6..2d2d4ac 100644 (file)
@@ -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
index b564f18..4e7727d 100644 (file)
@@ -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;
 };
index 4571ea3..4612d13 100644 (file)
@@ -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,
index 499344c..dcffc34 100644 (file)
@@ -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;
        }
 
index 7df2d82..900587a 100644 (file)
@@ -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;
        }
 
index a936e7a..20cb98a 100644 (file)
@@ -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,
index 64b9c31..b6bc049 100644 (file)
@@ -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);
index 4a26292..76cb1f8 100644 (file)
@@ -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;
                }
index bc2fce6..fe79d15 100644 (file)
@@ -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);
 
index 78dd163..2b2ec10 100644 (file)
@@ -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,
index 60e2aac..bb23ed2 100644 (file)
@@ -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,
index 7e97649..b154938 100644 (file)
@@ -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;
        }
 
index cd3a1e7..7f8b009 100644 (file)
@@ -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);
 }
index e08dbe0..4bad588 100644 (file)
@@ -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
index ce44cce..184c412 100644 (file)
@@ -11,3 +11,4 @@ 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 (file)
index 0000000..d448bb5
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * 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 <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);
index 7665fd9..19b1b01 100644 (file)
@@ -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;
        }
 
index 81fd7a9..9abed18 100644 (file)
@@ -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
index dd8c6a9..b45a45c 100644 (file)
@@ -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
 
 
@@ -509,14 +506,14 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        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;
        }
-       set_irq_type(spi->irq, IRQT_FALLING);
 
        dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
 
index 4844d25..3226830 100644 (file)
@@ -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;
 
index ed6d317..69596f6 100644 (file)
@@ -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;
index 1235135..442e2be 100644 (file)
@@ -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;
 }
 
index efe4adf..74039db 100644 (file)
@@ -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);
 }
 
index 87727d8..f3759dd 100644 (file)
@@ -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,
index 375aa24..fdec1e2 100644 (file)
@@ -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;
index a6f2dc6..9b1e2f5 100644 (file)
@@ -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,
index 8c16359..e9adeb9 100644 (file)
@@ -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.
index 0b6c209..aad4a18 100644 (file)
@@ -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],
index 8a2e265..33ace37 100644 (file)
@@ -29,6 +29,8 @@
 #  For mptctl:
 #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
 #
+#  For mptfc:
+#CFLAGS_mptfc.o += -DMPT_DEBUG_FC
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
 
index d890b2b..9a2c760 100644 (file)
@@ -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);
        }
@@ -1444,6 +1448,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 +1490,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 +2147,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 +2170,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 +2787,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;
 }
@@ -4386,6 +4406,138 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
        return 0;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+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.
@@ -4598,6 +4750,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)
                                 */
@@ -5967,6 +6127,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;
        }
@@ -6046,7 +6210,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 +6218,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";
index 47053ac..ea2649e 100644 (file)
@@ -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)  \
 #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;
 };
 
 /*
@@ -631,6 +632,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 +805,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) \
index b102c76..c3a3499 100644 (file)
@@ -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,
@@ -347,15 +348,34 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
        return 0;
 }
 
+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);
@@ -426,6 +449,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.
@@ -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;
index 5a06d8d..2512d0e 100644 (file)
@@ -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
index cdac557..05789e5 100644 (file)
@@ -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,
@@ -2015,6 +2040,42 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
        return status;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+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
@@ -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;
@@ -2584,16 +2650,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
        return 1;               /* currently means nothing really */
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* 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);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
index d3cba12..44b248d 100644 (file)
@@ -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);
index 7dce292..f148dfa 100644 (file)
@@ -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"));
index 7e98434..9783caf 100644 (file)
@@ -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;
 
index 9e21e6c..0f915ac 100644 (file)
@@ -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,
index 626508a..6a6a084 100644 (file)
@@ -2034,13 +2034,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.
@@ -2050,8 +2065,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
index b8953de..b508812 100644 (file)
@@ -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) {
index df9d6e8..c3267e4 100644 (file)
@@ -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, "
index 49fa1e4..a24200d 100644 (file)
@@ -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))
 
@@ -315,6 +315,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);
 
@@ -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;
index 76bb5f1..9f691cb 100644 (file)
@@ -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
index ab07a49..0c21bd8 100644 (file)
@@ -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,
index 2582d98..4ff006c 100644 (file)
@@ -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;
index 6139f06..94d5ea1 100644 (file)
@@ -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>
index 40ae36b..7ef4b04 100644 (file)
@@ -444,6 +444,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
                        netif_rx(skb);
 #endif
                }
+               dev->last_rx = jiffies;
        }
 
        return received_packets;
@@ -461,7 +462,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);
@@ -1047,16 +1048,15 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
 
 static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
 {
-        unsigned int frag;
-        skb_frag_t *fragp;
+       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;
+       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;
 }
 
 
@@ -2137,26 +2137,26 @@ static void eth_port_set_multicast_list(struct net_device *dev)
         */
        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);
-               }
+                       /* 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;
        }
 
@@ -2617,7 +2617,6 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
        struct eth_tx_desc *current_descriptor;
        struct eth_tx_desc *first_descriptor;
        u32 command;
-       unsigned long flags;
 
        /* Do not process Tx ring in case of Tx ring resource error */
        if (mp->tx_resource_err)
@@ -2634,8 +2633,6 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
                return ETH_ERROR;
        }
 
-       spin_lock_irqsave(&mp->lock, flags);
-
        mp->tx_ring_skbs++;
        BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
 
@@ -2685,15 +2682,11 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
                mp->tx_resource_err = 1;
                mp->tx_curr_desc_q = tx_first_desc;
 
-               spin_unlock_irqrestore(&mp->lock, flags);
-
                return ETH_QUEUE_LAST_RESOURCE;
        }
 
        mp->tx_curr_desc_q = tx_next_desc;
 
-       spin_unlock_irqrestore(&mp->lock, flags);
-
        return ETH_OK;
 }
 #else
@@ -2704,14 +2697,11 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
        int tx_desc_used;
        struct eth_tx_desc *current_descriptor;
        unsigned int command_status;
-       unsigned long flags;
 
        /* Do not process Tx ring in case of Tx ring resource error */
        if (mp->tx_resource_err)
                return ETH_QUEUE_FULL;
 
-       spin_lock_irqsave(&mp->lock, flags);
-
        mp->tx_ring_skbs++;
        BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
 
@@ -2742,12 +2732,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
        /* Check for ring index overlap in the Tx desc ring */
        if (tx_desc_curr == tx_desc_used) {
                mp->tx_resource_err = 1;
-
-               spin_unlock_irqrestore(&mp->lock, flags);
                return ETH_QUEUE_LAST_RESOURCE;
        }
 
-       spin_unlock_irqrestore(&mp->lock, flags);
        return ETH_OK;
 }
 #endif
@@ -2898,8 +2885,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 */
@@ -2980,7 +2969,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) },
@@ -3131,9 +3120,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);
@@ -3142,39 +3130,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;
        }
index 89c4678..49b597c 100644 (file)
@@ -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;
        }
index c8f6286..308f773 100644 (file)
@@ -75,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.
 
index 8bf0276..6290c9f 100644 (file)
@@ -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
 
 /*
  *
@@ -7112,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 ||
@@ -7151,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;
 }
index 4c28e33..14beab4 100644 (file)
@@ -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 */
@@ -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");
@@ -11035,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;
@@ -11121,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));
                }
        }
 
index b664708..3c128b6 100644 (file)
@@ -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;
                        }
index 2f1289e..222a1cc 100644 (file)
@@ -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.
index 7e7f913..317457d 100644 (file)
@@ -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__);
index aabf1e7..dc59da6 100644 (file)
@@ -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) {
index 7d93dba..3eefe2c 100644 (file)
@@ -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)) {
index 57ea71a..310b618 100644 (file)
@@ -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);
        
index cf075c3..6e79f56 100644 (file)
@@ -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);
index 396b54b..6f6cbed 100644 (file)
 #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;
-}
index daa89ae..78943e0 100644 (file)
 
 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;
        }       
index ce0e9b6..7d6f521 100644 (file)
@@ -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)
index 25ccb0e..643252d 100644 (file)
@@ -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));
index 202b750..48723d6 100644 (file)
@@ -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)
index 402136a..4ac52d4 100644 (file)
@@ -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
  */
index d2a633e..d2d1879 100644 (file)
@@ -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
index 50d6685..ea9277b 100644 (file)
@@ -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)
 {
index a86a650..721787c 100644 (file)
@@ -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"
index ef4c687..abdf1ee 100644 (file)
@@ -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>
@@ -675,11 +674,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 +1304,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 +1389,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 +1455,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));
        }
index 84565c8..1d11c2a 100644 (file)
@@ -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)"
index c143ecb..4ee0f93 100644 (file)
@@ -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>
index 01e8717..dc86144 100644 (file)
@@ -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)"
index 2a23b74..4a5b795 100644 (file)
@@ -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)"
index 4f365bf..e88f73e 100644 (file)
@@ -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)
  *
index caee16a..1629b27 100644 (file)
@@ -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>
index ba80fde..3f9d704 100644 (file)
@@ -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>
index a4f80bd..38a4e55 100644 (file)
@@ -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
index 96eb482..822e2a2 100644 (file)
@@ -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>
index b6888c6..bc3823d 100644 (file)
@@ -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
index 7cb98d2..8fd71ab 100644 (file)
@@ -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>
index 8ec75dc..9114569 100644 (file)
@@ -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>
index 624f040..da1fa91 100644 (file)
@@ -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
index a601c9a..65dc844 100644 (file)
@@ -9,7 +9,6 @@
  *
  * gendisk related functions for the dasd driver.
  *
- * $Revision: 1.51 $
  */
 
 #include <linux/config.h>
index e4b4015..c20af98 100644 (file)
@@ -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
index 9396fca..fafeeae 100644 (file)
@@ -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
index fff9020..2d5da3c 100644 (file)
@@ -9,7 +9,6 @@
  *
  * /proc interface for the dasd driver.
  *
- * $Revision: 1.33 $
  */
 
 #include <linux/config.h>
index 1f06091..606f6ad 100644 (file)
@@ -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 *)
index c570a9f..ef607a1 100644 (file)
@@ -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))
index 5bda234..a317a12 100644 (file)
@@ -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)) {
index 20be88e..682039c 100644 (file)
@@ -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);
index fcaee44..b3569c8 100644 (file)
@@ -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");
 
index 33133ad..3d0ca05 100644 (file)
@@ -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
  *
index 8f486e1..4ea438c 100644 (file)
@@ -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);
index cd2cc28..5287631 100644 (file)
@@ -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)
index 72f27c1..cb8e2e6 100644 (file)
@@ -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
index 6c077ad..8013c8e 100644 (file)
@@ -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
index 2cbb724..92be75d 100644 (file)
@@ -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
index 6223b06..cbb86fa 100644 (file)
@@ -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
index 0b03714..07ef3f6 100644 (file)
@@ -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
  *
index 5161087..1bbf231 100644 (file)
@@ -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
index a67e7e6..062fb10 100644 (file)
@@ -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",
@@ -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;
index 8b02189..3a50b19 100644 (file)
@@ -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)
index 77be2c3..45ce032 100644 (file)
@@ -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;
index fa385e7..ceb3ab3 100644 (file)
@@ -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 */
index f87c785..dbbcda3 100644 (file)
@@ -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
index 3a18443..5e6b1f5 100644 (file)
@@ -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
index d7f7494..4141919 100644 (file)
 #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;
index 2f54d03..7d6f190 100644 (file)
 #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
index e70af7f..a86436a 100644 (file)
@@ -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__);
index 3df7197..969be46 100644 (file)
@@ -2,7 +2,7 @@
 *  Define constants                                    *
 *                                                      *
 ********************************************************/
-#define VERSION_CLAW_H "$Revision: 1.6 $"
+
 /*-----------------------------------------------------*
 *     CCW command codes for CLAW protocol              *
 *------------------------------------------------------*/
index 0e2a8bb..e6e72de 100644 (file)
@@ -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;
 }
 
-
index 7d6afa1..413925e 100644 (file)
@@ -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)
index 1901fee..af9f212 100644 (file)
@@ -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;
 }
 
index ba3605f..d2e835c 100644 (file)
@@ -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_
index 93d1725..5cdcdbf 100644 (file)
@@ -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
index 84b2f8f..7254dc0 100644 (file)
@@ -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
index 2014fb7..b125331 100644 (file)
@@ -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
index 24029bd..6caf5fa 100644 (file)
@@ -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
  *
  */
index 5b98253..af679c1 100644 (file)
@@ -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_
 
index ea81773..760e77e 100644 (file)
@@ -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 $
- *
  */
 \f
 /* #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");
 }
 
 /**
index da8c515..6229ba4 100644 (file)
@@ -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];
 
 /**
index a7f348e..08e60ad 100644 (file)
@@ -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); \
index ac4c4b8..71d3853 100644 (file)
@@ -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 $
- *
  */
 \f
 #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
index d238c7e..9a064d4 100644 (file)
@@ -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
index f94f1f2..b023131 100644 (file)
@@ -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>
index e1b5186..cae9ba2 100644 (file)
@@ -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__
index c0b4c8d..e422b41 100644 (file)
 #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);
index 97f927c..410abea 100644 (file)
@@ -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";
 
 /**
@@ -8626,12 +8622,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);
index 5f8754a..77c8320 100644 (file)
@@ -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,
index 864cec5..011c410 100644 (file)
 
 #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)
index 7bf3509..3c6339d 100644 (file)
@@ -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;
index 0ea185f..c1831f5 100644 (file)
@@ -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 !!!                              */
index 3c50b6f..1286dde 100644 (file)
@@ -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__
index 206518c..e3f6471 100644 (file)
@@ -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
index d9ea7ed..7abb42a 100644 (file)
@@ -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 */
index 167fef3..95b92f3 100644 (file)
@@ -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) */
index 0fc4638..241136d 100644 (file)
@@ -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
index 9559971..4d7d47c 100644 (file)
@@ -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"
index 9bb5110..e260d19 100644 (file)
@@ -34,8 +34,6 @@
 #ifndef ZFCP_DEF_H
 #define ZFCP_DEF_H
 
-#define ZFCP_DEF_REVISION "$Revision: 1.111 $"
-
 /*************************** INCLUDES *****************************************/
 
 #include <linux/init.h>
index c065cb8..da947e6 100644 (file)
@@ -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 *);
index c378226..c1ba7cf 100644 (file)
@@ -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;
index cbfab09..9f0cb3d 100644 (file)
@@ -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 *);
index d719f66..1c32751 100644 (file)
@@ -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);
index 3c2cbcc..e080375 100644 (file)
@@ -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);
index 9f26225..dfc0737 100644 (file)
@@ -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
index 77a5e2d..6622d55 100644 (file)
@@ -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
index 3924eb3..f401d42 100644 (file)
@@ -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
index 2f50815..ad5dfb8 100644 (file)
@@ -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
index 19bd346..a800fb5 100644 (file)
@@ -286,6 +286,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          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 */
 };
 
@@ -802,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;
@@ -836,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);
@@ -1082,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)
index 69ed77f..7955ebe 100644 (file)
@@ -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"
index 2cfdbef..1d11f7e 100644 (file)
@@ -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 */
index 3a32047..be14e2e 100644 (file)
@@ -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 ****************************/
index bef1f9d..58bc175 100644 (file)
@@ -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;
index db8f5ce..342f779 100644 (file)
@@ -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);
@@ -3292,6 +3331,15 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
        if (tinfo->width == MSG_EXT_WDTR_BUS_16_BIT)
                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
@@ -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);
index 91c4f7f..8ad3ce9 100644 (file)
@@ -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));
index 2567e29..7254ea5 100644 (file)
@@ -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);
 }
 
index cb74fcc..9cb1013 100644 (file)
@@ -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)
index bf360ae..ebbf7e4 100644 (file)
@@ -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);
index 196a634..757242e 100644 (file)
@@ -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.
                 */
index 8763b15..2068e00 100644 (file)
@@ -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 {
@@ -2203,6 +2203,20 @@ ahd_reg_print_t ahd_cmdsize_table_print;
     ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap)
 #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
@@ -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
index a4137c9..db38a61 100644 (file)
@@ -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));
 }
 
@@ -3449,6 +3450,20 @@ ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap)
            0x158, regvalue, cur_col, 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)
 {
index b1e5365..11bed07 100644 (file)
@@ -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)
index f936b69..9241027 100644 (file)
@@ -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);
 }
index 67e046d..c328596 100644 (file)
@@ -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 ';'
        {
index e64f802..9df9e2c 100644 (file)
  * 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
index 45c0b23..7c3983f 100644 (file)
@@ -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; }
index c8a32cf..cbf8252 100644 (file)
@@ -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 =
index 822b9fa..eaefedd 100644 (file)
@@ -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;
index 5b0edd1..4550d71 100644 (file)
@@ -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,
index ce15d9e..7eed0b0 100644 (file)
@@ -123,6 +123,19 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
        return 0;
 }
 
+/**
+ * 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
index 75db2f5..f47dd87 100644 (file)
@@ -280,6 +280,28 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
        return -1;
 }
 
+/**
+ * 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
index 3c688ef..0cf0e4c 100644 (file)
@@ -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;
index e5e1ca4..86c5461 100644 (file)
@@ -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);
index cfbceb5..07b1e7c 100644 (file)
@@ -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;
 
index 511ed52..a487f41 100644 (file)
@@ -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.02
  *
  * Authors:
  *     Sreenivas Bagalkote     <Sreenivas.Bagalkote@lsil.com>
@@ -55,13 +55,13 @@ 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_DELL,
-        PCI_DEVICE_ID_DELL_PERC5,
+        PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
         PCI_ANY_ID,
         PCI_ANY_ID,
         },
@@ -119,12 +119,18 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
        spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
 }
 
+
+/**
+*      The following functions are defined for xscale 
+*      (deviceid : 1064R, PERC5) controllers
+*/
+
 /**
- * megasas_enable_intr -       Enables interrupts
+ * 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);
 
@@ -132,6 +138,66 @@ megasas_enable_intr(struct megasas_register_set __iomem * regs)
        readl(&regs->outbound_intr_mask);
 }
 
+/**
+ * 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
+*/
+
 /**
  * megasas_disable_intr -      Disables interrupts
  * @regs:                      MFI register set
@@ -139,7 +205,7 @@ megasas_enable_intr(struct megasas_register_set __iomem * regs)
 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 +233,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 +263,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 +306,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 +621,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 +664,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 +696,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 +1107,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 +1114,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 +1151,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 +1159,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 +1184,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 +1194,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 +1244,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 +1607,20 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 
        reg_set = instance->reg_set;
 
+       instance->instancet = &megasas_instance_template_xscale;
+
        /*
         * 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 +1929,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;
 }
@@ -2126,7 +2118,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 +2673,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);
        }
index eaec9d5..d6d166c 100644 (file)
 /**
  * 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.02"
+#define MEGASAS_RELDATE                                "Jan 23, 2006"
+#define MEGASAS_EXT_VERSION                    "Mon Jan 23 14:09:01 PST 2006"
 /*
  * =====================================
  * MegaRAID SAS MFI firmware definitions
@@ -1013,6 +1012,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 +1065,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 +1136,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 {
index 0878f95..e023024 100644 (file)
 * 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
 #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
 
 
 
 #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");
index 79d8a91..bad066e 100644 (file)
@@ -1680,7 +1680,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;
@@ -2270,6 +2271,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
index 32be4c1..35266bd 100644 (file)
@@ -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,8 +72,8 @@ 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_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 void qla2x00_blink_led(scsi_qla_host_t *);
 
index a91fea6..e67bb09 100644 (file)
@@ -32,7 +32,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 +1687,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 +1724,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 +2014,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 +2038,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 +2049,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 +2064,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 +2202,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 +2678,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 +2726,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 +2839,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 +2974,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 +3014,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,
index f63af08..71a46fc 100644 (file)
@@ -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);
@@ -432,7 +432,7 @@ 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;
@@ -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:
index 4916847..5866a7c 100644 (file)
@@ -756,7 +756,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
@@ -1642,6 +1642,31 @@ 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;
+               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;
+               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 +1677,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 +1727,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 +1741,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);
 }
 
 /*
@@ -2161,6 +2189,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 +2250,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 */
@@ -2469,6 +2495,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
        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) ||
index a2333d2..5cc97b7 100644 (file)
@@ -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);
 }
 
index 3574ba9..4a60285 100644 (file)
@@ -436,6 +436,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 +446,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 +473,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;
index a3e0b7b..210dab5 100644 (file)
@@ -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;
index 78aad95..7d07000 100644 (file)
@@ -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)) {
index 13b1d3a..7f96f33 100644 (file)
@@ -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 */
index 221999b..7aef751 100644 (file)
@@ -366,7 +366,7 @@ static struct uart_port serial21285_port = {
        .irq            = NO_IRQ,
        .fifosize       = 16,
        .ops            = &serial21285_ops,
-       .flags          = ASYNC_BOOT_AUTOCONF,
+       .flags          = UPF_BOOT_AUTOCONF,
 };
 
 static void serial21285_setup_ports(void)
index bc36edf..179c1f0 100644 (file)
@@ -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>
@@ -2026,12 +2025,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
        int probeflags = PROBE_ANY;
        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) {
@@ -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,8 @@ 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);
+       serial_out(up, UART_IER, ier | UART_IER_THRI);
 }
 
 static int serial8250_console_setup(struct console *co, char *options)
index 9fd1925..0d38f0f 100644 (file)
@@ -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
index 3490022..429de27 100644 (file)
@@ -566,7 +566,7 @@ static struct uart_amba_port amba_ports[UART_NR] = {
                        .uartclk        = 14745600,
                        .fifosize       = 16,
                        .ops            = &amba_pl010_pops,
-                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .flags          = UPF_BOOT_AUTOCONF,
                        .line           = 0,
                },
                .dtr_mask       = 1 << 5,
@@ -581,7 +581,7 @@ static struct uart_amba_port amba_ports[UART_NR] = {
                        .uartclk        = 14745600,
                        .fifosize       = 16,
                        .ops            = &amba_pl010_pops,
-                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .flags          = UPF_BOOT_AUTOCONF,
                        .line           = 1,
                },
                .dtr_mask       = 1 << 7,
index 8ef9994..ce7b2e4 100644 (file)
@@ -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,
        }
 };
 
index 587cc6a..858048e 100644 (file)
@@ -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
@@ -674,7 +674,7 @@ static struct imx_port imx_ports[] = {
                .irq            = UART1_MINT_RX,
                .uartclk        = 16000000,
                .fifosize       = 8,
-               .flags          = ASYNC_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF,
                .ops            = &imx_pops,
                .line           = 0,
        },
@@ -690,7 +690,7 @@ static struct imx_port imx_ports[] = {
                .irq            = UART2_MINT_RX,
                .uartclk        = 16000000,
                .fifosize       = 8,
-               .flags          = ASYNC_BOOT_AUTOCONF,
+               .flags          = UPF_BOOT_AUTOCONF,
                .ops            = &imx_pops,
                .line           = 1,
        },
index 6f22b42..87e4e2c 100644 (file)
@@ -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;
 
index eb4883e..0a2dd6c 100644 (file)
@@ -1060,7 +1060,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");
index 1bd9316..ff7b60b 100644 (file)
@@ -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:
index 9437704..0717abf 100644 (file)
@@ -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);
index d4a1f0e..d0490f6 100644 (file)
@@ -506,7 +506,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
                        .uartclk        = 14745600/2,
                        .fifosize       = 16,
                        .ops            = &lh7a40x_uart_ops,
-                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .flags          = UPF_BOOT_AUTOCONF,
                        .line           = 0,
                },
        },
@@ -519,7 +519,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
                        .uartclk        = 14745600/2,
                        .fifosize       = 16,
                        .ops            = &lh7a40x_uart_ops,
-                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .flags          = UPF_BOOT_AUTOCONF,
                        .line           = 1,
                },
        },
@@ -532,7 +532,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
                        .uartclk        = 14745600/2,
                        .fifosize       = 16,
                        .ops            = &lh7a40x_uart_ops,
-                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .flags          = UPF_BOOT_AUTOCONF,
                        .line           = 2,
                },
        },
index a9e0707..80737c1 100644 (file)
@@ -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         = SERIAL_IO_MEM,
+                       .irq            = 61,
+                       .ops            = &sci_uart_ops,
+                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .line           = 0,
+               },
+               .type           = PORT_SCIF,
+               .irqs           = SH7770_SCIF0_IRQS,
+               .init_pins      = sci_init_pins_scif,
+       },
+       {
+               .port   = {
+                       .membase        = (void *)0xff924000,
+                       .mapbase        = 0xff924000,
+                       .iotype         = SERIAL_IO_MEM,
+                       .irq            = 62,
+                       .ops            = &sci_uart_ops,
+                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .line           = 1,
+               },
+               .type           = PORT_SCIF,
+               .irqs           = SH7770_SCIF1_IRQS,
+               .init_pins      = sci_init_pins_scif,
+       },
+       {
+               .port   = {
+                       .membase        = (void *)0xff925000,
+                       .mapbase        = 0xff925000,
+                       .iotype         = SERIAL_IO_MEM,
+                       .irq            = 63,
+                       .ops            = &sci_uart_ops,
+                       .flags          = ASYNC_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         = SERIAL_IO_MEM,
+                       .irq            = 43,
+                       .ops            = &sci_uart_ops,
+                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .line           = 0,
+               },
+               .type           = PORT_SCIF,
+               .irqs           = SH7780_SCIF0_IRQS,
+               .init_pins      = sci_init_pins_scif,
+       },
+       {
+               .port   = {
+                       .membase        = (void *)0xffe10000,
+                       .mapbase        = 0xffe10000,
+                       .iotype         = SERIAL_IO_MEM,
+                       .irq            = 79,
+                       .ops            = &sci_uart_ops,
+                       .flags          = ASYNC_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,13 +1573,20 @@ 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;
index 2892169..1f14bb4 100644 (file)
 #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
 
 # 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 */
        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 */
 # 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
 #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
 # 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
 # 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)
 
index 9a3665b..bc67442 100644 (file)
@@ -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;
@@ -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);
 
index aaa009f..c70ae81 100644 (file)
@@ -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);
index 3639c3f..36e476d 100644 (file)
@@ -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/
index af0a41e..04631dc 100644 (file)
@@ -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,
 };
index c1b47d7..7860c8a 100644 (file)
 #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)
index 7d2a679..830d2c9 100644 (file)
 #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");
        }
 
index 7af1883..c1211fc 100644 (file)
@@ -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;
index 1adacd6..ff8551e 100644 (file)
 #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))
        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...)    \
 #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];
 };
index 5c76e3a..42d6823 100644 (file)
@@ -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];
        }
index b9fd39f..97bdeb1 100644 (file)
@@ -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);
index dba4cc0..d34848a 100644 (file)
@@ -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;
 }
 
index 319de03..7135e54 100644 (file)
@@ -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"
index 0817967..dad4d8f 100644 (file)
@@ -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);
index 9a4edc5..0aab7d2 100644 (file)
@@ -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;
index c32e1f7..67b13ab 100644 (file)
@@ -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>
index 2fc110d..ae7a1c0 100644 (file)
@@ -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);
index 08ca0f8..3a6687d 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
-/* 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);
index 57e7737..ebcca97 100644 (file)
@@ -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;
index 584b8dc..972ce04 100644 (file)
@@ -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,
+                  },
 };
 
 /*-----------------------------------------------------------------*/
index 77cd6ac..db280ca 100644 (file)
@@ -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);
 }
 
 
index 3ef2c0c..e9e5bc1 100644 (file)
@@ -190,7 +190,7 @@ 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 "
+                       printk(KERN_WARNING "%s %s: BIOS handoff "
                                        "failed (BIOS bug ?)\n",
                                        pdev->dev.bus_id, "OHCI");
 
@@ -212,8 +212,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 +225,80 @@ 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");
+
+                               /* 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);
+                       }
+
+                       /* 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 "
+                               printk(KERN_WARNING "%s %s: 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);
+                               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
index b607600..7823980 100644 (file)
@@ -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;
index a91e72c..6f7a684 100644 (file)
@@ -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
@@ -1453,6 +1453,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.
  */
@@ -1566,6 +1569,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 +1832,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:
index 4dff847..925f5ab 100644 (file)
@@ -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");
 }
index 3b3c7b4..697c5e5 100644 (file)
@@ -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);
index 1bfc105..37d2f0b 100644 (file)
@@ -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;
index 21232ee..0d3d2cc 100644 (file)
@@ -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.
-
-
index d83adff..3957aa1 100644 (file)
@@ -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 (file)
index 0000000..652238f
--- /dev/null
@@ -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 (file)
index 0000000..2c0171a
--- /dev/null
@@ -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 (file)
index 0000000..b9df910
--- /dev/null
@@ -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 (file)
index 0000000..65f1ae9
--- /dev/null
@@ -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;
+}
index 8af665b..51e9cc0 100644 (file)
@@ -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);
index 359c4b2..3ebb6e9 100644 (file)
@@ -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;
        }
        */
index e5cea0e..17d60c1 100644 (file)
@@ -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>
 
 /*****************************************************************************/
 
-#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_ */
index 8d1a1c3..c81397e 100644 (file)
@@ -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    *
 
 /*****************************************************************************/
 
+#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;
+
+       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 (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));
-
-       switch (cmd) {
-
-       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;
-       }
-
-       case VIDIOC_ENUMINPUT:
-       {
-               struct v4l2_input i;
-
-               if (copy_from_user(&i, arg, sizeof(i)))
-                       return -EFAULT;
+       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;
 
-               if (i.index)
-                       return -EINVAL;
+       return 0;
+}
 
-               memset(&i, 0, sizeof(i));
-               strcpy(i.name, "USB");
 
-               if (copy_to_user(arg, &i, sizeof(i)))
-                       return -EFAULT;
+static int
+sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_input i;
 
-               return 0;
-       }
+       if (copy_from_user(&i, arg, sizeof(i)))
+               return -EFAULT;
 
-       case VIDIOC_G_INPUT:
-       case VIDIOC_S_INPUT:
-       {
-               int index;
+       if (i.index)
+               return -EINVAL;
 
-               if (copy_from_user(&index, arg, sizeof(index)))
-                       return -EFAULT;
+       memset(&i, 0, sizeof(i));
+       strcpy(i.name, "Camera");
 
-               if (index != 0)
-                       return -EINVAL;
+       if (copy_to_user(arg, &i, sizeof(i)))
+               return -EFAULT;
 
-               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_gs_input(struct sn9c102_device* cam, void __user * arg)
+{
+       int index;
 
-               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 (copy_from_user(&index, arg, sizeof(index)))
+               return -EFAULT;
 
+       if (index != 0)
                return -EINVAL;
-       }
 
-       case VIDIOC_G_CTRL:
-       {
-               struct sn9c102_sensor* s = cam->sensor;
-               struct v4l2_control ctrl;
-               int err = 0;
+       return 0;
+}
 
-               if (!s->get_ctrl)
-                       return -EINVAL;
 
-               if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
-                       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;
 
-               err = s->get_ctrl(cam, &ctrl);
+       if (copy_from_user(&qc, arg, sizeof(qc)))
+               return -EFAULT;
 
-               if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
-                       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 err;
-       }
+       return -EINVAL;
+}
 
-       case VIDIOC_S_CTRL_OLD:
-       case VIDIOC_S_CTRL:
-       {
-               struct sn9c102_sensor* s = cam->sensor;
-               struct v4l2_control ctrl;
-               u8 i;
-               int err = 0;
 
-               if (!s->set_ctrl)
-                       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 (copy_from_user(&ctrl, arg, sizeof(ctrl)))
-                       return -EFAULT;
+       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) {
-                               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 (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);
 
-               if ((err = s->set_ctrl(cam, &ctrl)))
-                       return err;
+exit:
+       if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
+               return -EFAULT;
 
-               s->_qctrl[i].default_value = ctrl.value;
+       return err;
+}
 
-               PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
-                     (unsigned long)ctrl.id, (unsigned long)ctrl.value)
 
-               return 0;
-       }
+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;
 
-       case VIDIOC_CROPCAP:
-       {
-               struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
+       if (!s->set_ctrl)
+               return -EINVAL;
 
-               cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               cc->pixelaspect.numerator = 1;
-               cc->pixelaspect.denominator = 1;
+       if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+               return -EFAULT;
 
-               if (copy_to_user(arg, cc, sizeof(*cc)))
-                       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;
+               }
 
-               return 0;
-       }
+       if ((err = s->set_ctrl(cam, &ctrl)))
+               return err;
 
-       case VIDIOC_G_CROP:
-       {
-               struct sn9c102_sensor* s = cam->sensor;
-               struct v4l2_crop crop = {
-                       .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               };
+       s->_qctrl[i].default_value = ctrl.value;
 
-               memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
+       PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
+             (unsigned long)ctrl.id, (unsigned long)ctrl.value);
 
-               if (copy_to_user(arg, &crop, sizeof(crop)))
-                       return -EFAULT;
+       return 0;
+}
 
-               return 0;
-       }
 
-       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;
+static int
+sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
 
-               rect = &(crop.c);
+       cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       cc->pixelaspect.numerator = 1;
+       cc->pixelaspect.denominator = 1;
 
-               if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
+       if (copy_to_user(arg, cc, sizeof(*cc)))
+               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_crop(struct sn9c102_device* cam, void __user * arg)
+{
+       struct sn9c102_sensor* s = cam->sensor;
+       struct v4l2_crop crop = {
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+       };
 
-               err = sn9c102_set_crop(cam, rect);
-               if (s->set_crop)
-                       err += s->set_crop(cam, rect);
-               err += sn9c102_set_scale(cam, scale);
+       memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
 
-               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 (copy_to_user(arg, &crop, sizeof(crop)))
+               return -EFAULT;
 
-               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;
-               }
+       return 0;
+}
 
-               cam->stream = stream;
 
-               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;
 
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc fmtd;
+       if (copy_from_user(&crop, arg, sizeof(crop)))
+               return -EFAULT;
 
-               if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
-                       return -EFAULT;
+       rect = &(crop.c);
 
-               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 (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
 
-               fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
+       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 (copy_to_user(arg, &fmtd, sizeof(fmtd)))
-                       return -EFAULT;
+       /* 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;
 
-               return 0;
+       if (copy_to_user(arg, &crop, sizeof(crop))) {
+               cam->stream = stream;
+               return -EFAULT;
        }
 
-       case VIDIOC_G_FMT:
-       {
-               struct v4l2_format format;
-               struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
-
-               if (copy_from_user(&format, arg, sizeof(format)))
-                       return -EFAULT;
+       if (cam->module_param.force_munmap || cam->io == IO_READ)
+               sn9c102_release_buffers(cam);
 
-               if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
+       err = sn9c102_set_crop(cam, rect);
+       if (s->set_crop)
+               err += s->set_crop(cam, rect);
+       err += sn9c102_set_scale(cam, scale);
 
-               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));
+       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 (copy_to_user(arg, &format, sizeof(format)))
-                       return -EFAULT;
+       s->pix_format.width = rect->width/scale;
+       s->pix_format.height = rect->height/scale;
+       memcpy(&(s->_rect), rect, sizeof(*rect));
 
-               return 0;
+       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;
        }
 
-       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->io == IO_READ)
+               sn9c102_empty_framequeues(cam);
+       else if (cam->module_param.force_munmap)
+               sn9c102_requeue_outqueue(cam);
 
-               pix = &(format.fmt.pix);
+       cam->stream = stream;
 
-               if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-
-               memcpy(&rect, &(s->_rect), sizeof(rect));
+       return 0;
+}
 
-               { /* 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;
-               }
 
-               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;
-               }
+static int
+sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_fmtdesc fmtd;
 
-               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;
-               }
+       if (copy_from_user(&fmtd, arg, 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_FMT failed. "
-                                              "Unmap the buffers first.")
-                                       return -EINVAL;
-                               }
+       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 (cam->stream == STREAM_ON)
-                       if ((err = sn9c102_stream_interrupt(cam)))
-                               return err;
+       fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
 
-               if (copy_to_user(arg, &format, sizeof(format))) {
-                       cam->stream = stream;
-                       return -EFAULT;
-               }
+       if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
+               return -EFAULT;
 
-               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_fmt(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_format format;
+       struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
 
-               cam->stream = stream;
+       if (copy_from_user(&format, arg, sizeof(format)))
+               return -EFAULT;
 
-               return 0;
-       }
+       if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
 
-       case VIDIOC_G_JPEGCOMP:
-       {
-               if (copy_to_user(arg, &cam->compression,
-                                sizeof(cam->compression)))
-                       return -EFAULT;
+       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));
 
-               return 0;
-       }
+       if (copy_to_user(arg, &format, sizeof(format)))
+               return -EFAULT;
 
-       case VIDIOC_S_JPEGCOMP:
-       {
-               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;
 
-               if (jc.quality != 0 && jc.quality != 1)
-                       return -EINVAL;
+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 (cam->stream == STREAM_ON)
-                       if ((err = sn9c102_stream_interrupt(cam)))
-                               return err;
+       if (copy_from_user(&format, arg, sizeof(format)))
+               return -EFAULT;
 
-               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;
-               }
+       pix = &(format.fmt.pix);
 
-               cam->compression.quality = jc.quality;
+       if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
 
-               cam->stream = stream;
+       memcpy(&rect, &(s->_rect), sizeof(rect));
 
-               return 0;
+       { /* 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_REQBUFS:
-       {
-               struct v4l2_requestbuffers rb;
-               u32 i;
-               int err;
+       rect.width = scale * pix->width;
+       rect.height = scale * pix->height;
 
-               if (copy_from_user(&rb, arg, sizeof(rb)))
-                       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 (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-                   rb.memory != V4L2_MEMORY_MMAP)
-                       return -EINVAL;
+       rect.width &= ~15L;
+       rect.height &= ~15L;
 
-               if (cam->io == IO_READ) {
-                       DBG(3, "Close and open the device again to choose "
-                              "the mmap I/O method")
-                       return -EINVAL;
-               }
+       { /* 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;
+       }
+
+       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;
+       }
 
+       if (cam->module_param.force_munmap)
                for (i = 0; i < cam->nbuffers; i++)
                        if (cam->frame[i].vma_use_count) {
-                               DBG(3, "VIDIOC_REQBUFS failed. "
-                                      "Previous buffers are still mapped.")
+                               DBG(3, "VIDIOC_S_FMT failed. Unmap the "
+                                      "buffers first.");
                                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);
+       if (copy_to_user(arg, &format, sizeof(format))) {
+               cam->stream = stream;
+               return -EFAULT;
+       }
 
+       if (cam->module_param.force_munmap  || cam->io == IO_READ)
                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);
-                       cam->io = IO_NONE;
-                       return -EFAULT;
-               }
+       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);
 
-               cam->io = rb.count ? IO_MMAP : IO_NONE;
+       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;
        }
 
-       case VIDIOC_QUERYBUF:
-       {
-               struct v4l2_buffer b;
+       if (cam->io == IO_READ)
+               sn9c102_empty_framequeues(cam);
+       else if (cam->module_param.force_munmap)
+               sn9c102_requeue_outqueue(cam);
 
-               if (copy_from_user(&b, arg, sizeof(b)))
-                       return -EFAULT;
+       cam->stream = stream;
 
-               if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-                   b.index >= cam->nbuffers || cam->io != IO_MMAP)
-                       return -EINVAL;
+       return 0;
+}
 
-               memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
 
-               if (cam->frame[b.index].vma_use_count)
-                       b.flags |= V4L2_BUF_FLAG_MAPPED;
+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;
 
-               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;
+       return 0;
+}
 
-               if (copy_to_user(arg, &b, sizeof(b)))
-                       return -EFAULT;
 
-               return 0;
+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;
+
+       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 = sn9c102_stream_interrupt(cam)))
+                       return err;
+
+       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;
        }
 
-       case VIDIOC_QBUF:
-       {
-               struct v4l2_buffer b;
-               unsigned long lock_flags;
+       cam->compression.quality = jc.quality;
 
-               if (copy_from_user(&b, arg, sizeof(b)))
-                       return -EFAULT;
+       cam->stream = stream;
 
-               if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-                   b.index >= cam->nbuffers || cam->io != IO_MMAP)
-                       return -EINVAL;
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_reqbufs(struct sn9c102_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->frame[b.index].state != F_UNUSED)
+       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;
+               }
 
-               cam->frame[b.index].state = F_QUEUED;
+       if (cam->stream == STREAM_ON)
+               if ((err = sn9c102_stream_interrupt(cam)))
+                       return err;
 
-               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);
+       sn9c102_empty_framequeues(cam);
 
-               PDBGG("Frame #%lu queued", (unsigned long)b.index)
+       sn9c102_release_buffers(cam);
+       if (rb.count)
+               rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
 
-               return 0;
+       if (copy_to_user(arg, &rb, sizeof(rb))) {
+               sn9c102_release_buffers(cam);
+               cam->io = IO_NONE;
+               return -EFAULT;
        }
 
-       case VIDIOC_DQBUF:
-       {
-               struct v4l2_buffer b;
-               struct sn9c102_frame_t *f;
-               unsigned long lock_flags;
-               int err = 0;
+       cam->io = rb.count ? IO_MMAP : IO_NONE;
 
-               if (copy_from_user(&b, arg, sizeof(b)))
-                       return -EFAULT;
+       return 0;
+}
 
-               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;
-               }
+static int
+sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_buffer b;
 
-               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);
+       if (copy_from_user(&b, arg, sizeof(b)))
+               return -EFAULT;
 
-               f->state = F_UNUSED;
+       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           b.index >= cam->nbuffers || cam->io != IO_MMAP)
+               return -EINVAL;
 
-               memcpy(&b, &f->buf, sizeof(b));
-               if (f->vma_use_count)
-                       b.flags |= V4L2_BUF_FLAG_MAPPED;
+       memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
 
-               if (copy_to_user(arg, &b, sizeof(b)))
-                       return -EFAULT;
+       if (cam->frame[b.index].vma_use_count)
+               b.flags |= V4L2_BUF_FLAG_MAPPED;
 
-               PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index)
+       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;
 
-               return 0;
-       }
+       if (copy_to_user(arg, &b, sizeof(b)))
+               return -EFAULT;
 
-       case VIDIOC_STREAMON:
-       {
-               int type;
+       return 0;
+}
 
-               if (copy_from_user(&type, arg, sizeof(type)))
-                       return -EFAULT;
 
-               if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-                       return -EINVAL;
+static int
+sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_buffer b;
+       unsigned long lock_flags;
 
-               if (list_empty(&cam->inqueue))
-                       return -EINVAL;
+       if (copy_from_user(&b, arg, sizeof(b)))
+               return -EFAULT;
 
-               cam->stream = STREAM_ON;
+       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           b.index >= cam->nbuffers || cam->io != IO_MMAP)
+               return -EINVAL;
 
-               DBG(3, "Stream on")
+       if (cam->frame[b.index].state != F_UNUSED)
+               return -EINVAL;
 
-               return 0;
-       }
+       cam->frame[b.index].state = F_QUEUED;
 
-       case VIDIOC_STREAMOFF:
-       {
-               int type, err;
+       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);
 
-               if (copy_from_user(&type, arg, sizeof(type)))
-                       return -EFAULT;
+       PDBGG("Frame #%lu queued", (unsigned long)b.index);
 
-               if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-                       return -EINVAL;
+       return 0;
+}
 
-               if (cam->stream == STREAM_ON)
-                       if ((err = sn9c102_stream_interrupt(cam)))
-                               return err;
 
-               sn9c102_empty_framequeues(cam);
+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;
 
-               DBG(3, "Stream off")
+       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+               return -EINVAL;
 
-               return 0;
+       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;
        }
 
-       case VIDIOC_G_PARM:
-       {
-               struct v4l2_streamparm sp;
+       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);
 
-               if (copy_from_user(&sp, arg, sizeof(sp)))
-                       return -EFAULT;
+       f->state = F_UNUSED;
 
-               if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
+       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
+sn9c102_vidioc_streamon(struct sn9c102_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
+sn9c102_vidioc_streamoff(struct sn9c102_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 = sn9c102_stream_interrupt(cam)))
+                       return err;
+
+       sn9c102_empty_framequeues(cam);
+
+       DBG(3, "Stream off");
+
+       return 0;
+}
+
+
+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;
 
-               sp.parm.capture.extendedmode = 0;
+       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;
+
+       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) {
 
-               if (sp.parm.capture.readbuffers == 0)
-                       sp.parm.capture.readbuffers = cam->nreadbuffers;
+       case VIDIOC_QUERYCAP:
+               return sn9c102_vidioc_querycap(cam, arg);
 
-               if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
-                       sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
+       case VIDIOC_ENUMINPUT:
+               return sn9c102_vidioc_enuminput(cam, arg);
 
-               if (copy_to_user(arg, &sp, sizeof(sp)))
-                       return -EFAULT;
+       case VIDIOC_G_INPUT:
+       case VIDIOC_S_INPUT:
+               return sn9c102_vidioc_gs_input(cam, arg);
 
-               cam->nreadbuffers = sp.parm.capture.readbuffers;
+       case VIDIOC_QUERYCTRL:
+               return sn9c102_vidioc_query_ctrl(cam, arg);
 
-               return 0;
-       }
+       case VIDIOC_G_CTRL:
+               return sn9c102_vidioc_g_ctrl(cam, arg);
+
+       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;
 }
index 18070d5..46c12ec 100644 (file)
@@ -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    *
index 86676ab..d9aa7a6 100644 (file)
@@ -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    *
index d27c5ae..4a36519 100644 (file)
@@ -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);
index 48e3ec3..b1dee78 100644 (file)
@@ -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    *
index a45166c..7d953b2 100644 (file)
@@ -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.
index 8775999..32ddf23 100644 (file)
@@ -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    *
index 927eafd..a0728f0 100644 (file)
@@ -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    *
index bff9434..9937fc6 100644 (file)
@@ -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);
index 8acbfe2..47a6ff7 100644 (file)
@@ -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 */
index 3f5317d..f3b91b7 100644 (file)
@@ -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_ */
index 449b250..ad2f4cc 100644 (file)
@@ -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 */
index 981d8a5..331d4ae 100644 (file)
@@ -593,7 +593,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",
index 5411816..3094970 100644 (file)
@@ -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
 };
index da46b35..dc7a069 100644 (file)
@@ -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 */
 };
index 10bc1bf..f2b4ca8 100644 (file)
@@ -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 */
 };
index 00d45f8..ca40f16 100644 (file)
 #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 */
 /* (the VID is the standard ftdi vid (FTDI_VID) */
 #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 )
  * 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
 #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 */
index 0eb883f..e8e575e 100644 (file)
@@ -73,7 +73,9 @@ 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) },
        { }                                     /* Terminating entry */
 };
 
index 21d434d..1807087 100644 (file)
 /* 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
index 5b06f92..ab173b3 100644 (file)
 #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;
+}
+
index 4c1b2bd..f9907a5 100644 (file)
@@ -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);
index b28151d..b1ec4a7 100644 (file)
@@ -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;
 
index dc301e5..ee958f9 100644 (file)
@@ -145,6 +145,11 @@ UNUSUAL_DEV(  0x0451, 0x5416, 0x0100, 0x0100,
                US_SC_DEVICE, US_PR_BULK, NULL,
                US_FL_NEED_OVERRIDE ),
 
+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,
                "Kyocera",
@@ -424,11 +429,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 */
index 5d02f16..4de9fb5 100644 (file)
@@ -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",
index b218717..6761b68 100644 (file)
@@ -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;
 }
 
index 996d543..9d996f2 100644 (file)
@@ -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.
+
index 4af321f..744210c 100644 (file)
@@ -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/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
new file mode 100644 (file)
index 0000000..95da4c9
--- /dev/null
@@ -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");
index 2b97246..0ae0a97 100644 (file)
@@ -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);
 }
 
index bd410e0..e3c8b5f 100644 (file)
@@ -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;
                }
index 6c187d5..579195c 100644 (file)
@@ -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;
index 266d0ab..d8467c0 100644 (file)
@@ -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");
 
index ef78e3a..93b5dc4 100644 (file)
@@ -1327,7 +1327,7 @@ config UFS_FS
 
 config UFS_FS_WRITE
        bool "UFS file system write support (DANGEROUS)"
-       depends on UFS_FS && EXPERIMENTAL
+       depends on UFS_FS && EXPERIMENTAL && BROKEN
        help
          Say Y here if you want to try writing to UFS partitions. This is
          experimental, so you should back up your UFS partitions beforehand.
index bbc442b..1f3bb50 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -411,6 +411,7 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
 
 /**
  *     bio_add_pc_page -       attempt to add page to bio
+ *     @q: the target queue
  *     @bio: destination bio
  *     @page: page to add
  *     @len: vec entry length
index 3dc712f..5e4a90e 100644 (file)
@@ -1022,6 +1022,7 @@ try_again:
 
                bh->b_state = 0;
                atomic_set(&bh->b_count, 0);
+               bh->b_private = NULL;
                bh->b_size = size;
 
                /* Link the buffer to its page */
@@ -3049,6 +3050,66 @@ asmlinkage long sys_bdflush(int func, long data)
        return 0;
 }
 
+/*
+ * Migration function for pages with buffers. This function can only be used
+ * if the underlying filesystem guarantees that no other references to "page"
+ * exist.
+ */
+#ifdef CONFIG_MIGRATION
+int buffer_migrate_page(struct page *newpage, struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+       struct buffer_head *bh, *head;
+
+       if (!mapping)
+               return -EAGAIN;
+
+       if (!page_has_buffers(page))
+               return migrate_page(newpage, page);
+
+       head = page_buffers(page);
+
+       if (migrate_page_remove_references(newpage, page, 3))
+               return -EAGAIN;
+
+       bh = head;
+       do {
+               get_bh(bh);
+               lock_buffer(bh);
+               bh = bh->b_this_page;
+
+       } while (bh != head);
+
+       ClearPagePrivate(page);
+       set_page_private(newpage, page_private(page));
+       set_page_private(page, 0);
+       put_page(page);
+       get_page(newpage);
+
+       bh = head;
+       do {
+               set_bh_page(bh, newpage, bh_offset(bh));
+               bh = bh->b_this_page;
+
+       } while (bh != head);
+
+       SetPagePrivate(newpage);
+
+       migrate_page_copy(newpage, page);
+
+       bh = head;
+       do {
+               unlock_buffer(bh);
+               put_bh(bh);
+               bh = bh->b_this_page;
+
+       } while (bh != head);
+
+       return 0;
+}
+EXPORT_SYMBOL(buffer_migrate_page);
+#endif
+
 /*
  * Buffer-head allocation
  */
index 88f60aa..e488603 100644 (file)
@@ -1785,7 +1785,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                } else if(volume_info.wsize)
                        cifs_sb->wsize = volume_info.wsize;
                else
-                       cifs_sb->wsize = CIFSMaxBufSize; /* default */
+                       cifs_sb->wsize = 
+                               min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
+                                       127*1024);
+                       /* old default of CIFSMaxBufSize was too small now
+                          that SMB Write2 can send multiple pages in kvec.   
+                          RFC1001 does not describe what happens when frame
+                          bigger than 128K is sent so use that as max in
+                          conjunction with 52K kvec constraint on arch with 4K
+                          page size  */
+
                if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
                        cifs_sb->rsize = PAGE_CACHE_SIZE; 
                        /* Windows ME does this */
index 77c990f..d17c97d 100644 (file)
@@ -1190,7 +1190,6 @@ retry:
                                        /* BB what if continued retry is
                                           requested via mount flags? */
                                        set_bit(AS_EIO, &mapping->flags);
-                                       SetPageError(page);
                                } else {
                                        cifs_stats_bytes_written(cifs_sb->tcon,
                                                                 bytes_written);
@@ -1198,6 +1197,13 @@ retry:
                        }
                        for (i = 0; i < n_iov; i++) {
                                page = pvec.pages[first + i];
+                               /* Should we also set page error on
+                               success rc but too little data written? */
+                               /* BB investigate retry logic on temporary
+                               server crash cases and how recovery works
+                               when page marked as error */ 
+                               if(rc)
+                                       SetPageError(page);
                                kunmap(page);
                                unlock_page(page);
                                page_cache_release(page);
index 7b98792..b12cb8a 100644 (file)
@@ -498,7 +498,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
                        else
                                *pRespBufType = CIFS_SMALL_BUFFER;
                        iov[0].iov_len = receive_len + 4;
-                       iov[1].iov_len = 0;
 
                        dump_smb(midQ->resp_buf, 80);
                        /* convert the length into a more usable form */
index ff0bafc..70c5af4 100644 (file)
@@ -73,17 +73,17 @@ asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __
        return do_utimes(AT_FDCWD, filename, t ? tv : NULL);
 }
 
-asmlinkage long compat_sys_futimesat(int dfd, char __user *filename, struct compat_timeval __user *t)
+asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t)
 {
        struct timeval tv[2];
 
-       if (t) { 
+       if (t) {
                if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
                    get_user(tv[0].tv_usec, &t[0].tv_usec) ||
                    get_user(tv[1].tv_sec, &t[1].tv_sec) ||
                    get_user(tv[1].tv_usec, &t[1].tv_usec))
-                       return -EFAULT; 
-       } 
+                       return -EFAULT;
+       }
        return do_utimes(dfd, filename, t ? tv : NULL);
 }
 
@@ -114,7 +114,7 @@ asmlinkage long compat_sys_newlstat(char __user * filename,
        return error;
 }
 
-asmlinkage long compat_sys_newfstatat(int dfd, char __user *filename,
+asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename,
                struct compat_stat __user *statbuf, int flag)
 {
        struct kstat stat;
@@ -1326,7 +1326,7 @@ compat_sys_open(const char __user *filename, int flags, int mode)
  * O_LARGEFILE flag.
  */
 asmlinkage long
-compat_sys_openat(int dfd, const char __user *filename, int flags, int mode)
+compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode)
 {
        return do_sys_open(dfd, filename, flags, mode);
 }
@@ -1781,7 +1781,7 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
 {
        compat_sigset_t ss32;
        sigset_t ksigmask, sigsaved;
-       long timeout = MAX_SCHEDULE_TIMEOUT;
+       s64 timeout = MAX_SCHEDULE_TIMEOUT;
        struct compat_timespec ts;
        int ret;
 
index e7d3f05..a717837 100644 (file)
@@ -706,6 +706,7 @@ struct address_space_operations ext2_aops = {
        .bmap                   = ext2_bmap,
        .direct_IO              = ext2_direct_IO,
        .writepages             = ext2_writepages,
+       .migratepage            = buffer_migrate_page,
 };
 
 struct address_space_operations ext2_aops_xip = {
@@ -723,6 +724,7 @@ struct address_space_operations ext2_nobh_aops = {
        .bmap                   = ext2_bmap,
        .direct_IO              = ext2_direct_IO,
        .writepages             = ext2_writepages,
+       .migratepage            = buffer_migrate_page,
 };
 
 /*
index 8824e84..3fc4238 100644 (file)
@@ -1559,6 +1559,7 @@ static struct address_space_operations ext3_ordered_aops = {
        .invalidatepage = ext3_invalidatepage,
        .releasepage    = ext3_releasepage,
        .direct_IO      = ext3_direct_IO,
+       .migratepage    = buffer_migrate_page,
 };
 
 static struct address_space_operations ext3_writeback_aops = {
@@ -1572,6 +1573,7 @@ static struct address_space_operations ext3_writeback_aops = {
        .invalidatepage = ext3_invalidatepage,
        .releasepage    = ext3_releasepage,
        .direct_IO      = ext3_direct_IO,
+       .migratepage    = buffer_migrate_page,
 };
 
 static struct address_space_operations ext3_journalled_aops = {
index a7ef5e7..2963516 100644 (file)
@@ -335,9 +335,14 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file,
        loff_t pos = page_offset(req->pages[0]);
        size_t count = req->num_pages << PAGE_CACHE_SHIFT;
        req->out.page_zeroing = 1;
-       req->end = fuse_readpages_end;
        fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
-       request_send_background(fc, req);
+       if (fc->async_read) {
+               req->end = fuse_readpages_end;
+               request_send_background(fc, req);
+       } else {
+               request_send(fc, req);
+               fuse_readpages_end(fc, req);
+       }
 }
 
 struct fuse_readpages_data {
index 46cf933..4a83adf 100644 (file)
@@ -272,6 +272,9 @@ struct fuse_conn {
            reply, before any other request, and never cleared */
        unsigned conn_error : 1;
 
+       /** Do readpages asynchronously?  Only set in INIT */
+       unsigned async_read : 1;
+
        /*
         * The following bitfields are only for optimization purposes
         * and hence races in setting them will not cause malfunction
index c755a04..879e6fb 100644 (file)
@@ -473,6 +473,16 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
        if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
                fc->conn_error = 1;
        else {
+               unsigned long ra_pages;
+
+               if (arg->minor >= 6) {
+                       ra_pages = arg->max_readahead / PAGE_CACHE_SIZE;
+                       if (arg->flags & FUSE_ASYNC_READ)
+                               fc->async_read = 1;
+               } else
+                       ra_pages = fc->max_read / PAGE_CACHE_SIZE;
+
+               fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
                fc->minor = arg->minor;
                fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
        }
@@ -496,6 +506,8 @@ static void fuse_send_init(struct fuse_conn *fc)
 
        arg->major = FUSE_KERNEL_VERSION;
        arg->minor = FUSE_KERNEL_MINOR_VERSION;
+       arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
+       arg->flags |= FUSE_ASYNC_READ;
        req->in.h.opcode = FUSE_INIT;
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(*arg);
@@ -552,8 +564,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
        fc->max_read = d.max_read;
-       if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
-               fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
 
        /* Used by get_root_inode() */
        sb->s_fs_info = fc;
index f568102..b351952 100644 (file)
@@ -72,8 +72,8 @@ huge_pages_needed(struct address_space *mapping, struct vm_area_struct *vma)
        unsigned long start = vma->vm_start;
        unsigned long end = vma->vm_end;
        unsigned long hugepages = (end - start) >> HPAGE_SHIFT;
-       pgoff_t next = vma->vm_pgoff;
-       pgoff_t endpg = next + ((end - start) >> PAGE_SHIFT);
+       pgoff_t next = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT);
+       pgoff_t endpg = next + hugepages;
 
        pagevec_init(&pvec, 0);
        while (next < endpg) {
index 108138d..d0be615 100644 (file)
@@ -1179,7 +1179,7 @@ EXPORT_SYMBOL(bmap);
 /**
  *     touch_atime     -       update the access time
  *     @mnt: mount the inode is accessed on
- *     @inode: inode accessed
+ *     @dentry: dentry accessed
  *
  *     Update the accessed time on an inode and mark it for writeback.
  *     This function automatically handles read only file systems and media,
index 4acdac0..7ac9fb4 100644 (file)
@@ -1161,6 +1161,7 @@ static int __path_lookup_intent_open(int dfd, const char *name,
 
 /**
  * path_lookup_open - lookup a file path with open intent
+ * @dfd: the directory to use as base, or AT_FDCWD
  * @name: pointer to file name
  * @lookup_flags: lookup intent flags
  * @nd: pointer to nameidata
@@ -1175,6 +1176,7 @@ int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
 
 /**
  * path_lookup_create - lookup a file path with open + create intent
+ * @dfd: the directory to use as base, or AT_FDCWD
  * @name: pointer to file name
  * @lookup_flags: lookup intent flags
  * @nd: pointer to nameidata
index 89ed046..1d163b6 100644 (file)
@@ -64,6 +64,32 @@ struct nfsd_list {
 };
 static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
 
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+static struct svc_stat nfsd_acl_svcstats;
+static struct svc_version *    nfsd_acl_version[] = {
+       [2] = &nfsd_acl_version2,
+       [3] = &nfsd_acl_version3,
+};
+
+#define NFSD_ACL_MINVERS            2
+#define NFSD_ACL_NRVERS                (sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0]))
+static struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS];
+
+static struct svc_program      nfsd_acl_program = {
+       .pg_prog                = NFS_ACL_PROGRAM,
+       .pg_nvers               = NFSD_ACL_NRVERS,
+       .pg_vers                = nfsd_acl_versions,
+       .pg_name                = "nfsd",
+       .pg_class               = "nfsd",
+       .pg_stats               = &nfsd_acl_svcstats,
+       .pg_authenticate        = &svc_set_client,
+};
+
+static struct svc_stat nfsd_acl_svcstats = {
+       .program        = &nfsd_acl_program,
+};
+#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
+
 static struct svc_version *    nfsd_version[] = {
        [2] = &nfsd_version2,
 #if defined(CONFIG_NFSD_V3)
@@ -79,6 +105,9 @@ static struct svc_version *  nfsd_version[] = {
 static struct svc_version *nfsd_versions[NFSD_NRVERS];
 
 struct svc_program             nfsd_program = {
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+       .pg_next                = &nfsd_acl_program,
+#endif
        .pg_prog                = NFS_PROGRAM,          /* program number */
        .pg_nvers               = NFSD_NRVERS,          /* nr of entries in nfsd_version */
        .pg_vers                = nfsd_versions,        /* version table */
@@ -147,6 +176,26 @@ nfsd_svc(unsigned short port, int nrservs)
                                nfsd_program.pg_vers[i] = nfsd_version[i];
                }
 
+
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+               found_one = 0;
+
+               for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
+                       if (NFSCTL_VERISSET(nfsd_versbits, i)) {
+                               nfsd_acl_program.pg_vers[i] =
+                                       nfsd_acl_version[i];
+                               found_one = 1;
+                       } else
+                               nfsd_acl_program.pg_vers[i] = NULL;
+               }
+
+               if (!found_one) {
+                       for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
+                               nfsd_acl_program.pg_vers[i] =
+                                       nfsd_acl_version[i];
+               }
+#endif
+
                atomic_set(&nfsd_busy, 0);
                error = -ENOMEM;
                nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE);
@@ -411,30 +460,3 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
        nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
        return 1;
 }
-
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-static struct svc_stat nfsd_acl_svcstats;
-static struct svc_version *    nfsd_acl_version[] = {
-       [2] = &nfsd_acl_version2,
-       [3] = &nfsd_acl_version3,
-};
-
-#define NFSD_ACL_NRVERS                (sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0]))
-static struct svc_program      nfsd_acl_program = {
-       .pg_prog                = NFS_ACL_PROGRAM,
-       .pg_nvers               = NFSD_ACL_NRVERS,
-       .pg_vers                = nfsd_acl_version,
-       .pg_name                = "nfsd",
-       .pg_class               = "nfsd",
-       .pg_stats               = &nfsd_acl_svcstats,
-       .pg_authenticate        = &svc_set_client,
-};
-
-static struct svc_stat nfsd_acl_svcstats = {
-       .program        = &nfsd_acl_program,
-};
-
-#define nfsd_acl_program_p     &nfsd_acl_program
-#else
-#define nfsd_acl_program_p     NULL
-#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
index 9dd71e8..d71ac65 100644 (file)
@@ -150,18 +150,15 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                if (d_reclen <= 32) {
                                        local_buf = small_buf;
                                } else {
-                                       local_buf =
-                                           reiserfs_kmalloc(d_reclen, GFP_NOFS,
-                                                            inode->i_sb);
+                                       local_buf = kmalloc(d_reclen,
+                                                           GFP_NOFS);
                                        if (!local_buf) {
                                                pathrelse(&path_to_entry);
                                                ret = -ENOMEM;
                                                goto out;
                                        }
                                        if (item_moved(&tmp_ih, &path_to_entry)) {
-                                               reiserfs_kfree(local_buf,
-                                                              d_reclen,
-                                                              inode->i_sb);
+                                               kfree(local_buf);
                                                goto research;
                                        }
                                }
@@ -174,15 +171,12 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                    (dirent, local_buf, d_reclen, d_off, d_ino,
                                     DT_UNKNOWN) < 0) {
                                        if (local_buf != small_buf) {
-                                               reiserfs_kfree(local_buf,
-                                                              d_reclen,
-                                                              inode->i_sb);
+                                               kfree(local_buf);
                                        }
                                        goto end;
                                }
                                if (local_buf != small_buf) {
-                                       reiserfs_kfree(local_buf, d_reclen,
-                                                      inode->i_sb);
+                                       kfree(local_buf);
                                }
                                // next entry should be looked for with such offset
                                next_pos = deh_offset(deh) + 1;
index ad6fa96..f347317 100644 (file)
@@ -192,6 +192,8 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl
 
        allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) *
                                   sizeof(b_blocknr_t), GFP_NOFS);
+       if (!allocated_blocks)
+               return -ENOMEM;
 
        /* First we compose a key to point at the writing position, we want to do
           that outside of any locking region. */
@@ -1285,6 +1287,23 @@ static ssize_t reiserfs_file_write(struct file *file,    /* the file we are going t
        struct reiserfs_transaction_handle th;
        th.t_trans_id = 0;
 
+       /* If a filesystem is converted from 3.5 to 3.6, we'll have v3.5 items
+       * lying around (most of the disk, in fact). Despite the filesystem
+       * now being a v3.6 format, the old items still can't support large
+       * file sizes. Catch this case here, as the rest of the VFS layer is
+       * oblivious to the different limitations between old and new items.
+       * reiserfs_setattr catches this for truncates. This chunk is lifted
+       * from generic_write_checks. */
+       if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
+           *ppos + count > MAX_NON_LFS) {
+               if (*ppos >= MAX_NON_LFS) {
+                       send_sig(SIGXFSZ, current, 0);
+                       return -EFBIG;
+               }
+               if (count > MAX_NON_LFS - (unsigned long)*ppos)
+                       count = MAX_NON_LFS - (unsigned long)*ppos;
+       }
+
        if (file->f_flags & O_DIRECT) { // Direct IO needs treatment
                ssize_t result, after_file_end = 0;
                if ((*ppos + count >= inode->i_size)
index 4582988..aa22588 100644 (file)
@@ -2021,38 +2021,6 @@ static int get_neighbors(struct tree_balance *p_s_tb, int n_h)
        return CARRY_ON;
 }
 
-#ifdef CONFIG_REISERFS_CHECK
-void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s)
-{
-       void *vp;
-       static size_t malloced;
-
-       vp = kmalloc(size, flags);
-       if (vp) {
-               REISERFS_SB(s)->s_kmallocs += size;
-               if (REISERFS_SB(s)->s_kmallocs > malloced + 200000) {
-                       reiserfs_warning(s,
-                                        "vs-8301: reiserfs_kmalloc: allocated memory %d",
-                                        REISERFS_SB(s)->s_kmallocs);
-                       malloced = REISERFS_SB(s)->s_kmallocs;
-               }
-       }
-       return vp;
-}
-
-void reiserfs_kfree(const void *vp, size_t size, struct super_block *s)
-{
-       kfree(vp);
-
-       REISERFS_SB(s)->s_kmallocs -= size;
-       if (REISERFS_SB(s)->s_kmallocs < 0)
-               reiserfs_warning(s,
-                                "vs-8302: reiserfs_kfree: allocated memory %d",
-                                REISERFS_SB(s)->s_kmallocs);
-
-}
-#endif
-
 static int get_virtual_node_size(struct super_block *sb, struct buffer_head *bh)
 {
        int max_num_of_items;
@@ -2086,7 +2054,7 @@ static int get_mem_for_virtual_node(struct tree_balance *tb)
                /* we have to allocate more memory for virtual node */
                if (tb->vn_buf) {
                        /* free memory allocated before */
-                       reiserfs_kfree(tb->vn_buf, tb->vn_buf_size, tb->tb_sb);
+                       kfree(tb->vn_buf);
                        /* this is not needed if kfree is atomic */
                        check_fs = 1;
                }
@@ -2095,24 +2063,15 @@ static int get_mem_for_virtual_node(struct tree_balance *tb)
                tb->vn_buf_size = size;
 
                /* get memory for virtual item */
-               buf =
-                   reiserfs_kmalloc(size, GFP_ATOMIC | __GFP_NOWARN,
-                                    tb->tb_sb);
+               buf = kmalloc(size, GFP_ATOMIC | __GFP_NOWARN);
                if (!buf) {
                        /* getting memory with GFP_KERNEL priority may involve
                           balancing now (due to indirect_to_direct conversion on
                           dcache shrinking). So, release path and collected
                           resources here */
                        free_buffers_in_tb(tb);
-                       buf = reiserfs_kmalloc(size, GFP_NOFS, tb->tb_sb);
+                       buf = kmalloc(size, GFP_NOFS);
                        if (!buf) {
-#ifdef CONFIG_REISERFS_CHECK
-                               reiserfs_warning(tb->tb_sb,
-                                                "vs-8345: get_mem_for_virtual_node: "
-                                                "kmalloc failed. reiserfs kmalloced %d bytes",
-                                                REISERFS_SB(tb->tb_sb)->
-                                                s_kmallocs);
-#endif
                                tb->vn_buf_size = 0;
                        }
                        tb->vn_buf = buf;
@@ -2619,7 +2578,6 @@ void unfix_nodes(struct tree_balance *tb)
                }
        }
 
-       if (tb->vn_buf)
-               reiserfs_kfree(tb->vn_buf, tb->vn_buf_size, tb->tb_sb);
+       kfree(tb->vn_buf);
 
 }
index ffa34b8..b33d67b 100644 (file)
@@ -2363,6 +2363,13 @@ static int reiserfs_write_full_page(struct page *page,
        int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize;
        th.t_trans_id = 0;
 
+       /* no logging allowed when nonblocking or from PF_MEMALLOC */
+       if (checked && (current->flags & PF_MEMALLOC)) {
+               redirty_page_for_writepage(wbc, page);
+               unlock_page(page);
+               return 0;
+       }
+
        /* The page dirty bit is cleared before writepage is called, which
         * means we have to tell create_empty_buffers to make dirty buffers
         * The page really should be up to date at this point, so tossing
@@ -2743,6 +2750,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh)
        int ret = 1;
        struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb);
 
+       lock_buffer(bh);
        spin_lock(&j->j_dirty_buffers_lock);
        if (!buffer_mapped(bh)) {
                goto free_jh;
@@ -2758,7 +2766,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh)
                if (buffer_journaled(bh) || buffer_journal_dirty(bh)) {
                        ret = 0;
                }
-       } else if (buffer_dirty(bh) || buffer_locked(bh)) {
+       } else  if (buffer_dirty(bh)) {
                struct reiserfs_journal_list *jl;
                struct reiserfs_jh *jh = bh->b_private;
 
@@ -2784,6 +2792,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh)
                reiserfs_free_jh(bh);
        }
        spin_unlock(&j->j_dirty_buffers_lock);
+       unlock_buffer(bh);
        return ret;
 }
 
index 4491fcf..b7a1795 100644 (file)
@@ -152,18 +152,16 @@ static struct reiserfs_bitmap_node *allocate_bitmap_node(struct super_block
        struct reiserfs_bitmap_node *bn;
        static int id;
 
-       bn = reiserfs_kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS,
-                             p_s_sb);
+       bn = kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS);
        if (!bn) {
                return NULL;
        }
-       bn->data = reiserfs_kmalloc(p_s_sb->s_blocksize, GFP_NOFS, p_s_sb);
+       bn->data = kzalloc(p_s_sb->s_blocksize, GFP_NOFS);
        if (!bn->data) {
-               reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb);
+               kfree(bn);
                return NULL;
        }
        bn->id = id++;
-       memset(bn->data, 0, p_s_sb->s_blocksize);
        INIT_LIST_HEAD(&bn->list);
        return bn;
 }
@@ -197,8 +195,8 @@ static inline void free_bitmap_node(struct super_block *p_s_sb,
        struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
        journal->j_used_bitmap_nodes--;
        if (journal->j_free_bitmap_nodes > REISERFS_MAX_BITMAP_NODES) {
-               reiserfs_kfree(bn->data, p_s_sb->s_blocksize, p_s_sb);
-               reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb);
+               kfree(bn->data);
+               kfree(bn);
        } else {
                list_add(&bn->list, &journal->j_bitmap_nodes);
                journal->j_free_bitmap_nodes++;
@@ -276,8 +274,8 @@ static int free_bitmap_nodes(struct super_block *p_s_sb)
        while (next != &journal->j_bitmap_nodes) {
                bn = list_entry(next, struct reiserfs_bitmap_node, list);
                list_del(next);
-               reiserfs_kfree(bn->data, p_s_sb->s_blocksize, p_s_sb);
-               reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb);
+               kfree(bn->data);
+               kfree(bn);
                next = journal->j_bitmap_nodes.next;
                journal->j_free_bitmap_nodes--;
        }
@@ -581,7 +579,7 @@ static inline void put_journal_list(struct super_block *s,
                               jl->j_trans_id, jl->j_refcount);
        }
        if (--jl->j_refcount == 0)
-               reiserfs_kfree(jl, sizeof(struct reiserfs_journal_list), s);
+               kfree(jl);
 }
 
 /*
@@ -848,6 +846,14 @@ static int write_ordered_buffers(spinlock_t * lock,
                        spin_lock(lock);
                        goto loop_next;
                }
+               /* in theory, dirty non-uptodate buffers should never get here,
+                * but the upper layer io error paths still have a few quirks.
+                * Handle them here as gracefully as we can
+                */
+               if (!buffer_uptodate(bh) && buffer_dirty(bh)) {
+                       clear_buffer_dirty(bh);
+                       ret = -EIO;
+               }
                if (buffer_dirty(bh)) {
                        list_del_init(&jh->list);
                        list_add(&jh->list, &tmp);
@@ -879,6 +885,19 @@ static int write_ordered_buffers(spinlock_t * lock,
                if (!buffer_uptodate(bh)) {
                        ret = -EIO;
                }
+               /* ugly interaction with invalidatepage here.
+                * reiserfs_invalidate_page will pin any buffer that has a valid
+                * journal head from an older transaction.  If someone else sets
+                * our buffer dirty after we write it in the first loop, and
+                * then someone truncates the page away, nobody will ever write
+                * the buffer. We're safe if we write the page one last time
+                * after freeing the journal header.
+                */
+               if (buffer_dirty(bh) && unlikely(bh->b_page->mapping == NULL)) {
+                       spin_unlock(lock);
+                       ll_rw_block(WRITE, 1, &bh);
+                       spin_lock(lock);
+               }
                put_bh(bh);
                cond_resched_lock(lock);
        }
@@ -977,6 +996,7 @@ static int flush_commit_list(struct super_block *s,
        struct reiserfs_journal *journal = SB_JOURNAL(s);
        int barrier = 0;
        int retval = 0;
+       int write_len;
 
        reiserfs_check_lock_depth(s, "flush_commit_list");
 
@@ -1018,24 +1038,35 @@ static int flush_commit_list(struct super_block *s,
        }
 
        if (!list_empty(&jl->j_bh_list)) {
+               int ret;
                unlock_kernel();
-               write_ordered_buffers(&journal->j_dirty_buffers_lock,
-                                     journal, jl, &jl->j_bh_list);
+               ret = write_ordered_buffers(&journal->j_dirty_buffers_lock,
+                                           journal, jl, &jl->j_bh_list);
+               if (ret < 0 && retval == 0)
+                       retval = ret;
                lock_kernel();
        }
        BUG_ON(!list_empty(&jl->j_bh_list));
        /*
         * for the description block and all the log blocks, submit any buffers
-        * that haven't already reached the disk
+        * that haven't already reached the disk.  Try to write at least 256
+        * log blocks. later on, we will only wait on blocks that correspond
+        * to this transaction, but while we're unplugging we might as well
+        * get a chunk of data on there.
         */
        atomic_inc(&journal->j_async_throttle);
-       for (i = 0; i < (jl->j_len + 1); i++) {
+       write_len = jl->j_len + 1;
+       if (write_len < 256)
+               write_len = 256;
+       for (i = 0 ; i < write_len ; i++) {
                bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + (jl->j_start + i) %
                    SB_ONDISK_JOURNAL_SIZE(s);
                tbh = journal_find_get_block(s, bn);
-               if (buffer_dirty(tbh))  /* redundant, ll_rw_block() checks */
-                       ll_rw_block(SWRITE, 1, &tbh);
-               put_bh(tbh);
+               if (tbh) {
+                       if (buffer_dirty(tbh))
+                           ll_rw_block(WRITE, 1, &tbh) ;
+                       put_bh(tbh) ;
+               }
        }
        atomic_dec(&journal->j_async_throttle);
 
@@ -1818,8 +1849,7 @@ void remove_journal_hash(struct super_block *sb,
 static void free_journal_ram(struct super_block *p_s_sb)
 {
        struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
-       reiserfs_kfree(journal->j_current_jl,
-                      sizeof(struct reiserfs_journal_list), p_s_sb);
+       kfree(journal->j_current_jl);
        journal->j_num_lists--;
 
        vfree(journal->j_cnode_free_orig);
@@ -2093,21 +2123,15 @@ static int journal_read_transaction(struct super_block *p_s_sb,
        }
        trans_id = get_desc_trans_id(desc);
        /* now we know we've got a good transaction, and it was inside the valid time ranges */
-       log_blocks =
-           reiserfs_kmalloc(get_desc_trans_len(desc) *
-                            sizeof(struct buffer_head *), GFP_NOFS, p_s_sb);
-       real_blocks =
-           reiserfs_kmalloc(get_desc_trans_len(desc) *
-                            sizeof(struct buffer_head *), GFP_NOFS, p_s_sb);
+       log_blocks = kmalloc(get_desc_trans_len(desc) *
+                            sizeof(struct buffer_head *), GFP_NOFS);
+       real_blocks = kmalloc(get_desc_trans_len(desc) *
+                             sizeof(struct buffer_head *), GFP_NOFS);
        if (!log_blocks || !real_blocks) {
                brelse(c_bh);
                brelse(d_bh);
-               reiserfs_kfree(log_blocks,
-                              get_desc_trans_len(desc) *
-                              sizeof(struct buffer_head *), p_s_sb);
-               reiserfs_kfree(real_blocks,
-                              get_desc_trans_len(desc) *
-                              sizeof(struct buffer_head *), p_s_sb);
+               kfree(log_blocks);
+               kfree(real_blocks);
                reiserfs_warning(p_s_sb,
                                 "journal-1169: kmalloc failed, unable to mount FS");
                return -1;
@@ -2145,12 +2169,8 @@ static int journal_read_transaction(struct super_block *p_s_sb,
                        brelse_array(real_blocks, i);
                        brelse(c_bh);
                        brelse(d_bh);
-                       reiserfs_kfree(log_blocks,
-                                      get_desc_trans_len(desc) *
-                                      sizeof(struct buffer_head *), p_s_sb);
-                       reiserfs_kfree(real_blocks,
-                                      get_desc_trans_len(desc) *
-                                      sizeof(struct buffer_head *), p_s_sb);
+                       kfree(log_blocks);
+                       kfree(real_blocks);
                        return -1;
                }
        }
@@ -2166,12 +2186,8 @@ static int journal_read_transaction(struct super_block *p_s_sb,
                        brelse_array(real_blocks, get_desc_trans_len(desc));
                        brelse(c_bh);
                        brelse(d_bh);
-                       reiserfs_kfree(log_blocks,
-                                      get_desc_trans_len(desc) *
-                                      sizeof(struct buffer_head *), p_s_sb);
-                       reiserfs_kfree(real_blocks,
-                                      get_desc_trans_len(desc) *
-                                      sizeof(struct buffer_head *), p_s_sb);
+                       kfree(log_blocks);
+                       kfree(real_blocks);
                        return -1;
                }
                memcpy(real_blocks[i]->b_data, log_blocks[i]->b_data,
@@ -2193,12 +2209,8 @@ static int journal_read_transaction(struct super_block *p_s_sb,
                                     get_desc_trans_len(desc) - i);
                        brelse(c_bh);
                        brelse(d_bh);
-                       reiserfs_kfree(log_blocks,
-                                      get_desc_trans_len(desc) *
-                                      sizeof(struct buffer_head *), p_s_sb);
-                       reiserfs_kfree(real_blocks,
-                                      get_desc_trans_len(desc) *
-                                      sizeof(struct buffer_head *), p_s_sb);
+                       kfree(log_blocks);
+                       kfree(real_blocks);
                        return -1;
                }
                brelse(real_blocks[i]);
@@ -2217,12 +2229,8 @@ static int journal_read_transaction(struct super_block *p_s_sb,
        journal->j_trans_id = trans_id + 1;
        brelse(c_bh);
        brelse(d_bh);
-       reiserfs_kfree(log_blocks,
-                      le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *),
-                      p_s_sb);
-       reiserfs_kfree(real_blocks,
-                      le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *),
-                      p_s_sb);
+       kfree(log_blocks);
+       kfree(real_blocks);
        return 0;
 }
 
@@ -2471,14 +2479,8 @@ static int journal_read(struct super_block *p_s_sb)
 static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s)
 {
        struct reiserfs_journal_list *jl;
-      retry:
-       jl = reiserfs_kmalloc(sizeof(struct reiserfs_journal_list), GFP_NOFS,
-                             s);
-       if (!jl) {
-               yield();
-               goto retry;
-       }
-       memset(jl, 0, sizeof(*jl));
+       jl = kzalloc(sizeof(struct reiserfs_journal_list),
+                    GFP_NOFS | __GFP_NOFAIL);
        INIT_LIST_HEAD(&jl->j_list);
        INIT_LIST_HEAD(&jl->j_working_list);
        INIT_LIST_HEAD(&jl->j_tail_bh_list);
@@ -2821,6 +2823,9 @@ int journal_transaction_should_end(struct reiserfs_transaction_handle *th,
            journal->j_cnode_free < (journal->j_trans_max * 3)) {
                return 1;
        }
+       /* protected by the BKL here */
+       journal->j_len_alloc += new_alloc;
+       th->t_blocks_allocated += new_alloc ;
        return 0;
 }
 
@@ -3042,14 +3047,12 @@ struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct
                }
                return th;
        }
-       th = reiserfs_kmalloc(sizeof(struct reiserfs_transaction_handle),
-                             GFP_NOFS, s);
+       th = kmalloc(sizeof(struct reiserfs_transaction_handle), GFP_NOFS);
        if (!th)
                return NULL;
        ret = journal_begin(th, s, nblocks);
        if (ret) {
-               reiserfs_kfree(th, sizeof(struct reiserfs_transaction_handle),
-                              s);
+               kfree(th);
                return NULL;
        }
 
@@ -3067,8 +3070,7 @@ int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *th)
                ret = -EIO;
        if (th->t_refcount == 0) {
                SB_JOURNAL(s)->j_persistent_trans--;
-               reiserfs_kfree(th, sizeof(struct reiserfs_transaction_handle),
-                              s);
+               kfree(th);
        }
        return ret;
 }
index 8f8d8d0..c812330 100644 (file)
@@ -456,7 +456,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
        /* get memory for composing the entry */
        buflen = DEH_SIZE + ROUND_UP(namelen);
        if (buflen > sizeof(small_buf)) {
-               buffer = reiserfs_kmalloc(buflen, GFP_NOFS, dir->i_sb);
+               buffer = kmalloc(buflen, GFP_NOFS);
                if (buffer == 0)
                        return -ENOMEM;
        } else
@@ -490,7 +490,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
        retval = reiserfs_find_entry(dir, name, namelen, &path, &de);
        if (retval != NAME_NOT_FOUND) {
                if (buffer != small_buf)
-                       reiserfs_kfree(buffer, buflen, dir->i_sb);
+                       kfree(buffer);
                pathrelse(&path);
 
                if (retval == IO_ERROR) {
@@ -515,7 +515,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
                reiserfs_warning(dir->i_sb,
                                 "reiserfs_add_entry: Congratulations! we have got hash function screwed up");
                if (buffer != small_buf)
-                       reiserfs_kfree(buffer, buflen, dir->i_sb);
+                       kfree(buffer);
                pathrelse(&path);
                return -EBUSY;
        }
@@ -535,7 +535,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
                                         &entry_key);
 
                        if (buffer != small_buf)
-                               reiserfs_kfree(buffer, buflen, dir->i_sb);
+                               kfree(buffer);
                        pathrelse(&path);
                        return -EBUSY;
                }
@@ -546,7 +546,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
            reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer,
                                     paste_size);
        if (buffer != small_buf)
-               reiserfs_kfree(buffer, buflen, dir->i_sb);
+               kfree(buffer);
        if (retval) {
                reiserfs_check_path(&path);
                return retval;
@@ -1065,7 +1065,7 @@ static int reiserfs_symlink(struct inode *parent_dir,
                goto out_failed;
        }
 
-       name = reiserfs_kmalloc(item_len, GFP_NOFS, parent_dir->i_sb);
+       name = kmalloc(item_len, GFP_NOFS);
        if (!name) {
                drop_new_inode(inode);
                retval = -ENOMEM;
@@ -1079,14 +1079,14 @@ static int reiserfs_symlink(struct inode *parent_dir,
        retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);
        if (retval) {
                drop_new_inode(inode);
-               reiserfs_kfree(name, item_len, parent_dir->i_sb);
+               kfree(name);
                goto out_failed;
        }
 
        retval =
            reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),
                               dentry, inode);
-       reiserfs_kfree(name, item_len, parent_dir->i_sb);
+       kfree(name);
        if (retval) {           /* reiserfs_new_inode iputs for us */
                goto out_failed;
        }
index fc2f43c..ef6caed 100644 (file)
@@ -88,7 +88,6 @@ static int show_super(struct seq_file *m, struct super_block *sb)
        seq_printf(m, "state: \t%s\n"
                   "mount options: \t%s%s%s%s%s%s%s%s%s%s%s\n"
                   "gen. counter: \t%i\n"
-                  "s_kmallocs: \t%i\n"
                   "s_disk_reads: \t%i\n"
                   "s_disk_writes: \t%i\n"
                   "s_fix_nodes: \t%i\n"
@@ -128,7 +127,7 @@ static int show_super(struct seq_file *m, struct super_block *sb)
                   "SMALL_TAILS " : "NO_TAILS ",
                   replay_only(sb) ? "REPLAY_ONLY " : "",
                   convert_reiserfs(sb) ? "CONV " : "",
-                  atomic_read(&r->s_generation_counter), SF(s_kmallocs),
+                  atomic_read(&r->s_generation_counter),
                   SF(s_disk_reads), SF(s_disk_writes), SF(s_fix_nodes),
                   SF(s_do_balance), SF(s_unneeded_left_neighbor),
                   SF(s_good_search_by_key_reada), SF(s_bmaps),
index 397d959..77891de 100644 (file)
@@ -472,12 +472,6 @@ static void reiserfs_put_super(struct super_block *s)
 
        print_statistics(s);
 
-       if (REISERFS_SB(s)->s_kmallocs != 0) {
-               reiserfs_warning(s,
-                                "vs-2004: reiserfs_put_super: allocated memory left %d",
-                                REISERFS_SB(s)->s_kmallocs);
-       }
-
        if (REISERFS_SB(s)->reserved_blocks != 0) {
                reiserfs_warning(s,
                                 "green-2005: reiserfs_put_super: reserved blocks left %d",
index cc061bf..ffb79c4 100644 (file)
@@ -368,15 +368,13 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
                if (d_reclen <= 32) {
                        local_buf = small_buf;
                } else {
-                       local_buf =
-                           reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb);
+                       local_buf = kmalloc(d_reclen, GFP_NOFS);
                        if (!local_buf) {
                                pathrelse(&path_to_entry);
                                return -ENOMEM;
                        }
                        if (item_moved(&tmp_ih, &path_to_entry)) {
-                               reiserfs_kfree(local_buf, d_reclen,
-                                              inode->i_sb);
+                               kfree(local_buf);
 
                                /* sigh, must retry.  Do this same offset again */
                                next_pos = d_off;
@@ -399,13 +397,12 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
                if (filldir(dirent, local_buf, d_reclen, d_off, d_ino,
                            DT_UNKNOWN) < 0) {
                        if (local_buf != small_buf) {
-                               reiserfs_kfree(local_buf, d_reclen,
-                                              inode->i_sb);
+                               kfree(local_buf);
                        }
                        goto end;
                }
                if (local_buf != small_buf) {
-                       reiserfs_kfree(local_buf, d_reclen, inode->i_sb);
+                       kfree(local_buf);
                }
        }                       /* while */
 
@@ -1322,109 +1319,44 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
        return err;
 }
 
-static int
-__reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd,
-                     int need_lock)
+static int reiserfs_check_acl(struct inode *inode, int mask)
 {
-       umode_t mode = inode->i_mode;
-
-       if (mask & MAY_WRITE) {
-               /*
-                * Nobody gets write access to a read-only fs.
-                */
-               if (IS_RDONLY(inode) &&
-                   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-                       return -EROFS;
+       struct posix_acl *acl;
+       int error = -EAGAIN; /* do regular unix permission checks by default */
 
-               /*
-                * Nobody gets write access to an immutable file.
-                */
-               if (IS_IMMUTABLE(inode))
-                       return -EACCES;
-       }
+       reiserfs_read_lock_xattr_i(inode);
+       reiserfs_read_lock_xattrs(inode->i_sb);
 
-       /* We don't do permission checks on the internal objects.
-        * Permissions are determined by the "owning" object. */
-       if (is_reiserfs_priv_object(inode))
-               return 0;
+       acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
 
-       if (current->fsuid == inode->i_uid) {
-               mode >>= 6;
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
-       } else if (reiserfs_posixacl(inode->i_sb) &&
-                  get_inode_sd_version(inode) != STAT_DATA_V1) {
-               struct posix_acl *acl;
-
-               /* ACL can't contain additional permissions if
-                  the ACL_MASK entry is 0 */
-               if (!(mode & S_IRWXG))
-                       goto check_groups;
-
-               if (need_lock) {
-                       reiserfs_read_lock_xattr_i(inode);
-                       reiserfs_read_lock_xattrs(inode->i_sb);
-               }
-               acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
-               if (need_lock) {
-                       reiserfs_read_unlock_xattrs(inode->i_sb);
-                       reiserfs_read_unlock_xattr_i(inode);
-               }
-               if (IS_ERR(acl)) {
-                       if (PTR_ERR(acl) == -ENODATA)
-                               goto check_groups;
-                       return PTR_ERR(acl);
-               }
+       reiserfs_read_unlock_xattrs(inode->i_sb);
+       reiserfs_read_unlock_xattr_i(inode);
 
-               if (acl) {
-                       int err = posix_acl_permission(inode, acl, mask);
+       if (acl) {
+               if (!IS_ERR(acl)) {
+                       error = posix_acl_permission(inode, acl, mask);
                        posix_acl_release(acl);
-                       if (err == -EACCES) {
-                               goto check_capabilities;
-                       }
-                       return err;
-               } else {
-                       goto check_groups;
-               }
-#endif
-       } else {
-             check_groups:
-               if (in_group_p(inode->i_gid))
-                       mode >>= 3;
+               } else if (PTR_ERR(acl) != -ENODATA)
+                       error = PTR_ERR(acl);
        }
 
-       /*
-        * If the DACs are ok we don't need any capability check.
-        */
-       if (((mode & mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == mask))
-               return 0;
+       return error;
+}
 
-      check_capabilities:
+int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
        /*
-        * Read/write DACs are always overridable.
-        * Executable DACs are overridable if at least one exec bit is set.
+        * We don't do permission checks on the internal objects.
+        * Permissions are determined by the "owning" object.
         */
-       if (!(mask & MAY_EXEC) ||
-           (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
-               if (capable(CAP_DAC_OVERRIDE))
-                       return 0;
+       if (is_reiserfs_priv_object(inode))
+               return 0;
 
        /*
-        * Searching includes executable on directories, else just read.
+        * Stat data v1 doesn't support ACLs.
         */
-       if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
-               if (capable(CAP_DAC_READ_SEARCH))
-                       return 0;
-
-       return -EACCES;
-}
-
-int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd)
-{
-       return __reiserfs_permission(inode, mask, nd, 1);
-}
-
-int
-reiserfs_permission_locked(struct inode *inode, int mask, struct nameidata *nd)
-{
-       return __reiserfs_permission(inode, mask, nd, 0);
+       if (get_inode_sd_version(inode) == STAT_DATA_V1)
+               return generic_permission(inode, mask, NULL);
+       else
+               return generic_permission(inode, mask, reiserfs_check_acl);
 }
index c6c33e1..0424d06 100644 (file)
@@ -209,6 +209,8 @@ init_cache:
        ctl.valid  = 1;
 read_really:
        result = server->ops->readdir(filp, dirent, filldir, &ctl);
+       if (result == -ERESTARTSYS && page)
+               ClearPageUptodate(page);
        if (ctl.idx == -1)
                goto invalid_cache;     /* retry */
        ctl.head.end = ctl.fpos - 1;
@@ -217,7 +219,8 @@ finished:
        if (page) {
                cache->head = ctl.head;
                kunmap(page);
-               SetPageUptodate(page);
+               if (result != -ERESTARTSYS)
+                       SetPageUptodate(page);
                unlock_page(page);
                page_cache_release(page);
        }
index 1206267..9892268 100644 (file)
@@ -1462,4 +1462,5 @@ struct address_space_operations linvfs_aops = {
        .commit_write           = generic_commit_write,
        .bmap                   = linvfs_bmap,
        .direct_IO              = linvfs_direct_IO,
+       .migratepage            = buffer_migrate_page,
 };
index e44b7c1..bfb4f29 100644 (file)
@@ -822,6 +822,13 @@ xfs_buf_rele(
 
        XB_TRACE(bp, "rele", bp->b_relse);
 
+       if (unlikely(!hash)) {
+               ASSERT(!bp->b_relse);
+               if (atomic_dec_and_test(&bp->b_hold))
+                       xfs_buf_free(bp);
+               return;
+       }
+
        if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) {
                if (bp->b_relse) {
                        atomic_inc(&bp->b_hold);
@@ -1514,6 +1521,7 @@ xfs_mapping_buftarg(
        struct address_space    *mapping;
        static struct address_space_operations mapping_aops = {
                .sync_page = block_sync_page,
+               .migratepage = fail_migrate_page,
        };
 
        inode = new_inode(bdev->bd_inode->i_sb);
index 76c6df3..eda7919 100644 (file)
@@ -262,6 +262,31 @@ has_fs_struct(struct task_struct *task)
        return (task->fs != init_task.fs);
 }
 
+STATIC inline void
+cleanup_inode(
+       vnode_t         *dvp,
+       vnode_t         *vp,
+       struct dentry   *dentry,        
+       int             mode)
+{
+       struct dentry   teardown = {};
+       int             err2;
+
+       /* Oh, the horror.
+        * If we can't add the ACL or we fail in 
+        * linvfs_init_security we must back out.
+        * ENOSPC can hit here, among other things.
+        */
+       teardown.d_inode = LINVFS_GET_IP(vp);
+       teardown.d_name = dentry->d_name;
+
+       if (S_ISDIR(mode))
+               VOP_RMDIR(dvp, &teardown, NULL, err2);
+       else
+               VOP_REMOVE(dvp, &teardown, NULL, err2);
+       VN_RELE(vp);
+}
+
 STATIC int
 linvfs_mknod(
        struct inode    *dir,
@@ -316,30 +341,19 @@ linvfs_mknod(
        }
 
        if (!error)
+       {
                error = linvfs_init_security(vp, dir);
+               if (error)
+                       cleanup_inode(dvp, vp, dentry, mode);
+       }
 
        if (default_acl) {
                if (!error) {
                        error = _ACL_INHERIT(vp, &va, default_acl);
-                       if (!error) {
+                       if (!error) 
                                VMODIFY(vp);
-                       } else {
-                               struct dentry   teardown = {};
-                               int             err2;
-
-                               /* Oh, the horror.
-                                * If we can't add the ACL we must back out.
-                                * ENOSPC can hit here, among other things.
-                                */
-                               teardown.d_inode = ip = LINVFS_GET_IP(vp);
-                               teardown.d_name = dentry->d_name;
-
-                               if (S_ISDIR(mode))
-                                       VOP_RMDIR(dvp, &teardown, NULL, err2);
-                               else
-                                       VOP_REMOVE(dvp, &teardown, NULL, err2);
-                               VN_RELE(vp);
-                       }
+                       else
+                               cleanup_inode(dvp, vp, dentry, mode);
                }
                _ACL_FREE(default_acl);
        }
index 9dc7256..62d0d66 100644 (file)
@@ -30,6 +30,7 @@
 
 #else  /* no PCI - no IOMMU. */
 
+struct scatterlist;
 void *dma_alloc_coherent(struct device *dev, size_t size,
                         dma_addr_t *dma_handle, gfp_t gfp);
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
index abfbe45..5f8223e 100644 (file)
@@ -25,7 +25,7 @@
                .macro addruart, rx
                mrc     p15, 0, \rx, c1, c0
                tst     \rx, #1
-               ldreq   \rx, = S3C2410_PA_UART
+               ldreq   \rx, = S3C24XX_PA_UART
                ldrne   \rx, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C2410_UART != 0
                add     \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C2410_UART)
@@ -44,7 +44,7 @@
 1003:
                mrc     p15, 0, \rd, c1, c0
                tst     \rd, #1
-               addeq   \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
+               addeq   \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
                addne   \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
                bic     \rd, \rd, #0xff000
                ldr     \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
@@ -75,7 +75,7 @@
 1003:
                mrc     p15, 0, \rd, c1, c0
                tst     \rd, #1
-               addeq   \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
+               addeq   \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
                addne   \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
                bic     \rd, \rd, #0xff000
                ldr     \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
index 1833ea5..c380d26 100644 (file)
@@ -14,6 +14,7 @@
  *  06-Jan-2003 BJD   Linux 2.6.0 version, moved bast specifics out
  *  10-Feb-2005 BJD   Added CAMIF definition from guillaume.gourat@nexvision.tv
  *  10-Mar-2005 LCVR  Added support to S3C2400, changed {VA,SZ} names
+ *  15-Jan-2006 LCVR  Added S3C24XX_PA macros for common S3C24XX resources
 */
 
 #ifndef __ASM_ARCH_MAP_H
 
 #define S3C2400_SDRAM_PA    (S3C2400_CS6)
 
+/* Use a single interface for common resources between S3C24XX cpus */
+
+#ifdef CONFIG_CPU_S3C2400
+#define S3C24XX_PA_IRQ      S3C2400_PA_IRQ
+#define S3C24XX_PA_MEMCTRL  S3C2400_PA_MEMCTRL
+#define S3C24XX_PA_USBHOST  S3C2400_PA_USBHOST
+#define S3C24XX_PA_DMA      S3C2400_PA_DMA
+#define S3C24XX_PA_CLKPWR   S3C2400_PA_CLKPWR
+#define S3C24XX_PA_LCD      S3C2400_PA_LCD
+#define S3C24XX_PA_UART     S3C2400_PA_UART
+#define S3C24XX_PA_TIMER    S3C2400_PA_TIMER
+#define S3C24XX_PA_USBDEV   S3C2400_PA_USBDEV
+#define S3C24XX_PA_WATCHDOG S3C2400_PA_WATCHDOG
+#define S3C24XX_PA_IIC      S3C2400_PA_IIC
+#define S3C24XX_PA_IIS      S3C2400_PA_IIS
+#define S3C24XX_PA_GPIO     S3C2400_PA_GPIO
+#define S3C24XX_PA_RTC      S3C2400_PA_RTC
+#define S3C24XX_PA_ADC      S3C2400_PA_ADC
+#define S3C24XX_PA_SPI      S3C2400_PA_SPI
+#else
+#define S3C24XX_PA_IRQ      S3C2410_PA_IRQ
+#define S3C24XX_PA_MEMCTRL  S3C2410_PA_MEMCTRL
+#define S3C24XX_PA_USBHOST  S3C2410_PA_USBHOST
+#define S3C24XX_PA_DMA      S3C2410_PA_DMA
+#define S3C24XX_PA_CLKPWR   S3C2410_PA_CLKPWR
+#define S3C24XX_PA_LCD      S3C2410_PA_LCD
+#define S3C24XX_PA_UART     S3C2410_PA_UART
+#define S3C24XX_PA_TIMER    S3C2410_PA_TIMER
+#define S3C24XX_PA_USBDEV   S3C2410_PA_USBDEV
+#define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG
+#define S3C24XX_PA_IIC      S3C2410_PA_IIC
+#define S3C24XX_PA_IIS      S3C2410_PA_IIS
+#define S3C24XX_PA_GPIO     S3C2410_PA_GPIO
+#define S3C24XX_PA_RTC      S3C2410_PA_RTC
+#define S3C24XX_PA_ADC      S3C2410_PA_ADC
+#define S3C24XX_PA_SPI      S3C2410_PA_SPI
+#endif
 
 #endif /* __ASM_ARCH_MAP_H */
index ce1bbba..83b0125 100644 (file)
@@ -39,9 +39,9 @@
 #define S3C24XX_VA_UART1      (S3C24XX_VA_UART + 0x4000 )
 #define S3C24XX_VA_UART2      (S3C24XX_VA_UART + 0x8000 )
 
-#define S3C2410_PA_UART0      (S3C2410_PA_UART)
-#define S3C2410_PA_UART1      (S3C2410_PA_UART + 0x4000 )
-#define S3C2410_PA_UART2      (S3C2410_PA_UART + 0x8000 )
+#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
+#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
+#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
 
 #define S3C2410_URXH     (0x24)
 #define S3C2410_UTXH     (0x20)
index ddd1578..4367ec0 100644 (file)
 #undef S3C2410_GPIOREG
 #undef S3C2410_WDOGREG
 
-#define S3C2410_GPIOREG(x) ((S3C2410_PA_GPIO + (x)))
-#define S3C2410_WDOGREG(x) ((S3C2410_PA_WATCHDOG + (x)))
+#define S3C2410_GPIOREG(x) ((S3C24XX_PA_GPIO + (x)))
+#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
 
 /* how many bytes we allow into the FIFO at a time in FIFO mode */
 #define FIFO_MAX        (14)
 
-#define uart_base S3C2410_PA_UART + (0x4000*CONFIG_S3C2410_LOWLEVEL_UART_PORT)
+#define uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C2410_LOWLEVEL_UART_PORT)
 
 static __inline__ void
 uart_wr(unsigned int reg, unsigned int val)
index 3351b77..e8ea67c 100644 (file)
@@ -26,6 +26,7 @@ struct meminfo;
 #define MT_MEMORY              5
 #define MT_ROM                 6
 #define MT_IXP2000_DEVICE      7
+#define MT_NONSHARED_DEVICE    8
 
 extern void create_memmap_holes(struct meminfo *);
 extern void memtable_init(struct meminfo *);
index 5a0d19b..70e00d0 100644 (file)
@@ -168,6 +168,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 #define PMD_SECT_WB            (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
 #define PMD_SECT_MINICACHE     (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
 #define PMD_SECT_WBWA          (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2))
 
 /*
  *   - coarse table (not used)
index 15cc6f2..d87f863 100644 (file)
@@ -186,7 +186,7 @@ extern void _change_bit_le(int nr, volatile unsigned long * p);
 extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
 extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
 extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
-extern int _find_first_zero_bit_le(void * p, unsigned size);
+extern int _find_first_zero_bit_le(const unsigned long * p, unsigned size);
 extern int _find_next_zero_bit_le(void * p, int size, int offset);
 extern int _find_first_bit_le(const unsigned long *p, unsigned size);
 extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
@@ -326,7 +326,7 @@ static inline int sched_find_first_bit(unsigned long *b)
 #define minix_test_and_clear_bit(nr,p)         \
                __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
 #define minix_find_first_zero_bit(p,sz)                \
-               _find_first_zero_bit_le(p,sz)
+               _find_first_zero_bit_le((unsigned long *)(p),sz)
 
 #endif /* __KERNEL__ */
 
index dc28daa..87c19d2 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
+#include <asm/irq.h>
 
 typedef struct {
        unsigned int __softirq_pending;
@@ -26,13 +27,6 @@ typedef struct {
 
 extern asmlinkage void __do_softirq(void);
 
-#define irq_exit()                                                      \
-        do {                                                            \
-                preempt_count() -= IRQ_EXIT_OFFSET;                     \
-                if (!in_interrupt() && local_softirq_pending())         \
-                        __do_softirq();                                 \
-                preempt_enable_no_resched();                            \
-        } while (0)
 #endif
 
 
index b88344a..f8d1eb4 100644 (file)
@@ -44,6 +44,7 @@ typedef unsigned int          __kernel_gid32_t;
 
 typedef unsigned short         __kernel_old_uid_t;
 typedef unsigned short         __kernel_old_gid_t;
+typedef unsigned short         __kernel_old_dev_t;
 
 #ifdef __GNUC__
 typedef long long              __kernel_loff_t;
index ca4ccfc..7028849 100644 (file)
@@ -98,9 +98,8 @@ extern unsigned int user_debug;
  * spin_unlock_irq() and friends are implemented.  This avoids
  * us needlessly decrementing and incrementing the preempt count.
  */
-#define prepare_arch_switch(rq,next)   local_irq_enable()
-#define finish_arch_switch(rq,prev)    spin_unlock(&(rq)->lock)
-#define task_running(rq,p)             ((rq)->curr == (p))
+#define prepare_arch_switch(next)      local_irq_enable()
+#define finish_arch_switch(prev)       spin_unlock(&(rq)->lock)
 
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
index 73296d9..997ca5d 100644 (file)
@@ -110,10 +110,10 @@ extern int page_is_ram(unsigned long pagenr);
 #endif /* __ASSEMBLY__ */
 
 #ifdef __ASSEMBLY__
-#define __PAGE_OFFSET          (0xC0000000)
+#define __PAGE_OFFSET          CONFIG_PAGE_OFFSET
 #define __PHYSICAL_START       CONFIG_PHYSICAL_START
 #else
-#define __PAGE_OFFSET          (0xC0000000UL)
+#define __PAGE_OFFSET          ((unsigned long)CONFIG_PAGE_OFFSET)
 #define __PHYSICAL_START       ((unsigned long)CONFIG_PHYSICAL_START)
 #endif
 #define __KERNEL_START         (__PAGE_OFFSET + __PHYSICAL_START)
index e68a808..9ca642c 100644 (file)
@@ -8,7 +8,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2005 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2005-2006 Silicon Graphics, Inc.  All rights reserved.
  */
 
 
@@ -27,14 +27,12 @@ extern int sn_prom_feature_available(int id);
  * "false" for new features.
  *
  * Use:
- *             if (sn_prom_feature_available(PRF_FEATURE_XXX))
+ *             if (sn_prom_feature_available(PRF_XXX))
  *                     ...
  */
 
-/*
- * Example: feature XXX
- */
-#define PRF_FEATURE_XXX                0
+#define PRF_PAL_CACHE_FLUSH_SAFE       0
+#define PRF_DEVICE_FLUSH_LIST          1
 
 
 
@@ -51,7 +49,7 @@ extern int sn_prom_feature_available(int id);
  *
  * By default, features are disabled unless explicitly enabled.
  */
-#define  OSF_MCA_SLV_TO_OS_INIT_SLV            0
-#define  OSF_FEAT_LOG_SBES                     1
+#define  OSF_MCA_SLV_TO_OS_INIT_SLV    0
+#define  OSF_FEAT_LOG_SBES             1
 
 #endif /* _ASM_IA64_SN_FEATURE_SETS_H */
index 640a645..bda2f21 100644 (file)
@@ -33,6 +33,7 @@
 
 #ifdef CONFIG_KEXEC
 
+#ifndef __ASSEMBLY__
 #ifdef __powerpc64__
 /*
  * This function is responsible for capturing register states if coming
@@ -104,7 +105,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
                                        struct pt_regs *oldregs) { }
 #endif /* !__powerpc64 __ */
 
-#ifndef __ASSEMBLY__
 #define MAX_NOTE_BYTES 1024
 
 #ifdef __powerpc64__
@@ -121,6 +121,8 @@ extern void default_machine_kexec(struct kimage *image);
 extern int default_machine_kexec_prepare(struct kimage *image);
 extern void default_machine_crash_shutdown(struct pt_regs *regs);
 
+extern void machine_kexec_simple(struct kimage *image);
+
 #endif /* ! __ASSEMBLY__ */
 #endif /* CONFIG_KEXEC */
 #endif /* __KERNEL__ */
index d9728c8..cef6130 100644 (file)
@@ -167,6 +167,7 @@ struct pmf_irq_client {
        void                    *data;
        struct module           *owner;
        struct list_head        link;
+       struct pmf_function     *func;
 };
 
 
@@ -187,9 +188,7 @@ extern int pmf_register_irq_client(struct device_node *np,
                                   const char *name,
                                   struct pmf_irq_client *client);
 
-extern void pmf_unregister_irq_client(struct device_node *np,
-                                     const char *name,
-                                     struct pmf_irq_client *client);
+extern void pmf_unregister_irq_client(struct pmf_irq_client *client);
 
 /*
  * Called by the handlers when an irq happens
index 77b10d6..1630c26 100644 (file)
@@ -8,8 +8,6 @@
  * any future changes wrt the API will result in a change of the APIVERSION reported
  * to userspace by the DASDAPIVER-ioctl
  *
- * $Revision: 1.6 $
- *
  */
 
 #ifndef DASD_H
index 7bc15f0..a2f37a9 100644 (file)
@@ -11,8 +11,6 @@
 #ifndef __QDIO_H__
 #define __QDIO_H__
 
-#define VERSION_QDIO_H "$Revision: 1.57 $"
-
 /* note, that most of the typedef's are from ingo. */
 
 #include <linux/interrupt.h>
index f3797a5..8e0c7ed 100644 (file)
@@ -2,7 +2,7 @@
  *  include/asm-s390/thread_info.h
  *
  *  S390 version
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 2002,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
@@ -88,7 +88,7 @@ static inline struct thread_info *current_thread_info(void)
  * thread information flags bit numbers
  */
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
-#define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
+#define TIF_RESTORE_SIGMASK    1       /* restore signal mask in do_signal() */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_RESTART_SVC                4       /* restart svc with new svc number */
@@ -102,7 +102,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_MEMDIE             19
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
+#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_RESTART_SVC       (1<<TIF_RESTART_SVC)
index 2861cdc..29a9f35 100644 (file)
 #define __NR_inotify_init      284
 #define __NR_inotify_add_watch 285
 #define __NR_inotify_rm_watch  286
+/* Number 287 is reserved for new sys_migrate_pages */
+#define __NR_openat            288
+#define __NR_mkdirat           289
+#define __NR_mknodat           290
+#define __NR_fchownat          291
+#define __NR_futimesat         292
+#define __NR_newfstatat                293
+#define __NR_unlinkat          294
+#define __NR_renameat          295
+#define __NR_linkat            296
+#define __NR_symlinkat         297
+#define __NR_readlinkat                298
+#define __NR_fchmodat          299
+#define __NR_faccessat         300
+#define __NR_pselect6          301
+#define __NR_ppoll             302
 
-#define NR_syscalls 287
+#define NR_syscalls 303
 
 /* 
  * There are some system calls that are not present on 64 bit, some
@@ -539,11 +555,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,    \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 # ifndef CONFIG_64BIT
 #   define __ARCH_WANT_STAT64
 #   define __ARCH_WANT_SYS_TIME
 # endif
-# define __ARCH_WANT_COMPAT_SYS_TIME
+# ifdef CONFIG_COMPAT
+#   define __ARCH_WANT_COMPAT_SYS_TIME
+#   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+# endif
 #endif
 
 #ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-sh/bus-sh.h b/include/asm-sh/bus-sh.h
deleted file mode 100644 (file)
index e42d63b..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * include/asm-sh/bus-sh.h
- *
- * Copyright (C) 2004 Paul Mundt
- *
- * 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.
- */
-#ifndef __ASM_SH_BUS_SH_H
-#define __ASM_SH_BUS_SH_H
-
-extern struct bus_type sh_bus_types[];
-
-struct sh_dev {
-       struct device   dev;
-       char            *name;
-       unsigned int    dev_id;
-       unsigned int    bus_id;
-       struct resource res;
-       void            *mapbase;
-       unsigned int    irq[6];
-       u64             *dma_mask;
-       u64             coherent_dma_mask;
-};
-
-#define to_sh_dev(d)   container_of((d), struct sh_dev, dev)
-
-#define sh_get_drvdata(d)      dev_get_drvdata(&(d)->dev)
-#define sh_set_drvdata(d,p)    dev_set_drvdata(&(d)->dev, (p))
-
-struct sh_driver {
-       struct device_driver    drv;
-       unsigned int            dev_id;
-       unsigned int            bus_id;
-       int (*probe)(struct sh_dev *);
-       int (*remove)(struct sh_dev *);
-       int (*suspend)(struct sh_dev *, pm_message_t);
-       int (*resume)(struct sh_dev *);
-};
-
-#define to_sh_driver(d)        container_of((d), struct sh_driver, drv)
-#define sh_name(d)     ((d)->dev.driver->name)
-
-/*
- * Device ID numbers for bus types
- */
-enum {
-       SH_DEV_ID_USB_OHCI,
-};
-
-#define SH_NR_BUSES            1
-#define SH_BUS_NAME_VIRT       "shbus"
-
-enum {
-       SH_BUS_VIRT,
-};
-
-/* arch/sh/kernel/cpu/bus.c */
-extern int sh_device_register(struct sh_dev *dev);
-extern void sh_device_unregister(struct sh_dev *dev);
-extern int sh_driver_register(struct sh_driver *drv);
-extern void sh_driver_unregister(struct sh_driver *drv);
-
-#endif /* __ASM_SH_BUS_SH_H */
-
index 5cfaa6b..a844ea0 100644 (file)
 #define MMU_NTLB_WAYS          4
 #define MMU_CONTROL_INIT       0x007   /* SV=0, TF=1, IX=1, AT=1 */
 
+#define TRA    0xffffffd0
+#define EXPEVT 0xffffffd4
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#define INTEVT 0xa4000000      /* INTEVTE2(0xa4000000) */
+#else
+#define INTEVT 0xffffffd8
+#endif
+
 #endif /* __ASM_CPU_SH3_MMU_CONTEXT_H */
 
index 5b64d04..ff4c5fb 100644 (file)
 #define MMU_PAGE_ASSOC_BIT     0x80
 
 #define MMU_NTLB_ENTRIES       64      /* for 7750 */
+#ifdef CONFIG_SH_STORE_QUEUES
+#define MMU_CONTROL_INIT       0x05    /* SQMD=0, SV=0, TI=1, AT=1 */
+#else
 #define MMU_CONTROL_INIT       0x205   /* SQMD=1, SV=0, TI=1, AT=1 */
+#endif
 
 #define MMU_ITLB_DATA_ARRAY    0xF3000000
 #define MMU_UTLB_DATA_ARRAY    0xF7000000
@@ -35,5 +39,9 @@
 #define MMU_I_ENTRY_SHIFT          8
 #define MMU_ITLB_VALID         0x100
 
+#define TRA    0xff000020
+#define EXPEVT 0xff000024
+#define INTEVT 0xff000028
+
 #endif /* __ASM_CPU_SH4_MMU_CONTEXT_H */
 
index 1866f3f..9d84a2d 100644 (file)
@@ -94,6 +94,6 @@
 #define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* 0x545B */ /* Set multiport config */
 
 #define TIOCMIWAIT     _IO('T', 92) /* 0x545C */       /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    _IOR('T', 93, struct async_icount) /* 0x545D */ /* read serial port inline interrupt counts */
+#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
 
 #endif /* __ASM_SH_IOCTLS_H */
index bf2e431..d705252 100644 (file)
 #undef DMA_IPR_POS
 #undef DMA_PRIORITY
 
-#undef NR_IRQS
-
-#undef __irq_demux
-#undef irq_demux
-
 #undef INTC_IMCR0
 #undef INTC_IMCR1
 #undef INTC_IMCR2
 #define SIU_IPR_POS    1
 #define SIU_PRIORITY   3
 
-
-/* ONCHIP_NR_IRQS */
-#define NR_IRQS 109
-
-/* In a generic kernel, NR_IRQS is an upper bound, and we should use
- * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value.
- */
-#define ACTUAL_NR_IRQS NR_IRQS
-
-
-extern void disable_irq(unsigned int);
-extern void disable_irq_nosync(unsigned int);
-extern void enable_irq(unsigned int);
-
-/*
- * Simple Mask Register Support
- */
-extern void make_maskreg_irq(unsigned int irq);
-extern unsigned short *irq_mask_register;
-
-/*
- * Function for "on chip support modules".
- */
-extern void make_ipr_irq(unsigned int irq, unsigned int addr,
-                        int pos,  int priority);
-extern void make_imask_irq(unsigned int irq);
-
 #define PORT_PACR      0xA4050100UL
 #define PORT_PBCR      0xA4050102UL
 #define PORT_PCCR      0xA4050104UL
@@ -343,8 +311,6 @@ extern void make_imask_irq(unsigned int irq);
 #define IRQ6_PRIORITY  1
 #define IRQ7_PRIORITY  1
 
-extern int shmse_irq_demux(int irq);
-#define __irq_demux(irq) shmse_irq_demux(irq)
-#define irq_demux(irq) __irq_demux(irq)
+int shmse_irq_demux(int irq);
 
 #endif /* __ASM_SH_IRQ_SH73180_H */
index 8c8ca12..7f90315 100644 (file)
 #define        GPIO_IPR_POS    2
 #define        GPIO_PRIORITY   3
 
-/* ONCHIP_NR_IRQS */
-#define NR_IRQS 150    /* 111 + 16 */
-
-/* In a generic kernel, NR_IRQS is an upper bound, and we should use
- * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value.
- */
-#define ACTUAL_NR_IRQS NR_IRQS
-
-extern void disable_irq(unsigned int);
-extern void disable_irq_nosync(unsigned int);
-extern void enable_irq(unsigned int);
-
-/*
- * Simple Mask Register Support
- */
-extern void make_maskreg_irq(unsigned int irq);
-extern unsigned short *irq_mask_register;
-
-/*
- * Function for "on chip support modules".
- */
-extern void make_imask_irq(unsigned int irq);
-
 #define        INTC_TMU0_MSK   0
 #define        INTC_TMU3_MSK   1
 #define        INTC_RTC_MSK    2
index 060ec3c..42b8394 100644 (file)
 #endif /* ST40STB1 */
 
 #endif /* 775x / SH4-202 / ST40STB1 */
+#endif /* 7780 */
 
 /* NR_IRQS is made from three components:
  *   1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules
 # define ONCHIP_NR_IRQS 72
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 # define ONCHIP_NR_IRQS 144
-#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+      defined(CONFIG_CPU_SUBTYPE_SH73180)
 # define ONCHIP_NR_IRQS 109
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+# define ONCHIP_NR_IRQS 111
 #elif defined(CONFIG_SH_UNKNOWN)       /* Most be last */
 # define ONCHIP_NR_IRQS 144
 #endif
 # define OFFCHIP_NR_IRQS 96
 #elif defined (CONFIG_SH_TITAN)
 # define OFFCHIP_NR_IRQS 4
+#elif defined(CONFIG_SH_R7780RP)
+# define OFFCHIP_NR_IRQS 16
 #elif defined(CONFIG_SH_UNKNOWN)
 # define OFFCHIP_NR_IRQS 16    /* Must also be last */
 #else
@@ -550,7 +556,7 @@ extern int ipr_irq_demux(int irq);
 #define INTC_ICR_IRLM  (1<<7)
 #endif
 
-#else
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
 #include <asm/irq-sh7780.h>
 #endif
 
diff --git a/include/asm-sh/microdev.h b/include/asm-sh/microdev.h
new file mode 100644 (file)
index 0000000..018332a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * linux/include/asm-sh/microdev.h
+ *
+ * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
+ *
+ * Definitions for the SuperH SH4-202 MicroDev board.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#ifndef __ASM_SH_MICRODEV_H
+#define __ASM_SH_MICRODEV_H
+
+extern void init_microdev_irq(void);
+extern void microdev_print_fpga_intc_status(void);
+
+/*
+ * The following are useful macros for manipulating the interrupt
+ * controller (INTC) on the CPU-board FPGA.  should be noted that there
+ * is an INTC on the FPGA, and a seperate INTC on the SH4-202 core -
+ * these are two different things, both of which need to be prorammed to
+ * correctly route - unfortunately, they have the same name and
+ * abbreviations!
+ */
+#define        MICRODEV_FPGA_INTC_BASE         0xa6110000ul                            /* INTC base address on CPU-board FPGA */
+#define        MICRODEV_FPGA_INTENB_REG        (MICRODEV_FPGA_INTC_BASE+0ul)           /* Interrupt Enable Register on INTC on CPU-board FPGA */
+#define        MICRODEV_FPGA_INTDSB_REG        (MICRODEV_FPGA_INTC_BASE+8ul)           /* Interrupt Disable Register on INTC on CPU-board FPGA */
+#define        MICRODEV_FPGA_INTC_MASK(n)      (1ul<<(n))                              /* Interupt mask to enable/disable INTC in CPU-board FPGA */
+#define        MICRODEV_FPGA_INTPRI_REG(n)     (MICRODEV_FPGA_INTC_BASE+0x10+((n)/8)*8)/* Interrupt Priority Register on INTC on CPU-board FPGA */
+#define        MICRODEV_FPGA_INTPRI_LEVEL(n,x) ((x)<<(((n)%8)*4))                      /* MICRODEV_FPGA_INTPRI_LEVEL(int_number, int_level) */
+#define        MICRODEV_FPGA_INTPRI_MASK(n)    (MICRODEV_FPGA_INTPRI_LEVEL((n),0xful)) /* Interrupt Priority Mask on INTC on CPU-board FPGA */
+#define        MICRODEV_FPGA_INTSRC_REG        (MICRODEV_FPGA_INTC_BASE+0x30ul)        /* Interrupt Source Register on INTC on CPU-board FPGA */
+#define        MICRODEV_FPGA_INTREQ_REG        (MICRODEV_FPGA_INTC_BASE+0x38ul)        /* Interrupt Request Register on INTC on CPU-board FPGA */
+
+
+/*
+ * The following are the IRQ numbers for the Linux Kernel for external
+ * interrupts.  i.e. the numbers seen by 'cat /proc/interrupt'.
+ */
+#define MICRODEV_LINUX_IRQ_KEYBOARD     1      /* SuperIO Keyboard */
+#define MICRODEV_LINUX_IRQ_SERIAL1      2      /* SuperIO Serial #1 */
+#define MICRODEV_LINUX_IRQ_ETHERNET     3      /* on-board Ethnernet */
+#define MICRODEV_LINUX_IRQ_SERIAL2      4      /* SuperIO Serial #2 */
+#define MICRODEV_LINUX_IRQ_USB_HC       7      /* on-board USB HC */
+#define MICRODEV_LINUX_IRQ_MOUSE       12      /* SuperIO PS/2 Mouse */
+#define MICRODEV_LINUX_IRQ_IDE2                13      /* SuperIO IDE #2 */
+#define MICRODEV_LINUX_IRQ_IDE1                14      /* SuperIO IDE #1 */
+
+/*
+ * The following are the IRQ numbers for the INTC on the FPGA for
+ * external interrupts.  i.e. the bits in the INTC registers in the
+ * FPGA.
+ */
+#define MICRODEV_FPGA_IRQ_KEYBOARD      1      /* SuperIO Keyboard */
+#define MICRODEV_FPGA_IRQ_SERIAL1       3      /* SuperIO Serial #1 */
+#define MICRODEV_FPGA_IRQ_SERIAL2       4      /* SuperIO Serial #2 */
+#define MICRODEV_FPGA_IRQ_MOUSE                12      /* SuperIO PS/2 Mouse */
+#define MICRODEV_FPGA_IRQ_IDE1         14      /* SuperIO IDE #1 */
+#define MICRODEV_FPGA_IRQ_IDE2         15      /* SuperIO IDE #2 */
+#define MICRODEV_FPGA_IRQ_USB_HC       16      /* on-board USB HC */
+#define MICRODEV_FPGA_IRQ_ETHERNET     18      /* on-board Ethnernet */
+
+#define MICRODEV_IRQ_PCI_INTA           8
+#define MICRODEV_IRQ_PCI_INTB           9
+#define MICRODEV_IRQ_PCI_INTC          10
+#define MICRODEV_IRQ_PCI_INTD          11
+
+#define __IO_PREFIX microdev
+#include <asm/io_generic.h>
+
+#if defined(CONFIG_PCI)
+unsigned char  microdev_pci_inb(unsigned long port);
+unsigned short microdev_pci_inw(unsigned long port);
+unsigned long  microdev_pci_inl(unsigned long port);
+void           microdev_pci_outb(unsigned char  data, unsigned long port);
+void           microdev_pci_outw(unsigned short data, unsigned long port);
+void           microdev_pci_outl(unsigned long  data, unsigned long port);
+#endif
+
+#endif /* __ASM_SH_MICRODEV_H */
diff --git a/include/asm-sh/microdev/io.h b/include/asm-sh/microdev/io.h
deleted file mode 100644 (file)
index f2ca4ac..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * linux/include/asm-sh/io_microdev.h
- *
- * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
- *
- * IO functions for the SuperH SH4-202 MicroDev board.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- */
-
-
-#ifndef _ASM_SH_IO_MICRODEV_H
-#define _ASM_SH_IO_MICRODEV_H
-
-extern unsigned long microdev_isa_port2addr(unsigned long offset);
-
-extern unsigned char microdev_inb(unsigned long port);
-extern unsigned short microdev_inw(unsigned long port);
-extern unsigned int microdev_inl(unsigned long port);
-
-extern void microdev_outb(unsigned char value, unsigned long port);
-extern void microdev_outw(unsigned short value, unsigned long port);
-extern void microdev_outl(unsigned int value, unsigned long port);
-
-extern unsigned char microdev_inb_p(unsigned long port);
-extern unsigned short microdev_inw_p(unsigned long port);
-extern unsigned int microdev_inl_p(unsigned long port);
-
-extern void microdev_outb_p(unsigned char value, unsigned long port);
-extern void microdev_outw_p(unsigned short value, unsigned long port);
-extern void microdev_outl_p(unsigned int value, unsigned long port);
-
-extern void microdev_insb(unsigned long port, void *addr, unsigned long count);
-extern void microdev_insw(unsigned long port, void *addr, unsigned long count);
-extern void microdev_insl(unsigned long port, void *addr, unsigned long count);
-
-extern void microdev_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void microdev_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void microdev_outsl(unsigned long port, const void *addr, unsigned long count);
-
-#if defined(CONFIG_PCI)
-extern unsigned char  microdev_pci_inb(unsigned long port);
-extern unsigned short microdev_pci_inw(unsigned long port);
-extern unsigned long  microdev_pci_inl(unsigned long port);
-extern void           microdev_pci_outb(unsigned char  data, unsigned long port);
-extern void           microdev_pci_outw(unsigned short data, unsigned long port);
-extern void           microdev_pci_outl(unsigned long  data, unsigned long port);
-#endif
-
-#endif /* _ASM_SH_IO_MICRODEV_H */
-
diff --git a/include/asm-sh/microdev/irq.h b/include/asm-sh/microdev/irq.h
deleted file mode 100644 (file)
index 47f6f77..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * linux/include/asm-sh/irq_microdev.h
- *
- * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
- *
- * IRQ functions for the SuperH SH4-202 MicroDev board.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- */
-
-
-#ifndef _ASM_SH_IRQ_MICRODEV_H
-#define _ASM_SH_IRQ_MICRODEV_H
-
-extern void init_microdev_irq(void);
-extern void microdev_print_fpga_intc_status(void);
-
-
-       /*
-        *      The following are useful macros for manipulating the
-        *      interrupt controller (INTC) on the CPU-board FPGA.
-        *      It should be noted that there is an INTC on the FPGA,
-        *      and a seperate INTC on the SH4-202 core - these are
-        *      two different things, both of which need to be prorammed
-        *      to correctly route - unfortunately, they have the
-        *      same name and abbreviations!
-        */
-#define        MICRODEV_FPGA_INTC_BASE         0xa6110000ul                            /* INTC base address on CPU-board FPGA */
-#define        MICRODEV_FPGA_INTENB_REG        (MICRODEV_FPGA_INTC_BASE+0ul)           /* Interrupt Enable Register on INTC on CPU-board FPGA */
-#define        MICRODEV_FPGA_INTDSB_REG        (MICRODEV_FPGA_INTC_BASE+8ul)           /* Interrupt Disable Register on INTC on CPU-board FPGA */
-#define        MICRODEV_FPGA_INTC_MASK(n)      (1ul<<(n))                              /* Interupt mask to enable/disable INTC in CPU-board FPGA */
-#define        MICRODEV_FPGA_INTPRI_REG(n)     (MICRODEV_FPGA_INTC_BASE+0x10+((n)/8)*8)/* Interrupt Priority Register on INTC on CPU-board FPGA */
-#define        MICRODEV_FPGA_INTPRI_LEVEL(n,x) ((x)<<(((n)%8)*4))                      /* MICRODEV_FPGA_INTPRI_LEVEL(int_number, int_level) */
-#define        MICRODEV_FPGA_INTPRI_MASK(n)    (MICRODEV_FPGA_INTPRI_LEVEL((n),0xful)) /* Interrupt Priority Mask on INTC on CPU-board FPGA */
-#define        MICRODEV_FPGA_INTSRC_REG        (MICRODEV_FPGA_INTC_BASE+0x30ul)        /* Interrupt Source Register on INTC on CPU-board FPGA */
-#define        MICRODEV_FPGA_INTREQ_REG        (MICRODEV_FPGA_INTC_BASE+0x38ul)        /* Interrupt Request Register on INTC on CPU-board FPGA */
-
-
-       /*
-        *      The following are the IRQ numbers for the Linux Kernel for external interrupts.
-        *      i.e. the numbers seen by 'cat /proc/interrupt'.
-        */
-#define MICRODEV_LINUX_IRQ_KEYBOARD     1      /* SuperIO Keyboard */
-#define MICRODEV_LINUX_IRQ_SERIAL1      2      /* SuperIO Serial #1 */
-#define MICRODEV_LINUX_IRQ_ETHERNET     3      /* on-board Ethnernet */
-#define MICRODEV_LINUX_IRQ_SERIAL2      4      /* SuperIO Serial #2 */
-#define MICRODEV_LINUX_IRQ_USB_HC       7      /* on-board USB HC */
-#define MICRODEV_LINUX_IRQ_MOUSE       12      /* SuperIO PS/2 Mouse */
-#define MICRODEV_LINUX_IRQ_IDE2                13      /* SuperIO IDE #2 */
-#define MICRODEV_LINUX_IRQ_IDE1                14      /* SuperIO IDE #1 */
-
-       /*
-        *      The following are the IRQ numbers for the INTC on the FPGA for external interrupts.
-        *      i.e. the bits in the INTC registers in the FPGA.
-        */
-#define MICRODEV_FPGA_IRQ_KEYBOARD      1      /* SuperIO Keyboard */
-#define MICRODEV_FPGA_IRQ_SERIAL1       3      /* SuperIO Serial #1 */
-#define MICRODEV_FPGA_IRQ_SERIAL2       4      /* SuperIO Serial #2 */
-#define MICRODEV_FPGA_IRQ_MOUSE                12      /* SuperIO PS/2 Mouse */
-#define MICRODEV_FPGA_IRQ_IDE1         14      /* SuperIO IDE #1 */
-#define MICRODEV_FPGA_IRQ_IDE2         15      /* SuperIO IDE #2 */
-#define MICRODEV_FPGA_IRQ_USB_HC       16      /* on-board USB HC */
-#define MICRODEV_FPGA_IRQ_ETHERNET     18      /* on-board Ethnernet */
-
-#define MICRODEV_IRQ_PCI_INTA           8
-#define MICRODEV_IRQ_PCI_INTB           9
-#define MICRODEV_IRQ_PCI_INTC          10
-#define MICRODEV_IRQ_PCI_INTD          11
-
-#endif /* _ASM_SH_IRQ_MICRODEV_H */
index c490479..fa5bd2d 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/page.h>
 #include <asm/types.h>
 #include <asm/cache.h>
-#include <linux/threads.h>
 #include <asm/ptrace.h>
 
 /*
@@ -30,7 +29,7 @@
  *  CPU type and hardware bug flags. Kept separately for each CPU.
  *
  *  Each one of these also needs a CONFIG_CPU_SUBTYPE_xxx entry
- *  in arch/sh/Kconfig, as well as an entry in arch/sh/kernel/setup.c
+ *  in arch/sh/mm/Kconfig, as well as an entry in arch/sh/kernel/setup.c
  *  for parsing the subtype in get_cpu_subtype().
  */
 enum cpu_type {
@@ -44,7 +43,7 @@ enum cpu_type {
        /* SH-4 types */
        CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R,
        CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
-       CPU_SH73180,
+       CPU_SH73180, CPU_SH7770, CPU_SH7780, CPU_SH7781,
 
        /* Unknown subtype */
        CPU_SH_NONE
@@ -52,14 +51,8 @@ enum cpu_type {
 
 struct sh_cpuinfo {
        enum cpu_type type;
-       char    hard_math;
        unsigned long loops_per_jiffy;
 
-       unsigned int cpu_clock, master_clock, bus_clock, module_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-       unsigned int memory_clock;
-#endif
-
        struct cache_info icache;
        struct cache_info dcache;
 
@@ -131,7 +124,7 @@ union sh_fpu_union {
        struct sh_fpu_soft_struct soft;
 };
 
-/* 
+/*
  * Processor flags
  */
 
@@ -140,6 +133,7 @@ union sh_fpu_union {
 #define CPU_HAS_MMU_PAGE_ASSOC 0x0004  /* SH3: TLB way selection bit support */
 #define CPU_HAS_DSP            0x0008  /* SH-DSP: DSP support */
 #define CPU_HAS_PERF_COUNTER   0x0010  /* Hardware performance counters */
+#define CPU_HAS_PTEA           0x0020  /* PTEA register */
 
 struct thread_struct {
        unsigned long sp;
@@ -160,10 +154,10 @@ extern int ubc_usercnt;
 #define INIT_THREAD  {                                         \
        sizeof(init_stack) + (long) &init_stack, /* sp */       \
        0,                                       /* pc */       \
-       0, 0,                                                   \
-       0,                                                      \
-       0,                                                      \
-       {{{0,}},}                               /* fpu state */ \
+       0, 0,                                                   \
+       0,                                                      \
+       0,                                                      \
+       {{{0,}},}                               /* fpu state */ \
 }
 
 /*
@@ -171,7 +165,7 @@ extern int ubc_usercnt;
  */
 #define start_thread(regs, new_pc, new_sp)      \
        set_fs(USER_DS);                         \
-       regs->pr = 0;                            \
+       regs->pr = 0;                            \
        regs->sr = SR_FD;       /* User mode. */ \
        regs->pc = new_pc;                       \
        regs->regs[15] = new_sp
@@ -239,16 +233,16 @@ extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs);
 #define save_fpu(tsk)  do { } while (0)
 #endif
 
-#define unlazy_fpu(tsk, regs) do {                             \
+#define unlazy_fpu(tsk, regs) do {                     \
        if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {   \
-               save_fpu(tsk, regs);                            \
+               save_fpu(tsk, regs);                    \
        }                                               \
 } while (0)
 
-#define clear_fpu(tsk, regs) do {                                      \
-       if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {           \
-               clear_tsk_thread_flag(tsk, TIF_USEDFPU);        \
-               release_fpu(regs);                                      \
+#define clear_fpu(tsk, regs) do {                              \
+       if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {           \
+               clear_tsk_thread_flag(tsk, TIF_USEDFPU);        \
+               release_fpu(regs);                              \
        }                                                       \
 } while (0)
 
index 08f3c1f..6b0c04f 100644 (file)
 #define TIOCSERSETMULTI 0x40a8545b     /* _IOW('T', 91, struct serial_multiport_struct) 0x545B */ /* Set multiport config */
 
 #define TIOCMIWAIT     0x545c          /* _IO('T', 92) wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x802c545d      /* _IOR('T', 93, struct async_icount) 0x545D */ /* read serial port inline interrupt counts */
+#define TIOCGICOUNT    0x545d          /* read serial port inline interrupt counts */
 
 #endif /* __ASM_SH64_IOCTLS_H */
index ec85d12..508c416 100644 (file)
@@ -131,6 +131,28 @@ static void inline __read_lock(raw_rwlock_t *lock)
        : "memory");
 }
 
+static int inline __read_trylock(raw_rwlock_t *lock)
+{
+       int tmp1, tmp2;
+
+       __asm__ __volatile__ (
+"1:    ldsw            [%2], %0\n"
+"      brlz,a,pn       %0, 2f\n"
+"       mov            0, %0\n"
+"      add             %0, 1, %1\n"
+"      cas             [%2], %0, %1\n"
+"      cmp             %0, %1\n"
+"      membar          #StoreLoad | #StoreStore\n"
+"      bne,pn          %%icc, 1b\n"
+"       mov            1, %0\n"
+"2:"
+       : "=&r" (tmp1), "=&r" (tmp2)
+       : "r" (lock)
+       : "memory");
+
+       return tmp1;
+}
+
 static void inline __read_unlock(raw_rwlock_t *lock)
 {
        unsigned long tmp1, tmp2;
@@ -211,12 +233,12 @@ static int inline __write_trylock(raw_rwlock_t *lock)
 }
 
 #define __raw_read_lock(p)     __read_lock(p)
+#define __raw_read_trylock(p)  __read_trylock(p)
 #define __raw_read_unlock(p)   __read_unlock(p)
 #define __raw_write_lock(p)    __write_lock(p)
 #define __raw_write_unlock(p)  __write_unlock(p)
 #define __raw_write_trylock(p) __write_trylock(p)
 
-#define __raw_read_trylock(lock)       generic__raw_read_trylock(lock)
 #define __raw_read_can_lock(rw)                (!((rw)->lock & 0x80000000UL))
 #define __raw_write_can_lock(rw)       (!(rw)->lock)
 
index 175722a..96b35aa 100644 (file)
@@ -5,8 +5,8 @@
  * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
  */
 
-#ifndef __ASM_LDT_I386_H
-#define __ASM_LDT_I386_H
+#ifndef __ASM_LDT_X86_64_H
+#define __ASM_LDT_X86_64_H
 
 #include "asm/semaphore.h"
 #include "asm/arch/ldt.h"
@@ -39,11 +39,13 @@ typedef struct uml_ldt {
 } uml_ldt_t;
 
 /*
- * macros stolen from include/asm-i386/desc.h
+ * macros stolen from include/asm-x86_64/desc.h
  */
 #define LDT_entry_a(info) \
        ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
 
+/* Don't allow setting of the lm bit. It is useless anyways because
+ * 64bit system calls require __USER_CS. */
 #define LDT_entry_b(info) \
        (((info)->base_addr & 0xff000000) | \
        (((info)->base_addr & 0x00ff0000) >> 16) | \
@@ -54,6 +56,7 @@ typedef struct uml_ldt {
        ((info)->seg_32bit << 22) | \
        ((info)->limit_in_pages << 23) | \
        ((info)->useable << 20) | \
+       /* ((info)->lm << 21) | */ \
        0x7000)
 
 #define LDT_empty(info) (\
@@ -64,6 +67,7 @@ typedef struct uml_ldt {
        (info)->seg_32bit       == 0    && \
        (info)->limit_in_pages  == 0    && \
        (info)->seg_not_present == 1    && \
-       (info)->useable         == 0    )
+       (info)->useable         == 0    && \
+       (info)->lm              == 0)
 
 #endif
index d879eba..aeda665 100644 (file)
@@ -23,6 +23,8 @@ extern inline void smp_cpus_done(unsigned int maxcpus)
 {
 }
 
+extern struct task_struct *idle_threads[NR_CPUS];
+
 #endif
 
 #endif
index e87cd83..9afc0c7 100644 (file)
 #define __NR_ia32_inotify_add_watch    292
 #define __NR_ia32_inotify_rm_watch     293
 #define __NR_ia32_migrate_pages                294
-#define __NR_ia32_opanat               295
+#define __NR_ia32_openat               295
 #define __NR_ia32_mkdirat              296
 #define __NR_ia32_mknodat              297
 #define __NR_ia32_fchownat             298
diff --git a/include/asm-xtensa/futex.h b/include/asm-xtensa/futex.h
new file mode 100644 (file)
index 0000000..0b74582
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/futex.h>
index 17a17c5..6d59c8e 100644 (file)
@@ -111,6 +111,7 @@ typedef struct _agp_unbind {
 } agp_unbind;
 
 #else                          /* __KERNEL__ */
+#include <linux/mutex.h>
 
 #define AGPGART_MINOR 175
 
@@ -201,7 +202,7 @@ struct agp_file_private {
 };
 
 struct agp_front_data {
-       struct semaphore agp_mutex;
+       struct mutex agp_mutex;
        struct agp_controller *current_controller;
        struct agp_controller *controllers;
        struct agp_file_private *file_priv_list;
index 02a585f..860e7a4 100644 (file)
@@ -392,8 +392,8 @@ struct request_queue
        unsigned int            nr_congestion_off;
        unsigned int            nr_batching;
 
-       unsigned short          max_sectors;
-       unsigned short          max_hw_sectors;
+       unsigned int            max_sectors;
+       unsigned int            max_hw_sectors;
        unsigned short          max_phys_segments;
        unsigned short          max_hw_segments;
        unsigned short          hardsect_size;
@@ -697,7 +697,7 @@ extern request_queue_t *blk_init_queue(request_fn_proc *, spinlock_t *);
 extern void blk_cleanup_queue(request_queue_t *);
 extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
 extern void blk_queue_bounce_limit(request_queue_t *, u64);
-extern void blk_queue_max_sectors(request_queue_t *, unsigned short);
+extern void blk_queue_max_sectors(request_queue_t *, unsigned int);
 extern void blk_queue_max_phys_segments(request_queue_t *, unsigned short);
 extern void blk_queue_max_hw_segments(request_queue_t *, unsigned short);
 extern void blk_queue_max_segment_size(request_queue_t *, unsigned int);
index c31650d..17866d7 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef _LINUX_CPUFREQ_H
 #define _LINUX_CPUFREQ_H
 
+#include <linux/mutex.h>
 #include <linux/config.h>
 #include <linux/notifier.h>
 #include <linux/threads.h>
@@ -82,7 +83,7 @@ struct cpufreq_policy {
         unsigned int           policy; /* see above */
        struct cpufreq_governor *governor; /* see below */
 
-       struct semaphore        lock;   /* CPU ->setpolicy or ->target may
+       struct mutex            lock;   /* CPU ->setpolicy or ->target may
                                           only be called once a time */
 
        struct work_struct      update; /* if update_policy() needs to be
index 83c7d20..51e0e95 100644 (file)
@@ -91,7 +91,7 @@ struct target_type {
 };
 
 struct io_restrictions {
-       unsigned short          max_sectors;
+       unsigned int            max_sectors;
        unsigned short          max_phys_segments;
        unsigned short          max_hw_segments;
        unsigned short          hardsect_size;
index 84bb449..e059da9 100644 (file)
@@ -363,6 +363,8 @@ struct address_space_operations {
                        loff_t offset, unsigned long nr_segs);
        struct page* (*get_xip_page)(struct address_space *, sector_t,
                        int);
+       /* migrate the contents of a page to the specified target */
+       int (*migratepage) (struct page *, struct page *);
 };
 
 struct backing_dev_info;
@@ -1719,6 +1721,12 @@ extern void simple_release_fs(struct vfsmount **mount, int *count);
 
 extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);
 
+#ifdef CONFIG_MIGRATION
+extern int buffer_migrate_page(struct page *, struct page *);
+#else
+#define buffer_migrate_page NULL
+#endif
+
 extern int inode_change_ok(struct inode *, struct iattr *);
 extern int __must_check inode_setattr(struct inode *, struct iattr *);
 
index 528959c..5425b60 100644 (file)
@@ -14,7 +14,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 5
+#define FUSE_KERNEL_MINOR_VERSION 6
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -58,6 +58,9 @@ struct fuse_kstatfs {
        __u32   spare[6];
 };
 
+/**
+ * Bitmasks for fuse_setattr_in.valid
+ */
 #define FATTR_MODE     (1 << 0)
 #define FATTR_UID      (1 << 1)
 #define FATTR_GID      (1 << 2)
@@ -75,6 +78,11 @@ struct fuse_kstatfs {
 #define FOPEN_DIRECT_IO                (1 << 0)
 #define FOPEN_KEEP_CACHE       (1 << 1)
 
+/**
+ * INIT request/reply flags
+ */
+#define FUSE_ASYNC_READ                (1 << 0)
+
 enum fuse_opcode {
        FUSE_LOOKUP        = 1,
        FUSE_FORGET        = 2,  /* no reply */
@@ -247,12 +255,16 @@ struct fuse_access_in {
 struct fuse_init_in {
        __u32   major;
        __u32   minor;
+       __u32   max_readahead;
+       __u32   flags;
 };
 
 struct fuse_init_out {
        __u32   major;
        __u32   minor;
-       __u32   unused[3];
+       __u32   max_readahead;
+       __u32   flags;
+       __u32   unused;
        __u32   max_write;
 };
 
index 089bfb1..6361544 100644 (file)
@@ -40,6 +40,7 @@ enum hrtimer_restart {
 enum hrtimer_state {
        HRTIMER_INACTIVE,       /* Timer is inactive */
        HRTIMER_EXPIRED,                /* Timer is expired */
+       HRTIMER_RUNNING,                /* Timer is running the callback function */
        HRTIMER_PENDING,                /* Timer is pending */
 };
 
@@ -100,9 +101,8 @@ struct hrtimer_base {
 /* Exported timer functions: */
 
 /* Initialize timers: */
-extern void hrtimer_init(struct hrtimer *timer, const clockid_t which_clock);
-extern void hrtimer_rebase(struct hrtimer *timer, const clockid_t which_clock);
-
+extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
+                        enum hrtimer_mode mode);
 
 /* Basic timer operations: */
 extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
diff --git a/include/linux/io.h b/include/linux/io.h
new file mode 100644 (file)
index 0000000..85533ec
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 PathScale, Inc.  All Rights Reserved.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _LINUX_IO_H
+#define _LINUX_IO_H
+
+#include <asm/io.h>
+
+void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
+
+#endif /* _LINUX_IO_H */
index 1bd6552..6aca67a 100644 (file)
  *
  *  Started by: Thomas Gleixner and Ingo Molnar
  *
+ *  Credits:
+ *
+ *     Roman Zippel provided the ideas and primary code snippets of
+ *     the ktime_t union and further simplifications of the original
+ *     code.
+ *
  *  For licencing details see kernel-base/COPYING
  */
 #ifndef _LINUX_KTIME_H
index 93a849f..ebfc238 100644 (file)
@@ -91,10 +91,21 @@ struct per_cpu_pageset {
  * be 8 (2 ** 3) zonelists.  GFP_ZONETYPES defines the number of possible
  * combinations of zone modifiers in "zone modifier space".
  *
+ * As an optimisation any zone modifier bits which are only valid when
+ * no other zone modifier bits are set (loners) should be placed in
+ * the highest order bits of this field.  This allows us to reduce the
+ * extent of the zonelists thus saving space.  For example in the case
+ * of three zone modifier bits, we could require up to eight zonelists.
+ * If the left most zone modifier is a "loner" then the highest valid
+ * zonelist would be four allowing us to allocate only five zonelists.
+ * Use the first form for GFP_ZONETYPES when the left most bit is not
+ * a "loner", otherwise use the second.
+ *
  * NOTE! Make sure this matches the zones in <linux/gfp.h>
  */
 #define GFP_ZONEMASK   0x07
-#define GFP_ZONETYPES  5
+/* #define GFP_ZONETYPES       (GFP_ZONEMASK + 1) */           /* Non-loner */
+#define GFP_ZONETYPES  ((GFP_ZONEMASK + 1) / 2 + 1)            /* Loner */
 
 /*
  * On machines where it is needed (eg PCs) we divide physical memory
index 59ff6c4..6500d4e 100644 (file)
@@ -19,7 +19,21 @@ struct xt_get_revision
 /* For standard target */
 #define XT_RETURN (-NF_REPEAT - 1)
 
-#define XT_ALIGN(s) (((s) + (__alignof__(u_int64_t)-1)) & ~(__alignof__(u_int64_t)-1))
+/* this is a dummy structure to find out the alignment requirement for a struct
+ * containing all the fundamental data types that are used in ipt_entry,
+ * ip6t_entry and arpt_entry.  This sucks, and it is a hack.  It will be my
+ * personal pleasure to remove it -HW
+ */
+struct _xt_align
+{
+       u_int8_t u8;
+       u_int16_t u16;
+       u_int32_t u32;
+       u_int64_t u64;
+};
+
+#define XT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1))         \
+                       & ~(__alignof__(struct _xt_align)-1))
 
 /* Standard return verdict, or do jump. */
 #define XT_STANDARD_TARGET ""
index 0a44072..fe1a2b0 100644 (file)
@@ -406,7 +406,6 @@ struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int devic
 struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
 int pci_find_capability (struct pci_dev *dev, int cap);
 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
-int pci_find_ext_capability (struct pci_dev *dev, int cap);
 struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
 
 struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
@@ -626,7 +625,6 @@ static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
 static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
-static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
 
 /* Power management related routines */
index ecc1fc1..b0b908f 100644 (file)
 #define PCI_DEVICE_ID_NS_SC1100_SMI    0x0511
 #define PCI_DEVICE_ID_NS_SC1100_XBUS   0x0515
 #define PCI_DEVICE_ID_NS_87410         0xd001
-#define PCI_DEVICE_ID_NS_CS5535_IDE    0x002d
 
 #define PCI_DEVICE_ID_NS_CS5535_HOST_BRIDGE  0x0028
 #define PCI_DEVICE_ID_NS_CS5535_ISA_BRIDGE   0x002b
-#define PCI_DEVICE_ID_NS_CS5535_IDE          0x002d
-#define PCI_DEVICE_ID_NS_CS5535_AUDIO        0x002e
-#define PCI_DEVICE_ID_NS_CS5535_USB          0x002f
-#define PCI_DEVICE_ID_NS_CS5535_VIDEO        0x0030
 
 #define PCI_VENDOR_ID_TSENG            0x100c
 #define PCI_DEVICE_ID_TSENG_W32P_2     0x3202
 #define PCI_DEVICE_ID_AMD_CS5536_UOC    0x2097
 #define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
 
-#define PCI_DEVICE_ID_AMD_CS5536_IDE   0x209A
-
 #define PCI_DEVICE_ID_AMD_LX_VIDEO  0x2081
 #define PCI_DEVICE_ID_AMD_LX_AES    0x2082
 
 #define PCI_DEVICE_ID_INTEL_82801EB_5  0x24d5
 #define PCI_DEVICE_ID_INTEL_82801EB_6  0x24d6
 #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db
+#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd
 #define PCI_DEVICE_ID_INTEL_ESB_1      0x25a1
 #define PCI_DEVICE_ID_INTEL_ESB_2      0x25a2
 #define PCI_DEVICE_ID_INTEL_ESB_4      0x25a4
 #define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
 #define PCI_DEVICE_ID_INTEL_82945G_HB  0x2770
 #define PCI_DEVICE_ID_INTEL_82945G_IG  0x2772
+#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0
+#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2
 #define PCI_DEVICE_ID_INTEL_ICH6_0     0x2640
 #define PCI_DEVICE_ID_INTEL_ICH6_1     0x2641
 #define PCI_DEVICE_ID_INTEL_ICH6_2     0x2642
 #define PCI_DEVICE_ID_INTEL_ICH7_19    0x27dd
 #define PCI_DEVICE_ID_INTEL_ICH7_20    0x27de
 #define PCI_DEVICE_ID_INTEL_ICH7_21    0x27df
+#define PCI_DEVICE_ID_INTEL_ICH8_0     0x2810
+#define PCI_DEVICE_ID_INTEL_ICH8_1     0x2811
+#define PCI_DEVICE_ID_INTEL_ICH8_2     0x2812
+#define PCI_DEVICE_ID_INTEL_ICH8_3     0x2814
+#define PCI_DEVICE_ID_INTEL_ICH8_4     0x2815
+#define PCI_DEVICE_ID_INTEL_ICH8_5     0x283e
+#define PCI_DEVICE_ID_INTEL_ICH8_6     0x2850
 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
 #define PCI_DEVICE_ID_INTEL_82830_HB   0x3575
 #define PCI_DEVICE_ID_INTEL_82830_CGC  0x3577
 #define PCI_DEVICE_ID_INTEL_82443GX_2  0x71a2
 #define PCI_DEVICE_ID_INTEL_82372FB_1  0x7601
 #define PCI_DEVICE_ID_INTEL_82454GX    0x84c4
+#define PCI_DEVICE_ID_INTEL_82450GX    0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX    0x84ca
 #define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
 #define PCI_DEVICE_ID_INTEL_84460GX    0x84ea
index 54faf52..95572c4 100644 (file)
@@ -84,7 +84,6 @@ struct k_clock {
 void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock);
 
 /* error handlers for timer_create, nanosleep and settime */
-int do_posix_clock_notimer_create(struct k_itimer *timer);
 int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *,
                               struct timespec __user *);
 int do_posix_clock_nosettime(const clockid_t, struct timespec *tp);
index e276c5b..7d51149 100644 (file)
@@ -1971,22 +1971,6 @@ extern struct file_operations reiserfs_file_operations;
 extern struct address_space_operations reiserfs_address_space_operations;
 
 /* fix_nodes.c */
-#ifdef CONFIG_REISERFS_CHECK
-void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s);
-void reiserfs_kfree(const void *vp, size_t size, struct super_block *s);
-#else
-static inline void *reiserfs_kmalloc(size_t size, int flags,
-                                    struct super_block *s)
-{
-       return kmalloc(size, flags);
-}
-
-static inline void reiserfs_kfree(const void *vp, size_t size,
-                                 struct super_block *s)
-{
-       kfree(vp);
-}
-#endif
 
 int fix_nodes(int n_op_mode, struct tree_balance *p_s_tb,
              struct item_head *p_s_ins_ih, const void *);
index 3e68592..31b4c0b 100644 (file)
@@ -382,7 +382,6 @@ struct reiserfs_sb_info {
                                           on-disk FS format */
 
        /* session statistics */
-       int s_kmallocs;
        int s_disk_reads;
        int s_disk_writes;
        int s_fix_nodes;
index c84354e..87280eb 100644 (file)
@@ -43,8 +43,6 @@ int reiserfs_delete_xattrs(struct inode *inode);
 int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
 int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
 int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd);
-int reiserfs_permission_locked(struct inode *inode, int mask,
-                              struct nameidata *nd);
 
 int reiserfs_xattr_del(struct inode *, const char *);
 int reiserfs_xattr_get(const struct inode *, const char *, void *, size_t);
index 9d6fbee..d6b9bcd 100644 (file)
@@ -91,7 +91,8 @@ static inline void page_dup_rmap(struct page *page)
  * Called from mm/vmscan.c to handle paging out
  */
 int page_referenced(struct page *, int is_locked);
-int try_to_unmap(struct page *);
+int try_to_unmap(struct page *, int ignore_refs);
+void remove_from_swap(struct page *page);
 
 /*
  * Called from mm/filemap_xip.c to unmap empty zero page
@@ -111,7 +112,7 @@ unsigned long page_address_in_vma(struct page *, struct vm_area_struct *);
 #define anon_vma_link(vma)     do {} while (0)
 
 #define page_referenced(page,l) TestClearPageReferenced(page)
-#define try_to_unmap(page)     SWAP_FAIL
+#define try_to_unmap(page, refs) SWAP_FAIL
 
 #endif /* CONFIG_MMU */
 
index ef75365..bb1da86 100644 (file)
@@ -2617,6 +2617,25 @@ static inline int security_netlink_recv (struct sk_buff *skb)
        return cap_netlink_recv (skb);
 }
 
+static inline struct dentry *securityfs_create_dir(const char *name,
+                                       struct dentry *parent)
+{
+       return ERR_PTR(-ENODEV);
+}
+
+static inline struct dentry *securityfs_create_file(const char *name,
+                                               mode_t mode,
+                                               struct dentry *parent,
+                                               void *data,
+                                               struct file_operations *fops)
+{
+       return ERR_PTR(-ENODEV);
+}
+
+static inline void securityfs_remove(struct dentry *dentry)
+{
+}
+
 #endif /* CONFIG_SECURITY */
 
 #ifdef CONFIG_SECURITY_NETWORK
index cee302a..73b464f 100644 (file)
@@ -26,7 +26,7 @@ struct plat_serial8250_port {
        unsigned char   regshift;       /* register shift */
        unsigned char   iotype;         /* UPIO_* */
        unsigned char   hub6;
-       unsigned int    flags;          /* UPF_* flags */
+       upf_t           flags;          /* UPF_* flags */
 };
 
 /*
index ec35100..4041122 100644 (file)
@@ -203,6 +203,8 @@ struct uart_icount {
        __u32   buf_overrun;
 };
 
+typedef unsigned int __bitwise__ upf_t;
+
 struct uart_port {
        spinlock_t              lock;                   /* port lock */
        unsigned int            iobase;                 /* in/out[bwl] */
@@ -230,36 +232,34 @@ struct uart_port {
        unsigned long           sysrq;                  /* sysrq timeout */
 #endif
 
-       unsigned int            flags;
-
-#define UPF_FOURPORT           (1 << 1)
-#define UPF_SAK                        (1 << 2)
-#define UPF_SPD_MASK           (0x1030)
-#define UPF_SPD_HI             (0x0010)
-#define UPF_SPD_VHI            (0x0020)
-#define UPF_SPD_CUST           (0x0030)
-#define UPF_SPD_SHI            (0x1000)
-#define UPF_SPD_WARP           (0x1010)
-#define UPF_SKIP_TEST          (1 << 6)
-#define UPF_AUTO_IRQ           (1 << 7)
-#define UPF_HARDPPS_CD         (1 << 11)
-#define UPF_LOW_LATENCY                (1 << 13)
-#define UPF_BUGGY_UART         (1 << 14)
-#define UPF_AUTOPROBE          (1 << 15)
-#define UPF_MAGIC_MULTIPLIER   (1 << 16)
-#define UPF_BOOT_ONLYMCA       (1 << 22)
-#define UPF_CONS_FLOW          (1 << 23)
-#define UPF_SHARE_IRQ          (1 << 24)
-#define UPF_BOOT_AUTOCONF      (1 << 28)
-#define UPF_IOREMAP            (1 << 31)
-
-#define UPF_CHANGE_MASK                (0x17fff)
-#define UPF_USR_MASK           (UPF_SPD_MASK|UPF_LOW_LATENCY)
+       upf_t                   flags;
+
+#define UPF_FOURPORT           ((__force upf_t) (1 << 1))
+#define UPF_SAK                        ((__force upf_t) (1 << 2))
+#define UPF_SPD_MASK           ((__force upf_t) (0x1030))
+#define UPF_SPD_HI             ((__force upf_t) (0x0010))
+#define UPF_SPD_VHI            ((__force upf_t) (0x0020))
+#define UPF_SPD_CUST           ((__force upf_t) (0x0030))
+#define UPF_SPD_SHI            ((__force upf_t) (0x1000))
+#define UPF_SPD_WARP           ((__force upf_t) (0x1010))
+#define UPF_SKIP_TEST          ((__force upf_t) (1 << 6))
+#define UPF_AUTO_IRQ           ((__force upf_t) (1 << 7))
+#define UPF_HARDPPS_CD         ((__force upf_t) (1 << 11))
+#define UPF_LOW_LATENCY                ((__force upf_t) (1 << 13))
+#define UPF_BUGGY_UART         ((__force upf_t) (1 << 14))
+#define UPF_MAGIC_MULTIPLIER   ((__force upf_t) (1 << 16))
+#define UPF_CONS_FLOW          ((__force upf_t) (1 << 23))
+#define UPF_SHARE_IRQ          ((__force upf_t) (1 << 24))
+#define UPF_BOOT_AUTOCONF      ((__force upf_t) (1 << 28))
+#define UPF_IOREMAP            ((__force upf_t) (1 << 31))
+
+#define UPF_CHANGE_MASK                ((__force upf_t) (0x17fff))
+#define UPF_USR_MASK           ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
 
        unsigned int            mctrl;                  /* current modem ctrl settings */
        unsigned int            timeout;                /* character-based timeout */
        unsigned int            type;                   /* port type */
-       struct uart_ops         *ops;
+       const struct uart_ops   *ops;
        unsigned int            custom_divisor;
        unsigned int            line;                   /* port index */
        unsigned long           mapbase;                /* for ioremap */
@@ -289,6 +289,9 @@ struct uart_state {
 };
 
 #define UART_XMIT_SIZE PAGE_SIZE
+
+typedef unsigned int __bitwise__ uif_t;
+
 /*
  * This is the state information which is only valid when the port
  * is open; it may be freed by the core driver once the device has
@@ -298,17 +301,16 @@ struct uart_state {
 struct uart_info {
        struct tty_struct       *tty;
        struct circ_buf         xmit;
-       unsigned int            flags;
+       uif_t                   flags;
 
 /*
- * These are the flags that specific to info->flags, and reflect our
- * internal state.  They can not be accessed via port->flags.  Low
- * level drivers must not change these, but may query them instead.
+ * Definitions for info->flags.  These are _private_ to serial_core, and
+ * are specific to this structure.  They may be queried by low level drivers.
  */
-#define UIF_CHECK_CD           (1 << 25)
-#define UIF_CTS_FLOW           (1 << 26)
-#define UIF_NORMAL_ACTIVE      (1 << 29)
-#define UIF_INITIALIZED                (1 << 31)
+#define UIF_CHECK_CD           ((__force uif_t) (1 << 25))
+#define UIF_CTS_FLOW           ((__force uif_t) (1 << 26))
+#define UIF_NORMAL_ACTIVE      ((__force uif_t) (1 << 29))
+#define UIF_INITIALIZED                ((__force uif_t) (1 << 31))
 
        int                     blocked_open;
 
@@ -430,7 +432,7 @@ static inline int uart_handle_break(struct uart_port *port)
                port->sysrq = 0;
        }
 #endif
-       if (info->flags & UPF_SAK)
+       if (port->flags & UPF_SAK)
                do_SAK(info->tty);
        return 0;
 }
index 1fb77a9..8cf5293 100644 (file)
@@ -76,7 +76,14 @@ struct cache_sizes {
        kmem_cache_t    *cs_dmacachep;
 };
 extern struct cache_sizes malloc_sizes[];
+
+#ifndef CONFIG_DEBUG_SLAB
 extern void *__kmalloc(size_t, gfp_t);
+#else
+extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
+#define __kmalloc(size, flags) \
+    __kmalloc_track_caller(size, flags, __builtin_return_address(0))
+#endif
 
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
index 4a99e4a..f3e17d5 100644 (file)
@@ -178,6 +178,7 @@ extern int vm_swappiness;
 
 #ifdef CONFIG_NUMA
 extern int zone_reclaim_mode;
+extern int zone_reclaim_interval;
 extern int zone_reclaim(struct zone *, gfp_t, unsigned int);
 #else
 #define zone_reclaim_mode 0
@@ -190,13 +191,20 @@ static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order)
 #ifdef CONFIG_MIGRATION
 extern int isolate_lru_page(struct page *p);
 extern int putback_lru_pages(struct list_head *l);
+extern int migrate_page(struct page *, struct page *);
+extern void migrate_page_copy(struct page *, struct page *);
+extern int migrate_page_remove_references(struct page *, struct page *, int);
 extern int migrate_pages(struct list_head *l, struct list_head *t,
                struct list_head *moved, struct list_head *failed);
+extern int fail_migrate_page(struct page *, struct page *);
 #else
 static inline int isolate_lru_page(struct page *p) { return -ENOSYS; }
 static inline int putback_lru_pages(struct list_head *l) { return 0; }
 static inline int migrate_pages(struct list_head *l, struct list_head *t,
        struct list_head *moved, struct list_head *failed) { return -ENOSYS; }
+/* Possible settings for the migrate_page() method in address_operations */
+#define migrate_page NULL
+#define fail_migrate_page NULL
 #endif
 
 #ifdef CONFIG_MMU
@@ -245,6 +253,7 @@ extern int remove_exclusive_swap_page(struct page *);
 struct backing_dev_info;
 
 extern spinlock_t swap_lock;
+extern int remove_vma_swap(struct vm_area_struct *vma, struct page *page);
 
 /* linux/mm/thrash.c */
 extern struct mm_struct * swap_token_mm;
index e666d60..3877209 100644 (file)
@@ -50,6 +50,8 @@ struct timezone;
 struct tms;
 struct utimbuf;
 struct mq_attr;
+struct compat_stat;
+struct compat_timeval;
 
 #include <linux/config.h>
 #include <linux/types.h>
@@ -534,4 +536,35 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc,
 asmlinkage long sys_spu_create(const char __user *name,
                unsigned int flags, mode_t mode);
 
+asmlinkage long sys_mknodat(int dfd, const char __user * filename, int mode,
+                           unsigned dev);
+asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, int mode);
+asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag);
+asmlinkage long sys_symlinkat(const char __user * oldname,
+                             int newdfd, const char __user * newname);
+asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
+                          int newdfd, const char __user *newname);
+asmlinkage long sys_renameat(int olddfd, const char __user * oldname,
+                            int newdfd, const char __user * newname);
+asmlinkage long sys_futimesat(int dfd, char __user *filename,
+                             struct timeval __user *utimes);
+asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode);
+asmlinkage long sys_fchmodat(int dfd, const char __user * filename,
+                            mode_t mode);
+asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
+                            gid_t group, int flag);
+asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
+                          int mode);
+asmlinkage long sys_newfstatat(int dfd, char __user *filename,
+                              struct stat __user *statbuf, int flag);
+asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf,
+                              int bufsiz);
+asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename,
+                                    struct compat_timeval __user *t);
+asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename,
+                                     struct compat_stat __user *statbuf,
+                                     int flag);
+asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
+                                  int flags, int mode);
+
 #endif
index 8352a7c..32a4139 100644 (file)
@@ -182,7 +182,8 @@ enum
        VM_SWAP_TOKEN_TIMEOUT=28, /* default time for token time out */
        VM_DROP_PAGECACHE=29,   /* int: nuke lots of pagecache */
        VM_PERCPU_PAGELIST_FRACTION=30,/* int: fraction of pages in each percpu_pagelist */
-       VM_ZONE_RECLAIM_MODE=31,/* reclaim local zone memory before going off node */
+       VM_ZONE_RECLAIM_MODE=31, /* reclaim local zone memory before going off node */
+       VM_ZONE_RECLAIM_INTERVAL=32, /* time period to wait after reclaim failure */
 };
 
 
index 614dd84..7b4dc36 100644 (file)
@@ -48,7 +48,7 @@ extern void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec);
  * Returns true if the timespec is norm, false if denorm:
  */
 #define timespec_valid(ts) \
-       (((ts)->tv_sec >= 0) && (((unsigned) (ts)->tv_nsec) < NSEC_PER_SEC))
+       (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
 
 /*
  * 64-bit nanosec type. Large enough to span 292+ years in nanosecond
index 21b9ce8..54ae2d5 100644 (file)
@@ -8,6 +8,8 @@
        (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
 #define DECLARE_BITMAP(name,bits) \
        unsigned long name[BITS_TO_LONGS(bits)]
+
+#define BITS_PER_BYTE 8
 #endif
 
 #include <linux/posix_types.h>
index ee21e6b..a2aacfc 100644 (file)
@@ -535,9 +535,11 @@ enum usb_device_state {
         */
        USB_STATE_NOTATTACHED = 0,
 
-       /* the chapter 9 device states */
+       /* chapter 9 and authentication (wireless) device states */
        USB_STATE_ATTACHED,
-       USB_STATE_POWERED,
+       USB_STATE_POWERED,                      /* wired */
+       USB_STATE_UNAUTHENTICATED,              /* auth */
+       USB_STATE_RECONNECTING,                 /* auth */
        USB_STATE_DEFAULT,                      /* limited function */
        USB_STATE_ADDRESS,
        USB_STATE_CONFIGURED,                   /* most functions */
index ce40675..6f6c697 100644 (file)
@@ -315,6 +315,7 @@ struct v4l2_pix_format
 #define V4L2_PIX_FMT_SN9C10X  v4l2_fourcc('S','9','1','0') /* SN9C10x compression */
 #define V4L2_PIX_FMT_PWC1     v4l2_fourcc('P','W','C','1') /* pwc older webcam */
 #define V4L2_PIX_FMT_PWC2     v4l2_fourcc('P','W','C','2') /* pwc newer webcam */
+#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */
 
 /*
  *     F O R M A T   E N U M E R A T I O N
index df05f46..9a92aef 100644 (file)
@@ -803,9 +803,9 @@ enum ieee80211_state {
 #define IEEE80211_24GHZ_MAX_CHANNEL 14
 #define IEEE80211_24GHZ_CHANNELS    14
 
-#define IEEE80211_52GHZ_MIN_CHANNEL 36
+#define IEEE80211_52GHZ_MIN_CHANNEL 34
 #define IEEE80211_52GHZ_MAX_CHANNEL 165
-#define IEEE80211_52GHZ_CHANNELS    32
+#define IEEE80211_52GHZ_CHANNELS    131
 
 enum {
        IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
index e3e5436..9c04f15 100644 (file)
@@ -170,8 +170,8 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst,
        return ip_route_output_flow(rp, &fl, sk, 0);
 }
 
-static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport,
-                                   struct sock *sk)
+static inline int ip_route_newports(struct rtable **rp, u8 protocol,
+                                   u16 sport, u16 dport, struct sock *sk)
 {
        if (sport != (*rp)->fl.fl_ip_sport ||
            dport != (*rp)->fl.fl_ip_dport) {
@@ -180,6 +180,7 @@ static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport,
                memcpy(&fl, &(*rp)->fl, sizeof(fl));
                fl.fl_ip_sport = sport;
                fl.fl_ip_dport = dport;
+               fl.proto = protocol;
                ip_rt_put(*rp);
                *rp = NULL;
                return ip_route_output_flow(rp, &fl, sk, 0);
index e94ca4d..290e3b4 100644 (file)
@@ -275,7 +275,7 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
                            int data_direction, void *buffer, unsigned bufflen,
                            struct scsi_sense_hdr *, int timeout, int retries);
 extern int scsi_execute_async(struct scsi_device *sdev,
-                             const unsigned char *cmd, int data_direction,
+                             const unsigned char *cmd, 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),
index 467274a..8279929 100644 (file)
@@ -554,7 +554,6 @@ struct Scsi_Host {
        /*
         * ordered write support
         */
-       unsigned ordered_flush:1;
        unsigned ordered_tag:1;
 
        /*
index 4ae8cfc..7f0ab5e 100644 (file)
@@ -802,7 +802,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
        init_sigpending(&sig->shared_pending);
        INIT_LIST_HEAD(&sig->posix_timers);
 
-       hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC);
+       hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL);
        sig->it_real_incr.tv64 = 0;
        sig->real_timer.function = it_real_fn;
        sig->real_timer.data = tsk;
index f1c4155..2b6e175 100644 (file)
  *  Credits:
  *     based on kernel/timer.c
  *
+ *     Help, testing, suggestions, bugfixes, improvements were
+ *     provided by:
+ *
+ *     George Anzinger, Andrew Morton, Steven Rostedt, Roman Zippel
+ *     et. al.
+ *
  *  For licencing details see kernel-base/COPYING
  */
 
@@ -66,6 +72,12 @@ EXPORT_SYMBOL_GPL(ktime_get_real);
 
 /*
  * The timer bases:
+ *
+ * Note: If we want to add new timer bases, we have to skip the two
+ * clock ids captured by the cpu-timers. We do this by holding empty
+ * entries rather than doing math adjustment of the clock ids.
+ * This ensures that we capture erroneous accesses to these clock ids
+ * rather than moving them into the range of valid clock id's.
  */
 
 #define MAX_HRTIMER_BASES 2
@@ -483,29 +495,25 @@ ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
 }
 
 /**
- * hrtimer_rebase - rebase an initialized hrtimer to a different base
+ * hrtimer_init - initialize a timer to the given clock
  *
- * @timer:     the timer to be rebased
+ * @timer:     the timer to be initialized
  * @clock_id:  the clock to be used
+ * @mode:      timer mode abs/rel
  */
-void hrtimer_rebase(struct hrtimer *timer, const clockid_t clock_id)
+void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+                 enum hrtimer_mode mode)
 {
        struct hrtimer_base *bases;
 
+       memset(timer, 0, sizeof(struct hrtimer));
+
        bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
-       timer->base = &bases[clock_id];
-}
 
-/**
- * hrtimer_init - initialize a timer to the given clock
- *
- * @timer:     the timer to be initialized
- * @clock_id:  the clock to be used
- */
-void hrtimer_init(struct hrtimer *timer, const clockid_t clock_id)
-{
-       memset(timer, 0, sizeof(struct hrtimer));
-       hrtimer_rebase(timer, clock_id);
+       if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS)
+               clock_id = CLOCK_MONOTONIC;
+
+       timer->base = &bases[clock_id];
 }
 
 /**
@@ -550,6 +558,7 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
                fn = timer->function;
                data = timer->data;
                set_curr_timer(base, timer);
+               timer->state = HRTIMER_RUNNING;
                __remove_hrtimer(timer, base);
                spin_unlock_irq(&base->lock);
 
@@ -565,6 +574,10 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
 
                spin_lock_irq(&base->lock);
 
+               /* Another CPU has added back the timer */
+               if (timer->state != HRTIMER_RUNNING)
+                       continue;
+
                if (restart == HRTIMER_RESTART)
                        enqueue_hrtimer(timer, base);
                else
@@ -638,8 +651,7 @@ schedule_hrtimer_interruptible(struct hrtimer *timer,
        return schedule_hrtimer(timer, mode);
 }
 
-static long __sched
-nanosleep_restart(struct restart_block *restart, clockid_t clockid)
+static long __sched nanosleep_restart(struct restart_block *restart)
 {
        struct timespec __user *rmtp;
        struct timespec tu;
@@ -649,7 +661,7 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid)
 
        restart->fn = do_no_restart_syscall;
 
-       hrtimer_init(&timer, clockid);
+       hrtimer_init(&timer, (clockid_t) restart->arg3, HRTIMER_ABS);
 
        timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
 
@@ -669,16 +681,6 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid)
        return -ERESTART_RESTARTBLOCK;
 }
 
-static long __sched nanosleep_restart_mono(struct restart_block *restart)
-{
-       return nanosleep_restart(restart, CLOCK_MONOTONIC);
-}
-
-static long __sched nanosleep_restart_real(struct restart_block *restart)
-{
-       return nanosleep_restart(restart, CLOCK_REALTIME);
-}
-
 long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
                       const enum hrtimer_mode mode, const clockid_t clockid)
 {
@@ -687,7 +689,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
        struct timespec tu;
        ktime_t rem;
 
-       hrtimer_init(&timer, clockid);
+       hrtimer_init(&timer, clockid, mode);
 
        timer.expires = timespec_to_ktime(*rqtp);
 
@@ -695,7 +697,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
        if (rem.tv64 <= 0)
                return 0;
 
-       /* Absolute timers do not update the rmtp value: */
+       /* Absolute timers do not update the rmtp value and restart: */
        if (mode == HRTIMER_ABS)
                return -ERESTARTNOHAND;
 
@@ -705,11 +707,11 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
                return -EFAULT;
 
        restart = &current_thread_info()->restart_block;
-       restart->fn = (clockid == CLOCK_MONOTONIC) ?
-               nanosleep_restart_mono : nanosleep_restart_real;
+       restart->fn = nanosleep_restart;
        restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF;
        restart->arg1 = timer.expires.tv64 >> 32;
        restart->arg2 = (unsigned long) rmtp;
+       restart->arg3 = (unsigned long) timer.base->index;
 
        return -ERESTART_RESTARTBLOCK;
 }
@@ -736,10 +738,8 @@ static void __devinit init_hrtimers_cpu(int cpu)
        struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu);
        int i;
 
-       for (i = 0; i < MAX_HRTIMER_BASES; i++) {
+       for (i = 0; i < MAX_HRTIMER_BASES; i++, base++)
                spin_lock_init(&base->lock);
-               base++;
-       }
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index c2c05c4..379be2f 100644 (file)
@@ -49,9 +49,11 @@ int do_getitimer(int which, struct itimerval *value)
 
        switch (which) {
        case ITIMER_REAL:
+               spin_lock_irq(&tsk->sighand->siglock);
                value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
                value->it_interval =
                        ktime_to_timeval(tsk->signal->it_real_incr);
+               spin_unlock_irq(&tsk->sighand->siglock);
                break;
        case ITIMER_VIRTUAL:
                read_lock(&tasklist_lock);
@@ -150,18 +152,25 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
 
        switch (which) {
        case ITIMER_REAL:
+again:
+               spin_lock_irq(&tsk->sighand->siglock);
                timer = &tsk->signal->real_timer;
-               hrtimer_cancel(timer);
                if (ovalue) {
                        ovalue->it_value = itimer_get_remtime(timer);
                        ovalue->it_interval
                                = ktime_to_timeval(tsk->signal->it_real_incr);
                }
+               /* We are sharing ->siglock with it_real_fn() */
+               if (hrtimer_try_to_cancel(timer) < 0) {
+                       spin_unlock_irq(&tsk->sighand->siglock);
+                       goto again;
+               }
                tsk->signal->it_real_incr =
                        timeval_to_ktime(value->it_interval);
                expires = timeval_to_ktime(value->it_value);
                if (expires.tv64 != 0)
                        hrtimer_start(timer, expires, HRTIMER_REL);
+               spin_unlock_irq(&tsk->sighand->siglock);
                break;
        case ITIMER_VIRTUAL:
                nval = timeval_to_cputime(&value->it_value);
index 197208b..216f574 100644 (file)
@@ -194,9 +194,7 @@ static inline int common_clock_set(const clockid_t which_clock,
 
 static int common_timer_create(struct k_itimer *new_timer)
 {
-       hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock);
-       new_timer->it.real.timer.data = new_timer;
-       new_timer->it.real.timer.function = posix_timer_fn;
+       hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0);
        return 0;
 }
 
@@ -290,7 +288,8 @@ void do_schedule_next_timer(struct siginfo *info)
                info->si_overrun = timr->it_overrun_last;
        }
 
-       unlock_timer(timr, flags);
+       if (timr)
+               unlock_timer(timr, flags);
 }
 
 int posix_timer_event(struct k_itimer *timr,int si_private)
@@ -692,6 +691,7 @@ common_timer_set(struct k_itimer *timr, int flags,
                 struct itimerspec *new_setting, struct itimerspec *old_setting)
 {
        struct hrtimer *timer = &timr->it.real.timer;
+       enum hrtimer_mode mode;
 
        if (old_setting)
                common_timer_get(timr, old_setting);
@@ -713,14 +713,10 @@ common_timer_set(struct k_itimer *timr, int flags,
        if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)
                return 0;
 
-       /* Posix madness. Only absolute CLOCK_REALTIME timers
-        * are affected by clock sets. So we must reiniatilize
-        * the timer.
-        */
-       if (timr->it_clock == CLOCK_REALTIME && (flags & TIMER_ABSTIME))
-               hrtimer_rebase(timer, CLOCK_REALTIME);
-       else
-               hrtimer_rebase(timer, CLOCK_MONOTONIC);
+       mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
+       hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
+       timr->it.real.timer.data = timr;
+       timr->it.real.timer.function = posix_timer_fn;
 
        timer->expires = timespec_to_ktime(new_setting->it_value);
 
@@ -728,11 +724,15 @@ common_timer_set(struct k_itimer *timr, int flags,
        timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
 
        /* SIGEV_NONE timers are not queued ! See common_timer_get */
-       if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+       if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
+               /* Setup correct expiry time for relative timers */
+               if (mode == HRTIMER_REL)
+                       timer->expires = ktime_add(timer->expires,
+                                                  timer->base->get_time());
                return 0;
+       }
 
-       hrtimer_start(timer, timer->expires, (flags & TIMER_ABSTIME) ?
-                     HRTIMER_ABS : HRTIMER_REL);
+       hrtimer_start(timer, timer->expires, mode);
        return 0;
 }
 
@@ -875,12 +875,6 @@ int do_posix_clock_nosettime(const clockid_t clockid, struct timespec *tp)
 }
 EXPORT_SYMBOL_GPL(do_posix_clock_nosettime);
 
-int do_posix_clock_notimer_create(struct k_itimer *timer)
-{
-       return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create);
-
 int do_posix_clock_nonanosleep(const clockid_t clock, int flags,
                               struct timespec *t, struct timespec __user *r)
 {
@@ -947,21 +941,8 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp)
 static int common_nsleep(const clockid_t which_clock, int flags,
                         struct timespec *tsave, struct timespec __user *rmtp)
 {
-       int mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
-       int clockid = which_clock;
-
-       switch (which_clock) {
-       case CLOCK_REALTIME:
-               /* Posix madness. Only absolute timers on clock realtime
-                  are affected by clock set. */
-               if (mode != HRTIMER_ABS)
-                       clockid = CLOCK_MONOTONIC;
-       case CLOCK_MONOTONIC:
-               break;
-       default:
-               return -EINVAL;
-       }
-       return hrtimer_nanosleep(tsave, rmtp, mode, clockid);
+       return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
+                                HRTIMER_ABS : HRTIMER_REL, which_clock);
 }
 
 asmlinkage long
index 7ff375e..579d239 100644 (file)
@@ -9,18 +9,11 @@
 #include <linux/console.h>
 #include "power.h"
 
-static int new_loglevel = 10;
-static int orig_loglevel;
 #ifdef SUSPEND_CONSOLE
 static int orig_fgconsole, orig_kmsg;
-#endif
 
 int pm_prepare_console(void)
 {
-       orig_loglevel = console_loglevel;
-       console_loglevel = new_loglevel;
-
-#ifdef SUSPEND_CONSOLE
        acquire_console_sem();
 
        orig_fgconsole = fg_console;
@@ -41,18 +34,15 @@ int pm_prepare_console(void)
        }
        orig_kmsg = kmsg_redirect;
        kmsg_redirect = SUSPEND_CONSOLE;
-#endif
        return 0;
 }
 
 void pm_restore_console(void)
 {
-       console_loglevel = orig_loglevel;
-#ifdef SUSPEND_CONSOLE
        acquire_console_sem();
        set_console(orig_fgconsole);
        release_console_sem();
        kmsg_redirect = orig_kmsg;
-#endif
        return;
 }
+#endif
index e03d85e..0b43847 100644 (file)
@@ -360,14 +360,14 @@ power_attr(resume);
 
 static ssize_t image_size_show(struct subsystem * subsys, char *buf)
 {
-       return sprintf(buf, "%u\n", image_size);
+       return sprintf(buf, "%lu\n", image_size);
 }
 
 static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n)
 {
-       unsigned int size;
+       unsigned long size;
 
-       if (sscanf(buf, "%u", &size) == 1) {
+       if (sscanf(buf, "%lu", &size) == 1) {
                image_size = size;
                return n;
        }
index 7e8492f..d8f0d1a 100644 (file)
@@ -42,8 +42,13 @@ static struct subsys_attribute _name##_attr = {      \
 
 extern struct subsystem power_subsys;
 
+#ifdef SUSPEND_CONSOLE
 extern int pm_prepare_console(void);
 extern void pm_restore_console(void);
+#else
+static int pm_prepare_console(void) { return 0; }
+static void pm_restore_console(void) {}
+#endif
 
 /* References to section boundaries */
 extern const void __nosave_begin, __nosave_end;
@@ -51,8 +56,8 @@ extern const void __nosave_begin, __nosave_end;
 extern unsigned int nr_copy_pages;
 extern struct pbe *pagedir_nosave;
 
-/* Preferred image size in MB (default 500) */
-extern unsigned int image_size;
+/* Preferred image size in bytes (default 500 MB) */
+extern unsigned long image_size;
 
 extern asmlinkage int swsusp_arch_suspend(void);
 extern asmlinkage int swsusp_arch_resume(void);
index 55a18d2..59c91c1 100644 (file)
 #include "power.h"
 
 /*
- * Preferred image size in MB (tunable via /sys/power/image_size).
+ * Preferred image size in bytes (tunable via /sys/power/image_size).
  * When it is set to N, swsusp will do its best to ensure the image
- * size will not exceed N MB, but if that is impossible, it will
+ * size will not exceed N bytes, but if that is impossible, it will
  * try to create the smallest image possible.
  */
-unsigned int image_size = 500;
+unsigned long image_size = 500 * 1024 * 1024;
 
 #ifdef CONFIG_HIGHMEM
 unsigned int count_highmem_pages(void);
@@ -590,7 +590,7 @@ int swsusp_shrink_memory(void)
                        if (!tmp)
                                return -ENOMEM;
                        pages += tmp;
-               } else if (size > (image_size * 1024 * 1024) / PAGE_SIZE) {
+               } else if (size > image_size / PAGE_SIZE) {
                        tmp = shrink_all_memory(SHRINK_BITE);
                        pages += tmp;
                }
index 7732199..7712912 100644 (file)
@@ -114,16 +114,16 @@ rcu_torture_alloc(void)
 {
        struct list_head *p;
 
-       spin_lock(&rcu_torture_lock);
+       spin_lock_bh(&rcu_torture_lock);
        if (list_empty(&rcu_torture_freelist)) {
                atomic_inc(&n_rcu_torture_alloc_fail);
-               spin_unlock(&rcu_torture_lock);
+               spin_unlock_bh(&rcu_torture_lock);
                return NULL;
        }
        atomic_inc(&n_rcu_torture_alloc);
        p = rcu_torture_freelist.next;
        list_del_init(p);
-       spin_unlock(&rcu_torture_lock);
+       spin_unlock_bh(&rcu_torture_lock);
        return container_of(p, struct rcu_torture, rtort_free);
 }
 
@@ -134,9 +134,9 @@ static void
 rcu_torture_free(struct rcu_torture *p)
 {
        atomic_inc(&n_rcu_torture_free);
-       spin_lock(&rcu_torture_lock);
+       spin_lock_bh(&rcu_torture_lock);
        list_add_tail(&p->rtort_free, &rcu_torture_freelist);
-       spin_unlock(&rcu_torture_lock);
+       spin_unlock_bh(&rcu_torture_lock);
 }
 
 static void
index 3ee2ae4..f77f23f 100644 (file)
@@ -4031,7 +4031,7 @@ long sched_getaffinity(pid_t pid, cpumask_t *mask)
                goto out_unlock;
 
        retval = 0;
-       cpus_and(*mask, p->cpus_allowed, cpu_possible_map);
+       cpus_and(*mask, p->cpus_allowed, cpu_online_map);
 
 out_unlock:
        read_unlock(&tasklist_lock);
@@ -5141,7 +5141,7 @@ static void init_sched_build_groups(struct sched_group groups[], cpumask_t span,
 #define SEARCH_SCOPE           2
 #define MIN_CACHE_SIZE         (64*1024U)
 #define DEFAULT_CACHE_SIZE     (5*1024*1024U)
-#define ITERATIONS             2
+#define ITERATIONS             1
 #define SIZE_THRESH            130
 #define COST_THRESH            130
 
@@ -5480,9 +5480,9 @@ static unsigned long long measure_migration_cost(int cpu1, int cpu2)
                                break;
                        }
                /*
-                * Increase the cachesize in 5% steps:
+                * Increase the cachesize in 10% steps:
                 */
-               size = size * 20 / 19;
+               size = size * 10 / 9;
        }
 
        if (migration_debug)
index cb99a42..71dd6f6 100644 (file)
@@ -878,7 +878,17 @@ static ctl_table vm_table[] = {
                .maxlen         = sizeof(zone_reclaim_mode),
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
-               .strategy       = &zero,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+       },
+       {
+               .ctl_name       = VM_ZONE_RECLAIM_INTERVAL,
+               .procname       = "zone_reclaim_interval",
+               .data           = &zone_reclaim_interval,
+               .maxlen         = sizeof(zone_reclaim_interval),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
        },
 #endif
        { .ctl_name = 0 }
index 7477b1d..1f23e68 100644 (file)
@@ -155,7 +155,7 @@ int do_sys_settimeofday(struct timespec *tv, struct timezone *tz)
        static int firsttime = 1;
        int error = 0;
 
-       if (!timespec_valid(tv))
+       if (tv && !timespec_valid(tv))
                return -EINVAL;
 
        error = security_settime(tv, tz);
index 89e562f..d9deae4 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/key.h>
+#include <linux/interrupt.h>
 
 /*
  * UID task count cache, to get fast user lookup in "alloc_uid"
 
 static kmem_cache_t *uid_cachep;
 static struct list_head uidhash_table[UIDHASH_SZ];
+
+/*
+ * The uidhash_lock is mostly taken from process context, but it is
+ * occasionally also taken from softirq/tasklet context, when
+ * task-structs get RCU-freed. Hence all locking must be softirq-safe.
+ * But free_uid() is also called with local interrupts disabled, and running
+ * local_bh_enable() with local interrupts disabled is an error - we'll run
+ * softirq callbacks, and they can unconditionally enable interrupts, and
+ * the caller of free_uid() didn't expect that..
+ */
 static DEFINE_SPINLOCK(uidhash_lock);
 
 struct user_struct root_user = {
@@ -82,15 +93,19 @@ static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *has
 struct user_struct *find_user(uid_t uid)
 {
        struct user_struct *ret;
+       unsigned long flags;
 
-       spin_lock(&uidhash_lock);
+       spin_lock_irqsave(&uidhash_lock, flags);
        ret = uid_hash_find(uid, uidhashentry(uid));
-       spin_unlock(&uidhash_lock);
+       spin_unlock_irqrestore(&uidhash_lock, flags);
        return ret;
 }
 
 void free_uid(struct user_struct *up)
 {
+       unsigned long flags;
+
+       local_irq_save(flags);
        if (up && atomic_dec_and_lock(&up->__count, &uidhash_lock)) {
                uid_hash_remove(up);
                key_put(up->uid_keyring);
@@ -98,6 +113,7 @@ void free_uid(struct user_struct *up)
                kmem_cache_free(uid_cachep, up);
                spin_unlock(&uidhash_lock);
        }
+       local_irq_restore(flags);
 }
 
 struct user_struct * alloc_uid(uid_t uid)
@@ -105,9 +121,9 @@ struct user_struct * alloc_uid(uid_t uid)
        struct list_head *hashent = uidhashentry(uid);
        struct user_struct *up;
 
-       spin_lock(&uidhash_lock);
+       spin_lock_irq(&uidhash_lock);
        up = uid_hash_find(uid, hashent);
-       spin_unlock(&uidhash_lock);
+       spin_unlock_irq(&uidhash_lock);
 
        if (!up) {
                struct user_struct *new;
@@ -137,7 +153,7 @@ struct user_struct * alloc_uid(uid_t uid)
                 * Before adding this, check whether we raced
                 * on adding the same user already..
                 */
-               spin_lock(&uidhash_lock);
+               spin_lock_irq(&uidhash_lock);
                up = uid_hash_find(uid, hashent);
                if (up) {
                        key_put(new->uid_keyring);
@@ -147,7 +163,7 @@ struct user_struct * alloc_uid(uid_t uid)
                        uid_hash_insert(new, hashent);
                        up = new;
                }
-               spin_unlock(&uidhash_lock);
+               spin_unlock_irq(&uidhash_lock);
 
        }
        return up;
@@ -183,9 +199,9 @@ static int __init uid_cache_init(void)
                INIT_LIST_HEAD(uidhash_table + n);
 
        /* Insert the root user immediately (init already runs as root) */
-       spin_lock(&uidhash_lock);
+       spin_lock_irq(&uidhash_lock);
        uid_hash_insert(&root_user, uidhashentry(0));
-       spin_unlock(&uidhash_lock);
+       spin_unlock_irq(&uidhash_lock);
 
        return 0;
 }
index 8535f4d..648b2c1 100644 (file)
@@ -9,7 +9,7 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 
 lib-y  += kobject.o kref.o kobject_uevent.o klist.o
 
-obj-y += sort.o parser.o halfmd4.o
+obj-y += sort.o parser.o halfmd4.o iomap_copy.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/iomap_copy.c b/lib/iomap_copy.c
new file mode 100644 (file)
index 0000000..a6b1e27
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 PathScale, Inc.  All Rights Reserved.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+
+/**
+ * __iowrite32_copy - copy data to MMIO space, in 32-bit units
+ * @to: destination, in MMIO space (must be 32-bit aligned)
+ * @from: source (must be 32-bit aligned)
+ * @count: number of 32-bit quantities to copy
+ *
+ * Copy data from kernel space to MMIO space, in units of 32 bits at a
+ * time.  Order of access is not guaranteed, nor is a memory barrier
+ * performed afterwards.
+ */
+void __attribute__((weak)) __iowrite32_copy(void __iomem *to,
+                                           const void *from,
+                                           size_t count)
+{
+       u32 __iomem *dst = to;
+       const u32 *src = from;
+       const u32 *end = src + count;
+
+       while (src < end)
+               __raw_writel(*src++, dst++);
+}
+EXPORT_SYMBOL_GPL(__iowrite32_copy);
index 7a11ddd..2bee1f2 100644 (file)
@@ -1871,6 +1871,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
                goto out;
 
        entry = pte_to_swp_entry(orig_pte);
+again:
        page = lookup_swap_cache(entry);
        if (!page) {
                swapin_readahead(entry, address, vma);
@@ -1894,6 +1895,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
 
        mark_page_accessed(page);
        lock_page(page);
+       if (!PageSwapCache(page)) {
+               /* Page migration has occured */
+               unlock_page(page);
+               page_cache_release(page);
+               goto again;
+       }
 
        /*
         * Back out if somebody else already faulted in this pte.
index 7379018..27da6d5 100644 (file)
@@ -95,6 +95,9 @@
 #define MPOL_MF_INVERT (MPOL_MF_INTERNAL << 1)         /* Invert check for nodemask */
 #define MPOL_MF_STATS (MPOL_MF_INTERNAL << 2)          /* Gather statistics */
 
+/* The number of pages to migrate per call to migrate_pages() */
+#define MIGRATE_CHUNK_SIZE 256
+
 static kmem_cache_t *policy_cache;
 static kmem_cache_t *sn_cache;
 
@@ -543,24 +546,91 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
        }
 }
 
-static int swap_pages(struct list_head *pagelist)
+/*
+ * Migrate the list 'pagelist' of pages to a certain destination.
+ *
+ * Specify destination with either non-NULL vma or dest_node >= 0
+ * Return the number of pages not migrated or error code
+ */
+static int migrate_pages_to(struct list_head *pagelist,
+                       struct vm_area_struct *vma, int dest)
 {
+       LIST_HEAD(newlist);
        LIST_HEAD(moved);
        LIST_HEAD(failed);
-       int n;
+       int err = 0;
+       int nr_pages;
+       struct page *page;
+       struct list_head *p;
 
-       n = migrate_pages(pagelist, NULL, &moved, &failed);
-       putback_lru_pages(&failed);
-       putback_lru_pages(&moved);
+redo:
+       nr_pages = 0;
+       list_for_each(p, pagelist) {
+               if (vma)
+                       page = alloc_page_vma(GFP_HIGHUSER, vma, vma->vm_start);
+               else
+                       page = alloc_pages_node(dest, GFP_HIGHUSER, 0);
 
-       return n;
+               if (!page) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+               list_add(&page->lru, &newlist);
+               nr_pages++;
+               if (nr_pages > MIGRATE_CHUNK_SIZE);
+                       break;
+       }
+       err = migrate_pages(pagelist, &newlist, &moved, &failed);
+
+       putback_lru_pages(&moved);      /* Call release pages instead ?? */
+
+       if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist))
+               goto redo;
+out:
+       /* Return leftover allocated pages */
+       while (!list_empty(&newlist)) {
+               page = list_entry(newlist.next, struct page, lru);
+               list_del(&page->lru);
+               __free_page(page);
+       }
+       list_splice(&failed, pagelist);
+       if (err < 0)
+               return err;
+
+       /* Calculate number of leftover pages */
+       nr_pages = 0;
+       list_for_each(p, pagelist)
+               nr_pages++;
+       return nr_pages;
+}
+
+/*
+ * Migrate pages from one node to a target node.
+ * Returns error or the number of pages not migrated.
+ */
+int migrate_to_node(struct mm_struct *mm, int source, int dest, int flags)
+{
+       nodemask_t nmask;
+       LIST_HEAD(pagelist);
+       int err = 0;
+
+       nodes_clear(nmask);
+       node_set(source, nmask);
+
+       check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nmask,
+                       flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+
+       if (!list_empty(&pagelist)) {
+               err = migrate_pages_to(&pagelist, NULL, dest);
+               if (!list_empty(&pagelist))
+                       putback_lru_pages(&pagelist);
+       }
+       return err;
 }
 
 /*
- * For now migrate_pages simply swaps out the pages from nodes that are in
- * the source set but not in the target set. In the future, we would
- * want a function that moves pages between the two nodesets in such
- * a way as to preserve the physical layout as much as possible.
+ * Move pages between the two nodesets so as to preserve the physical
+ * layout as much as possible.
  *
  * Returns the number of page that could not be moved.
  */
@@ -568,22 +638,76 @@ int do_migrate_pages(struct mm_struct *mm,
        const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags)
 {
        LIST_HEAD(pagelist);
-       int count = 0;
-       nodemask_t nodes;
+       int busy = 0;
+       int err = 0;
+       nodemask_t tmp;
 
-       nodes_andnot(nodes, *from_nodes, *to_nodes);
+       down_read(&mm->mmap_sem);
 
-       down_read(&mm->mmap_sem);
-       check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nodes,
-                       flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+/*
+ * Find a 'source' bit set in 'tmp' whose corresponding 'dest'
+ * bit in 'to' is not also set in 'tmp'.  Clear the found 'source'
+ * bit in 'tmp', and return that <source, dest> pair for migration.
+ * The pair of nodemasks 'to' and 'from' define the map.
+ *
+ * If no pair of bits is found that way, fallback to picking some
+ * pair of 'source' and 'dest' bits that are not the same.  If the
+ * 'source' and 'dest' bits are the same, this represents a node
+ * that will be migrating to itself, so no pages need move.
+ *
+ * If no bits are left in 'tmp', or if all remaining bits left
+ * in 'tmp' correspond to the same bit in 'to', return false
+ * (nothing left to migrate).
+ *
+ * This lets us pick a pair of nodes to migrate between, such that
+ * if possible the dest node is not already occupied by some other
+ * source node, minimizing the risk of overloading the memory on a
+ * node that would happen if we migrated incoming memory to a node
+ * before migrating outgoing memory source that same node.
+ *
+ * A single scan of tmp is sufficient.  As we go, we remember the
+ * most recent <s, d> pair that moved (s != d).  If we find a pair
+ * that not only moved, but what's better, moved to an empty slot
+ * (d is not set in tmp), then we break out then, with that pair.
+ * Otherwise when we finish scannng from_tmp, we at least have the
+ * most recent <s, d> pair that moved.  If we get all the way through
+ * the scan of tmp without finding any node that moved, much less
+ * moved to an empty node, then there is nothing left worth migrating.
+ */
 
-       if (!list_empty(&pagelist)) {
-               count = swap_pages(&pagelist);
-               putback_lru_pages(&pagelist);
+       tmp = *from_nodes;
+       while (!nodes_empty(tmp)) {
+               int s,d;
+               int source = -1;
+               int dest = 0;
+
+               for_each_node_mask(s, tmp) {
+                       d = node_remap(s, *from_nodes, *to_nodes);
+                       if (s == d)
+                               continue;
+
+                       source = s;     /* Node moved. Memorize */
+                       dest = d;
+
+                       /* dest not in remaining from nodes? */
+                       if (!node_isset(dest, tmp))
+                               break;
+               }
+               if (source == -1)
+                       break;
+
+               node_clear(source, tmp);
+               err = migrate_to_node(mm, source, dest, flags);
+               if (err > 0)
+                       busy += err;
+               if (err < 0)
+                       break;
        }
 
        up_read(&mm->mmap_sem);
-       return count;
+       if (err < 0)
+               return err;
+       return busy;
 }
 
 long do_mbind(unsigned long start, unsigned long len,
@@ -643,8 +767,9 @@ long do_mbind(unsigned long start, unsigned long len,
                int nr_failed = 0;
 
                err = mbind_range(vma, start, end, new);
+
                if (!list_empty(&pagelist))
-                       nr_failed = swap_pages(&pagelist);
+                       nr_failed = migrate_pages_to(&pagelist, vma, -1);
 
                if (!err && nr_failed && (flags & MPOL_MF_STRICT))
                        err = -EIO;
index 14bd4ec..b05ab8f 100644 (file)
@@ -271,6 +271,7 @@ void out_of_memory(gfp_t gfp_mask, int order)
        if (printk_ratelimit()) {
                printk("oom-killer: gfp_mask=0x%x, order=%d\n",
                        gfp_mask, order);
+               dump_stack();
                show_mem();
        }
 
index df54e2f..44b4eb4 100644 (file)
@@ -1799,7 +1799,7 @@ void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
        memmap_init_zone((size), (nid), (zone), (start_pfn))
 #endif
 
-static int __meminit zone_batchsize(struct zone *zone)
+static int __cpuinit zone_batchsize(struct zone *zone)
 {
        int batch;
 
@@ -1893,7 +1893,7 @@ static struct per_cpu_pageset
  * Dynamically allocate memory for the
  * per cpu pageset array in struct zone.
  */
-static int __meminit process_zones(int cpu)
+static int __cpuinit process_zones(int cpu)
 {
        struct zone *zone, *dzone;
 
@@ -1934,7 +1934,7 @@ static inline void free_zone_pagesets(int cpu)
        }
 }
 
-static int __meminit pageset_cpuup_callback(struct notifier_block *nfb,
+static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
                unsigned long action,
                void *hcpu)
 {
index d85a99d..df2c41c 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -52,6 +52,7 @@
 #include <linux/init.h>
 #include <linux/rmap.h>
 #include <linux/rcupdate.h>
+#include <linux/module.h>
 
 #include <asm/tlbflush.h>
 
@@ -205,6 +206,36 @@ out:
        return anon_vma;
 }
 
+#ifdef CONFIG_MIGRATION
+/*
+ * Remove an anonymous page from swap replacing the swap pte's
+ * through real pte's pointing to valid pages and then releasing
+ * the page from the swap cache.
+ *
+ * Must hold page lock on page.
+ */
+void remove_from_swap(struct page *page)
+{
+       struct anon_vma *anon_vma;
+       struct vm_area_struct *vma;
+
+       if (!PageAnon(page) || !PageSwapCache(page))
+               return;
+
+       anon_vma = page_lock_anon_vma(page);
+       if (!anon_vma)
+               return;
+
+       list_for_each_entry(vma, &anon_vma->head, anon_vma_node)
+               remove_vma_swap(vma, page);
+
+       spin_unlock(&anon_vma->lock);
+
+       delete_from_swap_cache(page);
+}
+EXPORT_SYMBOL(remove_from_swap);
+#endif
+
 /*
  * At what user virtual address is page expected in vma?
  */
@@ -541,7 +572,8 @@ void page_remove_rmap(struct page *page)
  * Subfunctions of try_to_unmap: try_to_unmap_one called
  * repeatedly from either try_to_unmap_anon or try_to_unmap_file.
  */
-static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
+static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
+                               int ignore_refs)
 {
        struct mm_struct *mm = vma->vm_mm;
        unsigned long address;
@@ -564,7 +596,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
         * skipped over this mm) then we should reactivate it.
         */
        if ((vma->vm_flags & VM_LOCKED) ||
-                       ptep_clear_flush_young(vma, address, pte)) {
+                       (ptep_clear_flush_young(vma, address, pte)
+                               && !ignore_refs)) {
                ret = SWAP_FAIL;
                goto out_unmap;
        }
@@ -698,7 +731,7 @@ static void try_to_unmap_cluster(unsigned long cursor,
        pte_unmap_unlock(pte - 1, ptl);
 }
 
-static int try_to_unmap_anon(struct page *page)
+static int try_to_unmap_anon(struct page *page, int ignore_refs)
 {
        struct anon_vma *anon_vma;
        struct vm_area_struct *vma;
@@ -709,7 +742,7 @@ static int try_to_unmap_anon(struct page *page)
                return ret;
 
        list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
-               ret = try_to_unmap_one(page, vma);
+               ret = try_to_unmap_one(page, vma, ignore_refs);
                if (ret == SWAP_FAIL || !page_mapped(page))
                        break;
        }
@@ -726,7 +759,7 @@ static int try_to_unmap_anon(struct page *page)
  *
  * This function is only called from try_to_unmap for object-based pages.
  */
-static int try_to_unmap_file(struct page *page)
+static int try_to_unmap_file(struct page *page, int ignore_refs)
 {
        struct address_space *mapping = page->mapping;
        pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
@@ -740,7 +773,7 @@ static int try_to_unmap_file(struct page *page)
 
        spin_lock(&mapping->i_mmap_lock);
        vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
-               ret = try_to_unmap_one(page, vma);
+               ret = try_to_unmap_one(page, vma, ignore_refs);
                if (ret == SWAP_FAIL || !page_mapped(page))
                        goto out;
        }
@@ -825,16 +858,16 @@ out:
  * SWAP_AGAIN  - we missed a mapping, try again later
  * SWAP_FAIL   - the page is unswappable
  */
-int try_to_unmap(struct page *page)
+int try_to_unmap(struct page *page, int ignore_refs)
 {
        int ret;
 
        BUG_ON(!PageLocked(page));
 
        if (PageAnon(page))
-               ret = try_to_unmap_anon(page);
+               ret = try_to_unmap_anon(page, ignore_refs);
        else
-               ret = try_to_unmap_file(page);
+               ret = try_to_unmap_file(page, ignore_refs);
 
        if (!page_mapped(page))
                ret = SWAP_SUCCESS;
index ce501bc..f7ac7b8 100644 (file)
@@ -1028,6 +1028,14 @@ repeat:
                        page_cache_release(swappage);
                        goto repeat;
                }
+               if (!PageSwapCache(swappage)) {
+                       /* Page migration has occured */
+                       shmem_swp_unmap(entry);
+                       spin_unlock(&info->lock);
+                       unlock_page(swappage);
+                       page_cache_release(swappage);
+                       goto repeat;
+               }
                if (PageWriteback(swappage)) {
                        shmem_swp_unmap(entry);
                        spin_unlock(&info->lock);
index 6f8495e..7137025 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -55,7 +55,7 @@
  *
  * SMP synchronization:
  *  constructors and destructors are called without any locking.
- *  Several members in kmem_cache_t and struct slab never change, they
+ *  Several members in struct kmem_cache and struct slab never change, they
  *     are accessed without any locking.
  *  The per-cpu arrays are never accessed from the wrong cpu, no locking,
  *     and local interrupts are disabled so slab code is preempt-safe.
@@ -244,7 +244,7 @@ struct slab {
  */
 struct slab_rcu {
        struct rcu_head head;
-       kmem_cache_t *cachep;
+       struct kmem_cache *cachep;
        void *addr;
 };
 
@@ -316,6 +316,8 @@ struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
  */
 static __always_inline int index_of(const size_t size)
 {
+       extern void __bad_size(void);
+
        if (__builtin_constant_p(size)) {
                int i = 0;
 
@@ -326,19 +328,16 @@ static __always_inline int index_of(const size_t size)
                i++;
 #include "linux/kmalloc_sizes.h"
 #undef CACHE
-               {
-                       extern void __bad_size(void);
-                       __bad_size();
-               }
+               __bad_size();
        } else
-               BUG();
+               __bad_size();
        return 0;
 }
 
 #define INDEX_AC index_of(sizeof(struct arraycache_init))
 #define INDEX_L3 index_of(sizeof(struct kmem_list3))
 
-static inline void kmem_list3_init(struct kmem_list3 *parent)
+static void kmem_list3_init(struct kmem_list3 *parent)
 {
        INIT_LIST_HEAD(&parent->slabs_full);
        INIT_LIST_HEAD(&parent->slabs_partial);
@@ -364,7 +363,7 @@ static inline void kmem_list3_init(struct kmem_list3 *parent)
        } while (0)
 
 /*
- * kmem_cache_t
+ * struct kmem_cache
  *
  * manages a cache.
  */
@@ -375,7 +374,7 @@ struct kmem_cache {
        unsigned int batchcount;
        unsigned int limit;
        unsigned int shared;
-       unsigned int objsize;
+       unsigned int buffer_size;
 /* 2) touched by every alloc & free from the backend */
        struct kmem_list3 *nodelists[MAX_NUMNODES];
        unsigned int flags;     /* constant flags */
@@ -392,15 +391,15 @@ struct kmem_cache {
        size_t colour;          /* cache colouring range */
        unsigned int colour_off;        /* colour offset */
        unsigned int colour_next;       /* cache colouring */
-       kmem_cache_t *slabp_cache;
+       struct kmem_cache *slabp_cache;
        unsigned int slab_size;
        unsigned int dflags;    /* dynamic flags */
 
        /* constructor func */
-       void (*ctor) (void *, kmem_cache_t *, unsigned long);
+       void (*ctor) (void *, struct kmem_cache *, unsigned long);
 
        /* de-constructor func */
-       void (*dtor) (void *, kmem_cache_t *, unsigned long);
+       void (*dtor) (void *, struct kmem_cache *, unsigned long);
 
 /* 4) cache creation/removal */
        const char *name;
@@ -423,8 +422,14 @@ struct kmem_cache {
        atomic_t freemiss;
 #endif
 #if DEBUG
-       int dbghead;
-       int reallen;
+       /*
+        * If debugging is enabled, then the allocator can add additional
+        * fields and/or padding to every object. buffer_size contains the total
+        * object size including these internal fields, the following two
+        * variables contain the offset to the user object and its size.
+        */
+       int obj_offset;
+       int obj_size;
 #endif
 };
 
@@ -495,50 +500,50 @@ struct kmem_cache {
 
 /* memory layout of objects:
  * 0           : objp
- * 0 .. cachep->dbghead - BYTES_PER_WORD - 1: padding. This ensures that
+ * 0 .. cachep->obj_offset - BYTES_PER_WORD - 1: padding. This ensures that
  *             the end of an object is aligned with the end of the real
  *             allocation. Catches writes behind the end of the allocation.
- * cachep->dbghead - BYTES_PER_WORD .. cachep->dbghead - 1:
+ * cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1:
  *             redzone word.
- * cachep->dbghead: The real object.
- * cachep->objsize - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long]
- * cachep->objsize - 1* BYTES_PER_WORD: last caller address [BYTES_PER_WORD long]
+ * cachep->obj_offset: The real object.
+ * cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long]
+ * cachep->buffer_size - 1* BYTES_PER_WORD: last caller address [BYTES_PER_WORD long]
  */
-static int obj_dbghead(kmem_cache_t *cachep)
+static int obj_offset(struct kmem_cache *cachep)
 {
-       return cachep->dbghead;
+       return cachep->obj_offset;
 }
 
-static int obj_reallen(kmem_cache_t *cachep)
+static int obj_size(struct kmem_cache *cachep)
 {
-       return cachep->reallen;
+       return cachep->obj_size;
 }
 
-static unsigned long *dbg_redzone1(kmem_cache_t *cachep, void *objp)
+static unsigned long *dbg_redzone1(struct kmem_cache *cachep, void *objp)
 {
        BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
-       return (unsigned long*) (objp+obj_dbghead(cachep)-BYTES_PER_WORD);
+       return (unsigned long*) (objp+obj_offset(cachep)-BYTES_PER_WORD);
 }
 
-static unsigned long *dbg_redzone2(kmem_cache_t *cachep, void *objp)
+static unsigned long *dbg_redzone2(struct kmem_cache *cachep, void *objp)
 {
        BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
        if (cachep->flags & SLAB_STORE_USER)
-               return (unsigned long *)(objp + cachep->objsize -
+               return (unsigned long *)(objp + cachep->buffer_size -
                                         2 * BYTES_PER_WORD);
-       return (unsigned long *)(objp + cachep->objsize - BYTES_PER_WORD);
+       return (unsigned long *)(objp + cachep->buffer_size - BYTES_PER_WORD);
 }
 
-static void **dbg_userword(kmem_cache_t *cachep, void *objp)
+static void **dbg_userword(struct kmem_cache *cachep, void *objp)
 {
        BUG_ON(!(cachep->flags & SLAB_STORE_USER));
-       return (void **)(objp + cachep->objsize - BYTES_PER_WORD);
+       return (void **)(objp + cachep->buffer_size - BYTES_PER_WORD);
 }
 
 #else
 
-#define obj_dbghead(x)                 0
-#define obj_reallen(cachep)            (cachep->objsize)
+#define obj_offset(x)                  0
+#define obj_size(cachep)               (cachep->buffer_size)
 #define dbg_redzone1(cachep, objp)     ({BUG(); (unsigned long *)NULL;})
 #define dbg_redzone2(cachep, objp)     ({BUG(); (unsigned long *)NULL;})
 #define dbg_userword(cachep, objp)     ({BUG(); (void **)NULL;})
@@ -591,6 +596,18 @@ static inline struct slab *page_get_slab(struct page *page)
        return (struct slab *)page->lru.prev;
 }
 
+static inline struct kmem_cache *virt_to_cache(const void *obj)
+{
+       struct page *page = virt_to_page(obj);
+       return page_get_cache(page);
+}
+
+static inline struct slab *virt_to_slab(const void *obj)
+{
+       struct page *page = virt_to_page(obj);
+       return page_get_slab(page);
+}
+
 /* These are the default caches for kmalloc. Custom caches can have other sizes. */
 struct cache_sizes malloc_sizes[] = {
 #define CACHE(x) { .cs_size = (x) },
@@ -619,16 +636,16 @@ static struct arraycache_init initarray_generic =
     { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
 
 /* internal cache of cache description objs */
-static kmem_cache_t cache_cache = {
+static struct kmem_cache cache_cache = {
        .batchcount = 1,
        .limit = BOOT_CPUCACHE_ENTRIES,
        .shared = 1,
-       .objsize = sizeof(kmem_cache_t),
+       .buffer_size = sizeof(struct kmem_cache),
        .flags = SLAB_NO_REAP,
        .spinlock = SPIN_LOCK_UNLOCKED,
        .name = "kmem_cache",
 #if DEBUG
-       .reallen = sizeof(kmem_cache_t),
+       .obj_size = sizeof(struct kmem_cache),
 #endif
 };
 
@@ -657,17 +674,17 @@ static enum {
 
 static DEFINE_PER_CPU(struct work_struct, reap_work);
 
-static void free_block(kmem_cache_t *cachep, void **objpp, int len, int node);
-static void enable_cpucache(kmem_cache_t *cachep);
+static void free_block(struct kmem_cache *cachep, void **objpp, int len, int node);
+static void enable_cpucache(struct kmem_cache *cachep);
 static void cache_reap(void *unused);
-static int __node_shrink(kmem_cache_t *cachep, int node);
+static int __node_shrink(struct kmem_cache *cachep, int node);
 
-static inline struct array_cache *ac_data(kmem_cache_t *cachep)
+static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
 {
        return cachep->array[smp_processor_id()];
 }
 
-static inline kmem_cache_t *__find_general_cachep(size_t size, gfp_t gfpflags)
+static inline struct kmem_cache *__find_general_cachep(size_t size, gfp_t gfpflags)
 {
        struct cache_sizes *csizep = malloc_sizes;
 
@@ -691,43 +708,80 @@ static inline kmem_cache_t *__find_general_cachep(size_t size, gfp_t gfpflags)
        return csizep->cs_cachep;
 }
 
-kmem_cache_t *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
+struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
 {
        return __find_general_cachep(size, gfpflags);
 }
 EXPORT_SYMBOL(kmem_find_general_cachep);
 
-/* Cal the num objs, wastage, and bytes left over for a given slab size. */
-static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
-                          int flags, size_t *left_over, unsigned int *num)
+static size_t slab_mgmt_size(size_t nr_objs, size_t align)
 {
-       int i;
-       size_t wastage = PAGE_SIZE << gfporder;
-       size_t extra = 0;
-       size_t base = 0;
+       return ALIGN(sizeof(struct slab)+nr_objs*sizeof(kmem_bufctl_t), align);
+}
 
-       if (!(flags & CFLGS_OFF_SLAB)) {
-               base = sizeof(struct slab);
-               extra = sizeof(kmem_bufctl_t);
-       }
-       i = 0;
-       while (i * size + ALIGN(base + i * extra, align) <= wastage)
-               i++;
-       if (i > 0)
-               i--;
+/* Calculate the number of objects and left-over bytes for a given
+   buffer size. */
+static void cache_estimate(unsigned long gfporder, size_t buffer_size,
+                          size_t align, int flags, size_t *left_over,
+                          unsigned int *num)
+{
+       int nr_objs;
+       size_t mgmt_size;
+       size_t slab_size = PAGE_SIZE << gfporder;
+
+       /*
+        * The slab management structure can be either off the slab or
+        * on it. For the latter case, the memory allocated for a
+        * slab is used for:
+        *
+        * - The struct slab
+        * - One kmem_bufctl_t for each object
+        * - Padding to respect alignment of @align
+        * - @buffer_size bytes for each object
+        *
+        * If the slab management structure is off the slab, then the
+        * alignment will already be calculated into the size. Because
+        * the slabs are all pages aligned, the objects will be at the
+        * correct alignment when allocated.
+        */
+       if (flags & CFLGS_OFF_SLAB) {
+               mgmt_size = 0;
+               nr_objs = slab_size / buffer_size;
 
-       if (i > SLAB_LIMIT)
-               i = SLAB_LIMIT;
+               if (nr_objs > SLAB_LIMIT)
+                       nr_objs = SLAB_LIMIT;
+       } else {
+               /*
+                * Ignore padding for the initial guess. The padding
+                * is at most @align-1 bytes, and @buffer_size is at
+                * least @align. In the worst case, this result will
+                * be one greater than the number of objects that fit
+                * into the memory allocation when taking the padding
+                * into account.
+                */
+               nr_objs = (slab_size - sizeof(struct slab)) /
+                         (buffer_size + sizeof(kmem_bufctl_t));
+
+               /*
+                * This calculated number will be either the right
+                * amount, or one greater than what we want.
+                */
+               if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size
+                      > slab_size)
+                       nr_objs--;
 
-       *num = i;
-       wastage -= i * size;
-       wastage -= ALIGN(base + i * extra, align);
-       *left_over = wastage;
+               if (nr_objs > SLAB_LIMIT)
+                       nr_objs = SLAB_LIMIT;
+
+               mgmt_size = slab_mgmt_size(nr_objs, align);
+       }
+       *num = nr_objs;
+       *left_over = slab_size - nr_objs*buffer_size - mgmt_size;
 }
 
 #define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg)
 
-static void __slab_error(const char *function, kmem_cache_t *cachep, char *msg)
+static void __slab_error(const char *function, struct kmem_cache *cachep, char *msg)
 {
        printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
               function, cachep->name, msg);
@@ -774,9 +828,9 @@ static struct array_cache *alloc_arraycache(int node, int entries,
 }
 
 #ifdef CONFIG_NUMA
-static void *__cache_alloc_node(kmem_cache_t *, gfp_t, int);
+static void *__cache_alloc_node(struct kmem_cache *, gfp_t, int);
 
-static inline struct array_cache **alloc_alien_cache(int node, int limit)
+static struct array_cache **alloc_alien_cache(int node, int limit)
 {
        struct array_cache **ac_ptr;
        int memsize = sizeof(void *) * MAX_NUMNODES;
@@ -803,7 +857,7 @@ static inline struct array_cache **alloc_alien_cache(int node, int limit)
        return ac_ptr;
 }
 
-static inline void free_alien_cache(struct array_cache **ac_ptr)
+static void free_alien_cache(struct array_cache **ac_ptr)
 {
        int i;
 
@@ -816,8 +870,8 @@ static inline void free_alien_cache(struct array_cache **ac_ptr)
        kfree(ac_ptr);
 }
 
-static inline void __drain_alien_cache(kmem_cache_t *cachep,
-                                      struct array_cache *ac, int node)
+static void __drain_alien_cache(struct kmem_cache *cachep,
+                               struct array_cache *ac, int node)
 {
        struct kmem_list3 *rl3 = cachep->nodelists[node];
 
@@ -829,7 +883,7 @@ static inline void __drain_alien_cache(kmem_cache_t *cachep,
        }
 }
 
-static void drain_alien_cache(kmem_cache_t *cachep, struct kmem_list3 *l3)
+static void drain_alien_cache(struct kmem_cache *cachep, struct kmem_list3 *l3)
 {
        int i = 0;
        struct array_cache *ac;
@@ -854,7 +908,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
                                    unsigned long action, void *hcpu)
 {
        long cpu = (long)hcpu;
-       kmem_cache_t *cachep;
+       struct kmem_cache *cachep;
        struct kmem_list3 *l3 = NULL;
        int node = cpu_to_node(cpu);
        int memsize = sizeof(struct kmem_list3);
@@ -992,7 +1046,7 @@ static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 };
 /*
  * swap the static kmem_list3 with kmalloced memory
  */
-static void init_list(kmem_cache_t *cachep, struct kmem_list3 *list, int nodeid)
+static void init_list(struct kmem_cache *cachep, struct kmem_list3 *list, int nodeid)
 {
        struct kmem_list3 *ptr;
 
@@ -1032,14 +1086,14 @@ void __init kmem_cache_init(void)
 
        /* Bootstrap is tricky, because several objects are allocated
         * from caches that do not exist yet:
-        * 1) initialize the cache_cache cache: it contains the kmem_cache_t
+        * 1) initialize the cache_cache cache: it contains the struct kmem_cache
         *    structures of all caches, except cache_cache itself: cache_cache
         *    is statically allocated.
         *    Initially an __init data area is used for the head array and the
         *    kmem_list3 structures, it's replaced with a kmalloc allocated
         *    array at the end of the bootstrap.
         * 2) Create the first kmalloc cache.
-        *    The kmem_cache_t for the new cache is allocated normally.
+        *    The struct kmem_cache for the new cache is allocated normally.
         *    An __init data area is used for the head array.
         * 3) Create the remaining kmalloc caches, with minimally sized
         *    head arrays.
@@ -1057,9 +1111,9 @@ void __init kmem_cache_init(void)
        cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
        cache_cache.nodelists[numa_node_id()] = &initkmem_list3[CACHE_CACHE];
 
-       cache_cache.objsize = ALIGN(cache_cache.objsize, cache_line_size());
+       cache_cache.buffer_size = ALIGN(cache_cache.buffer_size, cache_line_size());
 
-       cache_estimate(0, cache_cache.objsize, cache_line_size(), 0,
+       cache_estimate(0, cache_cache.buffer_size, cache_line_size(), 0,
                       &left_over, &cache_cache.num);
        if (!cache_cache.num)
                BUG();
@@ -1132,8 +1186,8 @@ void __init kmem_cache_init(void)
                ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
 
                local_irq_disable();
-               BUG_ON(ac_data(&cache_cache) != &initarray_cache.cache);
-               memcpy(ptr, ac_data(&cache_cache),
+               BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
+               memcpy(ptr, cpu_cache_get(&cache_cache),
                       sizeof(struct arraycache_init));
                cache_cache.array[smp_processor_id()] = ptr;
                local_irq_enable();
@@ -1141,9 +1195,9 @@ void __init kmem_cache_init(void)
                ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
 
                local_irq_disable();
-               BUG_ON(ac_data(malloc_sizes[INDEX_AC].cs_cachep)
+               BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)
                       != &initarray_generic.cache);
-               memcpy(ptr, ac_data(malloc_sizes[INDEX_AC].cs_cachep),
+               memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
                       sizeof(struct arraycache_init));
                malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
                    ptr;
@@ -1170,7 +1224,7 @@ void __init kmem_cache_init(void)
 
        /* 6) resize the head arrays to their final sizes */
        {
-               kmem_cache_t *cachep;
+               struct kmem_cache *cachep;
                mutex_lock(&cache_chain_mutex);
                list_for_each_entry(cachep, &cache_chain, next)
                    enable_cpucache(cachep);
@@ -1181,7 +1235,7 @@ void __init kmem_cache_init(void)
        g_cpucache_up = FULL;
 
        /* Register a cpu startup notifier callback
-        * that initializes ac_data for all new cpus
+        * that initializes cpu_cache_get for all new cpus
         */
        register_cpu_notifier(&cpucache_notifier);
 
@@ -1213,7 +1267,7 @@ __initcall(cpucache_init);
  * did not request dmaable memory, we might get it, but that
  * would be relatively rare and ignorable.
  */
-static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid)
+static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
        struct page *page;
        void *addr;
@@ -1239,7 +1293,7 @@ static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid)
 /*
  * Interface to system's page release.
  */
-static void kmem_freepages(kmem_cache_t *cachep, void *addr)
+static void kmem_freepages(struct kmem_cache *cachep, void *addr)
 {
        unsigned long i = (1 << cachep->gfporder);
        struct page *page = virt_to_page(addr);
@@ -1261,7 +1315,7 @@ static void kmem_freepages(kmem_cache_t *cachep, void *addr)
 static void kmem_rcu_free(struct rcu_head *head)
 {
        struct slab_rcu *slab_rcu = (struct slab_rcu *)head;
-       kmem_cache_t *cachep = slab_rcu->cachep;
+       struct kmem_cache *cachep = slab_rcu->cachep;
 
        kmem_freepages(cachep, slab_rcu->addr);
        if (OFF_SLAB(cachep))
@@ -1271,12 +1325,12 @@ static void kmem_rcu_free(struct rcu_head *head)
 #if DEBUG
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
-static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr,
+static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr,
                            unsigned long caller)
 {
-       int size = obj_reallen(cachep);
+       int size = obj_size(cachep);
 
-       addr = (unsigned long *)&((char *)addr)[obj_dbghead(cachep)];
+       addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)];
 
        if (size < 5 * sizeof(unsigned long))
                return;
@@ -1304,10 +1358,10 @@ static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr,
 }
 #endif
 
-static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
+static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val)
 {
-       int size = obj_reallen(cachep);
-       addr = &((char *)addr)[obj_dbghead(cachep)];
+       int size = obj_size(cachep);
+       addr = &((char *)addr)[obj_offset(cachep)];
 
        memset(addr, val, size);
        *(unsigned char *)(addr + size - 1) = POISON_END;
@@ -1326,7 +1380,7 @@ static void dump_line(char *data, int offset, int limit)
 
 #if DEBUG
 
-static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
+static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines)
 {
        int i, size;
        char *realobj;
@@ -1344,8 +1398,8 @@ static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
                             (unsigned long)*dbg_userword(cachep, objp));
                printk("\n");
        }
-       realobj = (char *)objp + obj_dbghead(cachep);
-       size = obj_reallen(cachep);
+       realobj = (char *)objp + obj_offset(cachep);
+       size = obj_size(cachep);
        for (i = 0; i < size && lines; i += 16, lines--) {
                int limit;
                limit = 16;
@@ -1355,14 +1409,14 @@ static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
        }
 }
 
-static void check_poison_obj(kmem_cache_t *cachep, void *objp)
+static void check_poison_obj(struct kmem_cache *cachep, void *objp)
 {
        char *realobj;
        int size, i;
        int lines = 0;
 
-       realobj = (char *)objp + obj_dbghead(cachep);
-       size = obj_reallen(cachep);
+       realobj = (char *)objp + obj_offset(cachep);
+       size = obj_size(cachep);
 
        for (i = 0; i < size; i++) {
                char exp = POISON_FREE;
@@ -1395,20 +1449,20 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp)
                /* Print some data about the neighboring objects, if they
                 * exist:
                 */
-               struct slab *slabp = page_get_slab(virt_to_page(objp));
+               struct slab *slabp = virt_to_slab(objp);
                int objnr;
 
-               objnr = (objp - slabp->s_mem) / cachep->objsize;
+               objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size;
                if (objnr) {
-                       objp = slabp->s_mem + (objnr - 1) * cachep->objsize;
-                       realobj = (char *)objp + obj_dbghead(cachep);
+                       objp = slabp->s_mem + (objnr - 1) * cachep->buffer_size;
+                       realobj = (char *)objp + obj_offset(cachep);
                        printk(KERN_ERR "Prev obj: start=%p, len=%d\n",
                               realobj, size);
                        print_objinfo(cachep, objp, 2);
                }
                if (objnr + 1 < cachep->num) {
-                       objp = slabp->s_mem + (objnr + 1) * cachep->objsize;
-                       realobj = (char *)objp + obj_dbghead(cachep);
+                       objp = slabp->s_mem + (objnr + 1) * cachep->buffer_size;
+                       realobj = (char *)objp + obj_offset(cachep);
                        printk(KERN_ERR "Next obj: start=%p, len=%d\n",
                               realobj, size);
                        print_objinfo(cachep, objp, 2);
@@ -1417,25 +1471,23 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp)
 }
 #endif
 
-/* Destroy all the objs in a slab, and release the mem back to the system.
- * Before calling the slab must have been unlinked from the cache.
- * The cache-lock is not held/needed.
+#if DEBUG
+/**
+ * slab_destroy_objs - call the registered destructor for each object in
+ *      a slab that is to be destroyed.
  */
-static void slab_destroy(kmem_cache_t *cachep, struct slab *slabp)
+static void slab_destroy_objs(struct kmem_cache *cachep, struct slab *slabp)
 {
-       void *addr = slabp->s_mem - slabp->colouroff;
-
-#if DEBUG
        int i;
        for (i = 0; i < cachep->num; i++) {
-               void *objp = slabp->s_mem + cachep->objsize * i;
+               void *objp = slabp->s_mem + cachep->buffer_size * i;
 
                if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-                       if ((cachep->objsize % PAGE_SIZE) == 0
+                       if ((cachep->buffer_size % PAGE_SIZE) == 0
                            && OFF_SLAB(cachep))
                                kernel_map_pages(virt_to_page(objp),
-                                                cachep->objsize / PAGE_SIZE,
+                                                cachep->buffer_size / PAGE_SIZE,
                                                 1);
                        else
                                check_poison_obj(cachep, objp);
@@ -1452,18 +1504,32 @@ static void slab_destroy(kmem_cache_t *cachep, struct slab *slabp)
                                           "was overwritten");
                }
                if (cachep->dtor && !(cachep->flags & SLAB_POISON))
-                       (cachep->dtor) (objp + obj_dbghead(cachep), cachep, 0);
+                       (cachep->dtor) (objp + obj_offset(cachep), cachep, 0);
        }
+}
 #else
+static void slab_destroy_objs(struct kmem_cache *cachep, struct slab *slabp)
+{
        if (cachep->dtor) {
                int i;
                for (i = 0; i < cachep->num; i++) {
-                       void *objp = slabp->s_mem + cachep->objsize * i;
+                       void *objp = slabp->s_mem + cachep->buffer_size * i;
                        (cachep->dtor) (objp, cachep, 0);
                }
        }
+}
 #endif
 
+/**
+ * Destroy all the objs in a slab, and release the mem back to the system.
+ * Before calling the slab must have been unlinked from the cache.
+ * The cache-lock is not held/needed.
+ */
+static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
+{
+       void *addr = slabp->s_mem - slabp->colouroff;
+
+       slab_destroy_objs(cachep, slabp);
        if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) {
                struct slab_rcu *slab_rcu;
 
@@ -1478,9 +1544,9 @@ static void slab_destroy(kmem_cache_t *cachep, struct slab *slabp)
        }
 }
 
-/* For setting up all the kmem_list3s for cache whose objsize is same
+/* For setting up all the kmem_list3s for cache whose buffer_size is same
    as size of kmem_list3. */
-static inline void set_up_list3s(kmem_cache_t *cachep, int index)
+static void set_up_list3s(struct kmem_cache *cachep, int index)
 {
        int node;
 
@@ -1493,15 +1559,20 @@ static inline void set_up_list3s(kmem_cache_t *cachep, int index)
 }
 
 /**
- * calculate_slab_order - calculate size (page order) of slabs and the number
- *                        of objects per slab.
+ * calculate_slab_order - calculate size (page order) of slabs
+ * @cachep: pointer to the cache that is being created
+ * @size: size of objects to be created in this cache.
+ * @align: required alignment for the objects.
+ * @flags: slab allocation flags
+ *
+ * Also calculates the number of objects per slab.
  *
  * This could be made much more intelligent.  For now, try to avoid using
  * high order pages for slabs.  When the gfp() functions are more friendly
  * towards high-order requests, this should be changed.
  */
-static inline size_t calculate_slab_order(kmem_cache_t *cachep, size_t size,
-                                         size_t align, gfp_t flags)
+static inline size_t calculate_slab_order(struct kmem_cache *cachep,
+                       size_t size, size_t align, unsigned long flags)
 {
        size_t left_over = 0;
 
@@ -1572,13 +1643,13 @@ static inline size_t calculate_slab_order(kmem_cache_t *cachep, size_t size,
  * cacheline.  This can be beneficial if you're counting cycles as closely
  * as davem.
  */
-kmem_cache_t *
+struct kmem_cache *
 kmem_cache_create (const char *name, size_t size, size_t align,
-       unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long),
-       void (*dtor)(void*, kmem_cache_t *, unsigned long))
+       unsigned long flags, void (*ctor)(void*, struct kmem_cache *, unsigned long),
+       void (*dtor)(void*, struct kmem_cache *, unsigned long))
 {
        size_t left_over, slab_size, ralign;
-       kmem_cache_t *cachep = NULL;
+       struct kmem_cache *cachep = NULL;
        struct list_head *p;
 
        /*
@@ -1596,7 +1667,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        mutex_lock(&cache_chain_mutex);
 
        list_for_each(p, &cache_chain) {
-               kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
+               struct kmem_cache *pc = list_entry(p, struct kmem_cache, next);
                mm_segment_t old_fs = get_fs();
                char tmp;
                int res;
@@ -1611,7 +1682,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                set_fs(old_fs);
                if (res) {
                        printk("SLAB: cache with size %d has lost its name\n",
-                              pc->objsize);
+                              pc->buffer_size);
                        continue;
                }
 
@@ -1696,20 +1767,20 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        align = ralign;
 
        /* Get cache's description obj. */
-       cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
+       cachep = kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
        if (!cachep)
                goto oops;
-       memset(cachep, 0, sizeof(kmem_cache_t));
+       memset(cachep, 0, sizeof(struct kmem_cache));
 
 #if DEBUG
-       cachep->reallen = size;
+       cachep->obj_size = size;
 
        if (flags & SLAB_RED_ZONE) {
                /* redzoning only works with word aligned caches */
                align = BYTES_PER_WORD;
 
                /* add space for red zone words */
-               cachep->dbghead += BYTES_PER_WORD;
+               cachep->obj_offset += BYTES_PER_WORD;
                size += 2 * BYTES_PER_WORD;
        }
        if (flags & SLAB_STORE_USER) {
@@ -1722,8 +1793,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        }
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
        if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
-           && cachep->reallen > cache_line_size() && size < PAGE_SIZE) {
-               cachep->dbghead += PAGE_SIZE - size;
+           && cachep->obj_size > cache_line_size() && size < PAGE_SIZE) {
+               cachep->obj_offset += PAGE_SIZE - size;
                size = PAGE_SIZE;
        }
 #endif
@@ -1786,7 +1857,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        if (flags & SLAB_CACHE_DMA)
                cachep->gfpflags |= GFP_DMA;
        spin_lock_init(&cachep->spinlock);
-       cachep->objsize = size;
+       cachep->buffer_size = size;
 
        if (flags & CFLGS_OFF_SLAB)
                cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
@@ -1843,11 +1914,11 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                    jiffies + REAPTIMEOUT_LIST3 +
                    ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
 
-               BUG_ON(!ac_data(cachep));
-               ac_data(cachep)->avail = 0;
-               ac_data(cachep)->limit = BOOT_CPUCACHE_ENTRIES;
-               ac_data(cachep)->batchcount = 1;
-               ac_data(cachep)->touched = 0;
+               BUG_ON(!cpu_cache_get(cachep));
+               cpu_cache_get(cachep)->avail = 0;
+               cpu_cache_get(cachep)->limit = BOOT_CPUCACHE_ENTRIES;
+               cpu_cache_get(cachep)->batchcount = 1;
+               cpu_cache_get(cachep)->touched = 0;
                cachep->batchcount = 1;
                cachep->limit = BOOT_CPUCACHE_ENTRIES;
        }
@@ -1875,7 +1946,7 @@ static void check_irq_on(void)
        BUG_ON(irqs_disabled());
 }
 
-static void check_spinlock_acquired(kmem_cache_t *cachep)
+static void check_spinlock_acquired(struct kmem_cache *cachep)
 {
 #ifdef CONFIG_SMP
        check_irq_off();
@@ -1883,7 +1954,7 @@ static void check_spinlock_acquired(kmem_cache_t *cachep)
 #endif
 }
 
-static inline void check_spinlock_acquired_node(kmem_cache_t *cachep, int node)
+static void check_spinlock_acquired_node(struct kmem_cache *cachep, int node)
 {
 #ifdef CONFIG_SMP
        check_irq_off();
@@ -1916,24 +1987,24 @@ static void smp_call_function_all_cpus(void (*func)(void *arg), void *arg)
        preempt_enable();
 }
 
-static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac,
+static void drain_array_locked(struct kmem_cache *cachep, struct array_cache *ac,
                                int force, int node);
 
 static void do_drain(void *arg)
 {
-       kmem_cache_t *cachep = (kmem_cache_t *) arg;
+       struct kmem_cache *cachep = (struct kmem_cache *) arg;
        struct array_cache *ac;
        int node = numa_node_id();
 
        check_irq_off();
-       ac = ac_data(cachep);
+       ac = cpu_cache_get(cachep);
        spin_lock(&cachep->nodelists[node]->list_lock);
        free_block(cachep, ac->entry, ac->avail, node);
        spin_unlock(&cachep->nodelists[node]->list_lock);
        ac->avail = 0;
 }
 
-static void drain_cpu_caches(kmem_cache_t *cachep)
+static void drain_cpu_caches(struct kmem_cache *cachep)
 {
        struct kmem_list3 *l3;
        int node;
@@ -1954,7 +2025,7 @@ static void drain_cpu_caches(kmem_cache_t *cachep)
        spin_unlock_irq(&cachep->spinlock);
 }
 
-static int __node_shrink(kmem_cache_t *cachep, int node)
+static int __node_shrink(struct kmem_cache *cachep, int node)
 {
        struct slab *slabp;
        struct kmem_list3 *l3 = cachep->nodelists[node];
@@ -1983,7 +2054,7 @@ static int __node_shrink(kmem_cache_t *cachep, int node)
        return ret;
 }
 
-static int __cache_shrink(kmem_cache_t *cachep)
+static int __cache_shrink(struct kmem_cache *cachep)
 {
        int ret = 0, i = 0;
        struct kmem_list3 *l3;
@@ -2009,7 +2080,7 @@ static int __cache_shrink(kmem_cache_t *cachep)
  * Releases as many slabs as possible for a cache.
  * To help debugging, a zero exit status indicates all slabs were released.
  */
-int kmem_cache_shrink(kmem_cache_t *cachep)
+int kmem_cache_shrink(struct kmem_cache *cachep)
 {
        if (!cachep || in_interrupt())
                BUG();
@@ -2022,7 +2093,7 @@ EXPORT_SYMBOL(kmem_cache_shrink);
  * kmem_cache_destroy - delete a cache
  * @cachep: the cache to destroy
  *
- * Remove a kmem_cache_t object from the slab cache.
+ * Remove a struct kmem_cache object from the slab cache.
  * Returns 0 on success.
  *
  * It is expected this function will be called by a module when it is
@@ -2035,7 +2106,7 @@ EXPORT_SYMBOL(kmem_cache_shrink);
  * The caller must guarantee that noone will allocate memory from the cache
  * during the kmem_cache_destroy().
  */
-int kmem_cache_destroy(kmem_cache_t *cachep)
+int kmem_cache_destroy(struct kmem_cache *cachep)
 {
        int i;
        struct kmem_list3 *l3;
@@ -2086,7 +2157,7 @@ int kmem_cache_destroy(kmem_cache_t *cachep)
 EXPORT_SYMBOL(kmem_cache_destroy);
 
 /* Get the memory for a slab management obj. */
-static struct slab *alloc_slabmgmt(kmem_cache_t *cachep, void *objp,
+static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
                                   int colour_off, gfp_t local_flags)
 {
        struct slab *slabp;
@@ -2112,13 +2183,13 @@ static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)
        return (kmem_bufctl_t *) (slabp + 1);
 }
 
-static void cache_init_objs(kmem_cache_t *cachep,
+static void cache_init_objs(struct kmem_cache *cachep,
                            struct slab *slabp, unsigned long ctor_flags)
 {
        int i;
 
        for (i = 0; i < cachep->num; i++) {
-               void *objp = slabp->s_mem + cachep->objsize * i;
+               void *objp = slabp->s_mem + cachep->buffer_size * i;
 #if DEBUG
                /* need to poison the objs? */
                if (cachep->flags & SLAB_POISON)
@@ -2136,7 +2207,7 @@ static void cache_init_objs(kmem_cache_t *cachep,
                 * Otherwise, deadlock. They must also be threaded.
                 */
                if (cachep->ctor && !(cachep->flags & SLAB_POISON))
-                       cachep->ctor(objp + obj_dbghead(cachep), cachep,
+                       cachep->ctor(objp + obj_offset(cachep), cachep,
                                     ctor_flags);
 
                if (cachep->flags & SLAB_RED_ZONE) {
@@ -2147,10 +2218,10 @@ static void cache_init_objs(kmem_cache_t *cachep,
                                slab_error(cachep, "constructor overwrote the"
                                           " start of an object");
                }
-               if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)
+               if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)
                    && cachep->flags & SLAB_POISON)
                        kernel_map_pages(virt_to_page(objp),
-                                        cachep->objsize / PAGE_SIZE, 0);
+                                        cachep->buffer_size / PAGE_SIZE, 0);
 #else
                if (cachep->ctor)
                        cachep->ctor(objp, cachep, ctor_flags);
@@ -2161,7 +2232,7 @@ static void cache_init_objs(kmem_cache_t *cachep,
        slabp->free = 0;
 }
 
-static void kmem_flagcheck(kmem_cache_t *cachep, gfp_t flags)
+static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
 {
        if (flags & SLAB_DMA) {
                if (!(cachep->gfpflags & GFP_DMA))
@@ -2172,7 +2243,43 @@ static void kmem_flagcheck(kmem_cache_t *cachep, gfp_t flags)
        }
 }
 
-static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)
+static void *slab_get_obj(struct kmem_cache *cachep, struct slab *slabp, int nodeid)
+{
+       void *objp = slabp->s_mem + (slabp->free * cachep->buffer_size);
+       kmem_bufctl_t next;
+
+       slabp->inuse++;
+       next = slab_bufctl(slabp)[slabp->free];
+#if DEBUG
+       slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
+       WARN_ON(slabp->nodeid != nodeid);
+#endif
+       slabp->free = next;
+
+       return objp;
+}
+
+static void slab_put_obj(struct kmem_cache *cachep, struct slab *slabp, void *objp,
+                         int nodeid)
+{
+       unsigned int objnr = (unsigned)(objp-slabp->s_mem) / cachep->buffer_size;
+
+#if DEBUG
+       /* Verify that the slab belongs to the intended node */
+       WARN_ON(slabp->nodeid != nodeid);
+
+       if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
+               printk(KERN_ERR "slab: double free detected in cache "
+                      "'%s', objp %p\n", cachep->name, objp);
+               BUG();
+       }
+#endif
+       slab_bufctl(slabp)[objnr] = slabp->free;
+       slabp->free = objnr;
+       slabp->inuse--;
+}
+
+static void set_slab_attr(struct kmem_cache *cachep, struct slab *slabp, void *objp)
 {
        int i;
        struct page *page;
@@ -2191,7 +2298,7 @@ static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)
  * Grow (by 1) the number of slabs within a cache.  This is called by
  * kmem_cache_alloc() when there are no active objs left in a cache.
  */
-static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid)
+static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
        struct slab *slabp;
        void *objp;
@@ -2302,14 +2409,14 @@ static void kfree_debugcheck(const void *objp)
        }
 }
 
-static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp,
+static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
                                   void *caller)
 {
        struct page *page;
        unsigned int objnr;
        struct slab *slabp;
 
-       objp -= obj_dbghead(cachep);
+       objp -= obj_offset(cachep);
        kfree_debugcheck(objp);
        page = virt_to_page(objp);
 
@@ -2341,31 +2448,31 @@ static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp,
        if (cachep->flags & SLAB_STORE_USER)
                *dbg_userword(cachep, objp) = caller;
 
-       objnr = (objp - slabp->s_mem) / cachep->objsize;
+       objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size;
 
        BUG_ON(objnr >= cachep->num);
-       BUG_ON(objp != slabp->s_mem + objnr * cachep->objsize);
+       BUG_ON(objp != slabp->s_mem + objnr * cachep->buffer_size);
 
        if (cachep->flags & SLAB_DEBUG_INITIAL) {
                /* Need to call the slab's constructor so the
                 * caller can perform a verify of its state (debugging).
                 * Called without the cache-lock held.
                 */
-               cachep->ctor(objp + obj_dbghead(cachep),
+               cachep->ctor(objp + obj_offset(cachep),
                             cachep, SLAB_CTOR_CONSTRUCTOR | SLAB_CTOR_VERIFY);
        }
        if (cachep->flags & SLAB_POISON && cachep->dtor) {
                /* we want to cache poison the object,
                 * call the destruction callback
                 */
-               cachep->dtor(objp + obj_dbghead(cachep), cachep, 0);
+               cachep->dtor(objp + obj_offset(cachep), cachep, 0);
        }
        if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-               if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
+               if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
                        store_stackinfo(cachep, objp, (unsigned long)caller);
                        kernel_map_pages(virt_to_page(objp),
-                                        cachep->objsize / PAGE_SIZE, 0);
+                                        cachep->buffer_size / PAGE_SIZE, 0);
                } else {
                        poison_obj(cachep, objp, POISON_FREE);
                }
@@ -2376,7 +2483,7 @@ static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp,
        return objp;
 }
 
-static void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
+static void check_slabp(struct kmem_cache *cachep, struct slab *slabp)
 {
        kmem_bufctl_t i;
        int entries = 0;
@@ -2409,14 +2516,14 @@ static void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
 #define check_slabp(x,y) do { } while(0)
 #endif
 
-static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags)
+static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
 {
        int batchcount;
        struct kmem_list3 *l3;
        struct array_cache *ac;
 
        check_irq_off();
-       ac = ac_data(cachep);
+       ac = cpu_cache_get(cachep);
       retry:
        batchcount = ac->batchcount;
        if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
@@ -2461,22 +2568,12 @@ static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags)
                check_slabp(cachep, slabp);
                check_spinlock_acquired(cachep);
                while (slabp->inuse < cachep->num && batchcount--) {
-                       kmem_bufctl_t next;
                        STATS_INC_ALLOCED(cachep);
                        STATS_INC_ACTIVE(cachep);
                        STATS_SET_HIGH(cachep);
 
-                       /* get obj pointer */
-                       ac->entry[ac->avail++] = slabp->s_mem +
-                           slabp->free * cachep->objsize;
-
-                       slabp->inuse++;
-                       next = slab_bufctl(slabp)[slabp->free];
-#if DEBUG
-                       slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
-                       WARN_ON(numa_node_id() != slabp->nodeid);
-#endif
-                       slabp->free = next;
+                       ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
+                                                           numa_node_id());
                }
                check_slabp(cachep, slabp);
 
@@ -2498,7 +2595,7 @@ static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags)
                x = cache_grow(cachep, flags, numa_node_id());
 
                // cache_grow can reenable interrupts, then ac could change.
-               ac = ac_data(cachep);
+               ac = cpu_cache_get(cachep);
                if (!x && ac->avail == 0)       // no objects in sight? abort
                        return NULL;
 
@@ -2510,7 +2607,7 @@ static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags)
 }
 
 static inline void
-cache_alloc_debugcheck_before(kmem_cache_t *cachep, gfp_t flags)
+cache_alloc_debugcheck_before(struct kmem_cache *cachep, gfp_t flags)
 {
        might_sleep_if(flags & __GFP_WAIT);
 #if DEBUG
@@ -2519,16 +2616,16 @@ cache_alloc_debugcheck_before(kmem_cache_t *cachep, gfp_t flags)
 }
 
 #if DEBUG
-static void *cache_alloc_debugcheck_after(kmem_cache_t *cachep, gfp_t flags,
+static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, gfp_t flags,
                                        void *objp, void *caller)
 {
        if (!objp)
                return objp;
        if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-               if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
+               if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
                        kernel_map_pages(virt_to_page(objp),
-                                        cachep->objsize / PAGE_SIZE, 1);
+                                        cachep->buffer_size / PAGE_SIZE, 1);
                else
                        check_poison_obj(cachep, objp);
 #else
@@ -2553,7 +2650,7 @@ static void *cache_alloc_debugcheck_after(kmem_cache_t *cachep, gfp_t flags,
                *dbg_redzone1(cachep, objp) = RED_ACTIVE;
                *dbg_redzone2(cachep, objp) = RED_ACTIVE;
        }
-       objp += obj_dbghead(cachep);
+       objp += obj_offset(cachep);
        if (cachep->ctor && cachep->flags & SLAB_POISON) {
                unsigned long ctor_flags = SLAB_CTOR_CONSTRUCTOR;
 
@@ -2568,7 +2665,7 @@ static void *cache_alloc_debugcheck_after(kmem_cache_t *cachep, gfp_t flags,
 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
 #endif
 
-static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags)
+static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
        void *objp;
        struct array_cache *ac;
@@ -2583,7 +2680,7 @@ static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags)
 #endif
 
        check_irq_off();
-       ac = ac_data(cachep);
+       ac = cpu_cache_get(cachep);
        if (likely(ac->avail)) {
                STATS_INC_ALLOCHIT(cachep);
                ac->touched = 1;
@@ -2595,7 +2692,8 @@ static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags)
        return objp;
 }
 
-static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags)
+static __always_inline void *
+__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
 {
        unsigned long save_flags;
        void *objp;
@@ -2606,7 +2704,7 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags)
        objp = ____cache_alloc(cachep, flags);
        local_irq_restore(save_flags);
        objp = cache_alloc_debugcheck_after(cachep, flags, objp,
-                                           __builtin_return_address(0));
+                                           caller);
        prefetchw(objp);
        return objp;
 }
@@ -2615,13 +2713,12 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags)
 /*
  * A interface to enable slab creation on nodeid
  */
-static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
+static void *__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
        struct list_head *entry;
        struct slab *slabp;
        struct kmem_list3 *l3;
        void *obj;
-       kmem_bufctl_t next;
        int x;
 
        l3 = cachep->nodelists[nodeid];
@@ -2647,14 +2744,7 @@ static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
 
        BUG_ON(slabp->inuse == cachep->num);
 
-       /* get obj pointer */
-       obj = slabp->s_mem + slabp->free * cachep->objsize;
-       slabp->inuse++;
-       next = slab_bufctl(slabp)[slabp->free];
-#if DEBUG
-       slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
-#endif
-       slabp->free = next;
+       obj = slab_get_obj(cachep, slabp, nodeid);
        check_slabp(cachep, slabp);
        l3->free_objects--;
        /* move slabp to correct slabp list: */
@@ -2685,7 +2775,7 @@ static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
 /*
  * Caller needs to acquire correct kmem_list's list_lock
  */
-static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects,
+static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
                       int node)
 {
        int i;
@@ -2694,29 +2784,14 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects,
        for (i = 0; i < nr_objects; i++) {
                void *objp = objpp[i];
                struct slab *slabp;
-               unsigned int objnr;
 
-               slabp = page_get_slab(virt_to_page(objp));
+               slabp = virt_to_slab(objp);
                l3 = cachep->nodelists[node];
                list_del(&slabp->list);
-               objnr = (objp - slabp->s_mem) / cachep->objsize;
                check_spinlock_acquired_node(cachep, node);
                check_slabp(cachep, slabp);
-
-#if DEBUG
-               /* Verify that the slab belongs to the intended node */
-               WARN_ON(slabp->nodeid != node);
-
-               if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
-                       printk(KERN_ERR "slab: double free detected in cache "
-                              "'%s', objp %p\n", cachep->name, objp);
-                       BUG();
-               }
-#endif
-               slab_bufctl(slabp)[objnr] = slabp->free;
-               slabp->free = objnr;
+               slab_put_obj(cachep, slabp, objp, node);
                STATS_DEC_ACTIVE(cachep);
-               slabp->inuse--;
                l3->free_objects++;
                check_slabp(cachep, slabp);
 
@@ -2738,7 +2813,7 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects,
        }
 }
 
-static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
+static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
 {
        int batchcount;
        struct kmem_list3 *l3;
@@ -2797,9 +2872,9 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
  *
  * Called with disabled ints.
  */
-static inline void __cache_free(kmem_cache_t *cachep, void *objp)
+static inline void __cache_free(struct kmem_cache *cachep, void *objp)
 {
-       struct array_cache *ac = ac_data(cachep);
+       struct array_cache *ac = cpu_cache_get(cachep);
 
        check_irq_off();
        objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
@@ -2810,7 +2885,7 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp)
 #ifdef CONFIG_NUMA
        {
                struct slab *slabp;
-               slabp = page_get_slab(virt_to_page(objp));
+               slabp = virt_to_slab(objp);
                if (unlikely(slabp->nodeid != numa_node_id())) {
                        struct array_cache *alien = NULL;
                        int nodeid = slabp->nodeid;
@@ -2856,9 +2931,9 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp)
  * Allocate an object from this cache.  The flags are only relevant
  * if the cache has no available objects.
  */
-void *kmem_cache_alloc(kmem_cache_t *cachep, gfp_t flags)
+void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
-       return __cache_alloc(cachep, flags);
+       return __cache_alloc(cachep, flags, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(kmem_cache_alloc);
 
@@ -2876,12 +2951,12 @@ EXPORT_SYMBOL(kmem_cache_alloc);
  *
  * Currently only used for dentry validation.
  */
-int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr)
+int fastcall kmem_ptr_validate(struct kmem_cache *cachep, void *ptr)
 {
        unsigned long addr = (unsigned long)ptr;
        unsigned long min_addr = PAGE_OFFSET;
        unsigned long align_mask = BYTES_PER_WORD - 1;
-       unsigned long size = cachep->objsize;
+       unsigned long size = cachep->buffer_size;
        struct page *page;
 
        if (unlikely(addr < min_addr))
@@ -2917,32 +2992,23 @@ int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr)
  * New and improved: it will now make sure that the object gets
  * put on the correct node list so that there is no false sharing.
  */
-void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
+void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
        unsigned long save_flags;
        void *ptr;
 
-       if (nodeid == -1)
-               return __cache_alloc(cachep, flags);
-
-       if (unlikely(!cachep->nodelists[nodeid])) {
-               /* Fall back to __cache_alloc if we run into trouble */
-               printk(KERN_WARNING
-                      "slab: not allocating in inactive node %d for cache %s\n",
-                      nodeid, cachep->name);
-               return __cache_alloc(cachep, flags);
-       }
-
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
-       if (nodeid == numa_node_id())
+
+       if (nodeid == -1 || nodeid == numa_node_id() ||
+           !cachep->nodelists[nodeid])
                ptr = ____cache_alloc(cachep, flags);
        else
                ptr = __cache_alloc_node(cachep, flags, nodeid);
        local_irq_restore(save_flags);
-       ptr =
-           cache_alloc_debugcheck_after(cachep, flags, ptr,
-                                        __builtin_return_address(0));
+
+       ptr = cache_alloc_debugcheck_after(cachep, flags, ptr,
+                                          __builtin_return_address(0));
 
        return ptr;
 }
@@ -2950,7 +3016,7 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
 
 void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
-       kmem_cache_t *cachep;
+       struct kmem_cache *cachep;
 
        cachep = kmem_find_general_cachep(size, flags);
        if (unlikely(cachep == NULL))
@@ -2981,9 +3047,10 @@ EXPORT_SYMBOL(kmalloc_node);
  * platforms.  For example, on i386, it means that the memory must come
  * from the first 16MB.
  */
-void *__kmalloc(size_t size, gfp_t flags)
+static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
+                                         void *caller)
 {
-       kmem_cache_t *cachep;
+       struct kmem_cache *cachep;
 
        /* If you want to save a few bytes .text space: replace
         * __ with kmem_.
@@ -2993,10 +3060,27 @@ void *__kmalloc(size_t size, gfp_t flags)
        cachep = __find_general_cachep(size, flags);
        if (unlikely(cachep == NULL))
                return NULL;
-       return __cache_alloc(cachep, flags);
+       return __cache_alloc(cachep, flags, caller);
+}
+
+#ifndef CONFIG_DEBUG_SLAB
+
+void *__kmalloc(size_t size, gfp_t flags)
+{
+       return __do_kmalloc(size, flags, NULL);
 }
 EXPORT_SYMBOL(__kmalloc);
 
+#else
+
+void *__kmalloc_track_caller(size_t size, gfp_t flags, void *caller)
+{
+       return __do_kmalloc(size, flags, caller);
+}
+EXPORT_SYMBOL(__kmalloc_track_caller);
+
+#endif
+
 #ifdef CONFIG_SMP
 /**
  * __alloc_percpu - allocate one copy of the object for every present
@@ -3054,7 +3138,7 @@ EXPORT_SYMBOL(__alloc_percpu);
  * Free an object which was previously allocated from this
  * cache.
  */
-void kmem_cache_free(kmem_cache_t *cachep, void *objp)
+void kmem_cache_free(struct kmem_cache *cachep, void *objp)
 {
        unsigned long flags;
 
@@ -3075,15 +3159,15 @@ EXPORT_SYMBOL(kmem_cache_free);
  */
 void kfree(const void *objp)
 {
-       kmem_cache_t *c;
+       struct kmem_cache *c;
        unsigned long flags;
 
        if (unlikely(!objp))
                return;
        local_irq_save(flags);
        kfree_debugcheck(objp);
-       c = page_get_cache(virt_to_page(objp));
-       mutex_debug_check_no_locks_freed(objp, obj_reallen(c));
+       c = virt_to_cache(objp);
+       mutex_debug_check_no_locks_freed(objp, obj_size(c));
        __cache_free(c, (void *)objp);
        local_irq_restore(flags);
 }
@@ -3112,13 +3196,13 @@ void free_percpu(const void *objp)
 EXPORT_SYMBOL(free_percpu);
 #endif
 
-unsigned int kmem_cache_size(kmem_cache_t *cachep)
+unsigned int kmem_cache_size(struct kmem_cache *cachep)
 {
-       return obj_reallen(cachep);
+       return obj_size(cachep);
 }
 EXPORT_SYMBOL(kmem_cache_size);
 
-const char *kmem_cache_name(kmem_cache_t *cachep)
+const char *kmem_cache_name(struct kmem_cache *cachep)
 {
        return cachep->name;
 }
@@ -3127,7 +3211,7 @@ EXPORT_SYMBOL_GPL(kmem_cache_name);
 /*
  * This initializes kmem_list3 for all nodes.
  */
-static int alloc_kmemlist(kmem_cache_t *cachep)
+static int alloc_kmemlist(struct kmem_cache *cachep)
 {
        int node;
        struct kmem_list3 *l3;
@@ -3183,7 +3267,7 @@ static int alloc_kmemlist(kmem_cache_t *cachep)
 }
 
 struct ccupdate_struct {
-       kmem_cache_t *cachep;
+       struct kmem_cache *cachep;
        struct array_cache *new[NR_CPUS];
 };
 
@@ -3193,13 +3277,13 @@ static void do_ccupdate_local(void *info)
        struct array_cache *old;
 
        check_irq_off();
-       old = ac_data(new->cachep);
+       old = cpu_cache_get(new->cachep);
 
        new->cachep->array[smp_processor_id()] = new->new[smp_processor_id()];
        new->new[smp_processor_id()] = old;
 }
 
-static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
+static int do_tune_cpucache(struct kmem_cache *cachep, int limit, int batchcount,
                            int shared)
 {
        struct ccupdate_struct new;
@@ -3245,7 +3329,7 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
        return 0;
 }
 
-static void enable_cpucache(kmem_cache_t *cachep)
+static void enable_cpucache(struct kmem_cache *cachep)
 {
        int err;
        int limit, shared;
@@ -3258,13 +3342,13 @@ static void enable_cpucache(kmem_cache_t *cachep)
         * The numbers are guessed, we should auto-tune as described by
         * Bonwick.
         */
-       if (cachep->objsize > 131072)
+       if (cachep->buffer_size > 131072)
                limit = 1;
-       else if (cachep->objsize > PAGE_SIZE)
+       else if (cachep->buffer_size > PAGE_SIZE)
                limit = 8;
-       else if (cachep->objsize > 1024)
+       else if (cachep->buffer_size > 1024)
                limit = 24;
-       else if (cachep->objsize > 256)
+       else if (cachep->buffer_size > 256)
                limit = 54;
        else
                limit = 120;
@@ -3279,7 +3363,7 @@ static void enable_cpucache(kmem_cache_t *cachep)
         */
        shared = 0;
 #ifdef CONFIG_SMP
-       if (cachep->objsize <= PAGE_SIZE)
+       if (cachep->buffer_size <= PAGE_SIZE)
                shared = 8;
 #endif
 
@@ -3297,7 +3381,7 @@ static void enable_cpucache(kmem_cache_t *cachep)
                       cachep->name, -err);
 }
 
-static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac,
+static void drain_array_locked(struct kmem_cache *cachep, struct array_cache *ac,
                                int force, int node)
 {
        int tofree;
@@ -3342,12 +3426,12 @@ static void cache_reap(void *unused)
        }
 
        list_for_each(walk, &cache_chain) {
-               kmem_cache_t *searchp;
+               struct kmem_cache *searchp;
                struct list_head *p;
                int tofree;
                struct slab *slabp;
 
-               searchp = list_entry(walk, kmem_cache_t, next);
+               searchp = list_entry(walk, struct kmem_cache, next);
 
                if (searchp->flags & SLAB_NO_REAP)
                        goto next;
@@ -3359,7 +3443,7 @@ static void cache_reap(void *unused)
                        drain_alien_cache(searchp, l3);
                spin_lock_irq(&l3->list_lock);
 
-               drain_array_locked(searchp, ac_data(searchp), 0,
+               drain_array_locked(searchp, cpu_cache_get(searchp), 0,
                                   numa_node_id());
 
                if (time_after(l3->next_reap, jiffies))
@@ -3450,15 +3534,15 @@ static void *s_start(struct seq_file *m, loff_t *pos)
                if (p == &cache_chain)
                        return NULL;
        }
-       return list_entry(p, kmem_cache_t, next);
+       return list_entry(p, struct kmem_cache, next);
 }
 
 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
 {
-       kmem_cache_t *cachep = p;
+       struct kmem_cache *cachep = p;
        ++*pos;
        return cachep->next.next == &cache_chain ? NULL
-           : list_entry(cachep->next.next, kmem_cache_t, next);
+           : list_entry(cachep->next.next, struct kmem_cache, next);
 }
 
 static void s_stop(struct seq_file *m, void *p)
@@ -3468,7 +3552,7 @@ static void s_stop(struct seq_file *m, void *p)
 
 static int s_show(struct seq_file *m, void *p)
 {
-       kmem_cache_t *cachep = p;
+       struct kmem_cache *cachep = p;
        struct list_head *q;
        struct slab *slabp;
        unsigned long active_objs;
@@ -3528,7 +3612,7 @@ static int s_show(struct seq_file *m, void *p)
                printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
 
        seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
-                  name, active_objs, num_objs, cachep->objsize,
+                  name, active_objs, num_objs, cachep->buffer_size,
                   cachep->num, (1 << cachep->gfporder));
        seq_printf(m, " : tunables %4u %4u %4u",
                   cachep->limit, cachep->batchcount, cachep->shared);
@@ -3618,7 +3702,8 @@ ssize_t slabinfo_write(struct file *file, const char __user * buffer,
        mutex_lock(&cache_chain_mutex);
        res = -EINVAL;
        list_for_each(p, &cache_chain) {
-               kmem_cache_t *cachep = list_entry(p, kmem_cache_t, next);
+               struct kmem_cache *cachep = list_entry(p, struct kmem_cache,
+                                                      next);
 
                if (!strcmp(cachep->name, kbuf)) {
                        if (limit < 1 ||
@@ -3656,5 +3741,5 @@ unsigned int ksize(const void *objp)
        if (unlikely(objp == NULL))
                return 0;
 
-       return obj_reallen(page_get_cache(virt_to_page(objp)));
+       return obj_size(virt_to_cache(objp));
 }
index 7b09ac5..db8a3d3 100644 (file)
@@ -27,6 +27,7 @@ static struct address_space_operations swap_aops = {
        .writepage      = swap_writepage,
        .sync_page      = block_sync_page,
        .set_page_dirty = __set_page_dirty_nobuffers,
+       .migratepage    = migrate_page,
 };
 
 static struct backing_dev_info swap_backing_dev_info = {
index f1e69c3..1f9cf0d 100644 (file)
@@ -554,6 +554,15 @@ static int unuse_mm(struct mm_struct *mm,
        return 0;
 }
 
+#ifdef CONFIG_MIGRATION
+int remove_vma_swap(struct vm_area_struct *vma, struct page *page)
+{
+       swp_entry_t entry = { .val = page_private(page) };
+
+       return unuse_vma(vma, entry, page);
+}
+#endif
+
 /*
  * Scan swap_map from current position to next entry still in use.
  * Recycle to start on reaching the end, returning 0 when empty.
@@ -646,6 +655,7 @@ static int try_to_unuse(unsigned int type)
                 */
                swap_map = &si->swap_map[i];
                entry = swp_entry(type, i);
+again:
                page = read_swap_cache_async(entry, NULL, 0);
                if (!page) {
                        /*
@@ -680,6 +690,12 @@ static int try_to_unuse(unsigned int type)
                wait_on_page_locked(page);
                wait_on_page_writeback(page);
                lock_page(page);
+               if (!PageSwapCache(page)) {
+                       /* Page migration has occured */
+                       unlock_page(page);
+                       page_cache_release(page);
+                       goto again;
+               }
                wait_on_page_writeback(page);
 
                /*
index 2e34b61..5a61080 100644 (file)
@@ -477,7 +477,13 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
                 * processes. Try to unmap it here.
                 */
                if (page_mapped(page) && mapping) {
-                       switch (try_to_unmap(page)) {
+                       /*
+                        * No unmapping if we do not swap
+                        */
+                       if (!sc->may_swap)
+                               goto keep_locked;
+
+                       switch (try_to_unmap(page, 0)) {
                        case SWAP_FAIL:
                                goto activate_locked;
                        case SWAP_AGAIN:
@@ -492,7 +498,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
                                goto keep_locked;
                        if (!may_enter_fs)
                                goto keep_locked;
-                       if (laptop_mode && !sc->may_writepage)
+                       if (!sc->may_writepage)
                                goto keep_locked;
 
                        /* Page is dirty, try to write it out here */
@@ -608,6 +614,15 @@ int putback_lru_pages(struct list_head *l)
        return count;
 }
 
+/*
+ * Non migratable page
+ */
+int fail_migrate_page(struct page *newpage, struct page *page)
+{
+       return -EIO;
+}
+EXPORT_SYMBOL(fail_migrate_page);
+
 /*
  * swapout a single page
  * page is locked upon entry, unlocked on exit
@@ -617,7 +632,7 @@ static int swap_page(struct page *page)
        struct address_space *mapping = page_mapping(page);
 
        if (page_mapped(page) && mapping)
-               if (try_to_unmap(page) != SWAP_SUCCESS)
+               if (try_to_unmap(page, 0) != SWAP_SUCCESS)
                        goto unlock_retry;
 
        if (PageDirty(page)) {
@@ -653,6 +668,167 @@ unlock_retry:
 retry:
        return -EAGAIN;
 }
+EXPORT_SYMBOL(swap_page);
+
+/*
+ * Page migration was first developed in the context of the memory hotplug
+ * project. The main authors of the migration code are:
+ *
+ * IWAMOTO Toshihiro <iwamoto@valinux.co.jp>
+ * Hirokazu Takahashi <taka@valinux.co.jp>
+ * Dave Hansen <haveblue@us.ibm.com>
+ * Christoph Lameter <clameter@sgi.com>
+ */
+
+/*
+ * Remove references for a page and establish the new page with the correct
+ * basic settings to be able to stop accesses to the page.
+ */
+int migrate_page_remove_references(struct page *newpage,
+                               struct page *page, int nr_refs)
+{
+       struct address_space *mapping = page_mapping(page);
+       struct page **radix_pointer;
+
+       /*
+        * Avoid doing any of the following work if the page count
+        * indicates that the page is in use or truncate has removed
+        * the page.
+        */
+       if (!mapping || page_mapcount(page) + nr_refs != page_count(page))
+               return 1;
+
+       /*
+        * Establish swap ptes for anonymous pages or destroy pte
+        * maps for files.
+        *
+        * In order to reestablish file backed mappings the fault handlers
+        * will take the radix tree_lock which may then be used to stop
+        * processses from accessing this page until the new page is ready.
+        *
+        * A process accessing via a swap pte (an anonymous page) will take a
+        * page_lock on the old page which will block the process until the
+        * migration attempt is complete. At that time the PageSwapCache bit
+        * will be examined. If the page was migrated then the PageSwapCache
+        * bit will be clear and the operation to retrieve the page will be
+        * retried which will find the new page in the radix tree. Then a new
+        * direct mapping may be generated based on the radix tree contents.
+        *
+        * If the page was not migrated then the PageSwapCache bit
+        * is still set and the operation may continue.
+        */
+       try_to_unmap(page, 1);
+
+       /*
+        * Give up if we were unable to remove all mappings.
+        */
+       if (page_mapcount(page))
+               return 1;
+
+       write_lock_irq(&mapping->tree_lock);
+
+       radix_pointer = (struct page **)radix_tree_lookup_slot(
+                                               &mapping->page_tree,
+                                               page_index(page));
+
+       if (!page_mapping(page) || page_count(page) != nr_refs ||
+                       *radix_pointer != page) {
+               write_unlock_irq(&mapping->tree_lock);
+               return 1;
+       }
+
+       /*
+        * Now we know that no one else is looking at the page.
+        *
+        * Certain minimal information about a page must be available
+        * in order for other subsystems to properly handle the page if they
+        * find it through the radix tree update before we are finished
+        * copying the page.
+        */
+       get_page(newpage);
+       newpage->index = page->index;
+       newpage->mapping = page->mapping;
+       if (PageSwapCache(page)) {
+               SetPageSwapCache(newpage);
+               set_page_private(newpage, page_private(page));
+       }
+
+       *radix_pointer = newpage;
+       __put_page(page);
+       write_unlock_irq(&mapping->tree_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(migrate_page_remove_references);
+
+/*
+ * Copy the page to its new location
+ */
+void migrate_page_copy(struct page *newpage, struct page *page)
+{
+       copy_highpage(newpage, page);
+
+       if (PageError(page))
+               SetPageError(newpage);
+       if (PageReferenced(page))
+               SetPageReferenced(newpage);
+       if (PageUptodate(page))
+               SetPageUptodate(newpage);
+       if (PageActive(page))
+               SetPageActive(newpage);
+       if (PageChecked(page))
+               SetPageChecked(newpage);
+       if (PageMappedToDisk(page))
+               SetPageMappedToDisk(newpage);
+
+       if (PageDirty(page)) {
+               clear_page_dirty_for_io(page);
+               set_page_dirty(newpage);
+       }
+
+       ClearPageSwapCache(page);
+       ClearPageActive(page);
+       ClearPagePrivate(page);
+       set_page_private(page, 0);
+       page->mapping = NULL;
+
+       /*
+        * If any waiters have accumulated on the new page then
+        * wake them up.
+        */
+       if (PageWriteback(newpage))
+               end_page_writeback(newpage);
+}
+EXPORT_SYMBOL(migrate_page_copy);
+
+/*
+ * Common logic to directly migrate a single page suitable for
+ * pages that do not use PagePrivate.
+ *
+ * Pages are locked upon entry and exit.
+ */
+int migrate_page(struct page *newpage, struct page *page)
+{
+       BUG_ON(PageWriteback(page));    /* Writeback must be complete */
+
+       if (migrate_page_remove_references(newpage, page, 2))
+               return -EAGAIN;
+
+       migrate_page_copy(newpage, page);
+
+       /*
+        * Remove auxiliary swap entries and replace
+        * them with real ptes.
+        *
+        * Note that a real pte entry will allow processes that are not
+        * waiting on the page lock to use the new page via the page tables
+        * before the new page is unlocked.
+        */
+       remove_from_swap(newpage);
+       return 0;
+}
+EXPORT_SYMBOL(migrate_page);
+
 /*
  * migrate_pages
  *
@@ -666,11 +842,6 @@ retry:
  * are movable anymore because t has become empty
  * or no retryable pages exist anymore.
  *
- * SIMPLIFIED VERSION: This implementation of migrate_pages
- * is only swapping out pages and never touches the second
- * list. The direct migration patchset
- * extends this function to avoid the use of swap.
- *
  * Return: Number of pages not migrated when "to" ran empty.
  */
 int migrate_pages(struct list_head *from, struct list_head *to,
@@ -691,6 +862,9 @@ redo:
        retry = 0;
 
        list_for_each_entry_safe(page, page2, from, lru) {
+               struct page *newpage = NULL;
+               struct address_space *mapping;
+
                cond_resched();
 
                rc = 0;
@@ -698,6 +872,9 @@ redo:
                        /* page was freed from under us. So we are done. */
                        goto next;
 
+               if (to && list_empty(to))
+                       break;
+
                /*
                 * Skip locked pages during the first two passes to give the
                 * functions holding the lock time to release the page. Later we
@@ -734,12 +911,69 @@ redo:
                        }
                }
 
+               if (!to) {
+                       rc = swap_page(page);
+                       goto next;
+               }
+
+               newpage = lru_to_page(to);
+               lock_page(newpage);
+
                /*
-                * Page is properly locked and writeback is complete.
+                * Pages are properly locked and writeback is complete.
                 * Try to migrate the page.
                 */
-               rc = swap_page(page);
-               goto next;
+               mapping = page_mapping(page);
+               if (!mapping)
+                       goto unlock_both;
+
+               if (mapping->a_ops->migratepage) {
+                       rc = mapping->a_ops->migratepage(newpage, page);
+                       goto unlock_both;
+                }
+
+               /*
+                * Trigger writeout if page is dirty
+                */
+               if (PageDirty(page)) {
+                       switch (pageout(page, mapping)) {
+                       case PAGE_KEEP:
+                       case PAGE_ACTIVATE:
+                               goto unlock_both;
+
+                       case PAGE_SUCCESS:
+                               unlock_page(newpage);
+                               goto next;
+
+                       case PAGE_CLEAN:
+                               ; /* try to migrate the page below */
+                       }
+                }
+               /*
+                * If we have no buffer or can release the buffer
+                * then do a simple migration.
+                */
+               if (!page_has_buffers(page) ||
+                   try_to_release_page(page, GFP_KERNEL)) {
+                       rc = migrate_page(newpage, page);
+                       goto unlock_both;
+               }
+
+               /*
+                * On early passes with mapped pages simply
+                * retry. There may be a lock held for some
+                * buffers that may go away. Later
+                * swap them out.
+                */
+               if (pass > 4) {
+                       unlock_page(newpage);
+                       newpage = NULL;
+                       rc = swap_page(page);
+                       goto next;
+               }
+
+unlock_both:
+               unlock_page(newpage);
 
 unlock_page:
                unlock_page(page);
@@ -752,7 +986,10 @@ next:
                        list_move(&page->lru, failed);
                        nr_failed++;
                } else {
-                       /* Success */
+                       if (newpage) {
+                               /* Successful migration. Return page to LRU */
+                               move_to_lru(newpage);
+                       }
                        list_move(&page->lru, moved);
                }
        }
@@ -1170,7 +1407,7 @@ int try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
        int i;
 
        sc.gfp_mask = gfp_mask;
-       sc.may_writepage = 0;
+       sc.may_writepage = !laptop_mode;
        sc.may_swap = 1;
 
        inc_page_state(allocstall);
@@ -1273,7 +1510,7 @@ loop_again:
        total_scanned = 0;
        total_reclaimed = 0;
        sc.gfp_mask = GFP_KERNEL;
-       sc.may_writepage = 0;
+       sc.may_writepage = !laptop_mode;
        sc.may_swap = 1;
        sc.nr_mapped = read_page_state(nr_mapped);
 
@@ -1586,40 +1823,61 @@ module_init(kswapd_init)
  */
 int zone_reclaim_mode __read_mostly;
 
+#define RECLAIM_OFF 0
+#define RECLAIM_ZONE (1<<0)    /* Run shrink_cache on the zone */
+#define RECLAIM_WRITE (1<<1)   /* Writeout pages during reclaim */
+#define RECLAIM_SWAP (1<<2)    /* Swap pages out during reclaim */
+#define RECLAIM_SLAB (1<<3)    /* Do a global slab shrink if the zone is out of memory */
+
 /*
  * Mininum time between zone reclaim scans
  */
-#define ZONE_RECLAIM_INTERVAL HZ/2
+int zone_reclaim_interval __read_mostly = 30*HZ;
+
+/*
+ * Priority for ZONE_RECLAIM. This determines the fraction of pages
+ * of a node considered for each zone_reclaim. 4 scans 1/16th of
+ * a zone.
+ */
+#define ZONE_RECLAIM_PRIORITY 4
+
 /*
  * Try to free up some pages from this zone through reclaim.
  */
 int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
 {
-       int nr_pages = 1 << order;
+       int nr_pages;
        struct task_struct *p = current;
        struct reclaim_state reclaim_state;
-       struct scan_control sc = {
-               .gfp_mask       = gfp_mask,
-               .may_writepage  = 0,
-               .may_swap       = 0,
-               .nr_mapped      = read_page_state(nr_mapped),
-               .nr_scanned     = 0,
-               .nr_reclaimed   = 0,
-               .priority       = 0
-       };
+       struct scan_control sc;
+       cpumask_t mask;
+       int node_id;
+
+       if (time_before(jiffies,
+               zone->last_unsuccessful_zone_reclaim + zone_reclaim_interval))
+                       return 0;
 
        if (!(gfp_mask & __GFP_WAIT) ||
-               zone->zone_pgdat->node_id != numa_node_id() ||
                zone->all_unreclaimable ||
                atomic_read(&zone->reclaim_in_progress) > 0)
                        return 0;
 
-       if (time_before(jiffies,
-               zone->last_unsuccessful_zone_reclaim + ZONE_RECLAIM_INTERVAL))
-                       return 0;
+       node_id = zone->zone_pgdat->node_id;
+       mask = node_to_cpumask(node_id);
+       if (!cpus_empty(mask) && node_id != numa_node_id())
+               return 0;
+
+       sc.may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE);
+       sc.may_swap = !!(zone_reclaim_mode & RECLAIM_SWAP);
+       sc.nr_scanned = 0;
+       sc.nr_reclaimed = 0;
+       sc.priority = ZONE_RECLAIM_PRIORITY + 1;
+       sc.nr_mapped = read_page_state(nr_mapped);
+       sc.gfp_mask = gfp_mask;
 
        disable_swap_token();
 
+       nr_pages = 1 << order;
        if (nr_pages > SWAP_CLUSTER_MAX)
                sc.swap_cluster_max = nr_pages;
        else
@@ -1629,14 +1887,37 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
        p->flags |= PF_MEMALLOC;
        reclaim_state.reclaimed_slab = 0;
        p->reclaim_state = &reclaim_state;
-       shrink_zone(zone, &sc);
+
+       /*
+        * Free memory by calling shrink zone with increasing priorities
+        * until we have enough memory freed.
+        */
+       do {
+               sc.priority--;
+               shrink_zone(zone, &sc);
+
+       } while (sc.nr_reclaimed < nr_pages && sc.priority > 0);
+
+       if (sc.nr_reclaimed < nr_pages && (zone_reclaim_mode & RECLAIM_SLAB)) {
+               /*
+                * shrink_slab does not currently allow us to determine
+                * how many pages were freed in the zone. So we just
+                * shake the slab and then go offnode for a single allocation.
+                *
+                * shrink_slab will free memory on all zones and may take
+                * a long time.
+                */
+               shrink_slab(sc.nr_scanned, gfp_mask, order);
+               sc.nr_reclaimed = 1;    /* Avoid getting the off node timeout */
+       }
+
        p->reclaim_state = NULL;
        current->flags &= ~PF_MEMALLOC;
 
        if (sc.nr_reclaimed == 0)
                zone->last_unsuccessful_zone_reclaim = jiffies;
 
-       return sc.nr_reclaimed > nr_pages;
+       return sc.nr_reclaimed >= nr_pages;
 }
 #endif
 
index ba44288..da687c8 100644 (file)
@@ -104,6 +104,7 @@ static void destroy_nbp(struct net_bridge_port *p)
 {
        struct net_device *dev = p->dev;
 
+       dev->br_port = NULL;
        p->br = NULL;
        p->dev = NULL;
        dev_put(dev);
@@ -118,13 +119,24 @@ static void destroy_nbp_rcu(struct rcu_head *head)
        destroy_nbp(p);
 }
 
-/* called with RTNL */
+/* Delete port(interface) from bridge is done in two steps.
+ * via RCU. First step, marks device as down. That deletes
+ * all the timers and stops new packets from flowing through.
+ *
+ * Final cleanup doesn't occur until after all CPU's finished
+ * processing packets.
+ *
+ * Protected from multiple admin operations by RTNL mutex
+ */
 static void del_nbp(struct net_bridge_port *p)
 {
        struct net_bridge *br = p->br;
        struct net_device *dev = p->dev;
 
-       dev->br_port = NULL;
+       /* Race between RTNL notify and RCU callback */
+       if (p->deleted)
+               return;
+
        dev_set_promiscuity(dev, -1);
 
        cancel_delayed_work(&p->carrier_check);
@@ -132,16 +144,13 @@ static void del_nbp(struct net_bridge_port *p)
 
        spin_lock_bh(&br->lock);
        br_stp_disable_port(p);
+       p->deleted = 1;
        spin_unlock_bh(&br->lock);
 
        br_fdb_delete_by_port(br, p);
 
        list_del_rcu(&p->list);
 
-       del_timer_sync(&p->message_age_timer);
-       del_timer_sync(&p->forward_delay_timer);
-       del_timer_sync(&p->hold_timer);
-       
        call_rcu(&p->rcu, destroy_nbp_rcu);
 }
 
index c5bd631..e330b17 100644 (file)
@@ -68,6 +68,7 @@ struct net_bridge_port
        /* STP */
        u8                              priority;
        u8                              state;
+       u8                              deleted;
        u16                             port_no;
        unsigned char                   topology_change_ack;
        unsigned char                   config_pending;
index fd070a0..ffb8207 100644 (file)
@@ -2543,13 +2543,14 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
                case SIOCBONDENSLAVE:
                case SIOCBONDRELEASE:
                case SIOCBONDSETHWADDR:
-               case SIOCBONDSLAVEINFOQUERY:
-               case SIOCBONDINFOQUERY:
                case SIOCBONDCHANGEACTIVE:
                case SIOCBRADDIF:
                case SIOCBRDELIF:
                        if (!capable(CAP_NET_ADMIN))
                                return -EPERM;
+                       /* fall through */
+               case SIOCBONDSLAVEINFOQUERY:
+               case SIOCBONDINFOQUERY:
                        dev_load(ifr.ifr_name);
                        rtnl_lock();
                        ret = dev_ifsioc(&ifr, cmd);
index 9540946..93fbd01 100644 (file)
@@ -64,7 +64,7 @@ static inline void *load_pointer(struct sk_buff *skb, int k,
 }
 
 /**
- *     sk_run_filter   -       run a filter on a socket
+ *     sk_run_filter - run a filter on a socket
  *     @skb: buffer to run the filter on
  *     @filter: filter to apply
  *     @flen: length of filter
@@ -78,8 +78,8 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
 {
        struct sock_filter *fentry;     /* We walk down these */
        void *ptr;
-       u32 A = 0;                      /* Accumulator */
-       u32 X = 0;                      /* Index Register */
+       u32 A = 0;                      /* Accumulator */
+       u32 X = 0;                      /* Index Register */
        u32 mem[BPF_MEMWORDS];          /* Scratch Memory Store */
        u32 tmp;
        int k;
index d0732e9..6766f11 100644 (file)
@@ -135,13 +135,15 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
 struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
                            int fclone)
 {
+       kmem_cache_t *cache;
        struct skb_shared_info *shinfo;
        struct sk_buff *skb;
        u8 *data;
 
+       cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
+
        /* Get the HEAD */
-       skb = kmem_cache_alloc(fclone ? skbuff_fclone_cache : skbuff_head_cache,
-                               gfp_mask & ~__GFP_DMA);
+       skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA);
        if (!skb)
                goto out;
 
@@ -180,7 +182,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
 out:
        return skb;
 nodata:
-       kmem_cache_free(skbuff_head_cache, skb);
+       kmem_cache_free(cache, skb);
        skb = NULL;
        goto out;
 }
index 00f9832..dc0487b 100644 (file)
@@ -119,7 +119,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (err != 0)
                goto failure;
 
-       err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
+       err = ip_route_newports(&rt, IPPROTO_DCCP, inet->sport, inet->dport,
+                               sk);
        if (err != 0)
                goto failure;
 
index df07425..80c4d04 100644 (file)
@@ -468,6 +468,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
 done:
         if (opt && opt != np->opt)
                sock_kfree_s(sk, opt, opt->tot_len);
+       dst_release(dst);
        return err;
 }
 
index 7a12180..960aa78 100644 (file)
@@ -350,6 +350,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        u8 src[ETH_ALEN];
        struct ieee80211_crypt_data *crypt = NULL;
        int keyidx = 0;
+       int can_be_decrypted = 0;
 
        hdr = (struct ieee80211_hdr_4addr *)skb->data;
        stats = &ieee->stats;
@@ -410,12 +411,23 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                return 1;
        }
 
-       if (is_multicast_ether_addr(hdr->addr1)
-           ? ieee->host_mc_decrypt : ieee->host_decrypt) {
+       can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) ||
+                           is_broadcast_ether_addr(hdr->addr2)) ?
+           ieee->host_mc_decrypt : ieee->host_decrypt;
+
+       if (can_be_decrypted) {
                int idx = 0;
-               if (skb->len >= hdrlen + 3)
+               if (skb->len >= hdrlen + 3) {
+                       /* Top two-bits of byte 3 are the key index */
                        idx = skb->data[hdrlen + 3] >> 6;
+               }
+
+               /* ieee->crypt[] is WEP_KEY (4) in length.  Given that idx
+                * is only allowed 2-bits of storage, no value of idx can
+                * be provided via above code that would result in idx
+                * being out of range */
                crypt = ieee->crypt[idx];
+
 #ifdef NOT_YET
                sta = NULL;
 
@@ -553,7 +565,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 
        /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
 
-       if (ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+       if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted &&
            (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
                goto rx_dropped;
 
@@ -617,7 +629,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 
        /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
         * encrypted/authenticated */
-       if (ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+       if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted &&
            ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
                goto rx_dropped;
 
@@ -1439,7 +1451,7 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                break;
 
        case IEEE80211_STYPE_PROBE_REQ:
-               IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+               IEEE80211_DEBUG_MGMT("received auth (%d)\n",
                                     WLAN_FC_GET_STYPE(le16_to_cpu
                                                       (header->frame_ctl)));
 
@@ -1473,7 +1485,7 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                break;
        case IEEE80211_STYPE_AUTH:
 
-               IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+               IEEE80211_DEBUG_MGMT("received auth (%d)\n",
                                     WLAN_FC_GET_STYPE(le16_to_cpu
                                                       (header->frame_ctl)));
 
index 23e1630..f87c6b8 100644 (file)
@@ -232,15 +232,18 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
        return start;
 }
 
+#define SCAN_ITEM_SIZE 128
+
 int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
                          struct iw_request_info *info,
                          union iwreq_data *wrqu, char *extra)
 {
        struct ieee80211_network *network;
        unsigned long flags;
+       int err = 0;
 
        char *ev = extra;
-       char *stop = ev + IW_SCAN_MAX_DATA;
+       char *stop = ev + wrqu->data.length;
        int i = 0;
 
        IEEE80211_DEBUG_WX("Getting scan\n");
@@ -249,6 +252,11 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
 
        list_for_each_entry(network, &ieee->network_list, list) {
                i++;
+               if (stop - ev < SCAN_ITEM_SIZE) {
+                       err = -E2BIG;
+                       break;
+               }
+
                if (ieee->scan_age == 0 ||
                    time_after(network->last_scanned + ieee->scan_age, jiffies))
                        ev = ipw2100_translate_scan(ieee, ev, stop, network);
@@ -270,7 +278,7 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
 
        IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
 
-       return 0;
+       return err;
 }
 
 int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
index d8ce713..0b4e95f 100644 (file)
@@ -970,7 +970,7 @@ int igmp_rcv(struct sk_buff *skb)
        case IGMP_MTRACE_RESP:
                break;
        default:
-               NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type);
+               break;
        }
 
 drop:
index 3284cfb..128de4d 100644 (file)
@@ -230,7 +230,6 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
                        if (tp->snd_cwnd < tp->snd_cwnd_clamp)
                                tp->snd_cwnd++;
                        tp->snd_cwnd_cnt = 0;
-                       ca->ccount++;
                }
        }
 }
index 6ea3539..233bdf2 100644 (file)
@@ -236,7 +236,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (err)
                goto failure;
 
-       err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
+       err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk);
        if (err)
                goto failure;
 
@@ -1845,7 +1845,6 @@ void __init tcp_v4_init(struct net_proto_family *ops)
 }
 
 EXPORT_SYMBOL(ipv4_specific);
-EXPORT_SYMBOL(inet_bind_bucket_create);
 EXPORT_SYMBOL(tcp_hashinfo);
 EXPORT_SYMBOL(tcp_prot);
 EXPORT_SYMBOL(tcp_unhash);
index 6c05c79..4420948 100644 (file)
@@ -1252,8 +1252,7 @@ int igmp6_event_query(struct sk_buff *skb)
                }
        } else {
                for (ma = idev->mc_list; ma; ma=ma->next) {
-                       if (group_type != IPV6_ADDR_ANY &&
-                           !ipv6_addr_equal(group, &ma->mca_addr))
+                       if (!ipv6_addr_equal(group, &ma->mca_addr))
                                continue;
                        spin_lock_bh(&ma->mca_lock);
                        if (ma->mca_flags & MAF_TIMER_RUNNING) {
@@ -1268,11 +1267,10 @@ int igmp6_event_query(struct sk_buff *skb)
                                        ma->mca_flags &= ~MAF_GSQUERY;
                        }
                        if (!(ma->mca_flags & MAF_GSQUERY) ||
-                          mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs))
+                           mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs))
                                igmp6_group_queried(ma, max_delay);
                        spin_unlock_bh(&ma->mca_lock);
-                       if (group_type != IPV6_ADDR_ANY)
-                               break;
+                       break;
                }
        }
        read_unlock_bh(&idev->lock);
@@ -1351,7 +1349,7 @@ static int is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type,
                         * in all filters
                         */
                        if (psf->sf_count[MCAST_INCLUDE])
-                               return 0;
+                               return type == MLD2_MODE_IS_INCLUDE;
                        return pmc->mca_sfcount[MCAST_EXCLUDE] ==
                                psf->sf_count[MCAST_EXCLUDE];
                }
@@ -1966,7 +1964,7 @@ static void sf_markstate(struct ifmcaddr6 *pmc)
 
 static int sf_setstate(struct ifmcaddr6 *pmc)
 {
-       struct ip6_sf_list *psf;
+       struct ip6_sf_list *psf, *dpsf;
        int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE];
        int qrv = pmc->idev->mc_qrv;
        int new_in, rv;
@@ -1978,8 +1976,48 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
                                !psf->sf_count[MCAST_INCLUDE];
                } else
                        new_in = psf->sf_count[MCAST_INCLUDE] != 0;
-               if (new_in != psf->sf_oldin) {
-                       psf->sf_crcount = qrv;
+               if (new_in) {
+                       if (!psf->sf_oldin) {
+                               struct ip6_sf_list *prev = 0;
+
+                               for (dpsf=pmc->mca_tomb; dpsf;
+                                    dpsf=dpsf->sf_next) {
+                                       if (ipv6_addr_equal(&dpsf->sf_addr,
+                                           &psf->sf_addr))
+                                               break;
+                                       prev = dpsf;
+                               }
+                               if (dpsf) {
+                                       if (prev)
+                                               prev->sf_next = dpsf->sf_next;
+                                       else
+                                               pmc->mca_tomb = dpsf->sf_next;
+                                       kfree(dpsf);
+                               }
+                               psf->sf_crcount = qrv;
+                               rv++;
+                       }
+               } else if (psf->sf_oldin) {
+                       psf->sf_crcount = 0;
+                       /*
+                        * add or update "delete" records if an active filter
+                        * is now inactive
+                        */
+                       for (dpsf=pmc->mca_tomb; dpsf; dpsf=dpsf->sf_next)
+                               if (ipv6_addr_equal(&dpsf->sf_addr,
+                                   &psf->sf_addr))
+                                       break;
+                       if (!dpsf) {
+                               dpsf = (struct ip6_sf_list *)
+                                       kmalloc(sizeof(*dpsf), GFP_ATOMIC);
+                               if (!dpsf)
+                                       continue;
+                               *dpsf = *psf;
+                               /* pmc->mca_lock held by callers */
+                               dpsf->sf_next = pmc->mca_tomb;
+                               pmc->mca_tomb = dpsf;
+                       }
+                       dpsf->sf_crcount = qrv;
                        rv++;
                }
        }
index 66d0400..ca9cf68 100644 (file)
@@ -515,6 +515,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
 done:
         if (opt && opt != np->opt)
                sock_kfree_s(sk, opt, opt->tot_len);
+       dst_release(dst);
        return err;
 }
 
index 43f1ce7..ae86d23 100644 (file)
@@ -1620,6 +1620,7 @@ static int key_notify_sa_flush(struct km_event *c)
                return -ENOBUFS;
        hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
        hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto);
+       hdr->sadb_msg_type = SADB_FLUSH;
        hdr->sadb_msg_seq = c->seq;
        hdr->sadb_msg_pid = c->pid;
        hdr->sadb_msg_version = PF_KEY_V2;
@@ -2385,6 +2386,7 @@ static int key_notify_policy_flush(struct km_event *c)
        if (!skb_out)
                return -ENOBUFS;
        hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
+       hdr->sadb_msg_type = SADB_X_SPDFLUSH;
        hdr->sadb_msg_seq = c->seq;
        hdr->sadb_msg_pid = c->pid;
        hdr->sadb_msg_version = PF_KEY_V2;
index ee93abc..9db7dbd 100644 (file)
@@ -365,7 +365,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
         */
         
        err = -EMSGSIZE;
-       if(len>dev->mtu+dev->hard_header_len)
+       if (len > dev->mtu + dev->hard_header_len)
                goto out_unlock;
 
        err = -ENOBUFS;
@@ -935,7 +935,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int add
         *      Check legality
         */
         
-       if(addr_len!=sizeof(struct sockaddr))
+       if (addr_len != sizeof(struct sockaddr))
                return -EINVAL;
        strlcpy(name,uaddr->sa_data,sizeof(name));
 
@@ -1092,7 +1092,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
         *      retries.
         */
 
-       if(skb==NULL)
+       if (skb == NULL)
                goto out;
 
        /*
@@ -1392,8 +1392,8 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
        if (level != SOL_PACKET)
                return -ENOPROTOOPT;
 
-       if (get_user(len,optlen))
-               return -EFAULT;
+       if (get_user(len, optlen))
+               return -EFAULT;
 
        if (len < 0)
                return -EINVAL;
@@ -1419,9 +1419,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
                return -ENOPROTOOPT;
        }
 
-       if (put_user(len, optlen))
-               return -EFAULT;
-       return 0;
+       if (put_user(len, optlen))
+               return -EFAULT;
+       return 0;
 }
 
 
index 71c9a96..2b9a832 100644 (file)
@@ -884,7 +884,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
 {
        struct sctp_transport *transport = (struct sctp_transport *) arg;
 
-       if (asoc->overall_error_count > asoc->max_retrans) {
+       if (asoc->overall_error_count >= asoc->max_retrans) {
                /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
                sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
                                SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -2122,7 +2122,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
        struct sctp_bind_addr *bp;
        int attempts = asoc->init_err_counter + 1;
 
-       if (attempts >= asoc->max_init_attempts) {
+       if (attempts > asoc->max_init_attempts) {
                sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
                                SCTP_U32(SCTP_ERROR_STALE_COOKIE));
                return SCTP_DISPOSITION_DELETE_TCB;
@@ -4640,7 +4640,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
 
        SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
 
-       if (attempts < asoc->max_init_attempts) {
+       if (attempts <= asoc->max_init_attempts) {
                bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
                repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
                if (!repl)
@@ -4697,7 +4697,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
 
        SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
 
-       if (attempts < asoc->max_init_attempts) {
+       if (attempts <= asoc->max_init_attempts) {
                repl = sctp_make_cookie_echo(asoc, NULL);
                if (!repl)
                        return SCTP_DISPOSITION_NOMEM;
index fb1821d..0ea947e 100644 (file)
@@ -5426,7 +5426,7 @@ out:
        return err;
 
 do_error:
-       if (asoc->init_err_counter + 1 >= asoc->max_init_attempts)
+       if (asoc->init_err_counter + 1 > asoc->max_init_attempts)
                err = -ETIMEDOUT;
        else
                err = -ECONNREFUSED;
index 7415406..802d4fe 100644 (file)
@@ -908,10 +908,10 @@ void rpc_release_task(struct rpc_task *task)
 
 /**
  * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
- * @clnt - pointer to RPC client
- * @flags - RPC flags
- * @ops - RPC call ops
- * @data - user call data
+ * @clnt: pointer to RPC client
+ * @flags: RPC flags
+ * @ops: RPC call ops
+ * @data: user call data
  */
 struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
                                        const struct rpc_call_ops *ops,
@@ -930,6 +930,7 @@ EXPORT_SYMBOL(rpc_run_task);
 /**
  * rpc_find_parent - find the parent of a child task.
  * @child: child task
+ * @parent: parent task
  *
  * Checks that the parent task is still sleeping on the
  * queue 'childq'. If so returns a pointer to the parent.
index 9fd5f5b..99fe4b7 100755 (executable)
@@ -45,7 +45,7 @@ use strict;
 # Note: This only supports 'c'.
 
 # usage:
-# kerneldoc [ -docbook | -html | -text | -man ]
+# kernel-doc [ -docbook | -html | -text | -man ]
 #           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
 # or
 #           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
@@ -59,7 +59,7 @@ use strict;
 #  -nofunction funcname
 #      If set, then only generate documentation for the other function(s).  All
 #      other functions are ignored. Cannot be used with -function together
-#      (yes thats a bug - perl hackers can fix it 8))
+#      (yes, that's a bug -- perl hackers can fix it 8))
 #
 #  c files - list of 'c' files to process
 #
@@ -90,28 +90,28 @@ use strict;
 #  * my_function - does my stuff
 #  * @my_arg: its mine damnit
 #  *
-#  * Does my stuff explained. 
+#  * Does my stuff explained.
 #  */
 #
 #  or, could also use:
 # /**
 #  * my_function - does my stuff
 #  * @my_arg: its mine damnit
-#  * Description: Does my stuff explained. 
+#  * Description: Does my stuff explained.
 #  */
 # etc.
 #
-# Beside functions you can also write documentation for structs, unions, 
-# enums and typedefs. Instead of the function name you must write the name 
-# of the declaration;  the struct/union/enum/typedef must always precede 
-# the name. Nesting of declarations is not supported. 
+# Beside functions you can also write documentation for structs, unions,
+# enums and typedefs. Instead of the function name you must write the name
+# of the declaration;  the struct/union/enum/typedef must always precede
+# the name. Nesting of declarations is not supported.
 # Use the argument mechanism to document members or constants.
 # e.g.
 # /**
 #  * struct my_struct - short description
 #  * @a: first member
 #  * @b: second member
-#  * 
+#  *
 #  * Longer description
 #  */
 # struct my_struct {
@@ -122,12 +122,12 @@ use strict;
 # };
 #
 # All descriptions can be multiline, except the short function description.
-# 
-# You can also add additional sections. When documenting kernel functions you 
-# should document the "Context:" of the function, e.g. whether the functions 
+#
+# You can also add additional sections. When documenting kernel functions you
+# should document the "Context:" of the function, e.g. whether the functions
 # can be called form interrupts. Unlike other sections you can end it with an
-# empty line. 
-# Example-sections should contain the string EXAMPLE so that they are marked 
+# empty line.
+# Example-sections should contain the string EXAMPLE so that they are marked
 # appropriately in DocBook.
 #
 # Example:
@@ -135,7 +135,7 @@ use strict;
 #  * user_function - function that can only be called in user context
 #  * @a: some argument
 #  * Context: !in_interrupt()
-#  * 
+#  *
 #  * Some description
 #  * Example:
 #  *    user_function(22);
@@ -223,9 +223,9 @@ my %highlights = %highlights_man;
 my $blankline = $blankline_man;
 my $modulename = "Kernel API";
 my $function_only = 0;
-my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', 
-               'July', 'August', 'September', 'October', 
-               'November', 'December')[(localtime)[4]] . 
+my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
+               'July', 'August', 'September', 'October',
+               'November', 'December')[(localtime)[4]] .
   " " . ((localtime)[5]+1900);
 
 # Essentially these are globals
@@ -236,7 +236,7 @@ my ($function, %function_table,%parametertypes,$declaration_purpose);
 my ($type,$declaration_name,$return_type);
 my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map);
 
-# Generated docbook code is inserted in a template at a point where 
+# Generated docbook code is inserted in a template at a point where
 # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
 # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
 # We keep track of number of generated entries and generate a dummy
@@ -365,7 +365,7 @@ sub dump_section {
 #  parameterdescs => %parameter descriptions
 #  sectionlist => @list of sections
 #  sections => %descriont descriptions
-#  
+#
 
 sub output_highlight {
     my $contents = join "\n",@_;
@@ -400,7 +400,7 @@ sub output_section_html(%) {
        print "<blockquote>\n";
        output_highlight($args{'sections'}{$section});
        print "</blockquote>\n";
-    }  
+    }
 }
 
 # output enum in html
@@ -434,7 +434,7 @@ sub output_enum_html(%) {
     print "<hr>\n";
 }
 
-# output tyepdef in html
+# output typedef in html
 sub output_typedef_html(%) {
     my %args = %{$_[0]};
     my ($parameter);
@@ -551,7 +551,7 @@ sub output_intro_html(%) {
 
 sub output_section_xml(%) {
     my %args = %{$_[0]};
-    my $section;    
+    my $section;
     # print out each section
     $lineprefix="   ";
     foreach $section (@{$args{'sectionlist'}}) {
@@ -778,7 +778,7 @@ sub output_enum_xml(%) {
     print "</refsynopsisdiv>\n";
 
     print "<refsect1>\n";
-    print " <title>Constants</title>\n";    
+    print " <title>Constants</title>\n";
     print "  <variablelist>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
       my $parameter_name = $parameter;
@@ -1157,7 +1157,7 @@ sub output_section_text(%) {
     foreach $section (@{$args{'sectionlist'}}) {
        print "$section:\n\n";
        output_highlight($args{'sections'}{$section});
-    }  
+    }
     print "\n\n";
 }
 
@@ -1262,8 +1262,8 @@ sub output_declaration {
     my $name = shift;
     my $functype = shift;
     my $func = "output_${functype}_$output_mode";
-    if (($function_only==0) || 
-       ( $function_only == 1 && defined($function_table{$name})) || 
+    if (($function_only==0) ||
+       ( $function_only == 1 && defined($function_table{$name})) ||
        ( $function_only == 2 && !defined($function_table{$name})))
     {
         &$func(@_);
@@ -1282,7 +1282,7 @@ sub output_intro {
 }
 
 ##
-# takes a declaration (struct, union, enum, typedef) and 
+# takes a declaration (struct, union, enum, typedef) and
 # invokes the right handler. NOT called for functions.
 sub dump_declaration($$) {
     no strict 'refs';
@@ -1352,7 +1352,7 @@ sub dump_enum($$) {
            }
 
        }
-       
+
        output_declaration($declaration_name,
                           'enum',
                           {'enum' => $declaration_name,
@@ -1409,7 +1409,7 @@ sub create_parameterlist($$$) {
     while ($args =~ /(\([^\),]+),/) {
         $args =~ s/(\([^\),]+),/$1#/g;
     }
-    
+
     foreach my $arg (split($splitter, $args)) {
        # strip comments
        $arg =~ s/\/\*.*\*\///;
@@ -1529,7 +1529,7 @@ sub dump_function($$) {
     # the following functions' documentation still comes out right:
     # - parport_register_device (function pointer parameters)
     # - atomic_set (macro)
-    # - pci_match_device (long return type)
+    # - pci_match_device, __copy_to_user (long return type)
 
     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
@@ -1544,7 +1544,9 @@ sub dump_function($$) {
        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
        $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
        $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
-       $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
+       $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
        $return_type = $1;
        $declaration_name = $2;
        my $args = $3;
@@ -1556,7 +1558,7 @@ sub dump_function($$) {
        return;
     }
 
-    output_declaration($declaration_name, 
+    output_declaration($declaration_name,
                       'function',
                       {'function' => $declaration_name,
                        'module' => $modulename,
@@ -1615,11 +1617,11 @@ sub reset_state {
     %sections = ();
     @sectionlist = ();
     $prototype = "";
-    
+
     $state = 0;
 }
 
-sub process_state3_function($$) { 
+sub process_state3_function($$) {
     my $x = shift;
     my $file = shift;
 
@@ -1638,7 +1640,7 @@ sub process_state3_function($$) {
     }
 }
 
-sub process_state3_type($$) { 
+sub process_state3_type($$) {
     my $x = shift;
     my $file = shift;
 
@@ -1778,7 +1780,7 @@ sub process_file($) {
            } elsif (/$doc_content/) {
                # miguel-style comment kludge, look for blank lines after
                # @parameter line to signify start of description
-               if ($1 eq "" && 
+               if ($1 eq "" &&
                        ($section =~ m/^@/ || $section eq $section_context)) {
                    dump_section($section, xml_escape($contents));
                    $section = $section_default;
@@ -1788,7 +1790,7 @@ sub process_file($) {
                }
            } else {
                # i dont know - bad line?  ignore.
-               print STDERR "Warning(${file}:$.): bad line: $_"; 
+               print STDERR "Warning(${file}:$.): bad line: $_";
                ++$warnings;
            }
        } elsif ($state == 3) { # scanning for function { (end of prototype)
@@ -1843,7 +1845,7 @@ sub process_file($) {
                        else
                        {
                                $contents .= $1 . "\n";
-                       }       
+                       }
                }
           }
     }
index 1caac01..8529ea6 100644 (file)
@@ -368,8 +368,8 @@ static int seclvl_capable(struct task_struct *tsk, int cap)
  */
 static int seclvl_settime(struct timespec *tv, struct timezone *tz)
 {
-       struct timespec now;
-       if (seclvl > 1) {
+       if (tv && seclvl > 1) {
+               struct timespec now;
                now = current_kernel_time();
                if (tv->tv_sec < now.tv_sec ||
                    (tv->tv_sec == now.tv_sec && tv->tv_nsec < now.tv_nsec)) {
index b9f8d97..4ae834d 100644 (file)
@@ -127,7 +127,6 @@ static int task_alloc_security(struct task_struct *task)
        if (!tsec)
                return -ENOMEM;
 
-       tsec->magic = SELINUX_MAGIC;
        tsec->task = task;
        tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
        task->security = tsec;
@@ -138,10 +137,6 @@ static int task_alloc_security(struct task_struct *task)
 static void task_free_security(struct task_struct *task)
 {
        struct task_security_struct *tsec = task->security;
-
-       if (!tsec || tsec->magic != SELINUX_MAGIC)
-               return;
-
        task->security = NULL;
        kfree(tsec);
 }
@@ -157,14 +152,10 @@ static int inode_alloc_security(struct inode *inode)
 
        init_MUTEX(&isec->sem);
        INIT_LIST_HEAD(&isec->list);
-       isec->magic = SELINUX_MAGIC;
        isec->inode = inode;
        isec->sid = SECINITSID_UNLABELED;
        isec->sclass = SECCLASS_FILE;
-       if (tsec && tsec->magic == SELINUX_MAGIC)
-               isec->task_sid = tsec->sid;
-       else
-               isec->task_sid = SECINITSID_UNLABELED;
+       isec->task_sid = tsec->sid;
        inode->i_security = isec;
 
        return 0;
@@ -175,9 +166,6 @@ static void inode_free_security(struct inode *inode)
        struct inode_security_struct *isec = inode->i_security;
        struct superblock_security_struct *sbsec = inode->i_sb->s_security;
 
-       if (!isec || isec->magic != SELINUX_MAGIC)
-               return;
-
        spin_lock(&sbsec->isec_lock);
        if (!list_empty(&isec->list))
                list_del_init(&isec->list);
@@ -192,19 +180,13 @@ static int file_alloc_security(struct file *file)
        struct task_security_struct *tsec = current->security;
        struct file_security_struct *fsec;
 
-       fsec = kzalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
+       fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
        if (!fsec)
                return -ENOMEM;
 
-       fsec->magic = SELINUX_MAGIC;
        fsec->file = file;
-       if (tsec && tsec->magic == SELINUX_MAGIC) {
-               fsec->sid = tsec->sid;
-               fsec->fown_sid = tsec->sid;
-       } else {
-               fsec->sid = SECINITSID_UNLABELED;
-               fsec->fown_sid = SECINITSID_UNLABELED;
-       }
+       fsec->sid = tsec->sid;
+       fsec->fown_sid = tsec->sid;
        file->f_security = fsec;
 
        return 0;
@@ -213,10 +195,6 @@ static int file_alloc_security(struct file *file)
 static void file_free_security(struct file *file)
 {
        struct file_security_struct *fsec = file->f_security;
-
-       if (!fsec || fsec->magic != SELINUX_MAGIC)
-               return;
-
        file->f_security = NULL;
        kfree(fsec);
 }
@@ -233,7 +211,6 @@ static int superblock_alloc_security(struct super_block *sb)
        INIT_LIST_HEAD(&sbsec->list);
        INIT_LIST_HEAD(&sbsec->isec_head);
        spin_lock_init(&sbsec->isec_lock);
-       sbsec->magic = SELINUX_MAGIC;
        sbsec->sb = sb;
        sbsec->sid = SECINITSID_UNLABELED;
        sbsec->def_sid = SECINITSID_FILE;
@@ -246,9 +223,6 @@ static void superblock_free_security(struct super_block *sb)
 {
        struct superblock_security_struct *sbsec = sb->s_security;
 
-       if (!sbsec || sbsec->magic != SELINUX_MAGIC)
-               return;
-
        spin_lock(&sb_security_lock);
        if (!list_empty(&sbsec->list))
                list_del_init(&sbsec->list);
@@ -270,7 +244,6 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
        if (!ssec)
                return -ENOMEM;
 
-       ssec->magic = SELINUX_MAGIC;
        ssec->sk = sk;
        ssec->peer_sid = SECINITSID_UNLABELED;
        sk->sk_security = ssec;
@@ -282,7 +255,7 @@ static void sk_free_security(struct sock *sk)
 {
        struct sk_security_struct *ssec = sk->sk_security;
 
-       if (sk->sk_family != PF_UNIX || ssec->magic != SELINUX_MAGIC)
+       if (sk->sk_family != PF_UNIX)
                return;
 
        sk->sk_security = NULL;
@@ -1483,7 +1456,6 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
        if (!bsec)
                return -ENOMEM;
 
-       bsec->magic = SELINUX_MAGIC;
        bsec->bprm = bprm;
        bsec->sid = SECINITSID_UNLABELED;
        bsec->set = 0;
@@ -2454,35 +2426,27 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
                prot = reqprot;
 
 #ifndef CONFIG_PPC32
-       if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXECUTABLE) &&
-          (vma->vm_start >= vma->vm_mm->start_brk &&
-           vma->vm_end <= vma->vm_mm->brk)) {
-               /*
-                * We are making an executable mapping in the brk region.
-                * This has an additional execheap check.
-                */
-               rc = task_has_perm(current, current, PROCESS__EXECHEAP);
-               if (rc)
-                       return rc;
-       }
-       if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
-               /*
-                * We are making executable a file mapping that has
-                * had some COW done. Since pages might have been written,
-                * check ability to execute the possibly modified content.
-                * This typically should only occur for text relocations.
-                */
-               int rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD);
-               if (rc)
-                       return rc;
-       }
-       if (!vma->vm_file && (prot & PROT_EXEC) &&
-               vma->vm_start <= vma->vm_mm->start_stack &&
-               vma->vm_end >= vma->vm_mm->start_stack) {
-               /* Attempt to make the process stack executable.
-                * This has an additional execstack check.
-                */
-               rc = task_has_perm(current, current, PROCESS__EXECSTACK);
+       if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
+               rc = 0;
+               if (vma->vm_start >= vma->vm_mm->start_brk &&
+                   vma->vm_end <= vma->vm_mm->brk) {
+                       rc = task_has_perm(current, current,
+                                          PROCESS__EXECHEAP);
+               } else if (!vma->vm_file &&
+                          vma->vm_start <= vma->vm_mm->start_stack &&
+                          vma->vm_end >= vma->vm_mm->start_stack) {
+                       rc = task_has_perm(current, current, PROCESS__EXECSTACK);
+               } else if (vma->vm_file && vma->anon_vma) {
+                       /*
+                        * We are making executable a file mapping that has
+                        * had some COW done. Since pages might have been
+                        * written, check ability to execute the possibly
+                        * modified content.  This typically should only
+                        * occur for text relocations.
+                        */
+                       rc = file_has_perm(current, vma->vm_file,
+                                          FILE__EXECMOD);
+               }
                if (rc)
                        return rc;
        }
@@ -3642,14 +3606,9 @@ static int ipc_alloc_security(struct task_struct *task,
        if (!isec)
                return -ENOMEM;
 
-       isec->magic = SELINUX_MAGIC;
        isec->sclass = sclass;
        isec->ipc_perm = perm;
-       if (tsec) {
-               isec->sid = tsec->sid;
-       } else {
-               isec->sid = SECINITSID_UNLABELED;
-       }
+       isec->sid = tsec->sid;
        perm->security = isec;
 
        return 0;
@@ -3658,9 +3617,6 @@ static int ipc_alloc_security(struct task_struct *task,
 static void ipc_free_security(struct kern_ipc_perm *perm)
 {
        struct ipc_security_struct *isec = perm->security;
-       if (!isec || isec->magic != SELINUX_MAGIC)
-               return;
-
        perm->security = NULL;
        kfree(isec);
 }
@@ -3673,7 +3629,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg)
        if (!msec)
                return -ENOMEM;
 
-       msec->magic = SELINUX_MAGIC;
        msec->msg = msg;
        msec->sid = SECINITSID_UNLABELED;
        msg->security = msec;
@@ -3684,8 +3639,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg)
 static void msg_msg_free_security(struct msg_msg *msg)
 {
        struct msg_security_struct *msec = msg->security;
-       if (!msec || msec->magic != SELINUX_MAGIC)
-               return;
 
        msg->security = NULL;
        kfree(msec);
index 887937c..54c0307 100644 (file)
@@ -27,7 +27,6 @@
 #include "avc.h"
 
 struct task_security_struct {
-        unsigned long magic;           /* magic number for this module */
        struct task_struct *task;      /* back pointer to task object */
        u32 osid;            /* SID prior to last execve */
        u32 sid;             /* current SID */
@@ -37,7 +36,6 @@ struct task_security_struct {
 };
 
 struct inode_security_struct {
-       unsigned long magic;           /* magic number for this module */
         struct inode *inode;           /* back pointer to inode object */
        struct list_head list;         /* list of inode_security_struct */
        u32 task_sid;        /* SID of creating task */
@@ -49,14 +47,12 @@ struct inode_security_struct {
 };
 
 struct file_security_struct {
-       unsigned long magic;            /* magic number for this module */
        struct file *file;              /* back pointer to file object */
        u32 sid;              /* SID of open file description */
        u32 fown_sid;         /* SID of file owner (for SIGIO) */
 };
 
 struct superblock_security_struct {
-       unsigned long magic;            /* magic number for this module */
        struct super_block *sb;         /* back pointer to sb object */
        struct list_head list;          /* list of superblock_security_struct */
        u32 sid;              /* SID of file system */
@@ -70,20 +66,17 @@ struct superblock_security_struct {
 };
 
 struct msg_security_struct {
-        unsigned long magic;           /* magic number for this module */
        struct msg_msg *msg;            /* back pointer */
        u32 sid;              /* SID of message */
 };
 
 struct ipc_security_struct {
-        unsigned long magic;           /* magic number for this module */
        struct kern_ipc_perm *ipc_perm; /* back pointer */
        u16 sclass;     /* security class of this object */
        u32 sid;              /* SID of IPC resource */
 };
 
 struct bprm_security_struct {
-       unsigned long magic;           /* magic number for this module */
        struct linux_binprm *bprm;     /* back pointer to bprm object */
        u32 sid;                       /* SID for transformed process */
        unsigned char set;
@@ -102,7 +95,6 @@ struct netif_security_struct {
 };
 
 struct sk_security_struct {
-       unsigned long magic;            /* magic number for this module */
        struct sock *sk;                /* back pointer to sk object */
        u32 peer_sid;                   /* SID of peer */
 };
index b963c55..bdee050 100644 (file)
@@ -462,7 +462,7 @@ stop_dac(struct au1550_state *s)
        /* Wait for Transmit Busy to show disabled.
        */
        do {
-               stat = readl((void *)PSC_AC97STAT);
+               stat = au_readl(PSC_AC97STAT);
                au_sync();
        } while ((stat & PSC_AC97STAT_TB) != 0);
 
@@ -491,7 +491,7 @@ stop_adc(struct au1550_state *s)
        /* Wait for Receive Busy to show disabled.
        */
        do {
-               stat = readl((void *)PSC_AC97STAT);
+               stat = au_readl(PSC_AC97STAT);
                au_sync();
        } while ((stat & PSC_AC97STAT_RB) != 0);
 
@@ -541,7 +541,7 @@ set_xmit_slots(int num_channels)
        /* Wait for Device ready.
        */
        do {
-               stat = readl((void *)PSC_AC97STAT);
+               stat = au_readl(PSC_AC97STAT);
                au_sync();
        } while ((stat & PSC_AC97STAT_DR) == 0);
 }
@@ -573,7 +573,7 @@ set_recv_slots(int num_channels)
        /* Wait for Device ready.
        */
        do {
-               stat = readl((void *)PSC_AC97STAT);
+               stat = au_readl(PSC_AC97STAT);
                au_sync();
        } while ((stat & PSC_AC97STAT_DR) == 0);
 }
@@ -1995,7 +1995,7 @@ au1550_probe(void)
        /* Wait for PSC ready.
        */
        do {
-               val = readl((void *)PSC_AC97STAT);
+               val = au_readl(PSC_AC97STAT);
                au_sync();
        } while ((val & PSC_AC97STAT_SR) == 0);
 
@@ -2018,7 +2018,7 @@ au1550_probe(void)
        /* Wait for Device ready.
        */
        do {
-               val = readl((void *)PSC_AC97STAT);
+               val = au_readl(PSC_AC97STAT);
                au_sync();
        } while ((val & PSC_AC97STAT_DR) == 0);
 
index a642e4c..4988f87 100644 (file)
@@ -1216,7 +1216,7 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
                        goto __error;
                }
                for (i = 0; i < 3; i ++) {
-                       if (of_address_to_resource(np->parent, i,
+                       if (of_address_to_resource(np, i,
                                                   &chip->rsrc[i])) {
                                printk(KERN_ERR "snd: can't translate rsrc "
                                       " %d (%s)\n", i, rnames[i]);