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 fcbcbc35b122fda0223e22c267f7bca240e48b5b..6221464d1a7e4a39539ba30fdf40b4b00279a60b 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 e118a7c1a0928d9aadc5f4cd34d4e110a930a1ee..49e27cc19385385c25618d661566c13024a6c2fa 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 f8a54fa0d8ab57f20e3d6103bc9a79cef6982ee1..1fd175368a875107892f72f412a980e9a93f7d77 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 6fa092251586e14930c6d51d8bde1d4566512138..02e27bf1d36554d35038bdb6c962c2f091618d0a 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 3f60db41b2f0fdce0f6944cf527b3594f2ff8e8e..451de2ad8329022e3164f26cfa138f9a05dc1d33 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 15da16861fa3d6bfbec2e3f192ece4a22ace5b7f..5ed85af88789afc46c0f1065ca701552d96cfebc 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 b4a1ea76269857137a659e69102b1223b715f6cf..4d4897c8ef963284664e23729ca792f302fc464b 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 c406ce67edd0c80e5ea4f9a580c056c8cb1a9730..c65233d430f0bb6888117c251576422d3fa9811f 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 bd4ffb5bd49a1d4e79fbceff8d9dc8fdcaef4200..4117802af0f8ce560316d557045566a5f0ea8494 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 08c79d4dc54036af80bb6ac0bc8b9e6e3528fabf..b28b7f04abb8022a75bb6646c544212562a9c754 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 0aeef740a95a198eddad83113a2a301ac242b801..382b439b439e1ea8c16ee2326e1ab8469884455b 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 47e74ddc4bc9509b5856b2b8fef0067d6f4eb9d7..3481fcded4c2b5760bb40b79bde4602e369f2115 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 391dd64363e75b560f68bdd69879946b07cf03da..a46c10fcddfcf17969d42fb472af306d9e9eab6f 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 3f8a119db31b3018ad30da389bbc065eb7a35983..c6b76414172cd74455103acbec763b2e49882b90 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 18a47738d56c075c4ca37f6f724f3ca8d37401de..9d46cd0b19e3190064da339dbe108b3184e1c7f0 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 3f8a90ac47d7942d81f20ab9b3aa0f14056d8e88..42955fe1ffa056df2f412280b7d9e45a17060d31 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 8f2e5c718b50fc6a2e081876581f0788f1d25d6c..6c56c754a0b53c2947f662c0e3adde986ebdc513 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 e38671c922bc673016771d1ec94e18edf34b8b9f..7af15bf7e5ab64e9e4ad5e0abc2d1ef4be962f34 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 76be5cf0de13234ea413451dfccc53c62eed3e39..9006063e73691da7b68449955a135f7c9317e2cd 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 6886001b53666acc69f1adc802e73b7c8883446f..4a8564f386af9e42f575c6b07199225704507ca1 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 15468a0cf70e8de3583c2ad531f34e1a8992e884..c9aa878e610acd0fe9a7736456515113149987ce 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 33f31080a98c4e0a54833f324d498beaf72ce13f..1964ccd8a71f7fbd9a039fe2982d590e9c132d89 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 75e6f9a947133b5d2768cf8aa9ab73f1488e3625..d058e7c125681bccc28228f225d22525306925a7 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 2b92ce85f97feef93415fd25c9260afa6367a6ae..dbcb11a31f78167b5577c55cfe4660c922043a20 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 31820170f3068600a373915227d9f6a090cdf9f1..a0724f2b24cec783a242887971b5fc0d2e5a6592 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 9cbe5eef492b26a26a4d586ad6d96266f37de8fb..fc1067783f6d18ee7fb8a0572be4c9d81b871a17 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 f58406e6ef5a69a3d65103597813ecffdd3a587d..b8d994a24d1c18173252feedadceb562449a2a23 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 65feaf20d23e842d1d46ba88ed674f4942558c7a..4dbd8e758ea6f9691f73e5c06439fa4d2efec2fc 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 61768dac7feed7b3ebaada47062d0f71831d2748..e9a055b779b7f1158c1759ebd7cecab08e4a2ab7 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 de3ce1eec2ece4d222a2293bfa325fb585104433..da9b35974118d34d2b6fac17bb246306a6e19228 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 d0245a31d4dd15f8382e0de7087b3027e97acbc7..ef8d30a185a97574657ee66d31134b9feec76363 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 274e07019b461040660a0f10d6ed308c742813b9..dee23d87fc5acf482af0ed3d68afc26d4fc6b2ea 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 08a97c9498ff30c93310d934b424ea07e8125e4e..a24272b61f302c5aefc96b7c868b0ae297d9cb4f 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 ce2055bdc9ee82c342e35f63ca98835d66c9715b..2a48c12100c0144039a00b3182c06c057ebc8c3a 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 cbde675bc95c869d6bd06dc21b36a338a00c61b4..d86c865a7cd22b1d1892e03d3473b45767539677 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 394814e576720998c19573afcf23707695836e72..0dd92a23d62206e9d0fe0e59976c39872dee8ada 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 0f1eb507233b701c6bb7b158104e0e5cfd9e4d85..26892d2099b0278766b993cbde60d17ef2fcb534 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 270f2188d68b1857d3ef59c3a71adf7f106de2c4..cc73a7ae34bc3f92f7177bd606b698bcc192e28b 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 fbfd374aa336aff467612054031a19356b41b1a7..af591c73345fa4120e6716b37e262b35e12754af 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 1e9db198c440e3a1dac2c5bdcbe38038a31f3c26..3b4618bed70d56fd1bc79087652b7b3c10791376 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 47675bbbb316eedb7edd0ba6a0bd7982d8d982a0..7c86e3c5f1c1eb48fd4a30acba88416c488efcdd 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 e715aa930036aa1590aae77b09ad27f7c87c7cbb..3ca59cad05f33d41ac3e663070d4e44223449a37 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 4bb4d4b0f73ad00ce6e66e50a29ad877a2102c24..0ee8a983708c078b0e3e8f9b7c27548cd1936845 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 403a80a58c13bf9ef89118ae4f4b7063d28df7e0..60a464bfd9e27ce2afe46bb0de051806b9b0cbfa 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 43b45b65ee5a9da2c446d712b67ba152f1e4fce0..f9e0ae936d1a9e278ea56bb9af1d35ae8159df26 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 00700f7e68376c72d1be595c70b7fb1b7adca1b9..a4c78152b3366568edf0949935765a11a63a355f 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 8d950c778bb6c71a8ef13090f29e4ad7e224973d..36e5437a0fb6bdc281e104340b4b9ec8f4358a3a 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 9bf9f23b9a1f50b8384127305160779763d48c4b..5a36292388eb79d420db590c0ab0655bd9649afa 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 96d18c43dca0a0b47e68fd227413b7a28ea44276..d4f88e0af24c04fcb51271d50414242418f96ded 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 f970ace208d348bd0b8bafa70200da793be064cd..c7a799a095161b5fa8f57a03989c44126785aaef 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 3747ab0dac3fd66f1adf58b5365b62033b19ad62..c6d0595da6b5d74755d2eb8be8804672c862eae7 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 c32c623001dced0c7a88ed4a30a20ed2650077b6..356a739e52b2d9c446b0c720c50f1d843faf90c5 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 21934784f93679968076ebf8993c983528ac296b..bdaa8aabdaa64c4388c5ca4d933464a0293aa6f0 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 94ea346b7b4b8b7def5f003d5a4dfe8ce74623b4..1f01b7e2376b97a1f258eb2c0fdcb7abe955d91f 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 7d23edc6facbc8f9b464be573b21873b48fd22a3..3525c91204d4f87d19af240ddfbc26b58ee1d660 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 fa2b3bc22f206983bf9b1d19ba13a8df635ec3f1..ef706694a0c1d3897ab28330576901214d8d3a62 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 cfde1905d07d77c5d2513e14a3c019e1d56f01d6..6e27ac68ec3f01060093a7fb98b3ff0899f7f0ca 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 27b07730b7b8d172f4330aaea690f53e82152628..b2448487854cfbd5a36aae778be1eebec9184211 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 369ab4413ec71fe0123d16a2a2d187c2eb6603a9..2ac095bc0e250373588ba658916d0bdc700577fc 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 6ae4a77270b539023fd94dd00ead6d9decbb3778..ae1927e48cfb8fbef2fe082885245d3ed9c17e2a 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 426d7cafdab307192219807fc565537cbfee848d..3280345efacd7c6e4c2cdd45c9f7e9b059748a13 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 7c0fe152a111f394b6310a6fbd535615388372fd..fea043b69b913953c95d5c9ab97307d26e0083c5 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 f20b51ff1d86ee24b9c65a098781d58d0c688387..e05d087a6eae3b0d5d8cb2cadb3d0c3aa719de17 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 01bc7d589afe5afd4d43c0734548c89488f6aa85..504d56f8ca7fce9a674a8b8875714b446c7cb338 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 fe83b2c030764795742ee213866c78b87ca59c7c..1ed7f880b8c722142deb87cbdbb7be501c0caf94 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 1395c1e65da4546948548918473108d42ff0b4f6..efcbd86b7cd2ff0c546671aaa318916f3ba15def 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 1c1d65fb12df8cd1b5266ee4e7554d586af441bd..892b14d31405f10809f0d8d734b1c09e8923bea6 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 cffc21031e71c08968c2e82731bf5717135d2910..7d18f408b0c59820be18fd8827171c400b797dcf 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 7d772a6f88657ab7974b253b9a932fbaeb46eb48..02e84f03f45c09bae860c94ff73b96485be5dc97 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 3d9a02c093a39d948d0e43ff7b0e7da17199357e..07e8b9c5a5314ed437036ca54369b9c6ef61276e 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 1b6ac523b4584e7cf5518f992cb340d293859484..2ee330b3c38f68e5b2b3113ab1ffd56aaf54427e 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 a3bd280b53d6c5ef5015d38da47a154f60cd4e8d..ab3db76d1e51b5d4d6c92bf87c1ab8337889f003 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 7a86eeb226558829eef4cb0c67660e281e2e0d48..f05cd96f8867a5647b0adace1e3141bc1b38e405 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 5bfc33bec5d038a8471f3c2e0419e7730b509f88..59d5b748752fee2f271889b9150923d276763249 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 989e7fdd524d458d69abdb73537a606fdb9ecaea..97fa37f42b841e2bcaabbef4e07a933fad0fb73b 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 fdbd718ae5c69d1a83b20379effd882359bb43c1..e55150ed085619d5962e039e1ebb2a4fdc2e9b15 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 fb6368159dd08616da71a7fa788c4d663f7968b7..a440d36ee6187e3557edc577eea2f0c6bc59f60a 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 a4dc2b532e10842279dc8471118a4e2d0cb75309..9fd1723e62192dd524040589677541ed2ee186e1 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 036050b377cdd6458ae1cf1858bfb445a4aad4aa..a067a34e0b64fe2e6cd23573b2cbecd975cf5a1a 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 1195af37ee5aef321aaf7789971e158898169a53..0773c9f389f3b14798b8f912e009b0503c103d2d 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 c51d08d218ef9f193538e209b55e6041ca74fa5c..267ec8f6fb585a8d5763f1eea412102686c2bbc3 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 be2c80932e2673c82f1d7ebbccc15090d5dc6240..8613b3eb877c738ed71adcec2281865bcef924c2 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 e50e56e4ab61c584a606d52f42fb597c4fcd35fa..12911e7463f22c3b94830fc5d3d3577ff2b91670 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 9cd272ac3ac10342de0e8ff4f5e0e4c45a860013..60b59375aa78d31f78b832f76928fc6d4447ce72 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 bf0fc5bfbfbeb7d10563590674c2d80d9326d782..2881faf36635c522d247e8bc6953c7efce8a3248 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 6430a6383853494fecb56d562ada5918d9df424c..c58b657f00971e66c43fef5e8b2f1fed128439c5 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 ab0d0b17081677eb9a2d2f0b0ddc21c28c1fbdb6..7218c754505bf99a4a9a1888398d32d1b8aa849d 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 507e3cbac9d38a281d357f4c40c86309ce585f9e..a61b7b46bc025b217796e0a443336b63578dbb70 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 46ceb25a9959e18f235aba63b7b05a2304c33e06..6c2d4ccaf20f63cc59ed049e4f960bf546665af6 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 217438cdef336fff7e609fbb63378a541c3e93f4..c9b078fba03e4812848b33f9c3c15ceee0192575 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 e3d576567172bd9e64a854f7ab702eec34f05c6d..54388d10bcf98763976a8d2305fd2222e8b974a8 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 2ae76d8f1be1ee594a74d54ea9a64c0f068803d9..d574e0a9dc13c307f7a78894a8f08713ff227817 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 9a6f5c85f902ad997a11538a51c8015a99fb5209..a62f5ef445cfec0c06a266730d9e171dadb768fb 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 9864d27afdbe22f27319042030116caef12f93d9..33d7982be5d3aebe901b993020eb1edfb2142c6d 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 a32ef55cb244e1e581c9eefd0cebc8b71ec0164c..a4d6415bc8c4820340a299a58e7b340ee33cbcf0 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 c649108a9e9f298c4266c568ce88627bd8e2eab9..07176d92e1c92789daf5c75df5c901d7605bd5c5 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 569fe8b9b0535d362d20e3b14d215f46aaae67cb..c264e1c05ab39314f8a78c90e081fe317f4e9a5a 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 f3b583a878a6c9a4504e68f4bbce985251101fe6..544665e04513b33b4106ccd564be392e22d09b8f 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 6f1a3a288117985e1b4bc9d73bda578284c26d09..3ef73bf2e781a79dbd039c623fc20c3dd3f289d5 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 3d29c90514cc0e10093b15c40188281e9fe92e7b..3fda9a03c59aa5d0d767df04fe542d488e811171 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 0cdfd4481d5e4c4214e9dfaaaff8d965c3fbddad..1fa09a79a10b682fc74f81e9a4fcc072a5579b93 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 f05c2a802489052d1db9000dc444f09dc5321ec4..067c0f47bd0d75baadbcfc4330519eb798826c48 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 bba5db6cebd69aef528dcba68b60d0b4d5bd1581..ccef6ae747a3bd395ae2a0294fec8306604c29bd 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 f16c0d57c552f1fade440fb7a683fa649bc7099f..00d4ddbf980ccdddf23153f3e2758ac72ef90f9a 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 c9f424d5399c55b588779f252e8bb41b0fe51410..96a61e029ce5e7858d2e024c08eff817b5a998d6 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 8e27d0ab0d7ccefef5a53d42c52978200040ca18..f9fc07efd2da995d933fda955895175ec1e5012d 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 a05fe5843e6c7ee5645d9c5b71572c5d0632d4e6..f04d864770add163a966c2cd947a6ec6d4f345f9 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 4135d8c5bcae1e2d6f4278764bb42a6bbea13a33..4c67727d75b146f50fb8e0b368334af711cca314 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 810679dcbbb0cb006c619af994bb91f6e60cd7a0..9964c508c1113e4d2a4540427982e1c791c210d7 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 53372a83b6758420e7c586cdd20ceb79e412050b..5b74c36c116c7e112c0265ddf147e249586d8981 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 17f520c9d4714aa90a145f200c31675b38699882..97eeb2345b18ad897c429196530ce7d49dec3980 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 e7bed5047dcc9b8da874ef2e4007e795cc847a87..631531fd97a58dab4b619aa0c0ecb9728ddb3f41 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 40083241804eee1b48f09902e7c67a82d0cf7276..7c14a096b85eea4a3fc793ef329324989a27a77f 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 40a67c86420ccc4540c54b5c18b050e2e3338b3c..ac626418b3290e060c5feed990bbe8236ba626d6 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 c67ef3e47ad55603f08e1b8f3c91f9c2813459f3..6ed213bd702c2dc74c533cd29417a07ff79438ed 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 aedf7a8e6da7eec6d91c825f4e9121ae3774fb72..537aa45d8c67a9cb98ca4fb44c7abdf85d625414 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 8198dbb7370f1596a3b55eed4c7ac7cbaa429408..ec7590951af520378f77759abe0cc274421d6f7f 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 f1d9cb7feae65c7e54edadec884b1636424608e7..0900d1dbee59916e28bd60b7cb650cea7d9a3b41 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 277a843a87a60bc3cc001fe10529d7c053e8a7f5..7a511479ae29b615e0d8fe1fcfdd223212a7e2a8 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 39543a2bed0f43c232e724ce809f1c89d438f6e1..ac38766b2583eec5b5db349b7227e443d6b1177c 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 e69fd8dd1f1cb7bf6042a878b2545a714c7df133..9ee9411f186f9b8738f4a7320991f058576733d7 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 d32bf3593cd31433a40f7a1f70f839a1153e0a63..92a0be22a2a95bd92dd19c4c152880608910716d 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 acda7d63d6feb9bf24d481f81243e6d991931133..501cc054cb3b150d8af4bd3c1c6d0196560ffb65 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 96ea79b63df7221747e1ccd65cf1622d93dc6885..903f85a4bc0cf4dfb461d6b9daf71a2a3e7d64d8 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 a14eed08a0fcb5a4503ee59695671ae8e32ac82b..a19e0ed03d7c51eb4af6cf0960bc784696681fb7 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 be1791be627bcdd08b03ac7290741f8ae133e26b..f9b9b93dc5016b9fcaa28ff1b7b9e33da28060c9 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 a104ab041ea35477f0682a74c13f14d9eb61e2f5..2a165fd06e57085a569f5787a0788f5401e5b237 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 8b00d9a0f6f4b3d580f187edddb4bea4cddadcc5..9c849d27b06e72f9b0773fcc931af28079a4ad77 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 77bc6c746f43ac2783c837194b2b29ffd82c416c..321f11e707f22864f7d2e6263b38012577f914d5 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 9fb985a016e902d6ed6f977e18bdb78ee6ce7984..d709cb162a72a72d986c9b553a0f4aa072d27b5b 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 4fdca26eea85961c60dc5e062bc091eeeacd8403..36f1141a08aa6c84901d23adfea0dab0f7f1dadb 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 484a7e6b7f8c895de887e8d3cfdbdfb4345390ee..e88e39aef85a3cd3794c7de290c9332ab2ebfb50 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 fd3f5c862a5d92aef6b61202768bf9c29b24ccbe..c3b5f79d11681e2bd43cacad1bbdb73da88203a3 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 98039da0caf0e4ff67e958c3679540f4030b12a9..ccaa0c387076e8b0a36dc90dbb830528b09b93da 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 31207e664148e440d44790bc5f4cb85a31d66fb9..2d2d4ac3525ab5af66bdc2805791ef18db493e05 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 b564f18caf783049ee1b95bfe6c2c8b3be0bd65f..4e7727df32f12d9f17de6b1032851d600af91ef6 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 4571ea3a4b92f77004cebe725bf14c1d979b5b56..4612d13ea756640f1767f86532ca03a30d55203e 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 499344c72756dcbb6301f4c57101b4c0aa09b54c..dcffc34f30c3c130b7a61d5e8b30cf3c453874a8 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 7df2d82f2c83b2bb4c468ea08bed5e51f366a0e0..900587acdb47c16d1c983f9c36c27a067fb375d0 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 a936e7aedb103552e617010d7260a74664c6ff29..20cb98ac2d794d20de2a385555d337e97116bd1d 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 64b9c31c47fc6a153ec106fbe541c15709d8dd55..b6bc049980471892998d705b5068219c6412bede 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 4a2629243e1964461c60ae4e3c5587231bb6ec0a..76cb1f88f4e83d4177b8cb8c281861aef50325df 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 bc2fce60f9f8012484d8600fe9a8121065664498..fe79d158456d8256c0301ece36dc5ba87510d513 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 78dd163cd7021cb6d7f079a443c07d0dc5ce6562..2b2ec1057deeff1c9fc40f963da81cbbd7267de5 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 60e2aac7d06ec955e873f40dc8c3cd5f97a3c947..bb23ed2a04a6e8784c02fa6fc823410b35687887 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 7e9764937d064b6a6f861d9bde0e739ab820af87..b154938e88a4f0a1c287e69f30f37dc9edef1299 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 cd3a1e742a30ef255ee75234ecb9d26add0f0c71..7f8b0093c5bc5e16857338950706ad735a3b187c 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 e08dbe08f46dd0100b7f31d1b3a82ce2e640b5c0..4bad588d0e5d6c53499aff9dbdb65dfc390aed35 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 ce44cce012855a22142eec77fcc83e38eb88b39e..184c4129470db801c2146d485ca98a95ac50b0fd 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 7665fd9ce559c49a153289bd64e19d6255134c11..19b1b0121726faa5b5d66a9d22bdaf08192af351 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 81fd7a97a93df5e08574edd6b3551728e626225f..9abed18d2ecf79493b3d4be737b0db25ee60dd22 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 dd8c6a9ffc762a2bf8e071ced39cfa467b6920a9..b45a45ca7cc961c6152cb702cde8ae768b8b156e 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 4844d250a5ebc78ca09de77248d39156b08e0616..3226830eea08432d144a0c04e208039632cf8b83 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 ed6d3174d66050f1ca3358909469770682111243..69596f6438e9d5a6d37d4dc38c931332ab5e4d1b 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 1235135b384bea5ac1e82129926e30c85d36bd9f..442e2be6052e330f283379b3cc9eb02f7a5855df 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 efe4adf7853041bd61c43fcd87488b72a42bbaba..74039db846baa3eb19c4574c91827f4d58cb9050 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 87727d84dbbac9bdd013aab25e78122976b23980..f3759dd7828e585ed81b0819e9908fbf546da543 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 375aa24d4d7d88ee8e2b7fb437108db19349e916..fdec1e2dc87183926cac41e1d62fc961e9aab851 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 a6f2dc66c3db12b09606218e1595e147b20c8a57..9b1e2f5ca63049dbb1dd2dad9e642382374fbbf5 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 8c16359f8b0189c5a77d6eb19106ceb21231c0ce..e9adeb9d172fa80c0f6140a6fcf4a034f4f0fdca 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 0b6c2096ec66bb367eeb0928e4686eec23e68e07..aad4a18aafd662ff6de64d6ae1e5b328366b1540 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 8a2e2657f4c28c0c304cbe1859861c3f2190d5f8..33ace373241cb4b80997b60bb52b29dc46c87f8b 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 d890b2b8a93e94973f345068f95b75e9121b679d..9a2c7605d49c930a45c10aaad9b3cc772dd2805e 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 47053ac65068566fa6675fa2a5ed08eb8199684e..ea2649ecad1fcccb9f19e33cc8bf1cce9276bd96 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 b102c7666d0efcaf44f8a6e534ff340352b23489..c3a3499bce2ae8c3ece665ce11f98b6027a1cd83 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 5a06d8d8694eb3cff0322e479a089ffb5d7021c1..2512d0e6155ede3b55f1996b13fe69b6b78eda0a 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 cdac5578fdf220caefb48a3356710393558372ff..05789e50546491df632331c58b6b5ff3e867f4fa 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 d3cba12f4bd95c38c110327bfbde76d9d6ecf1af..44b248d51ea3174ff33d34024ac50b43e6bec672 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 7dce29277cb748e51e1ef8a3956f618cddc28818..f148dfa39117edb097bb5f481dcb9c8bad05bd60 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 7e98434cfa37783b1cfa45c1bd162e9a56f14bad..9783caf49696a8cf4cf74a77d907758c59ba846f 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 9e21e6c02f80df8af03aec9fdd9f0d8cd6cfd062..0f915ac3102e21dba8a8b9fc5c9a5624f20ff183 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 626508afe1b176ce9dd1d2b0fcdab52f766dc1bc..6a6a08441804b0bd1d902f6e2d691976d5471e9b 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 b8953de5664a4cdf091374af819525518414a6cd..b508812e97acc2bb0d632b0a49bb5f120a0439a6 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 df9d6e80c4f29f88fb8f96a542cdbe89c5e08021..c3267e4e1bb02d6c7bf552b1fc818aa4308fa0c2 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 49fa1e4413fa470ddf7feadae6ec937a22c80e6e..a24200d0a616d8285e3f597d9addd6803ffd1552 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 76bb5f1a250bd52f43567e54bcf6f71efc720344..9f691cbd666b4d6984423e2d5e07a50f1c4a60ad 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 ab07a4900e9aee0a472a8c99abec8750b52b7765..0c21bd849814fca86ada5cc087bb3a80f42dbddd 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 2582d98ef5c3308c16214b75f520ec1abb1b97e4..4ff006c37626b92c8e80085480fc01f090da1cdb 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 6139f06d7d2b9b398bb1649f14f87f90d1c513f6..94d5ea1ce8bd9b9c9e14f05694e699c387eff662 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 40ae36b20c9dea2811491e93e4de9ceb9d0c3ef5..7ef4b0434a3fa74cd438ce5d8abb45cc8ed5df22 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 89c46787676c9d9d3249597b38ce788a56fb5bc4..49b597cbc19a076e1ed2e737ff68b7b653922044 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 c8f6286dd35fd29e514654a69be5067fc0aca469..308f773ad566b17b2f394273fefb5f6d1507f652 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 8bf02763b5c72fc5ae116b113835cac1b8544c7d..6290c9f7e939c2b4b21c04d97879c231063e2b24 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 4c28e332ecc33c656e0b9d55372db514cd9d7798..14beab4bc91cba2e21a7af20a8a6cc6dbe8241b5 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 b664708481cc8ace4cbfb0bd74f3884e64900830..3c128b692bce23135343064458b501749f7d0724 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 2f1289eebb3c5e597ec5ffa828606cdb1bd1ac85..222a1cc4aa28814a118c9424dbe2e2cb8deb5fa9 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 7e7f913ba7b9e47712a9dc6cfd0d4ca5764bbe89..317457dd401451b2797f8c8135165d983f09d5f1 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 aabf1e70b5280f70210c7f9efe840d3964ab1a31..dc59da675c0807e3913a1dbf420bf2d15817fbde 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 7d93dbaf628deda9dc32811b5c0ed95c023ea500..3eefe2cec72d1aef2ad849820fd3b683d7704645 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 57ea71a7bda5049210b418cfb357a703a945a85c..310b6186c0e5f45aa19f11654a49c38fcb839458 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 cf075c34b578c4e4048b47da205efb882acff96f..6e79f5675b0d9b804a8c8465e07f0884d59dc63a 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 396b54b0c8474cc6fa38fc04aba030c073a5641e..6f6cbede5135cde8cd7f9a8a2b68c6a77b7c8ea9 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 daa89ae57123b52b97c0c4678c41867118ed39f9..78943e064b5977babc6d3d51bbd1ef3b113dbf08 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 ce0e9b6ce83378fa416e9f6ed46a7562a0c64689..7d6f521d02ea128adf2fa0472f9afcd093186476 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 25ccb0e475936b93e1fbda46d3b5154fa98d6e16..643252d9bf3b61e0b2333a082761a09950461c38 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 202b7507a357092906680bd9e937e7882e428324..48723d6fa60f249343ee4bc7b065aed0150d8c01 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 402136a5c9e43c1af7ff107e8e20cd992657c30c..4ac52d441e472d86e9e15e0f48d761e6a3c51223 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 d2a633efa10ab0822c3f8a6431a98f413c3b24bb..d2d1879166436cfee7f82c6e0fa0493cfdc8c3b0 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 50d6685dcbcce801682c9600a81be2a98f90f8a1..ea9277b7f8994120aed0b3d058da25de31e99c57 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 a86a650f3d6df13684cb07526469d9e8e7d283e3..721787cc5a1c71ef69e50d777cef841ccf23c637 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 ef4c687e7c01164af3e9ecc7417dcb8cb90d63b6..abdf1ee633e7ecf3dced11ca4850237e3b2fc807 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 84565c8f584e0361dabd8af6d26ab07e0083fa81..1d11c2a9525d3d1ab7f158efd6f96df53e541949 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 c143ecb53d9d1e750975b4caa3120345a69737bd..4ee0f934e325388c779e20c05e32098b55ebe1ce 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 01e87170a3a24e20fddf75ce22c6c3555620a20a..dc861446d0562b991427433df7605111429a818e 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 2a23b74faf3f74dd8d406ae15d9e950f640ed210..4a5b79569aaaa463461f55a25dffc09f0d9b3b32 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 4f365bff275c7881472ad1173bf01b1cc2bcd633..e88f73ee72ce7ae00f30e41a166af9720abb4a0d 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 caee16a3dc624d48c3fbb84de7678c9557adbe5d..1629b27c48ab7d57a73e433156269a323d4a900e 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 ba80fdea7ebf09f43e925ca3ce38e854a82d4622..3f9d704d2657483f739dcced896a212413665882 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 a4f80bd735f1e94730fabd434c7615b7c7972186..38a4e55f89539b90f514ea9f80b77d4f4d139475 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 96eb48258580f5a0b2b3d5a90cbd7e43a0c203ee..822e2a265578ca798afe71ee7279610de496ada2 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 b6888c68b2244c5f4de0caaea4c0cbcff3d37b14..bc3823d35223362d97a0b939f59ca687b1345759 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 7cb98d25f341683aaa987985acdbb34575800dfe..8fd71ab02ef055df625a0182cff83bd795459b66 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 8ec75dc08e2cc3ea16f4fa17335a051fa84297e8..91145698f8e926c7265e3d1581abf61479d62b9b 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 624f0402ee22e3adfec84abb7bc31ac46b4d7e44..da1fa91fc01dd42a94cffe047459c9ffc6a00136 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 a601c9a33541cb7362223fee666de8f5a54d7284..65dc844b975cffb00a5d45251c48f6dbddf1269a 100644 (file)
@@ -9,7 +9,6 @@
  *
  * gendisk related functions for the dasd driver.
  *
- * $Revision: 1.51 $
  */
 
 #include <linux/config.h>
index e4b401500b019e61b03ec8e5cf30694a8d42923f..c20af9874500019fff41d20b7d200cfd84f187c1 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 9396fcacb8f8900338b7479daa807735dea6246b..fafeeae52675ea396a1c71c67f9395fc635b78af 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 fff9020d48866bd2910fad640f105a9ccd0032e4..2d5da3c75ca712cf1f5abb3632993e8815ffa97a 100644 (file)
@@ -9,7 +9,6 @@
  *
  * /proc interface for the dasd driver.
  *
- * $Revision: 1.33 $
  */
 
 #include <linux/config.h>
index 1f060914cfa429275333377b21dcae3d27937135..606f6ad285a0e3db07ea97f919d467c35818d6c1 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 c570a9f6ce9cfcd499ca50cdb64cbae6be462ecb..ef607a1de55a30707ac2098eeea64a9f3cc41b24 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 5bda2340a39d93a843fd1f090da240f0d1c6af36..a317a123daba4bf0debbacfb4e9d59b6170e81f9 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 20be88e91fa1a7abff383f8e0aac20976f8beac0..682039cac15b7d0bbdf68b5f5fa5040a986a7bbf 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 fcaee447d6fe58122a4f8c5c9aa8855ce76c64ab..b3569c82bb16a2f7716147ca307ea1449b60db70 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 33133ad00ba218a370d547dcc8d5be80b8835eec..3d0ca054cdee75fb2b51dfcad55f92889216874b 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 8f486e1a85075657fd890c94b3016ab4f99a80f1..4ea438c749c9c6f4764ea1056c1baae1d1c52446 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 cd2cc28e16a70181780ac3cc2d425f4422ddb035..5287631fbfc8439d92c921c6664998bf1eea5caa 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 72f27c151c09fba2c78b5e6b3f1dfb0ef9484f4b..cb8e2e672b68664680dddf99832ec9940d980f66 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 6c077ad71edc41e5c16e24ae270107a4bb490828..8013c8eb76fef98ef9db541597153bf164b8dde3 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 2cbb724791a822bf34d3bea4cc4806140f7b5dcd..92be75d99a56eb84743cdea07e91e445e3e455b6 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 6223b06d27d5d767a86333451b3e11ef1d23d80c..cbb86fa5f293b71a244b37c4d9a39d323665e46c 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 0b03714e696a12c7960a54b1164b7efcbdedcbe7..07ef3f640f4aa73ec17460a93ab020f21a9bfb2e 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 516108779f6038b9e4c4ca2f9e68997b345ceba8..1bbf231f8aafa125b87e7a2842e51642eab0fcc8 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 a67e7e60e33009b27f7812003195dbccb93737b2..062fb100d94c17035c5b0cd30ef47930637f9e3e 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 8b0218949b6287eb9b4480821e0d197a6c82414c..3a50b190328792183aefa1b975ab31ba43852403 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 77be2c39bfe40df778ec6c021ba7bcf37b9170f9..45ce032772f4e6a785bcdc42f9f68744c44dc2e4 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 fa385e761fe177034551ab5a82038d8ff38f3693..ceb3ab31ee088409abc275dd0b0361ad1033fd89 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 f87c785f2039f04ffa67b1b06bf41c8bd24d3535..dbbcda3c846a34fa29f91a02cd0c698eef99a144 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 3a18443fdfa714412f3030ae4c34fa5eaf038365..5e6b1f535f625b700496fdc909328a25b39dd6e1 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 d7f7494a0cbef4db65233b1fbf8030b054cbb593..4141919da8053c56b3db2e446c62fadbba11ed4e 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 2f54d033d7cf8925502ba7a3f09c81c7599777d9..7d6f19030ef97f013059cb52cb46b275ee92f7d4 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 e70af7f39946b6fef7748d760761b74b50658cc5..a86436a7a606bc1ddcab90f2e3a1846598c6eb05 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 3df71970f6010de60801b4e43f68dde8eb08e941..969be465309c2a266a0f6f317d169ef8555bd5f0 100644 (file)
@@ -2,7 +2,7 @@
 *  Define constants                                    *
 *                                                      *
 ********************************************************/
-#define VERSION_CLAW_H "$Revision: 1.6 $"
+
 /*-----------------------------------------------------*
 *     CCW command codes for CLAW protocol              *
 *------------------------------------------------------*/
index 0e2a8bb930322ec9d4f6aacc4c8c5924df8a04ad..e6e72deb36b5559f00c62dc2837818e4b05d46c4 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 7d6afa1627c3534cc86f1805f9f4da45c92fa47e..413925ee23d17c31761df918eabee7534e25b743 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 1901feef07d9a83d7df43447c5c32ee13924cf04..af9f212314b3a3c00cf5e298daba5f95d9b1acce 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 ba3605f16335dba918a656bb1b94589fb8008490..d2e835c0c1344296de249deeb11e804c691534c1 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 93d1725eb79b988db630d07da7cb9e605eee5c2c..5cdcdbf92962ee89e8be5534ed5d5152f7a5a9a3 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 84b2f8f23ab3c93c121b8a0c8e13de78472c32a5..7254dc006311e0e751024aa12fac867d86cd9cf7 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 2014fb7a4881f131052c79716e37f920dca4e156..b12533104c1ff5b38242791d22d0e94c0f0293de 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 24029bd9c7d09e682fb97ab8397c4ff6b5c99b51..6caf5fa6a3b525166b4af47e4b29656bc88be74e 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 5b98253be7aa43b1bc196d92fd2c4e7dc8b0f477..af679c10f1bd307deea0674458fb96f9ecc866b6 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 ea8177392564194f4ce9e5c7389cfbda1e14550b..760e77ec5a11aa52e4907701372a3e6217fb2889 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 da8c515743e871e4066f3dcc583d6e4b922838ff..6229ba4995ad0e527e496f5b1775f8d90f277724 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 a7f348ef1b0891c556a8d8da58ff2cfba650f176..08e60ad439167ea987eaff40249dbd5db006d1af 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 ac4c4b83fe1701f297329c03e1ef9f2f1a7a752d..71d3853e86826da731b906ece3bb4a72cdeecede 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 d238c7ed103b2e6cfd3bf73e808116bd4712a5b7..9a064d4727ad196821b62cc89b2d038d0f9bd190 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 f94f1f25eec60a8e57ba9d311a90c47b2df58594..b023131277807f4d343cf3b59eaf9f8c19855331 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 e1b51860bc57b803258e8c3627b7af371b93d849..cae9ba26505689d5cd1ff57679def80211f5fc86 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 c0b4c8d82c45e3108927eb6c2d27c61147199db0..e422b41c656e26ba11185c225f350c0113d9cd38 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 97f927c01a82b57db43497217e4b97377ab47866..410abeada6c4990ee97df032cc25703a517ee675 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 5f8754addc14fe62fc0f4d675fc6822594644579..77c83209d70ee697da2abc2ad3c4c73a042aeaaf 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 864cec5f6c62c516aa91ed360ee5fd80f3f0c899..011c41041029addb84d96eb478bd533780f261e2 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 7bf35098831e50603107d74befd95314d4062893..3c6339df879d185bd45f7eb30cc1dc644af1b2c0 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 0ea185f70f75277f49a26221640db8c3bbf8859c..c1831f57258536b0f484a34b7c30e370e468cb48 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 3c50b6f24f5170aaa3093bbe3fc86f6c68feaaa5..1286ddea450b9e5b83d7642e9caed26c9817bc16 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 206518c7d3322dba7d723ada73df1d3b48dca6f8..e3f64716982786f23878d4554dc023ab25513452 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 d9ea7ed2e46e9ceead16eab686ebdff3086ee8fe..7abb42a09ae2e9a162123fc45fceda10500994d8 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 167fef39d8a789400d0a41968e23d64f7972ef79..95b92f317b6fcff2e0a073462d920434b74117aa 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 0fc46381fc22735d1a884fe24f913e200dfbb770..241136d0c6eb689b7ba3fcd3da02c1e459815b58 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 95599719f8ab9e02c8294b53e3885c7df7087c6a..4d7d47cf2394a38ea9d4d760cfecd12bbc10f149 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 9bb511083a261a4a40c9506a26d0f26a8a1d559a..e260d19fa717f212e60d3e7bbb40d0de652a47e7 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 c065cb836c97a8bd611dd482dfb5aa8e2242d84e..da947e662031f6114b02121591b0f912ac41ff73 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 c3782261cb5cc9f61dab8d4948e61cff6aed47fa..c1ba7cf1b49619367973ed84b02d915c9a54b2b9 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 cbfab09899c89ca7104dd3bfb4abc8c28f5e279b..9f0cb3d820c06ce1753854e3946ebc4add466cfd 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 d719f66a29a4f9d7ebde41e3b7060d81f9070e78..1c3275163c915fd9fdb20c83aa80cafad19cd8d2 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 3c2cbcccbf54c559598e663cc5caa522b2f42f55..e0803757c0fa054c8f23df5f43f477a501518b14 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 9f262250043a5d006e99b0b3850f3a351b4821f1..dfc07370f412acf1231303ac9ce5e3705a53d1d4 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 77a5e2dcc0ff56002718943dc41d31fc608c9fb7..6622d55e0a452142b703b9d1e331d1ef23d6b8d0 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 3924eb38805c5e24cae27b148af445f20ce73477..f401d42db21c26674fb147b599a4aabfa71cf5ac 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 2f50815f65c746d386d051545fe540637676ea9b..ad5dfb889bee81c6d9ec73d36c0d7d5c50df6696 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 19bd346951dd0e2073d33e8b5d964b1fc032c7a1..a800fb51168b0bb64b0540fdb133545ac881e4cf 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 69ed77fcb71f9076213761b2a18025a16408d406..7955ebe8e1e8d6d8be83c5f659efb878c8cedb85 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 2cfdbef447db6ba7c4f7b774fcce47fe5f53e409..1d11f7e77564e9d83379532bc892d06da4b7a4e4 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 3a3204703b155f374a7cf99cb86dcb2b028f8c05..be14e2ecb8f796b6bdaebe3c4926481160a238bd 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 bef1f9d369b6b90779d13f3ee54a53c7a105bb3a..58bc17591b54ce56082d67aa937f9a8f7e51a0fe 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 db8f5ce99ee3f815a018a1264bb3c50299a7ce99..342f77966a5ba6d066f2ba3eb96c3ba9801845ef 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 91c4f7f484b1271d37cf7b7334998aa30cff8344..8ad3ce945b9e5f36b20953af23ff1717d64403a4 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 2567e29960bd1697565490d2840a3312f6414ab1..7254ea535a160c81b9b016b4a254a8468ea96028 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 cb74fccc81007130f602eb75dda433a5d890f113..9cb10134510739933510327cdfaeda8db636c199 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 bf360ae021abb0582482d4702e903a9eda4ac7f8..ebbf7e4ff4cc653e6639caa0ccc8ae5c5867f267 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 196a6344b03703ec9b96182d747f20d5b50eafbb..757242e522c2cab761b8bddc1eeb821f8d5bd4d6 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 8763b158856b56aef0dd856c55cafe1a89c11c43..2068e00d2c750a09c8b733aff1fa01af385a395e 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 a4137c985376b6eabff30ed6a366356eafc4e87a..db38a61a8cb4f2cf15160f4406a4749fcb716ad9 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 b1e5365be23005f11957da625356bd7c0f147c20..11bed07e90b7ef8573ae0d5fc5afcb7f3211ab07 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 f936b691232f90d4d020998d8a3420508b36cc85..924102720b141fe969f0891924fa1384e8269a2f 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 67e046d966254929af3e88849bb7c8baa88fcaf5..c328596def3c557f25c4b6bc88ec3bba94bfa3d8 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 e64f802bbaaa165884bafc117082eab38c23f701..9df9e2ce3538e27a711e7ad6ee4fc5aa595ccdf3 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 45c0b233d0bc239ba99acbf39b8765f7e8bce7da..7c3983f868a9a8c171d9d165438abf5f187be6fd 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 c8a32cf47d738fba4e991d1c2f37e09c6a5b08c2..cbf825263f3b4a89512cf3ea18afc7aa74f92571 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 822b9fa706f385f789d6cbbe125b971d586e4ec1..eaefeddb2b4ad48aa57e124a6eef2dfefeaf472a 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 5b0edd1f19213e3d97c173c4659659e5c63b6891..4550d71e474475bec487075c96d1c7aed7df8d88 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 ce15d9e3962114f5f49d84df48de41814291ce79..7eed0b098171f6b37670ebe3db4b24689cfa68ad 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 75db2f5c545e999d2b06b313560bf3610447bdd5..f47dd87c05e7566bcb58e054fbcfcbd7eeb06613 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 3c688ef54660e781c638fd633dde208a57090e2a..0cf0e4c7ac0c751645945efdf29d582a1ac3ef36 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 e5e1ca44e1eea831e17814c84d81db91b62be2cf..86c546164da9f1dc78b98d4f2982e9b45d602d0c 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 cfbceb5047183e3096bb494bc3e2419c8956cd93..07b1e7cc61dfcbc0ab5ce762be6d83ecb4f1f1db 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 511ed52a580747be705be11e3f1d9dce325af7c8..a487f414960e5e9a6553c7c1b7dc7fe2042253c2 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 eaec9d531424cc8359e273629d0eebb677725360..d6d166c0663ff664930b06432b4c2753c93631b3 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 0878f95b54499fc0c26a807624c3cb1345821b0a..e0230249fa0fb55cb9cda06f399b2c8ee0318e9f 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 79d8a914f9d0f4ddb213fd1bd9d5b63f68c39138..bad066e5772acfce0079784ef2fada7c73a9a707 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 32be4c14cccb50044a77b1c53b5b9be1eb5cc81d..35266bd5d5383ba75919f1e285601577ad3abd54 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 a91fea69ad63597b938b9afde16260ebb358d476..e67bb099781818339b6a1ef6342694c54825860c 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 f63af081d4ff8aaf219e2255e06e7a0c334f7c09..71a46fcee8cc47d3b7e0cba5cf0aad80786f8d2b 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 4916847d84ec9321a58629c0eef15543e73d2873..5866a7c706a82d627e71f597fe89970eb493d10f 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 a2333d2c7af0be4712651b2780b7cc10566dab3b..5cc97b721661471b38a57346a6bebb759fc9ec10 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 3574ba935af8ea451741de17ae26b4e77087fe68..4a602853a98e72f89b94757c4b9e56b87587ad53 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 a3e0b7bc2d7bd1a71b31b0f4be0e091ae5b20b9b..210dab5879fa354bb99031f3e0981ca40e14c446 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 78aad9582bcfbef87399ac33e02fa60b39712cdc..7d0700091f3d6417e8c37ab6919b6a0de32042a9 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 13b1d3aac26521cf5b5e1518aaf9d062b5720dbb..7f96f33c1bb1c815b09f88c5458b556ce6c2fc81 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 221999bcf8fe3809b943e4f11c53ba4529810f52..7aef7518b0d1cb4291d38ad3f4e860d67dbbd9a0 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 bc36edff205805517a489e945826edce91943640..179c1f065e60a5662498c006f28c48b83828baa1 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 9fd1925de3611feba30e95ef035d01e6658863e4..0d38f0f2ae2975d41f08fa059ab796385be2e71e 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 3490022e9fdc7e923d265eb06e635f4dc32e5026..429de2723a1c4d95597038625db48e52a966cae3 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 8ef999481f9386fe351e77e0a7cd9b98d6250d73..ce7b2e4ecd17c33a6fa12e2451f0e6d5ba276c1a 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 587cc6a9511461732d355f7c32b4dc33117d52b3..858048efe1edbd4da7a5d2d49b5fb587a333ba28 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 6f22b42d93372065918ab21548f08f7ab74908aa..87e4e2cf8ce756e96882d66233360ec82a30df46 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 eb4883efb7c65953534797dc913752d5dbcefddf..0a2dd6c5b95fdecc116e78a4090552e31be90eaa 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 1bd93168f504117440acf790f2e0bfbe384d6c5c..ff7b60b4de37171d116bf34d2b9a5abf36cf5926 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 943770470b9db316af2ed25cce1fca9296df43a2..0717abfdae06f1eed3d132cdbd7e7a3cced60858 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 d4a1f0e798c1bc461f737ec343e92d196608183f..d0490f67f597fa1be96f0271be6b99339216339b 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 a9e070759628558c970487fa48209d40139aa4ef..80737c131ce70fe0b60f2053771980631c5fcdb3 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 2892169eff0544c52b6fee7847a9c7b192f37c49..1f14bb4382f6ef5bfc6094b1b766d432454e9791 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 9a3665b34d97218dca97b18bbf60740bb45dece7..bc67442c6b4ce92f227cf62c81b7f507c11cb6e5 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 aaa009f4a7bf0567afa499966286a996f96fb981..c70ae81b5d984d14350d047a6265bb1d079f17ec 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 3639c3f8d3578f0fdb9fa5841ed04a410f379b99..36e476dd912388d0257ccdd82c15af888c5e8256 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 af0a41e7870e0955eaf04e4e63608be04150982d..04631dcbabbce2673529aeffc7e16131d796d817 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 c1b47d74e206a468fdc9c2bce7792d19740256e1..7860c8a5800d5a184adc8abea047dbef16c37b89 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 7d2a679989edf5d8b11a803d15d13dd79b5eb8e7..830d2c982670db964f0263b1958617342c3f7f85 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 7af1883d4bf9cf127c183089ef52c8fbd5f2703d..c1211fc037d997b8a30cee323ded090d72d9da63 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 1adacd60d713fc24815cd8fd1141d3852ba79e33..ff8551e933723c25e16f9524a88458e413e4454b 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 5c76e3aaaa5e9aaa290936da377ed574011500c4..42d6823b82b3d4efac2658bba02302c48f9baff1 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 b9fd39fd1b5b3c37c9a8dc6c729a20bfc6b39fba..97bdeb1c2181650428841826f1c185f53ee81be0 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 dba4cc0260770ebf8d6c39963cd8345c80a98b2a..d34848ac30b0a9571db2dd6cd596cdf139b5c8df 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 319de03944e7a39d9d0bac12a46afc4f8c32a023..7135e542679d73431d145cee917da3fc18a492f2 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 081796726b951bf449b8b827b970cf7eec1b8571..dad4d8fd8180afc8ee779a04b380a7d364cdc9db 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 9a4edc5657aa695cb7f98030084433f6369435c9..0aab7d24c768d03c99c5a67aa154bf2df1e4e640 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 c32e1f7476da46d67b4e2f8336ab8cd5929b1b75..67b13ab2f3f5a18ef80456fc9362a701777ce797 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 2fc110d3ad5ab05b960578280f108de6304b9502..ae7a1c0f57488ca8f28533d767a21e61f8ee7143 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 08ca0f849dab03ddbf9688aeb1e77dd811dbf8c6..3a6687df559419c0cb6206fca819dc79f21c45eb 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 57e77374d228dd083053b78a26d331a44c4e20cd..ebcca97006712e3da3df4b8508f0fbf51dcd726d 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 584b8dc65119f80187efc3aa2368125bfba870f4..972ce04889f8a9d602c060e896c4efa83b2ab1af 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 77cd6ac07e3c5d4076129c13aad23211197db4ab..db280ca7b7a0f1c0ad7444fa38801e40cc12eccb 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 3ef2c0cdf1db2fe26c6235ea3410a36e543be617..e9e5bc178cef2e9a71eb2e70e96ced328ec7d00d 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 b6076004a4374d54c3ae641a5f606e8a0c0da529..782398045f9f477fa952294f0d31fbfa959ff5e2 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 a91e72c41415c213b8ece5824c16f4873161dc73..6f7a684c3e076fcc2467766e136a08f2ca6d90c9 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 4dff8473553dd9fc8eba3ebe33378741c8bc7898..925f5aba06f583555c4f521c7bc2e809caf9f921 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 3b3c7b4120a26c51fb8e8af875f75aa02a201242..697c5e573a115cbe1d38548448032705f4846543 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 1bfc105ad4d6811adda2d403870b591bb33c8a6b..37d2f0ba0319c28e73e688394c27c3f65ab28459 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 21232ee2974cb56902b3e59c6ef843da4fac169a..0d3d2cc5d7be7dfd67fb4b4b878abeb97683bbc5 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 d83adffa925f6c68f82fdae5cb527069a6bc5784..3957aa1be0f2ed6644acdfb248c80537d9a12cd2 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 8af665bbe330b40478b7d2588a263ccc8849f739..51e9cc06f7e313ebeda40572114d527399afb5bc 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 359c4b2df735917ff685920f160a1fa7ee1c7476..3ebb6e9cdf92cee2179fd3d43fc6bbbf3b50b26d 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 e5cea0e2eb5700195d24e858a66404048af9653f..17d60c1eea7eb6e9713b59b20aadf2712d03014a 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 8d1a1c357d5a6d7c01b39fc7b53036a5780f218a..c81397e4714ba42791c11dc9642e1b9634106dea 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 18070d5333cfac6df58fe9812704a767be62fa2e..46c12ec3ca6235c729ca9452fe43a11f25e32fa9 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 86676abf3547819d29813ea9532838c9d5f43c40..d9aa7a61095d3e5b3833dc7fb47f54360c98cb9f 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 d27c5aedeaf89fd08984c85671e36d99b0184bee..4a36519b5af40f067c05d80c3c1310cd01a4d612 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 48e3ec39d4e20a8006edcc014674cd63478aa999..b1dee78abe04ba961da5fc846a7ffde87d9d9adf 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 a45166c3488ca3c3177852e92ebd88ef5d308e3c..7d953b24f2f2a168cc52fe30c06e53c090c35bfc 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 8775999b5aff7e6410419958ab0c4f6e04bb861a..32ddf236cafed990b242404473cc3dc41f82f102 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 927eafdd8c73e1541f93381637bcaf479019b32b..a0728f0ae00cdd72ea5890aab6835176f9e192fb 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 bff9434c8e5578fcf0648dc6c6e09356e61613aa..9937fc64c8bf3c34a3e7a31b1cedaf0ee22065b3 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 8acbfe205bc760632397e9d1b32ab057129bb951..47a6ff7941712300dd492b2127b1b8243d47aa63 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 3f5317dc4c291522fee8ed8fd56e6749f5840bd3..f3b91b782671f4e6d14e12e8c67d80e2812800ea 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 449b2501acf365ac0b105c0bfd4d15b0fa4bf8d5..ad2f4cccd3889d7a6b55dc973600000deb686cd7 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 981d8a5fbfd9e9dd1a361e6939839d1cc629baaa..331d4ae949ed3ae175f39ecec2df72e2e72af125 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 541181695040b865ec73fae31b2c8616c0875d38..3094970615cb9c8ce2aefd5013fc0181b2a230f8 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 da46b351e188eed017254eb28dad90fb4d0cb4fa..dc7a069503e04528eeb03dfae7b55237e6ead0eb 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 10bc1bf23b3514cb9bc50acad7c47f3dc3998583..f2b4ca8692d822c65bdc215a164fadd3d8bf9a73 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 00d45f8600deeccccfa398bd79606f9168ec6296..ca40f16370f1106bb612e0dd87af0b0401d8c3b9 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 0eb883f44adaee3bfde6c2879ca63a7e98ae668a..e8e575e037c11352b1d1fc65c51192167ec3c74e 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 21d434d81813dde3c207d778ecb7067944092e43..1807087a76e3dbe0f218b73c873b172100ab79d4 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 5b06f9240d05caa2b348c7cf55cf520ff2ca2240..ab173b30076eb1b7ac2ec3a2fe257a78863918d5 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 4c1b2bd2e2e41edcc0378b2a8b8aadf90efe7319..f9907a5cf129f42057d590bd7ca3c6551533599d 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 b28151d1b609b9ba3554c6625f7662a0c16b2808..b1ec4a718547316c62cf39fa4872ffd7651424f9 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 dc301e567cfc6c6ec5037b7ff26246d72276e09b..ee958f986eb8a37c86422b837906f71d4fd1f508 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 5d02f16b7d0e7b007720486d7f2722b37f58f85e..4de9fb56ebfc02294636e65b1ca92303286e2b4e 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 b2187175d03fcde37c6daa66f240b0cdb36c4a71..6761b68c35e97182046e1774d1755ef810423bb7 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 996d543d6609af9d00fa70bb31a03f7f6885314b..9d996f2c10d5775099629340901c03bbac95774d 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 4af321fae3901a42c0e9b1473fb138d5ebfb696f..744210c38e743600ca283a8a73ee1959e8678047 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 2b972461a030b9f2cfa92ee4aea4a62fa2c8b56e..0ae0a97b0fed05c5ea8129b018d2179eecac87bc 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 bd410e06db73f1f267071450eba64d23a605a053..e3c8b5f1ca764261f9a89c44ebcc7040399da3c7 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 6c187d5fe95170e337ccc09f86457d993d98e207..579195c2bea3030bbd2922158cd3289c683d67cf 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 266d0ab926635fe760f646b00dbe8fe974d8124b..d8467c03b49f69d608a7aa506735cfdc5cf53f76 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 ef78e3a42d322c5435fc200f93f5c93a18ddc75f..93b5dc4082ff24e3e015244c31ff3e7a35d757d1 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 bbc442b8c86722dbe69651fb593bfe7d3f6c936c..1f3bb501c262bc9b94ad9e0b73c5af8acc511c90 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 3dc712f29d2d60fe4bdac9d1e84a20332384fef3..5e4a90ee103f5eacedc1f8acaafacb847f56b5ec 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 88f60aa520584a87acab13422d22940063f2b536..e488603fb1e77f29c601e7892d6f683d9e43b804 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 77c990f0cb981706c55dcd936958c654d8f543e5..d17c97d07c80e44895503e6d336b8328c0ffd348 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 7b98792150ea7ebba3d449e994906483dcadf4a3..b12cb8a7da7c87ec2fe01561dd1e5891f674c1ec 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 ff0bafcff7204ac1dc24204ef0c3a47f919eed6c..70c5af4cc2704d3097848783825835456a52f8ee 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 e7d3f0522d0165fc1f7d6ceb5aad03b607e168b2..a717837f272e66a9b422a8383ec3ae92b6da50ec 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 8824e84f8a56a58b8f0aee6ac99cbc9307038565..3fc4238e9703dca7b67b3fe9f81a221376901e45 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 a7ef5e716f3c3dd9a36ae9fd72fc8cf987c2e610..296351615b0014a2f564dfa3d2fb1ce725e00f6f 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 46cf933aa3bf2dc22129c74a866628d9313984c6..4a83adfec968ebae108b9ae71802e14db6ef6dbb 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 c755a0440a6640848fff524c522e940da50b294a..879e6fba94803eca6a1844d9d14d500116086ae7 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 f568102da1e8df3be5126e91a50914d55dc5c0bb..b351952899453be64165ba7315e5f59bd0c851ac 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 108138d4e909301ed1e6389bb3132127fdb9e4b4..d0be6159eb7fcd4ab65f82d6dc3f0cc353b51d94 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 4acdac043b6bb0a1d42b66b7a601513b2049f06b..7ac9fb4acb2c7d265fc48dff00810861f65cc4ce 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 89ed04696865a9595d67a2922ec33c55786862c2..1d163b6169151ce870c911dc1c7eb0eb40c80a74 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 9dd71e8070349c20f73102aad0d73de003cb7628..d71ac657928931e114ea0798342e501f27558a79 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 ad6fa964b0e7e892de207307223a71887d1bc6ac..f3473176c83a4dad8a137225923f375414e5b404 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 45829889dcdc0a13dd93bcd523b305c5756f71dc..aa22588019ecd56fd32b0e80ac7f5c58f9671899 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 ffa34b861bdb8c4d3db90d223a329a0abdd1e0e5..b33d67bba2fdfd548f30fd47ea81191b042e3e08 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 4491fcf2a0e60b55ca66d61f222b4a807ca0b385..b7a179560ab40a2a137754780d7a46c8784addd3 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 8f8d8d01107c880975c4d2d2de465be7a3041018..c8123308e060221d4a8f8d01f0f303cad68acbba 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 fc2f43c75df411ee4b3037b723023b4a13f5ceef..ef6caed9336b3c36f5c51a1616d866b735e247f7 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 397d9590c8f2c09ee65f173753f10d011bd9d66f..77891de0e02e7b0f470545b98fc1bb00e075e508 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 cc061bfd437b00b4c3aed01b3e0983fb83dba152..ffb79c48c5bf974fb6953fe6b761e64f16bbe8fa 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 c6c33e15143ab68baa8c944f14b108f391d1cad2..0424d06b147e3832273b068f2389b99057c28e0a 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 120626789406e836708b5050b6c14cce85341cbe..9892268e30050fdd4a21846160c74a708fe56545 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 e44b7c1a3a36d432617edfd66131c30a259359f9..bfb4f2917bb69b01c472dc31f7d2eb36d9e1cb28 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 76c6df34d0dbda279cfdda97822967d3fac632bb..eda7919b70a18814e82477828eeaa91794ccb8d6 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 9dc7256cf9798a39eeb0dbf11202c8c987a80bcb..62d0d6681aa91d587e52b5de824e90a790de9f2f 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 abfbe45cd17c9ff5c64b2e871bd00cc2682eb309..5f8223e700d353f22a75c94c3e173f14ad609b78 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 1833ea5c4220b34d2594189e61caa4ab444ca84d..c380d264a8479137fe2a979b91d9969fc64cac03 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 ce1bbbaad6d36a6876fdb2534ebfb2103970b90b..83b01254c4ac7374421cbad670debe9424ef42cc 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 ddd1578a7ee0a40d2877434176f7718797c9b1a4..4367ec054b51aeb277040bbee9c5f47bb99b5762 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 3351b77fab36e93bc86ef94c74a45a7b6b4295a4..e8ea67c97c73d3526b3c7025dbc9a468e1ef6331 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 5a0d19b466b0cd2242bbf6f1fca244ec90d12617..70e00d08345ec93d6b989fc47b2a5099272375d6 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 15cc6f2da792dc7dec67d6698b863bb47750b667..d87f8634e62525d1a67bf33014f5a299ab340eb5 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 dc28daab8aa8d7786fa619facc0116480c33858e..87c19d2bb6a8035df4c4f747f8214a76ad47f9b8 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 b88344ad390c6038e7f3b6f8d07d5b88b55ea5dd..f8d1eb4f4cb17b6d37763ed793e97229a5e0db47 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 ca4ccfc4b578cc44184667aaac94b5b0d9764022..702884926a55931254ad69f3aadd968845054596 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 73296d9924fb36ac196937e2d9d63e32f978aa2c..997ca5d17876dc410c6007398d138ebe6ad54545 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 e68a80853d5dfaf81beb54d45727e495ba8f013e..9ca642cad33878a0a3de28c74ae639998099ea86 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 640a6459f2f4604017c3fb14a452ecdbf0ba62ac..bda2f217e6fe4a79a05ae8c7d9c291062f1122cd 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 d9728c80f86de3d4f4a1a3ca61ce6d0598fc089a..cef61304ffc2b9004812cf07ac79db7a879dc2b7 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 77b10d6adabde1d2507fd629ed6499c9dacd22af..1630c26e8f45a5c27eef949454fb4702747fc7f0 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 7bc15f0231dbeaa52872f2973692e5ddf4339f69..a2f37a9353d393c3ec6fac66b3d1cd94b02a4fb7 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 f3797a52c4ea5e06d5bca508c14706123ecd116e..8e0c7ed73d0312a811c5a3f887527747a6c669c3 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 2861cdc243ad5fd2d025c3524fd50d7dcb259a5e..29a9f357eb9ebc394b330738c9934eb44d5ba1d6 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 5cfaa6bcf1edebbd0f3591693dccb0bec52c13d2..a844ea0965b6bb10d861e8eff63d045559334532 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 5b64d041f0b9683f60c945d2980693970c97d1a5..ff4c5fbbfaf038206de9b33e93f2c6a27bb5f738 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 1866f3f90028204119028e5e4c6f6ce2bd2c8e39..9d84a2d445a269eee10367b265b942ec7c268b11 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 bf2e4310ffac64d417cfa57642aecb5c61b5352d..d705252be260018902a68df8464b1730f7f0cdc9 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 8c8ca12810842936433261915a33eabfd2e2a319..7f90315cd8304359c9d35653fb9709822c3c8ef1 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 060ec3c272072a19e98d391d3c295afa75b21a08..42b8394c04ed6de00474532297b18c1d8ce84fd4 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 c4904797d6dfe19bbb0a524384fbccece72d2bc1..fa5bd2d8803e4d612abe73ba0c0de9011aa895cc 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 08f3c1f2e41903309eb7182afad88b2065c26ac8..6b0c04f63c576fb61a46bf6dd64720849601502a 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 ec85d12d73b98a353e0fdcaf346489b09f80839a..508c416e9d6a8b1423ab3bb88eef8ee27d67ec9a 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 175722a9116478545c8d8c90da1b8f92fe0fe9f5..96b35aada79a4480d881239cae02d8a5e74f8056 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 d879eba2b52c7d74e646a3213911304f877279c5..aeda6657f366e156ff8e6997f06a6726f19098ea 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 e87cd83a0e86dbbce4e9eb21fa09787400b6d6fb..9afc0c7d3661931fbb52efa6c4a4be09c1ddc6d2 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 17a17c55a17f97c2da02e7b83f1ca367f7bc6d5e..6d59c8efe3be2a1be4b1bb559bb506c551d3c213 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 02a585faa62cfd689510b943717cc6f79101184b..860e7a485a5f08d2aaa10129d65c6339c128a008 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 c31650df92412de9c6514e81bc5955e8f8a02dcb..17866d7e2b71ad08e12fc9340d5b77448032da48 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 83c7d207b80e7e8416e68813cf20dc38c9545e9e..51e0e95a421a1a19ed3bfbc30e6e530b112dee55 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 84bb449b9b01734dd864df59008724805de550af..e059da9470076a7af7a2a68e76bd29605369e75a 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 528959c52f1b6fd5f9f3f9722f22cfe6616876e1..5425b60021e36193877aac02e6911db800808c4b 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 089bfb1fa01a771d7c11ee7de4227deb88d29b00..6361544bb6ae5fef3ee1dcd84dc8788262bd7917 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 1bd6552cc34134c4e19d5565e992fc91b9785910..6aca67a569a2ff907830ef64e6b69dafc154996c 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 93a849f742dbbb47ae5ee00464f328b757d597fe..ebfc238cc243482d9baa9b7bb3bd92391d4f6479 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 59ff6c430cf6eb1e8609acf7abecfd347c54e512..6500d4e59d46c5c6f60bfba239aad63f4639b7bf 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 0a44072383ec417647194cc505fb5e4d19447302..fe1a2b02fc558d158182642b979d0f6159aceb18 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 ecc1fc1f0f0442f644269f921ac8563ea8c92642..b0b908f583c58a38a614e6e51f30d71ae43d9508 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 54faf5236da01370e7dc2f366dade682fec05de8..95572c434bc991dc23dd5b9074d3bb36bd69b192 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 e276c5ba2bb79c6cddcc99869744fa5fc2efcbac..7d51149bd79393c797a6ea73886d169dd08249b5 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 3e68592e52e9c3351f80294f4d2ef19230b67eb4..31b4c0bd4fa000e94a32f5b8b5f99c9211f68f4e 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 c84354e8374c9978dc4e6e00938be792521aedc7..87280eb6083d44b94133c635b4916255e60b93cb 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 9d6fbeef210472b21a7a974677303183747bc06e..d6b9bcd1384c2767fcef3c2a024ff2c780b65d47 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 ef753654daa56810568aa73bca8b952c533fd588..bb1da86747c701f410d7222e4c09f8a7e7bc9670 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 cee302aefdb71b3efcbd8027af9a68b79189ddee..73b464f0926a861438c73cbcf27e996a9ccabf0f 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 ec351005bf9d9ccb5c521a9048dfdcad7c2db57b..4041122dabfcf66cd2eca416a227569f474b5c84 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 1fb77a9cc148d2a61e3e2f1d1b0b469b01620703..8cf52939d0ab676698083140e8cb80384ee6b263 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 4a99e4a7fbf31edf83a86c5c35bfd0b4adbe9baa..f3e17d5963c38cf6697e2c0093fe3b3d80826e57 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 e666d6070569021b62fb6e22e1d15e08fbe0419e..3877209d23c35e27cd9e07355edf71b1bf1670c4 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 8352a7ce58951673caff4da3f1a7468d77445fc2..32a4139c4ad8f9277991be3173968d54942b6298 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 614dd8465839c215bebf815e1baaf11d6e399939..7b4dc36532bb192a1689dc84fb6da7fa97ab8dd7 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 21b9ce80364429abd04e9ef718834d0a6427eb15..54ae2d59e71bcd2b34c54a099dcb6773736b2bcb 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 ee21e6bf3867a8bff6d2ac30a32ce6f4743a9536..a2aacfc7af2f968ac6b16cb0fc31845f97dcd4d9 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 ce40675324bd5edb738c339bc56f61b01f1212bf..6f6c69777648f0f72f41a55fc1f79092a15092e1 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 df05f468fa5c312c028f45c9dc1ad81cbd1a2336..9a92aef8b0b29090696711728683d6caa8ac9942 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 e3e5436f8017929aeba0d271b7748d13c8a365b6..9c04f15090d2b6b6e75060ab56dfb69047ea5db7 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 e94ca4d360358bb535224bca0766af0f706cef61..290e3b4d2aec040c46f1fc2f0ff8b9a8b3398472 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 467274a764d172487c2717f0aa7eac2eb5f81b0d..827992949c4bfe2b94635262483a4863aa0b2550 100644 (file)
@@ -554,7 +554,6 @@ struct Scsi_Host {
        /*
         * ordered write support
         */
-       unsigned ordered_flush:1;
        unsigned ordered_tag:1;
 
        /*
index 4ae8cfc1c89cffdee486c2a3b28316e583a40747..7f0ab5ee948c633a8065e685a5147e0df3d439ad 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 f1c4155b49ac140051538f12046cb553674657f9..2b6e1757aeddf118f43c31111f46224b00f5d25e 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 c2c05c4ff28d5bd7bd32cf8ca1eea1dc768b71c2..379be2f8c84c33445b9cea549fe2c7215d3d6cc4 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 197208b3aa2ad837517d27662e5bacaafd75258b..216f574b5ffb758ca0630868bca07f03a3d9a116 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 7ff375e7c95f3cf24ab52adf62a688849684e05f..579d239d129fd5dd03458f8889577400b3b56aa1 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 e03d85e55291c89632d02d3f6880e584e810ab1e..0b43847dc9801950608f0943d3d6b7ea45776e54 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 7e8492fd142313ba4cac756274a76c8df4a66975..d8f0d1a76bae9fbf18a8c1d20326d9dc20dd232d 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 55a18d26abeda6a2df3641cdca9de0da2f201ef9..59c91c148e82d0f3ddbbea3a0cdf8260702cd9eb 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 773219907dd8a96698f6c0390778538071e2e890..7712912dbc8488d54c7be1c73947a285005ba8a7 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 3ee2ae45125f711bd52eb8635cf335cc9b15ffe9..f77f23f8f479c898666082f3c9da0d52bb5a5bab 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 cb99a42f8b37c60e991332ce33b4fba1dacb9dc6..71dd6f62efec11ce623d64ef31ec565a78084763 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 7477b1d2079e32a614ea82e6ae21fde3abe48373..1f23e683d6aa01da497a86a8cd5ac6804ef5d6fe 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 89e562feb1b10829ec3d689eb969f670868be686..d9deae43a9abbb0f8dfaeeb078e8fb83311bc481 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 8535f4d7d1c38420da8d8e7785a932d8ba5b7aa3..648b2c1242fd9066aae0aa966914ee0f47fbce04 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 7a11ddd5060ff51067523c7872b85e0539537385..2bee1f21aa8aa92294ef481778b3c370063413fb 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 73790188b0eb27a91edd4d0d8efba6c90d4b28be..27da6d5c77bade350dd88f15eed6424923d91de7 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 14bd4ec7959736106b1d2574e1fdd82f999242bf..b05ab8f2a562292277bca720ca40a7c14834f520 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 df54e2fc8ee09760c67d2dd4e6bd496e07286124..44b4eb4202d91e33acc45384f1468a4823ff5442 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 d85a99d28c0387a28d92538a88b92ddfef0efbb2..df2c41c2a9a2c1ac4d46b67c424a0001122a57ea 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 ce501bce1c2e2369959666de3923e0085112bb73..f7ac7b812f926a24b3ba71bb4757318ab75b357b 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 6f8495e2185b36c4d4e08402a111a59a3deeb01b..71370256a7eb11e8b6eeb0c88cbd0e23955ab163 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 7b09ac503fec9dde77422705a08b2a1f087d0d70..db8a3d3e163651c7c3baa85cd1c82434db177ae8 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 f1e69c30d203871146d10b13b4e90831b2f0f7cf..1f9cf0d073b84caad71234ddfb091618906d3047 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 2e34b61a70c727afc2895529c1997a1a8d399eee..5a610804cd06a938b902006d2780a540d66be704 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 ba442883e877fbda4808db858f215ac9c30334df..da687c8dc6ff013e62f04b535f2a26483e4db284 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 c5bd631ffcd5793d67c29009151c380b6af03cac..e330b17b6d816620f2706fc4eab15c1f4ef21481 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 fd070a098f20656027dca9c38a3b7a43a0ad1082..ffb82073056e761267dcbd480603d01645cfd7cf 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 9540946a48f35f9cbb89a0d82eacddcd2c4de3a3..93fbd01d225952c66228d228a66340101448166a 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 d0732e9c8560e10d8ec239957fa3b8d4d3c1df00..6766f118f07068719b551644066839a154267cf7 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 00f983226672a6c70aca4a67368cceae2d7a118b..dc0487b5bacec375dda26bbdc4515b5a5cedc621 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 df074259f9c3100581f649499dac1ae5554d1770..80c4d048869e10e2880b5dff67ea22ccd1d0e8f6 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 7a121802faa92d7aa33b07734d8c6a0f3165662e..960aa78cdb972e1662bde851d7b025c61502f0fe 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 23e1630f50b7cf872e01286c01a108cbc66c478f..f87c6b89f8450e513fd6c434864e7ae65b267ad0 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 d8ce7133cd8f28ede0740ab682243e4f78f2bddb..0b4e95f93dad62cbfed26297ada2fbe86cf07163 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 3284cfb993e6bd9c70963ba0f389b582f4183ab9..128de4d7c0b7dd40c95d94b3efdbab73a2e20041 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 6ea353907af5757de1abc84e6b87274afa4d26fe..233bdf2599658513c8ede17ebcc77c38bc2cac4a 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 6c05c7978bef2cf469111dfd891c5052a587dfac..4420948a1bfe9f23ec29de602551dd6bca9cbcf3 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 66d04004afdaec2a731d953752fb970f17121112..ca9cf6853755fc3081693334c6f8f3e70265dcac 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 43f1ce74187d524122d8fbf6d325c7395dfb534d..ae86d237a4569b47e764db78ebe359390bc63359 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 ee93abc71cb8aaefde9f24bbd6a5e5326fc5aee3..9db7dbdb16e6bd14c7ca23dc6c8dfe11e16f4566 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 71c9a961c321a13e6b68e837cc47652e27a4e437..2b9a832b29a70bdbb46d0ce401d680c9a0121654 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 fb1821d9f33809e5ace99b572cbbf813aea8d0ca..0ea947eb681320561d3e3d61ac91001aa1043926 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 7415406aa1ae510639e24bc103ea42d3a862db03..802d4fe0f55cb5fc37b358b360a7bffb5ee3bbb5 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 9fd5f5b87d1e47cc160ec86fe7cf8aff7c4c091d..99fe4b7fb2f1733a5b4412553c1734a58b39ec2f 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 1caac0164643c202a55c1e8394b9669706723591..8529ea6f7aa83437174727478988702d4e9db89b 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 b9f8d9731c3d54ba345ef7f2b24c09ffc7cad1ad..4ae834d89bce9e81a98c8be4a0056341603ffded 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 887937c8134a46557a39ccb8f30318d6ceab4f44..54c03077888214a37c0cfd88be4d87575d2377f4 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 b963c550dae6b50f069ffd52e38ece70b7360ba7..bdee0502f3e232e32cc2e70c90349ae2ae21e8e8 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 a642e4cfcf45e2188104b0b4488f26c6d6c12e97..4988f873a7bacc6bd1749bea5f1d137823401da1 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]);