]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'for-rmk' of git://pasiphae.extern.pengutronix.de/git/imx/linux-2.6.git
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Sat, 13 Sep 2008 19:10:59 +0000 (20:10 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 13 Sep 2008 19:11:15 +0000 (20:11 +0100)
443 files changed:
Documentation/ABI/testing/sysfs-firmware-sgi_uv [new file with mode: 0644]
Documentation/dontdiff
Documentation/filesystems/Locking
Documentation/filesystems/ntfs.txt
Documentation/filesystems/proc.txt
Documentation/laptops/thinkpad-acpi.txt
Documentation/video4linux/CARDLIST.au0828
Documentation/video4linux/gspca.txt
MAINTAINERS
Makefile
arch/arm/include/asm/byteorder.h
arch/arm/include/asm/io.h
arch/arm/include/asm/mach/map.h
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-pxa/tosa.c
arch/arm/mm/mmu.c
arch/arm/plat-mxc/clock.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/mach/mcbsp.h
arch/arm/plat-omap/mcbsp.c
arch/avr32/kernel/asm-offsets.c
arch/avr32/kernel/entry-avr32b.S
arch/avr32/mach-at32ap/pm-at32ap700x.S
arch/ia64/include/asm/sections.h
arch/ia64/kernel/module.c
arch/m68k/atari/atakeyb.c
arch/mips/Kconfig
arch/mips/kernel/setup.c
arch/mips/kernel/traps.c
arch/mips/mm/c-r3k.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-tx39.c
arch/mips/mm/cache.c
arch/mips/mm/tlbex.c
arch/mips/sgi-ip22/ip22-platform.c
arch/mips/txx9/generic/setup.c
arch/parisc/hpux/fs.c
arch/parisc/kernel/module.c
arch/powerpc/Makefile
arch/powerpc/boot/Makefile
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/include/asm/sections.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/align.c
arch/powerpc/kernel/idle_6xx.S
arch/powerpc/kernel/idle_e500.S
arch/powerpc/kernel/module_64.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/powermac/Makefile
arch/s390/kernel/compat_ptrace.h
arch/s390/kernel/ptrace.c
arch/sh/configs/ap325rxa_defconfig
arch/sh/configs/migor_defconfig
arch/sh/include/asm/uaccess_64.h
arch/sh/kernel/cpu/sh5/entry.S
arch/sh/kernel/entry-common.S
arch/sh/kernel/machine_kexec.c
arch/sh/kernel/ptrace_64.c
arch/sh/kernel/setup.c
arch/sh/kernel/sys_sh.c
arch/sh/mm/consistent.c
arch/sparc/include/asm/smp_32.h
arch/sparc/kernel/of_device.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/of_device.c
arch/sparc64/kernel/smp.c
arch/sparc64/mm/init.c
arch/x86/Kconfig.cpu
arch/x86/boot/cpucheck.c
arch/x86/kernel/alternative.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/centaur.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/common_64.c
arch/x86/kernel/cpu/cyrix.c
arch/x86/kernel/cpu/feature_names.c
arch/x86/kernel/e820.c
arch/x86/kernel/hpet.c
arch/x86/kernel/io_delay.c
arch/x86/kernel/tsc.c
arch/x86/pci/i386.c
arch/x86/xen/enlighten.c
block/cmd-filter.c
block/genhd.c
crypto/async_tx/async_tx.c
crypto/camellia.c
drivers/acpi/dispatcher/dsobject.c
drivers/acpi/processor_core.c
drivers/acpi/processor_perflib.c
drivers/acpi/sbshc.c
drivers/acpi/tables.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/libata-sff.c
drivers/ata/pata_marvell.c
drivers/ata/pata_sil680.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/char/random.c
drivers/clocksource/acpi_pm.c
drivers/firmware/iscsi_ibft.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/ide/Kconfig
drivers/ide/arm/palm_bk3710.c
drivers/ide/ide-cd.c
drivers/ide/ide-disk.c
drivers/input/mouse/bcm5974.c
drivers/input/serio/i8042-x86ia64io.h
drivers/md/bitmap.c
drivers/md/md.c
drivers/media/common/saa7146_video.c
drivers/media/common/tuners/mt2131.c
drivers/media/common/tuners/mt2131.h
drivers/media/common/tuners/mt2131_priv.h
drivers/media/common/tuners/mxl5005s.c
drivers/media/common/tuners/mxl5005s.h
drivers/media/common/tuners/tuner-simple.c
drivers/media/common/tuners/xc5000.c
drivers/media/common/tuners/xc5000.h
drivers/media/common/tuners/xc5000_priv.h
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/b2c2/flexcop-i2c.c
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/frontends/au8522.c
drivers/media/dvb/frontends/au8522.h
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx22702.h
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/cx24123.h
drivers/media/dvb/frontends/s5h1409.c
drivers/media/dvb/frontends/s5h1409.h
drivers/media/dvb/frontends/s5h1411.c
drivers/media/dvb/frontends/s5h1411.h
drivers/media/dvb/frontends/s5h1420.c
drivers/media/dvb/frontends/tda10048.c
drivers/media/dvb/frontends/tda10048.h
drivers/media/dvb/siano/sms-cards.c
drivers/media/dvb/siano/sms-cards.h
drivers/media/dvb/siano/smscoreapi.c
drivers/media/dvb/siano/smscoreapi.h
drivers/media/dvb/siano/smsdvb.c
drivers/media/dvb/siano/smsusb.c
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget.c
drivers/media/radio/Makefile
drivers/media/radio/dsbr100.c
drivers/media/radio/miropcm20-radio.c [deleted file]
drivers/media/radio/miropcm20-rds-core.c [deleted file]
drivers/media/radio/miropcm20-rds-core.h [deleted file]
drivers/media/radio/miropcm20-rds.c [deleted file]
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-si470x.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Makefile
drivers/media/video/au0828/Kconfig
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/au0828/au0828-cards.h
drivers/media/video/au0828/au0828-core.c
drivers/media/video/au0828/au0828-dvb.c
drivers/media/video/au0828/au0828-i2c.c
drivers/media/video/au0828/au0828-reg.h
drivers/media/video/au0828/au0828.h
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-risc.c
drivers/media/video/bt8xx/bttvp.h
drivers/media/video/btcx-risc.c
drivers/media/video/btcx-risc.h
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cpia.c
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cx18/cx18-av-firmware.c
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx18/cx18-dvb.c
drivers/media/video/cx18/cx18-dvb.h
drivers/media/video/cx18/cx18-irq.c
drivers/media/video/cx18/cx18-queue.c
drivers/media/video/cx18/cx18-queue.h
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-i2c.c
drivers/media/video/cx23885/cx23885-reg.h
drivers/media/video/cx23885/cx23885-vbi.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/dabusb.c
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/gspca/conex.c
drivers/media/video/gspca/etoms.c
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h
drivers/media/video/gspca/mars.c
drivers/media/video/gspca/ov519.c
drivers/media/video/gspca/pac207.c
drivers/media/video/gspca/pac7311.c
drivers/media/video/gspca/pac_common.h [new file with mode: 0644]
drivers/media/video/gspca/sonixb.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/gspca/spca500.c
drivers/media/video/gspca/spca501.c
drivers/media/video/gspca/spca505.c
drivers/media/video/gspca/spca506.c
drivers/media/video/gspca/spca508.c
drivers/media/video/gspca/spca561.c
drivers/media/video/gspca/stk014.c
drivers/media/video/gspca/sunplus.c
drivers/media/video/gspca/t613.c
drivers/media/video/gspca/tv8532.c
drivers/media/video/gspca/vc032x.c
drivers/media/video/gspca/zc3xx.c
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-irq.c
drivers/media/video/ivtv/ivtv-queue.h
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtv-vbi.c
drivers/media/video/ivtv/ivtv-version.h
drivers/media/video/ks0127.c
drivers/media/video/meye.c
drivers/media/video/mxb.c
drivers/media/video/ov511.c
drivers/media/video/pms.c
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/saa7115.c
drivers/media/video/se401.c
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/sn9c102/sn9c102_devtable.h
drivers/media/video/stv680.c
drivers/media/video/usbvideo/ibmcam.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/vivi.c
drivers/media/video/w9966.c
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zc0301/zc0301_sensor.h
drivers/misc/acer-wmi.c
drivers/misc/fujitsu-laptop.c
drivers/misc/hp-wmi.c
drivers/misc/thinkpad_acpi.c
drivers/mmc/card/block.c
drivers/mmc/host/at91_mci.c
drivers/mtd/mtdchar.c
drivers/mtd/nand/tmio_nand.c
drivers/net/bnx2x.h
drivers/net/bnx2x_main.c
drivers/net/forcedeth.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/usb/pegasus.c
drivers/net/wireless/ath9k/hw.c
drivers/net/wireless/ath9k/main.c
drivers/net/wireless/ath9k/recv.c
drivers/net/wireless/ath9k/xmit.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-fh.h
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/libertas/if_cs.c
drivers/net/wireless/orinoco.c
drivers/net/wireless/rt2x00/rt2x00reg.h
drivers/pci/setup-bus.c
drivers/pcmcia/soc_common.c
drivers/pnp/pnpacpi/rsparser.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-lib.c
drivers/s390/cio/chp.c
drivers/s390/cio/cio.c
drivers/s390/cio/css.c
drivers/s390/cio/device_fsm.c
drivers/scsi/sd.c
drivers/scsi/sr.c
drivers/serial/8250.c
drivers/serial/8250.h
drivers/usb/host/ohci-omap.c
drivers/usb/serial/console.c
drivers/video/atmel_lcdfb.c
drivers/video/cirrusfb.c
drivers/video/tdfxfb.c
drivers/xen/balloon.c
firmware/Makefile
fs/cifs/CHANGES
fs/cifs/README
fs/cifs/cifsencrypt.c
fs/cifs/file.c
fs/cifs/sess.c
fs/nfs/super.c
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4proc.c
fs/ntfs/usnjrnl.h
fs/proc/array.c
fs/proc/proc_misc.c
fs/ubifs/budget.c
fs/ubifs/dir.c
fs/ubifs/file.c
fs/ubifs/find.c
fs/ubifs/gc.c
fs/ubifs/misc.h
fs/ubifs/super.c
fs/ubifs/tnc.c
fs/ubifs/ubifs-media.h
fs/ubifs/ubifs.h
include/asm-generic/Kbuild.asm
include/asm-generic/sections.h
include/asm-generic/syscall.h
include/asm-mips/cacheflush.h
include/asm-parisc/sections.h
include/asm-x86/cpufeature.h
include/asm-x86/required-features.h
include/linux/Kbuild
include/linux/clockchips.h
include/linux/cpuset.h
include/linux/ide.h
include/linux/list.h
include/linux/mroute.h
include/linux/mroute6.h
include/linux/pim.h
include/linux/quicklist.h
include/linux/res_counter.h
include/linux/sched.h
include/linux/sunrpc/svc_rdma.h
include/linux/tracehook.h
include/linux/videodev2.h
include/net/bluetooth/hci_core.h
include/net/inet_timewait_sock.h
kernel/auditsc.c
kernel/cpuset.c
kernel/exit.c
kernel/pid_namespace.c
kernel/pm_qos_params.c
kernel/resource.c
kernel/sched.c
kernel/softlockup.c
kernel/sysctl.c
kernel/time/clockevents.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-internal.h
kernel/time/tick-oneshot.c
kernel/time/tick-sched.c
lib/Kconfig.debug
lib/debugobjects.c
lib/vsprintf.c
mm/filemap.c
mm/mmap.c
mm/page_alloc.c
mm/page_isolation.c
mm/quicklist.c
mm/truncate.c
net/bluetooth/af_bluetooth.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap.c
net/bluetooth/sco.c
net/bridge/br_ioctl.c
net/bridge/br_sysfs_br.c
net/core/dev.c
net/ipv4/devinet.c
net/ipv4/inet_timewait_sock.c
net/ipv4/tcp_ipv4.c
net/ipv6/ip6_output.c
net/ipv6/raw.c
net/ipv6/tcp_ipv6.c
net/mac80211/debugfs_key.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/netfilter/nf_conntrack_irc.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_conntrack_sip.c
net/sched/cls_api.c
net/sched/cls_route.c
net/sched/sch_api.c
net/sched/sch_cbq.c
net/sched/sch_htb.c
net/sched/sch_netem.c
net/sched/sch_teql.c
net/sunrpc/sysctl.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/tipc/bcast.c
net/tipc/bcast.h
net/tipc/bearer.c
net/tipc/bearer.h
net/tipc/cluster.c
net/tipc/cluster.h
net/tipc/discover.c
net/tipc/link.c
net/tipc/link.h
net/tipc/name_table.h
net/tipc/net.c
net/tipc/net.h
net/tipc/node.c
net/tipc/node.h
net/tipc/node_subscr.c
net/tipc/node_subscr.h
net/tipc/port.h
net/tipc/zone.c
net/tipc/zone.h
net/wireless/Kconfig
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
security/device_cgroup.c
security/selinux/ss/services.c
sound/Kconfig
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/pxa/pxa2xx-i2s.c

diff --git a/Documentation/ABI/testing/sysfs-firmware-sgi_uv b/Documentation/ABI/testing/sysfs-firmware-sgi_uv
new file mode 100644 (file)
index 0000000..4573fd4
--- /dev/null
@@ -0,0 +1,27 @@
+What:          /sys/firmware/sgi_uv/
+Date:          August 2008
+Contact:       Russ Anderson <rja@sgi.com>
+Description:
+               The /sys/firmware/sgi_uv directory contains information
+               about the SGI UV platform.
+
+               Under that directory are a number of files:
+
+                       partition_id
+                       coherence_id
+
+               The partition_id entry contains the partition id.
+               SGI UV systems can be partitioned into multiple physical
+               machines, which each partition running a unique copy
+               of the operating system.  Each partition will have a unique
+               partition id.  To display the partition id, use the command:
+
+                       cat /sys/firmware/sgi_uv/partition_id
+
+               The coherence_id entry contains the coherence id.
+               A partitioned SGI UV system can have one or more coherence
+               domain.  The coherence id indicates which coherence domain
+               this partition is in.  To display the coherence id, use the
+               command:
+
+                       cat /sys/firmware/sgi_uv/coherence_id
index 881e6dd03aea411bb9a1b0b11aa3b4fb3a90761e..27809357da58755c4484d711a6bc90534ec07a29 100644 (file)
@@ -5,6 +5,8 @@
 *.css
 *.dvi
 *.eps
+*.fw.gen.S
+*.fw
 *.gif
 *.grep
 *.grp
index 680fb566b9286bcc71a527c5f75d4b94fc9ac215..8362860e21a7d6b4db3595e83905b32b25e55ecf 100644 (file)
@@ -144,8 +144,8 @@ prototypes:
        void (*kill_sb) (struct super_block *);
 locking rules:
                may block       BKL
-get_sb         yes             yes
-kill_sb                yes             yes
+get_sb         yes             no
+kill_sb                yes             no
 
 ->get_sb() returns error or 0 with locked superblock attached to the vfsmount
 (exclusive on ->s_umount).
@@ -409,12 +409,12 @@ ioctl:                    yes     (see below)
 unlocked_ioctl:                no      (see below)
 compat_ioctl:          no
 mmap:                  no
-open:                  maybe   (see below)
+open:                  no
 flush:                 no
 release:               no
 fsync:                 no      (see below)
 aio_fsync:             no
-fasync:                        yes     (see below)
+fasync:                        no
 lock:                  yes
 readv:                 no
 writev:                        no
@@ -431,13 +431,6 @@ For many filesystems, it is probably safe to acquire the inode
 semaphore.  Note some filesystems (i.e. remote ones) provide no
 protection for i_size so you will need to use the BKL.
 
-->open() locking is in-transit: big lock partially moved into the methods.
-The only exception is ->open() in the instances of file_operations that never
-end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices
-(chrdev_open() takes lock before replacing ->f_op and calling the secondary
-method. As soon as we fix the handling of module reference counters all
-instances of ->open() will be called without the BKL.
-
 Note: ext2_release() was *the* source of contention on fs-intensive
 loads and dropping BKL on ->release() helps to get rid of that (we still
 grab BKL for cases when we close a file that had been opened r/w, but that
index e79ee2db183a0a19f09bccb810a29794ab72031e..ac2a261c5f7d736ed9daddbc25802d3e83fde07a 100644 (file)
@@ -40,7 +40,7 @@ Web site
 ========
 
 There is plenty of additional information on the linux-ntfs web site
-at http://linux-ntfs.sourceforge.net/
+at http://www.linux-ntfs.org/
 
 The web site has a lot of additional information, such as a comprehensive
 FAQ, documentation on the NTFS on-disk format, information on the Linux-NTFS
@@ -272,7 +272,7 @@ And you would know that /dev/hda2 has a size of 37768814 - 4209030 + 1 =
 For Win2k and later dynamic disks, you can for example use the ldminfo utility
 which is part of the Linux LDM tools (the latest version at the time of
 writing is linux-ldm-0.0.8.tar.bz2).  You can download it from:
-       http://linux-ntfs.sourceforge.net/downloads.html
+       http://www.linux-ntfs.org/
 Simply extract the downloaded archive (tar xvjf linux-ldm-0.0.8.tar.bz2), go
 into it (cd linux-ldm-0.0.8) and change to the test directory (cd test).  You
 will find the precompiled (i386) ldminfo utility there.  NOTE: You will not be
index 64557821ee5984f5babe336f701f172b8602a4dc..394eb2cc1c39b8fa863459b796bc95a427957013 100644 (file)
@@ -1339,6 +1339,25 @@ Enables/Disables the protection of the per-process proc entries "maps" and
 "smaps".  When enabled, the contents of these files are visible only to
 readers that are allowed to ptrace() the given process.
 
+msgmni
+------
+
+Maximum number of message queue ids on the system.
+This value scales to the amount of lowmem. It is automatically recomputed
+upon memory add/remove or ipc namespace creation/removal.
+When a value is written into this file, msgmni's value becomes fixed, i.e. it
+is not recomputed anymore when one of the above events occurs.
+Use auto_msgmni to change this behavior.
+
+auto_msgmni
+-----------
+
+Enables/Disables automatic recomputing of msgmni upon memory add/remove or
+upon ipc namespace creation/removal (see the msgmni description above).
+Echoing "1" into this file enables msgmni automatic recomputing.
+Echoing "0" turns it off.
+auto_msgmni default value is 1.
+
 
 2.4 /proc/sys/vm - The virtual memory subsystem
 -----------------------------------------------
index 02dc748b76c4ac861549077392ef1deb3ca9c652..71f0fe1fc1b0f341996fa3fbef5c59b6af8ebd46 100644 (file)
@@ -44,7 +44,7 @@ detailed description):
        - LCD brightness control
        - Volume control
        - Fan control and monitoring: fan speed, fan enable/disable
-       - Experimental: WAN enable and disable
+       - WAN enable and disable
 
 A compatibility table by model and feature is maintained on the web
 site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@@ -1375,18 +1375,13 @@ with EINVAL, try to set pwm1_enable to 1 and pwm1 to at least 128 (255
 would be the safest choice, though).
 
 
-EXPERIMENTAL: WAN
------------------
+WAN
+---
 
 procfs: /proc/acpi/ibm/wan
 sysfs device attribute: wwan_enable (deprecated)
 sysfs rfkill class: switch "tpacpi_wwan_sw"
 
-This feature is marked EXPERIMENTAL because the implementation
-directly accesses hardware registers and may not work as expected. USE
-WITH CAUTION! To use this feature, you need to supply the
-experimental=1 parameter when loading the module.
-
 This feature shows the presence and current state of a W-WAN (Sierra
 Wireless EV-DO) device.
 
index eedc399e8debd741fc8fb33e25f5a0d55393030f..aa05e5bb22fbf4ac4f7041d1d4cc01150e763209 100644 (file)
@@ -3,3 +3,4 @@
   2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
   3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
   4 -> Hauppauge HVR950Q rev xxF8               (au0828)        [2040:7201,2040:7211,2040:7281]
+  5 -> Hauppauge Woodbury                       (au0828)        [2040:8200]
index 78a863ab8a5ac0d99c212065d91d7e1dde2dc0c5..0f03900c48fbceac0fe2caf9979c14fc3421fb0f 100644 (file)
@@ -88,14 +88,14 @@ zc3xx               0471:0325       Philips SPC 200 NC
 zc3xx          0471:0326       Philips SPC 300 NC
 sonixj         0471:0327       Philips SPC 600 NC
 sonixj         0471:0328       Philips SPC 700 NC
-zc3xx          0471:032d       Philips spc210nc
-zc3xx          0471:032e       Philips spc315nc
-sonixj         0471:0330       Philips SPC 710NC
+zc3xx          0471:032d       Philips SPC 210 NC
+zc3xx          0471:032e       Philips SPC 315 NC
+sonixj         0471:0330       Philips SPC 710 NC
 spca501                0497:c001       Smile International
 sunplus                04a5:3003       Benq DC 1300
 sunplus                04a5:3008       Benq DC 1500
-sunplus                04a5:300a       Benq DC3410
-spca500                04a5:300c       Benq DC1016
+sunplus                04a5:300a       Benq DC 3410
+spca500                04a5:300c       Benq DC 1016
 sunplus                04f1:1001       JVC GC A50
 spca561                04fc:0561       Flexcam 100
 sunplus                04fc:500c       Sunplus CA500C
@@ -175,19 +175,21 @@ sunplus           08ca:2060       Aiptek PocketDV5300
 tv8532         0923:010f       ICM532 cams
 mars           093a:050f       Mars-Semi Pc-Camera
 pac207         093a:2460       PAC207 Qtec Webcam 100
-pac207         093a:2463       Philips spc200nc pac207
+pac207         093a:2463       Philips SPC 220 NC
 pac207         093a:2464       Labtec Webcam 1200
 pac207         093a:2468       PAC207
 pac207         093a:2470       Genius GF112
-pac207         093a:2471       PAC207 Genius VideoCam ge111
-pac207         093a:2472       PAC207 Genius VideoCam ge110
+pac207         093a:2471       Genius VideoCam ge111
+pac207         093a:2472       Genius VideoCam ge110
 pac7311                093a:2600       PAC7311 Typhoon
-pac7311                093a:2601       PAC7311 Phillips SPC610NC
+pac7311                093a:2601       Philips SPC 610 NC
 pac7311                093a:2603       PAC7312
-pac7311                093a:2608       PAC7311 Trust WB-3300p
-pac7311                093a:260e       PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
-pac7311                093a:260f       PAC7311 SnakeCam
+pac7311                093a:2608       Trust WB-3300p
+pac7311                093a:260e       Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
+pac7311                093a:260f       SnakeCam
 pac7311                093a:2621       PAC731x
+pac7311                093a:2624       PAC7302
+pac7311                093a:2626       Labtec 2200
 zc3xx          0ac8:0302       Z-star Vimicro zc0302
 vc032x         0ac8:0321       Vimicro generic vc0321
 vc032x         0ac8:0323       Vimicro Vc0323
@@ -220,6 +222,7 @@ sonixj              0c45:60c0       Sangha Sn535
 sonixj         0c45:60ec       SN9C105+MO4000
 sonixj         0c45:60fb       Surfer NoName
 sonixj         0c45:60fc       LG-LIC300
+sonixj         0c45:6128       Microdia/Sonix SNP325
 sonixj         0c45:612a       Avant Camera
 sonixj         0c45:612c       Typhoon Rasy Cam 1.3MPix
 sonixj         0c45:6130       Sonix Pccam
@@ -234,7 +237,7 @@ zc3xx               10fd:0128       Typhoon Webshot II USB 300k 0x0128
 spca561                10fd:7e50       FlyCam Usb 100
 zc3xx          10fd:8050       Typhoon Webshot II USB 300k
 spca501                1776:501c       Arowana 300K CMOS Camera
-t613           17a1:0128       T613/TAS5130A
+t613           17a1:0128       TASCORP JPEG Webcam, NGS Cyclops
 vc032x         17ef:4802       Lenovo Vc0323+MI1310_SOC
 pac207         2001:f115       D-Link DSB-C120
 spca500                2899:012c       Toptro Industrial
index c4ca99cf80dfcb35c1ac33a9c85c2e43c4c389b6..186be3ba50694c2c7a10f98cb9eaf2fd4c153b6f 100644 (file)
@@ -222,8 +222,7 @@ W:  http://code.google.com/p/aceracpi
 S:     Maintained
 
 ACPI
-P:     Andi Kleen
-M:     ak@linux.intel.com
+P:     Len Brown
 M:     lenb@kernel.org
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
@@ -419,6 +418,12 @@ L: linux-laptop@vger.kernel.org
 W:     http://www.canb.auug.org.au/~sfr/
 S:     Supported
 
+APPLE BCM5974 MULTITOUCH DRIVER
+P:     Henrik Rydberg
+M:     rydberg@euromail.se
+L:     linux-input@vger.kernel.org
+S:     Maintained
+
 APPLE SMC DRIVER
 P:     Nicolas Boichat
 M:     nicolas@boichat.ch
@@ -745,11 +750,13 @@ P:        Ville Syrjala
 M:     syrjala@sci.fi
 S:     Maintained
 
-ATL1 ETHERNET DRIVER
+ATLX ETHERNET DRIVERS
 P:     Jay Cliburn
 M:     jcliburn@gmail.com
 P:     Chris Snook
 M:     csnook@redhat.com
+P:     Jie Yang
+M:     jie.yang@atheros.com
 L:     atl1-devel@lists.sourceforge.net
 W:     http://sourceforge.net/projects/atl1
 W:     http://atl1.sourceforge.net
@@ -1588,7 +1595,7 @@ S:        Supported
 EMBEDDED LINUX
 P:     Paul Gortmaker
 M:     paul.gortmaker@windriver.com
-P      David Woodhouse
+P:     David Woodhouse
 M:     dwmw2@infradead.org
 L:     linux-embedded@vger.kernel.org
 S:     Maintained
@@ -3051,7 +3058,7 @@ P:        Anton Altaparmakov
 M:     aia21@cantab.net
 L:     linux-ntfs-dev@lists.sourceforge.net
 L:     linux-kernel@vger.kernel.org
-W:     http://linux-ntfs.sf.net/
+W:     http://www.linux-ntfs.org/
 T:     git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git
 S:     Maintained
 
index f448e0082ebf6726ba4a644164e5194edced6ff0..4ff83ea36c1920e585a63937e9887d703af04089 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 27
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Rotary Wombat
 
 # *DOCUMENTATION*
index d04a7a2bc2e9714e92870c12c3dabde9317dac0b..4fbfb22f65a0f4444818e455422b60d3e61545d0 100644 (file)
 #include <linux/compiler.h>
 #include <asm/types.h>
 
-#ifdef __ARMEB__
-# define __BIG_ENDIAN
-#else
-# define __LITTLE_ENDIAN
-#endif
-
-#define __SWAB_64_THRU_32__
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
 {
        __u32 t;
 
@@ -48,8 +40,19 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
 
        return x;
 }
-#define __arch_swab32 __arch_swab32
 
-#include <linux/byteorder.h>
+#define __arch__swab32(x) ___arch__swab32(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#ifdef __ARMEB__
+#include <linux/byteorder/big_endian.h>
+#else
+#include <linux/byteorder/little_endian.h>
+#endif
 
 #endif
+
index 94a95d7fafd6cdaf887e26dcfad35dbe6590c39a..71934856fc22c38ede7ab9f4a6c1380d9e1dad5d 100644 (file)
@@ -61,8 +61,9 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 #define MT_DEVICE_NONSHARED    1
 #define MT_DEVICE_CACHED       2
 #define MT_DEVICE_IXP2000      3
+#define MT_DEVICE_WC           4
 /*
- * types 4 onwards can be found in asm/mach/map.h and are undefined
+ * types 5 onwards can be found in asm/mach/map.h and are undefined
  * for ioremap
  */
 
@@ -215,11 +216,13 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
 #define ioremap(cookie,size)           __arm_ioremap(cookie, size, MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arm_ioremap(cookie, size, MT_DEVICE)
 #define ioremap_cached(cookie,size)    __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
+#define ioremap_wc(cookie,size)                __arm_ioremap(cookie, size, MT_DEVICE_WC)
 #define iounmap(cookie)                        __iounmap(cookie)
 #else
 #define ioremap(cookie,size)           __arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_cached(cookie,size)    __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
+#define ioremap_wc(cookie,size)                __arch_ioremap((cookie), (size), MT_DEVICE_WC)
 #define iounmap(cookie)                        __arch_iounmap(cookie)
 #endif
 
index 06f583b13999c220ba835658c657460ccb1a5783..9eb936e49cc349564f651ea973f71e6cdd273ee9 100644 (file)
@@ -18,13 +18,13 @@ struct map_desc {
        unsigned int type;
 };
 
-/* types 0-3 are defined in asm/io.h */
-#define MT_CACHECLEAN          4
-#define MT_MINICLEAN           5
-#define MT_LOW_VECTORS         6
-#define MT_HIGH_VECTORS                7
-#define MT_MEMORY              8
-#define MT_ROM                 9
+/* types 0-4 are defined in asm/io.h */
+#define MT_CACHECLEAN          5
+#define MT_MINICLEAN           6
+#define MT_LOW_VECTORS         7
+#define MT_HIGH_VECTORS                8
+#define MT_MEMORY              9
+#define MT_ROM                 10
 
 #define MT_NONSHARED_DEVICE    MT_DEVICE_NONSHARED
 #define MT_IXP2000_DEVICE      MT_DEVICE_IXP2000
index 826010d5d014f26f96df045d7e195c6359b9c997..2baeaeb0c9004d2038a7c1fde8b398068de77810 100644 (file)
@@ -159,6 +159,7 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 #ifdef CONFIG_ARCH_OMAP730
 static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP730_MCBSP1_BASE,
                .virt_base      = io_p2v(OMAP730_MCBSP1_BASE),
                .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
@@ -167,6 +168,7 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
                .ops            = &omap1_mcbsp_ops,
        },
        {
+               .phys_base      = OMAP730_MCBSP2_BASE,
                .virt_base      = io_p2v(OMAP730_MCBSP2_BASE),
                .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
@@ -184,6 +186,7 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP1510_MCBSP1_BASE,
                .virt_base      = OMAP1510_MCBSP1_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
@@ -193,6 +196,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
                },
        {
+               .phys_base      = OMAP1510_MCBSP2_BASE,
                .virt_base      = io_p2v(OMAP1510_MCBSP2_BASE),
                .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
@@ -201,6 +205,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
                .ops            = &omap1_mcbsp_ops,
        },
        {
+               .phys_base      = OMAP1510_MCBSP3_BASE,
                .virt_base      = OMAP1510_MCBSP3_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
@@ -219,6 +224,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 #ifdef CONFIG_ARCH_OMAP16XX
 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP1610_MCBSP1_BASE,
                .virt_base      = OMAP1610_MCBSP1_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
@@ -228,6 +234,7 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
        },
        {
+               .phys_base      = OMAP1610_MCBSP2_BASE,
                .virt_base      = io_p2v(OMAP1610_MCBSP2_BASE),
                .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
@@ -236,6 +243,7 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
                .ops            = &omap1_mcbsp_ops,
        },
        {
+               .phys_base      = OMAP1610_MCBSP3_BASE,
                .virt_base      = OMAP1610_MCBSP3_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
index 27eb6e3ca92622d98111b2d9bb030837541e1b30..b261f1f80b5e0fd7131a5586ca04bb6d9796a3ea 100644 (file)
@@ -134,6 +134,7 @@ static struct omap_mcbsp_ops omap2_mcbsp_ops = {
 #ifdef CONFIG_ARCH_OMAP24XX
 static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP24XX_MCBSP1_BASE,
                .virt_base      = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
@@ -143,6 +144,7 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
        },
        {
+               .phys_base      = OMAP24XX_MCBSP2_BASE,
                .virt_base      = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
@@ -161,6 +163,7 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
 #ifdef CONFIG_ARCH_OMAP34XX
 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP34XX_MCBSP1_BASE,
                .virt_base      = IO_ADDRESS(OMAP34XX_MCBSP1_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
@@ -170,6 +173,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
        },
        {
+               .phys_base      = OMAP34XX_MCBSP2_BASE,
                .virt_base      = IO_ADDRESS(OMAP34XX_MCBSP2_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
index 5dab30eafddc83c750d46a7990b51c1c032c8271..9f3ef9eb32e37366d0ecf5d3b6e8d1abaada4fab 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
+#include "clock.h"
 #include "devices.h"
 
 static unsigned long tosa_pin_config[] = {
@@ -521,6 +522,14 @@ static struct gpio_keys_button tosa_gpio_keys[] = {
                .wakeup = 1,
                .active_low = 1,
        },
+       {
+               .type   = EV_SW,
+               .code   = SW_HEADPHONE_INSERT,
+               .gpio   = TOSA_GPIO_EAR_IN,
+               .desc   = "HeadPhone insert",
+               .active_low = 1,
+               .debounce_interval = 300,
+       },
 };
 
 static struct gpio_keys_platform_data tosa_gpio_keys_platform_data = {
@@ -792,6 +801,8 @@ static void __init tosa_init(void)
        pxa_set_i2c_info(NULL);
        platform_scoop_config = &tosa_pcmcia_config;
 
+       clk_add_alias("CLK_CK3P6MI", &tc6393xb_device.dev, "GPIO11_CLK", NULL);
+
        platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
index 25d9a11eb61750ade3ba77abd7771068ebe668ee..a713e40e1f1a718549f333327c0f1a234e38a12c 100644 (file)
@@ -211,6 +211,12 @@ static struct mem_type mem_types[] = {
                                  PMD_SECT_TEX(1),
                .domain         = DOMAIN_IO,
        },
+       [MT_DEVICE_WC] = {      /* ioremap_wc */
+               .prot_pte       = PROT_PTE_DEVICE,
+               .prot_l1        = PMD_TYPE_TABLE,
+               .prot_sect      = PROT_SECT_DEVICE,
+               .domain         = DOMAIN_IO,
+       },
        [MT_CACHECLEAN] = {
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
                .domain    = DOMAIN_KERNEL,
@@ -272,6 +278,20 @@ static void __init build_mem_type_table(void)
                ecc_mask = 0;
        }
 
+       /*
+        * On non-Xscale3 ARMv5-and-older systems, use CB=01
+        * (Uncached/Buffered) for ioremap_wc() mappings.  On XScale3
+        * and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable
+        * in xsc3 parlance, Uncached Normal in ARMv6 parlance).
+        */
+       if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) {
+               mem_types[MT_DEVICE_WC].prot_pte_ext |= PTE_EXT_TEX(1);
+               mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
+       } else {
+               mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_BUFFERABLE;
+               mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
+       }
+
        /*
         * ARMv5 and lower, bit 4 must be set for page tables.
         * (was: cache "update-able on write" bit on ARM610)
index 2f8627218839130ccdba3c23c5f1d6b968b190f6..0a38f0b396eb997ce558584676ff3d1b2e8c49bc 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/proc_fs.h>
 #include <linux/semaphore.h>
 #include <linux/string.h>
-#include <linux/version.h>
 
 #include <mach/clock.h>
 
index 187e3d8bfdfe89512a454c128b0de4d8cb97a3b6..bc1cf30c83e0d36360eab2b64b19309f58c3c90f 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <mach/tc.h>
 #include <mach/board.h>
+#include <mach/mmc.h>
 #include <mach/mux.h>
 #include <mach/gpio.h>
 #include <mach/menelaus.h>
@@ -194,25 +195,38 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
 
 /*-------------------------------------------------------------------------*/
 
-#if    defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+#if    defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
+       defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 #define        OMAP_MMC1_BASE          0x4809c000
-#define OMAP_MMC1_INT          INT_24XX_MMC_IRQ
+#define        OMAP_MMC1_END           (OMAP_MMC1_BASE + 0x1fc)
+#define        OMAP_MMC1_INT           INT_24XX_MMC_IRQ
+
+#define        OMAP_MMC2_BASE          0x480b4000
+#define        OMAP_MMC2_END           (OMAP_MMC2_BASE + 0x1fc)
+#define        OMAP_MMC2_INT           INT_24XX_MMC2_IRQ
+
 #else
+
 #define        OMAP_MMC1_BASE          0xfffb7800
+#define        OMAP_MMC1_END           (OMAP_MMC1_BASE + 0x7f)
 #define OMAP_MMC1_INT          INT_MMC
-#endif
+
 #define        OMAP_MMC2_BASE          0xfffb7c00      /* omap16xx only */
+#define        OMAP_MMC2_END           (OMAP_MMC2_BASE + 0x7f)
+#define        OMAP_MMC2_INT           INT_1610_MMC2
 
-static struct omap_mmc_conf mmc1_conf;
+#endif
+
+static struct omap_mmc_platform_data mmc1_data;
 
 static u64 mmc1_dmamask = 0xffffffff;
 
 static struct resource mmc1_resources[] = {
        {
                .start          = OMAP_MMC1_BASE,
-               .end            = OMAP_MMC1_BASE + 0x7f,
+               .end            = OMAP_MMC1_END,
                .flags          = IORESOURCE_MEM,
        },
        {
@@ -226,26 +240,27 @@ static struct platform_device mmc_omap_device1 = {
        .id             = 1,
        .dev = {
                .dma_mask       = &mmc1_dmamask,
-               .platform_data  = &mmc1_conf,
+               .platform_data  = &mmc1_data,
        },
        .num_resources  = ARRAY_SIZE(mmc1_resources),
        .resource       = mmc1_resources,
 };
 
-#ifdef CONFIG_ARCH_OMAP16XX
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
+       defined(CONFIG_ARCH_OMAP34XX)
 
-static struct omap_mmc_conf mmc2_conf;
+static struct omap_mmc_platform_data mmc2_data;
 
 static u64 mmc2_dmamask = 0xffffffff;
 
 static struct resource mmc2_resources[] = {
        {
                .start          = OMAP_MMC2_BASE,
-               .end            = OMAP_MMC2_BASE + 0x7f,
+               .end            = OMAP_MMC2_END,
                .flags          = IORESOURCE_MEM,
        },
        {
-               .start          = INT_1610_MMC2,
+               .start          = OMAP_MMC2_INT,
                .flags          = IORESOURCE_IRQ,
        },
 };
@@ -255,26 +270,19 @@ static struct platform_device mmc_omap_device2 = {
        .id             = 2,
        .dev = {
                .dma_mask       = &mmc2_dmamask,
-               .platform_data  = &mmc2_conf,
+               .platform_data  = &mmc2_data,
        },
        .num_resources  = ARRAY_SIZE(mmc2_resources),
        .resource       = mmc2_resources,
 };
 #endif
 
-static void __init omap_init_mmc(void)
+static inline void omap_init_mmc_conf(const struct omap_mmc_config *mmc_conf)
 {
-       const struct omap_mmc_config    *mmc_conf;
-       const struct omap_mmc_conf      *mmc;
-
-       /* NOTE:  assumes MMC was never (wrongly) enabled */
-       mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config);
-       if (!mmc_conf)
+       if (cpu_is_omap2430() || cpu_is_omap34xx())
                return;
 
-       /* block 1 is always available and has just one pinout option */
-       mmc = &mmc_conf->mmc[0];
-       if (mmc->enabled) {
+       if (mmc_conf->mmc[0].enabled) {
                if (cpu_is_omap24xx()) {
                        omap_cfg_reg(H18_24XX_MMC_CMD);
                        omap_cfg_reg(H15_24XX_MMC_CLKI);
@@ -292,7 +300,7 @@ static void __init omap_init_mmc(void)
                                omap_cfg_reg(P20_1710_MMC_DATDIR0);
                        }
                }
-               if (mmc->wire4) {
+               if (mmc_conf->mmc[0].wire4) {
                        if (cpu_is_omap24xx()) {
                                omap_cfg_reg(H14_24XX_MMC_DAT1);
                                omap_cfg_reg(E19_24XX_MMC_DAT2);
@@ -303,25 +311,35 @@ static void __init omap_init_mmc(void)
                        } else {
                                omap_cfg_reg(MMC_DAT1);
                                /* NOTE:  DAT2 can be on W10 (here) or M15 */
-                               if (!mmc->nomux)
+                               if (!mmc_conf->mmc[0].nomux)
                                        omap_cfg_reg(MMC_DAT2);
                                omap_cfg_reg(MMC_DAT3);
                        }
                }
-               mmc1_conf = *mmc;
-               (void) platform_device_register(&mmc_omap_device1);
+#if defined(CONFIG_ARCH_OMAP2420)
+               if (mmc_conf->mmc[0].internal_clock) {
+                       /*
+                        * Use internal loop-back in MMC/SDIO
+                        * Module Input Clock selection
+                        */
+                       if (cpu_is_omap24xx()) {
+                               u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+                               v |= (1 << 24); /* not used in 243x */
+                               omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+                       }
+               }
+#endif
        }
 
 #ifdef CONFIG_ARCH_OMAP16XX
        /* block 2 is on newer chips, and has many pinout options */
-       mmc = &mmc_conf->mmc[1];
-       if (mmc->enabled) {
-               if (!mmc->nomux) {
+       if (mmc_conf->mmc[1].enabled) {
+               if (!mmc_conf->mmc[1].nomux) {
                        omap_cfg_reg(Y8_1610_MMC2_CMD);
                        omap_cfg_reg(Y10_1610_MMC2_CLK);
                        omap_cfg_reg(R18_1610_MMC2_CLKIN);
                        omap_cfg_reg(W8_1610_MMC2_DAT0);
-                       if (mmc->wire4) {
+                       if (mmc_conf->mmc[1].wire4) {
                                omap_cfg_reg(V8_1610_MMC2_DAT1);
                                omap_cfg_reg(W15_1610_MMC2_DAT2);
                                omap_cfg_reg(R10_1610_MMC2_DAT3);
@@ -337,14 +355,55 @@ static void __init omap_init_mmc(void)
                if (cpu_is_omap1710())
                        omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
                                     MOD_CONF_CTRL_1);
-               mmc2_conf = *mmc;
+       }
+#endif
+}
+
+static void __init omap_init_mmc(void)
+{
+       const struct omap_mmc_config    *mmc_conf;
+
+       /* NOTE:  assumes MMC was never (wrongly) enabled */
+       mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config);
+       if (!mmc_conf)
+               return;
+
+       omap_init_mmc_conf(mmc_conf);
+
+       if (mmc_conf->mmc[0].enabled) {
+               mmc1_data.conf = mmc_conf->mmc[0];
+               (void) platform_device_register(&mmc_omap_device1);
+       }
+
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
+       defined(CONFIG_ARCH_OMAP34XX)
+       if (mmc_conf->mmc[1].enabled) {
+               mmc2_data.conf = mmc_conf->mmc[1];
                (void) platform_device_register(&mmc_omap_device2);
        }
 #endif
-       return;
 }
+
+void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info)
+{
+       switch (host) {
+       case 1:
+               mmc1_data = *info;
+               break;
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
+       defined(CONFIG_ARCH_OMAP34XX)
+       case 2:
+               mmc2_data = *info;
+               break;
+#endif
+       default:
+               BUG();
+       }
+}
+
 #else
 static inline void omap_init_mmc(void) {}
+void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info) {}
 #endif
 
 /*-------------------------------------------------------------------------*/
index 3e76ee2bc731dfd91d7e6fb00461a9a43e9b6c55..9e1341ebc14e8842646ae8a53fb2aa9307031b69 100644 (file)
@@ -1488,7 +1488,7 @@ static int __init _omap_gpio_init(void)
                bank->chip.set = gpio_set;
                if (bank_is_mpuio(bank)) {
                        bank->chip.label = "mpuio";
-#ifdef CONFIG_ARCH_OMAP1
+#ifdef CONFIG_ARCH_OMAP16XX
                        bank->chip.dev = &omap_mpuio_device.dev;
 #endif
                        bank->chip.base = OMAP_MPUIO(0);
index 6eb44a92871db97961644ef2d147f30b5f1632cd..8fdb95e26fcd86775fe4fd494139e381b17f76e5 100644 (file)
@@ -315,6 +315,7 @@ struct omap_mcbsp_ops {
 };
 
 struct omap_mcbsp_platform_data {
+       unsigned long phys_base;
        u32 virt_base;
        u8 dma_rx_sync, dma_tx_sync;
        u16 rx_irq, tx_irq;
@@ -324,6 +325,7 @@ struct omap_mcbsp_platform_data {
 
 struct omap_mcbsp {
        struct device *dev;
+       unsigned long phys_base;
        u32 io_base;
        u8 id;
        u8 free;
index d0844050f2d2da0febf9e95e287f032ed95f3ef7..014d26574bb61cd52267db7edfff9ad439e0c4bd 100644 (file)
@@ -651,7 +651,7 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
        omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
                                 src_port,
                                 OMAP_DMA_AMODE_CONSTANT,
-                                mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
+                                mcbsp[id].phys_base + OMAP_MCBSP_REG_DXR1,
                                 0, 0);
 
        omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
@@ -712,7 +712,7 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
        omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
                                src_port,
                                OMAP_DMA_AMODE_CONSTANT,
-                               mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
+                               mcbsp[id].phys_base + OMAP_MCBSP_REG_DRR1,
                                0, 0);
 
        omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
@@ -830,6 +830,7 @@ static int __init omap_mcbsp_probe(struct platform_device *pdev)
        mcbsp[id].dma_tx_lch = -1;
        mcbsp[id].dma_rx_lch = -1;
 
+       mcbsp[id].phys_base = pdata->phys_base;
        mcbsp[id].io_base = pdata->virt_base;
        /* Default I/O is IRQ based */
        mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO;
index e4796c67a831aa930208c736de6722b1a460891b..d6a8193a1d2f09c8d9356212db5bd6ae44efeda4 100644 (file)
@@ -4,6 +4,8 @@
  * to extract and format the required data.
  */
 
+#include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/thread_info.h>
 #include <linux/kbuild.h>
 
@@ -17,4 +19,8 @@ void foo(void)
        OFFSET(TI_rar_saved, thread_info, rar_saved);
        OFFSET(TI_rsr_saved, thread_info, rsr_saved);
        OFFSET(TI_restart_block, thread_info, restart_block);
+       BLANK();
+       OFFSET(TSK_active_mm, task_struct, active_mm);
+       BLANK();
+       OFFSET(MM_pgd, mm_struct, pgd);
 }
index 2b398cae110c839fc5b3c3be3d9d7a48fcf3a2ec..33d49377b8beda6ae217cf40928d304d5eabfa6d 100644 (file)
@@ -334,9 +334,64 @@ save_full_context_ex:
 
        /* Low-level exception handlers */
 handle_critical:
+       /*
+        * AT32AP700x errata:
+        *
+        * After a Java stack overflow or underflow trap, any CPU
+        * memory access may cause erratic behavior. This will happen
+        * when the four least significant bits of the JOSP system
+        * register contains any value between 9 and 15 (inclusive).
+        *
+        * Possible workarounds:
+        *   - Don't use the Java Extension Module
+        *   - Ensure that the stack overflow and underflow trap
+        *     handlers do not do any memory access or trigger any
+        *     exceptions before the overflow/underflow condition is
+        *     cleared (by incrementing or decrementing the JOSP)
+        *   - Make sure that JOSP does not contain any problematic
+        *     value before doing any exception or interrupt
+        *     processing.
+        *   - Set up a critical exception handler which writes a
+        *     known-to-be-safe value, e.g. 4, to JOSP before doing
+        *     any further processing.
+        *
+        * We'll use the last workaround for now since we cannot
+        * guarantee that user space processes don't use Java mode.
+        * Non-well-behaving userland will be terminated with extreme
+        * prejudice.
+        */
+#ifdef CONFIG_CPU_AT32AP700X
+       /*
+        * There's a chance we can't touch memory, so temporarily
+        * borrow PTBR to save the stack pointer while we fix things
+        * up...
+        */
+       mtsr    SYSREG_PTBR, sp
+       mov     sp, 4
+       mtsr    SYSREG_JOSP, sp
+       mfsr    sp, SYSREG_PTBR
+       sub     pc, -2
+
+       /* Push most of pt_regs on stack. We'll do the rest later */
        sub     sp, 4
-       stmts   --sp, r0-lr
-       rcall   save_full_context_ex
+       pushm   r0-r12
+
+       /* PTBR mirrors current_thread_info()->task->active_mm->pgd */
+       get_thread_info r0
+       ld.w    r1, r0[TI_task]
+       ld.w    r2, r1[TSK_active_mm]
+       ld.w    r3, r2[MM_pgd]
+       mtsr    SYSREG_PTBR, r3
+#else
+       sub     sp, 4
+       pushm   r0-r12
+#endif
+       sub     r0, sp, -(14 * 4)
+       mov     r1, lr
+       mfsr    r2, SYSREG_RAR_EX
+       mfsr    r3, SYSREG_RSR_EX
+       pushm   r0-r3
+
        mfsr    r12, SYSREG_ECR
        mov     r11, sp
        rcall   do_critical_exception
index 5be4de65b209661edbaab3851f7283149c96dba0..17503b0ed6c9b3f5865406fb0d5f44241ce6bab7 100644 (file)
@@ -134,7 +134,7 @@ pm_standby:
        mov     r11, SDRAMC_LPR_LPCB_SELF_RFR
        bfins   r10, r11, 0, 2          /* LPCB <- self Refresh */
        sync    0                       /* flush write buffer */
-       st.w    r12[SDRAMC_LPR], r11    /* put SDRAM in self-refresh mode */
+       st.w    r12[SDRAMC_LPR], r10    /* put SDRAM in self-refresh mode */
        ld.w    r11, r12[SDRAMC_LPR]
        unmask_interrupts
        sleep   CPU_SLEEP_FROZEN
index 7286e4a9fe8449e1b02e5e762eb9dc7e1aeb53ce..a7acad2bc2f0b0f14f6b608bf43224b4411ce9d5 100644 (file)
@@ -21,5 +21,8 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b
 extern char __start_unwind[], __end_unwind[];
 extern char __start_ivt_text[], __end_ivt_text[];
 
+#undef dereference_function_descriptor
+void *dereference_function_descriptor(void *);
+
 #endif /* _ASM_IA64_SECTIONS_H */
 
index 29aad349e0c4fafd49eb6b8c07bce2f3db3a24d6..545626f66a4c571c65bcd8a5ae3a8e855db48012 100644 (file)
 #include <linux/elf.h>
 #include <linux/moduleloader.h>
 #include <linux/string.h>
+#include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 
 #include <asm/patch.h>
+#include <asm/sections.h>
 #include <asm/unaligned.h>
 
 #define ARCH_MODULE_DEBUG 0
@@ -941,3 +943,13 @@ module_arch_cleanup (struct module *mod)
        if (mod->arch.core_unw_table)
                unw_remove_unwind_table(mod->arch.core_unw_table);
 }
+
+void *dereference_function_descriptor(void *ptr)
+{
+       struct fdesc *desc = ptr;
+       void *p;
+
+       if (!probe_kernel_address(&desc->ip, p))
+               ptr = p;
+       return ptr;
+}
index 8a2a53b33616708a7bbe6815bfd9d58dce42bf98..bb959fbab2dc2b74805052b409142ffd2c43b965 100644 (file)
@@ -580,13 +580,15 @@ int atari_keyb_init(void)
        do {
                /* reset IKBD ACIA */
                acia.key_ctrl = ACIA_RESET |
-                               (atari_switches & ATARI_SWITCH_IKBD) ? ACIA_RHTID : 0;
+                               ((atari_switches & ATARI_SWITCH_IKBD) ?
+                                ACIA_RHTID : 0);
                (void)acia.key_ctrl;
                (void)acia.key_data;
 
                /* reset MIDI ACIA */
                acia.mid_ctrl = ACIA_RESET |
-                               (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
+                               ((atari_switches & ATARI_SWITCH_MIDI) ?
+                                ACIA_RHTID : 0);
                (void)acia.mid_ctrl;
                (void)acia.mid_data;
 
@@ -599,7 +601,8 @@ int atari_keyb_init(void)
                                 ACIA_RHTID : ACIA_RLTID);
 
                acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S |
-                               (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
+                               ((atari_switches & ATARI_SWITCH_MIDI) ?
+                                ACIA_RHTID : 0);
 
        /* make sure the interrupt line is up */
        } while ((mfp.par_dt_reg & 0x10) == 0);
index 4da736e25333abc8ce46440dcb8b97c4c9f2be9d..49896a2a1d722e0760a866487f8b80b7d8af8fb0 100644 (file)
@@ -1886,6 +1886,15 @@ config STACKTRACE_SUPPORT
 
 source "init/Kconfig"
 
+config PROBE_INITRD_HEADER
+       bool "Probe initrd header created by addinitrd"
+       depends on BLK_DEV_INITRD
+       help
+         Probe initrd header at the last page of kernel image.
+         Say Y here if you are using arch/mips/boot/addinitrd.c to
+         add initrd or initramfs image to the kernel image.
+         Otherwise, say N.
+
 menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)"
 
 config HW_HAS_EISA
index 2aae76bce29355183f9697cb314dec3306d89af5..16f8edfe5cdce81a63d850980cb0dda08e94049f 100644 (file)
@@ -160,30 +160,33 @@ early_param("rd_size", rd_size_early);
 static unsigned long __init init_initrd(void)
 {
        unsigned long end;
-       u32 *initrd_header;
 
        /*
         * Board specific code or command line parser should have
         * already set up initrd_start and initrd_end. In these cases
         * perfom sanity checks and use them if all looks good.
         */
-       if (initrd_start && initrd_end > initrd_start)
-               goto sanitize;
+       if (!initrd_start || initrd_end <= initrd_start) {
+#ifdef CONFIG_PROBE_INITRD_HEADER
+               u32 *initrd_header;
 
-       /*
-        * See if initrd has been added to the kernel image by
-        * arch/mips/boot/addinitrd.c. In that case a header is
-        * prepended to initrd and is made up by 8 bytes. The fisrt
-        * word is a magic number and the second one is the size of
-        * initrd.  Initrd start must be page aligned in any cases.
-        */
-       initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
-       if (initrd_header[0] != 0x494E5244)
+               /*
+                * See if initrd has been added to the kernel image by
+                * arch/mips/boot/addinitrd.c. In that case a header is
+                * prepended to initrd and is made up by 8 bytes. The first
+                * word is a magic number and the second one is the size of
+                * initrd.  Initrd start must be page aligned in any cases.
+                */
+               initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
+               if (initrd_header[0] != 0x494E5244)
+                       goto disable;
+               initrd_start = (unsigned long)(initrd_header + 2);
+               initrd_end = initrd_start + initrd_header[1];
+#else
                goto disable;
-       initrd_start = (unsigned long)(initrd_header + 2);
-       initrd_end = initrd_start + initrd_header[1];
+#endif
+       }
 
-sanitize:
        if (initrd_start & ~PAGE_MASK) {
                pr_err("initrd start must be page aligned\n");
                goto disable;
index 426cced1e9dce3e4d6e560fad38d26136a8c02e9..6bee29097a565e71459f80ee75c3affd3d0ed25b 100644 (file)
@@ -373,8 +373,8 @@ void __noreturn die(const char * str, const struct pt_regs * regs)
        do_exit(SIGSEGV);
 }
 
-extern const struct exception_table_entry __start___dbe_table[];
-extern const struct exception_table_entry __stop___dbe_table[];
+extern struct exception_table_entry __start___dbe_table[];
+extern struct exception_table_entry __stop___dbe_table[];
 
 __asm__(
 "      .section        __dbe_table, \"a\"\n"
@@ -1200,7 +1200,7 @@ void *set_except_vector(int n, void *addr)
        if (n == 0 && cpu_has_divec) {
                *(u32 *)(ebase + 0x200) = 0x08000000 |
                                          (0x03ffffff & (handler >> 2));
-               flush_icache_range(ebase + 0x200, ebase + 0x204);
+               local_flush_icache_range(ebase + 0x200, ebase + 0x204);
        }
        return (void *)old_handler;
 }
@@ -1283,7 +1283,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
                *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
                w = (u32 *)(b + ori_offset);
                *w = (*w & 0xffff0000) | ((u32)handler & 0xffff);
-               flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len));
+               local_flush_icache_range((unsigned long)b,
+                                        (unsigned long)(b+handler_len));
        }
        else {
                /*
@@ -1295,7 +1296,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
                w = (u32 *)b;
                *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */
                *w = 0;
-               flush_icache_range((unsigned long)b, (unsigned long)(b+8));
+               local_flush_icache_range((unsigned long)b,
+                                        (unsigned long)(b+8));
        }
 
        return (void *)old_handler;
@@ -1515,7 +1517,7 @@ void __cpuinit per_cpu_trap_init(void)
 void __init set_handler(unsigned long offset, void *addr, unsigned long size)
 {
        memcpy((void *)(ebase + offset), addr, size);
-       flush_icache_range(ebase + offset, ebase + offset + size);
+       local_flush_icache_range(ebase + offset, ebase + offset + size);
 }
 
 static char panic_null_cerr[] __cpuinitdata =
@@ -1680,6 +1682,8 @@ void __init trap_init(void)
        signal32_init();
 #endif
 
-       flush_icache_range(ebase, ebase + 0x400);
+       local_flush_icache_range(ebase, ebase + 0x400);
        flush_tlb_handlers();
+
+       sort_extable(__start___dbe_table, __stop___dbe_table);
 }
index 27a5b466c85ce0ef4f859ea47402dfd2d77f112c..5500c20c79aeafc491c3b9b43cbe8f5e816e084c 100644 (file)
@@ -320,6 +320,7 @@ void __cpuinit r3k_cache_init(void)
        flush_cache_range = r3k_flush_cache_range;
        flush_cache_page = r3k_flush_cache_page;
        flush_icache_range = r3k_flush_icache_range;
+       local_flush_icache_range = r3k_flush_icache_range;
 
        flush_cache_sigtramp = r3k_flush_cache_sigtramp;
        local_flush_data_cache_page = local_r3k_flush_data_cache_page;
index 71df3390c07bf76608ee9c25f3896f9d93eda94c..6e99665ae860e540cafee642d5d3daf0c1537738 100644 (file)
@@ -543,12 +543,8 @@ struct flush_icache_range_args {
        unsigned long end;
 };
 
-static inline void local_r4k_flush_icache_range(void *args)
+static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end)
 {
-       struct flush_icache_range_args *fir_args = args;
-       unsigned long start = fir_args->start;
-       unsigned long end = fir_args->end;
-
        if (!cpu_has_ic_fills_f_dc) {
                if (end - start >= dcache_size) {
                        r4k_blast_dcache();
@@ -564,6 +560,15 @@ static inline void local_r4k_flush_icache_range(void *args)
                protected_blast_icache_range(start, end);
 }
 
+static inline void local_r4k_flush_icache_range_ipi(void *args)
+{
+       struct flush_icache_range_args *fir_args = args;
+       unsigned long start = fir_args->start;
+       unsigned long end = fir_args->end;
+
+       local_r4k_flush_icache_range(start, end);
+}
+
 static void r4k_flush_icache_range(unsigned long start, unsigned long end)
 {
        struct flush_icache_range_args args;
@@ -571,7 +576,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
        args.start = start;
        args.end = end;
 
-       r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1);
+       r4k_on_each_cpu(local_r4k_flush_icache_range_ipi, &args, 1);
        instruction_hazard();
 }
 
@@ -1375,6 +1380,7 @@ void __cpuinit r4k_cache_init(void)
        local_flush_data_cache_page     = local_r4k_flush_data_cache_page;
        flush_data_cache_page   = r4k_flush_data_cache_page;
        flush_icache_range      = r4k_flush_icache_range;
+       local_flush_icache_range        = local_r4k_flush_icache_range;
 
 #if defined(CONFIG_DMA_NONCOHERENT)
        if (coherentio) {
index a9f7f1f5e9b4ae90a50993bd06335b77ac8f47f5..f7c8f9ce39c1b1e983d54b6414c3a4bd1a2b8010 100644 (file)
@@ -362,6 +362,7 @@ void __cpuinit tx39_cache_init(void)
                flush_cache_range       = (void *) tx39h_flush_icache_all;
                flush_cache_page        = (void *) tx39h_flush_icache_all;
                flush_icache_range      = (void *) tx39h_flush_icache_all;
+               local_flush_icache_range = (void *) tx39h_flush_icache_all;
 
                flush_cache_sigtramp    = (void *) tx39h_flush_icache_all;
                local_flush_data_cache_page     = (void *) tx39h_flush_icache_all;
@@ -390,6 +391,7 @@ void __cpuinit tx39_cache_init(void)
                flush_cache_range = tx39_flush_cache_range;
                flush_cache_page = tx39_flush_cache_page;
                flush_icache_range = tx39_flush_icache_range;
+               local_flush_icache_range = tx39_flush_icache_range;
 
                flush_cache_sigtramp = tx39_flush_cache_sigtramp;
                local_flush_data_cache_page = local_tx39_flush_data_cache_page;
index 034e8506f6ea712a9554d9f13de28f622d8db1d4..1eb7c71e3d6adfe25916070e180ae87e0b3eedbf 100644 (file)
@@ -29,6 +29,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
 void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
        unsigned long pfn);
 void (*flush_icache_range)(unsigned long start, unsigned long end);
+void (*local_flush_icache_range)(unsigned long start, unsigned long end);
 
 void (*__flush_cache_vmap)(void);
 void (*__flush_cache_vunmap)(void);
index 76da73a5ab3caff4fcf43921ed8a132a8a739897..979cf9197282ca1f315a0ca8430da4d527332cd8 100644 (file)
@@ -1273,10 +1273,10 @@ void __cpuinit build_tlb_refill_handler(void)
 
 void __cpuinit flush_tlb_handlers(void)
 {
-       flush_icache_range((unsigned long)handle_tlbl,
+       local_flush_icache_range((unsigned long)handle_tlbl,
                           (unsigned long)handle_tlbl + sizeof(handle_tlbl));
-       flush_icache_range((unsigned long)handle_tlbs,
+       local_flush_icache_range((unsigned long)handle_tlbs,
                           (unsigned long)handle_tlbs + sizeof(handle_tlbs));
-       flush_icache_range((unsigned long)handle_tlbm,
+       local_flush_icache_range((unsigned long)handle_tlbm,
                           (unsigned long)handle_tlbm + sizeof(handle_tlbm));
 }
index 60141235ec40a956162f6343b27d55d567f0d386..52486c4d2b019739be2db360e3cbc8b7dd1fd847 100644 (file)
@@ -150,7 +150,7 @@ static int __init sgiseeq_devinit(void)
                return res;
 
        /* Second HPC is missing? */
-       if (!ip22_is_fullhouse() ||
+       if (ip22_is_fullhouse() ||
            get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
                return 0;
 
index 0afe94c48fb65e82ee283f5fbd2fbce6362dcdb9..fe6bee09cecea23e640a40861a9dcbc4e4adfe94 100644 (file)
@@ -53,6 +53,7 @@ txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size)
                txx9_ce_res[i].name = txx9_ce_res_name[i];
        }
 
+       txx9_pcode = pcode;
        sprintf(txx9_pcode_str, "TX%x", pcode);
        if (base) {
                txx9_reg_res.start = base & 0xfffffffffULL;
index 69ff671498e53069af7a1575c2745702a117930d..12c04c5e558be01c1a219214721bfbd1901c1b4e 100644 (file)
@@ -104,7 +104,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
        buf->count -= reclen;
        return 0;
 Efault:
-       buffer->error = -EFAULT;
+       buf->error = -EFAULT;
        return -EFAULT;
 }
 
index fdacdd4341c9f3ccf3189afe683b7179ead823d4..44138c3e6ea74e3042b2ddb66058714eb74bc27f 100644 (file)
@@ -47,7 +47,9 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/bug.h>
+#include <linux/uaccess.h>
 
+#include <asm/sections.h>
 #include <asm/unwind.h>
 
 #if 0
@@ -860,3 +862,15 @@ void module_arch_cleanup(struct module *mod)
        deregister_unwind_table(mod);
        module_bug_cleanup(mod);
 }
+
+#ifdef CONFIG_64BIT
+void *dereference_function_descriptor(void *ptr)
+{
+       Elf64_Fdesc *desc = ptr;
+       void *p;
+
+       if (!probe_kernel_address(&desc->addr, p))
+               ptr = p;
+       return ptr;
+}
+#endif
index 9155c9312c1ec1b182453d5093235ace4f17b9a9..c6be19e9ceae99dd6f0d6a47f66e44634a71e3bb 100644 (file)
@@ -116,6 +116,11 @@ ifeq ($(CONFIG_6xx),y)
 KBUILD_CFLAGS          += -mcpu=powerpc
 endif
 
+# Work around a gcc code-gen bug with -fno-omit-frame-pointer.
+ifeq ($(CONFIG_FTRACE),y)
+KBUILD_CFLAGS          += -mno-sched-epilog
+endif
+
 cpu-as-$(CONFIG_4xx)           += -Wa,-m405
 cpu-as-$(CONFIG_6xx)           += -Wa,-maltivec
 cpu-as-$(CONFIG_POWER4)                += -Wa,-maltivec
index 14174aa240744783d6c0d77748a9b714d6cebea0..717a3bc1352e542d410e3713e2222e7ea2745516 100644 (file)
@@ -49,7 +49,7 @@ zlib       := inffast.c inflate.c inftrees.c
 zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
 zliblinuxheader := zlib.h zconf.h zutil.h
 
-$(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
+$(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \
        $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 
 src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
index db0b8f3b88071a57ea80b9758f486c01824f794c..4597c491e9b52ee72c854271a88e0b572823507a 100644 (file)
 #define __S110 PAGE_SHARED_X
 #define __S111 PAGE_SHARED_X
 
-#ifdef CONFIG_HUGETLB_PAGE
-
+#ifdef CONFIG_PPC_MM_SLICES
 #define HAVE_ARCH_UNMAPPED_AREA
 #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
-
-#endif
+#endif /* CONFIG_PPC_MM_SLICES */
 
 #ifndef __ASSEMBLY__
 
index 916018e425c4dc7112f6c0c1f49f884118d4bd0b..7710e9e6660fc52ef703c540a95b16a892ba3fca 100644 (file)
@@ -16,6 +16,9 @@ static inline int in_kernel_text(unsigned long addr)
        return 0;
 }
 
+#undef dereference_function_descriptor
+void *dereference_function_descriptor(void *);
+
 #endif
 
 #endif /* __KERNEL__ */
index 64f5948ebc9df94c7a0ae0978989ee65818dc2c2..946daea780f1ea6858624368e235142f0448a508 100644 (file)
@@ -14,12 +14,13 @@ endif
 
 ifdef CONFIG_FTRACE
 # Do not trace early boot code
-CFLAGS_REMOVE_cputable.o = -pg
-CFLAGS_REMOVE_prom_init.o = -pg
+CFLAGS_REMOVE_cputable.o = -pg -mno-sched-epilog
+CFLAGS_REMOVE_prom_init.o = -pg -mno-sched-epilog
+CFLAGS_REMOVE_btext.o = -pg -mno-sched-epilog
 
 ifdef CONFIG_DYNAMIC_FTRACE
 # dynamic ftrace setup.
-CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog
 endif
 
 endif
index 367129789cc0854a01fd96efc88824d7f9c995a8..5af4e9b2dbe2c6dcdde0213809f0d74673e19252 100644 (file)
@@ -647,7 +647,7 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
                       unsigned int flags, unsigned int length)
 {
        char *ptr = (char *) &current->thread.TS_FPR(reg);
-       int ret;
+       int ret = 0;
 
        flush_vsx_to_thread(current);
 
index 019b02d8844f86c0a2325520fffb4b1a0e62e8a7..15c611de1ee2a0cdb25cd7524179373aca32a1d2 100644 (file)
@@ -158,7 +158,7 @@ _GLOBAL(power_save_ppc32_restore)
        stw     r9,_NIP(r11)            /* make it do a blr */
 
 #ifdef CONFIG_SMP
-       mfspr   r12,SPRN_SPRG3
+       rlwinm  r12,r11,0,0,31-THREAD_SHIFT
        lwz     r11,TI_CPU(r12)         /* get cpu number * 4 */
        slwi    r11,r11,2
 #else
index 06304034b3939e63cb619849fc5d80ebd6b07ce4..47a1a983ff8840893a6a624fc109551b343e7a5f 100644 (file)
@@ -84,10 +84,11 @@ _GLOBAL(power_save_ppc32_restore)
        stw     r9,_NIP(r11)            /* make it do a blr */
 
 #ifdef CONFIG_SMP
-       mfspr   r12,SPRN_SPRG3
+       rlwinm  r12,r1,0,0,31-THREAD_SHIFT
        lwz     r11,TI_CPU(r12)         /* get cpu number * 4 */
        slwi    r11,r11,2
 #else
        li      r11,0
 #endif
+
        b       transfer_to_handler_cont
index ee6a2982d567351eb88ace12c2109918af6af59e..ad79de272ff3ec7f7ee14062f48eed082511e2e0 100644 (file)
@@ -21,8 +21,9 @@
 #include <linux/err.h>
 #include <linux/vmalloc.h>
 #include <linux/bug.h>
+#include <linux/uaccess.h>
 #include <asm/module.h>
-#include <asm/uaccess.h>
+#include <asm/sections.h>
 #include <asm/firmware.h>
 #include <asm/code-patching.h>
 #include <linux/sort.h>
@@ -451,3 +452,13 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 
        return 0;
 }
+
+void *dereference_function_descriptor(void *ptr)
+{
+       struct ppc64_opd_entry *desc = ptr;
+       void *p;
+
+       if (!probe_kernel_address(&desc->funcaddr, p))
+               ptr = p;
+       return ptr;
+}
index 4a8ce62fe1121c1a774f04a9af6223a96f945c23..9f6c1ca1739e08ecc1e56a64ffed6c6a610a3e1a 100644 (file)
@@ -66,11 +66,12 @@ SECTIONS
                __got2_end = .;
 #endif /* CONFIG_PPC32 */
 
-               . = ALIGN(PAGE_SIZE);
-               _etext = .;
-               PROVIDE32 (etext = .);
        } :kernel
 
+       . = ALIGN(PAGE_SIZE);
+       _etext = .;
+       PROVIDE32 (etext = .);
+
        /* Read-only data */
        RODATA
 
index 14be408dfc9bdfcdad5ecd9855f2e06e07e4390f..8920eea3452844dfb906fc3f9d6b67a01d37561f 100644 (file)
@@ -191,12 +191,17 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
                unsigned long hash, hpteg;
                unsigned long vsid = get_kernel_vsid(vaddr, ssize);
                unsigned long va = hpt_va(vaddr, vsid, ssize);
+               unsigned long tprot = prot;
+
+               /* Make kernel text executable */
+               if (in_kernel_text(vaddr))
+                       tprot &= ~HPTE_R_N;
 
                hash = hpt_hash(va, shift, ssize);
                hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
                BUG_ON(!ppc_md.hpte_insert);
-               ret = ppc_md.hpte_insert(hpteg, va, paddr, prot,
+               ret = ppc_md.hpte_insert(hpteg, va, paddr, tprot,
                                         HPTE_V_BOLTED, psize, ssize);
 
                if (ret < 0)
@@ -584,7 +589,7 @@ void __init htab_initialize(void)
 {
        unsigned long table;
        unsigned long pteg_count;
-       unsigned long prot, tprot;
+       unsigned long prot;
        unsigned long base = 0, size = 0, limit;
        int i;
 
@@ -660,10 +665,9 @@ void __init htab_initialize(void)
        for (i=0; i < lmb.memory.cnt; i++) {
                base = (unsigned long)__va(lmb.memory.region[i].base);
                size = lmb.memory.region[i].size;
-               tprot = prot | (in_kernel_text(base) ? _PAGE_EXEC : 0);
 
                DBG("creating mapping for region: %lx..%lx (prot: %x)\n",
-                   base, size, tprot);
+                   base, size, prot);
 
 #ifdef CONFIG_U3_DART
                /* Do not map the DART space. Fortunately, it will be aligned
@@ -680,21 +684,21 @@ void __init htab_initialize(void)
                        unsigned long dart_table_end = dart_tablebase + 16 * MB;
                        if (base != dart_tablebase)
                                BUG_ON(htab_bolt_mapping(base, dart_tablebase,
-                                                       __pa(base), tprot,
+                                                       __pa(base), prot,
                                                        mmu_linear_psize,
                                                        mmu_kernel_ssize));
                        if ((base + size) > dart_table_end)
                                BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB,
                                                        base + size,
                                                        __pa(dart_table_end),
-                                                        tprot,
+                                                        prot,
                                                         mmu_linear_psize,
                                                         mmu_kernel_ssize));
                        continue;
                }
 #endif /* CONFIG_U3_DART */
                BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
-                               tprot, mmu_linear_psize, mmu_kernel_ssize));
+                               prot, mmu_linear_psize, mmu_kernel_ssize));
        }
 
        /*
index 1c1b627ee8436dc8e2fce9098d274183b8f18011..67595bc380dc154465682f9be7f9c203d283bfe5 100644 (file)
@@ -643,9 +643,10 @@ static struct spu *find_victim(struct spu_context *ctx)
                            !(tmp->flags & SPU_CREATE_NOSCHED) &&
                            (!victim || tmp->prio > victim->prio)) {
                                victim = spu->ctx;
-                               get_spu_context(victim);
                        }
                }
+               if (victim)
+                       get_spu_context(victim);
                mutex_unlock(&cbe_spu_info[node].list_mutex);
 
                if (victim) {
@@ -727,17 +728,33 @@ static void spu_schedule(struct spu *spu, struct spu_context *ctx)
        /* not a candidate for interruptible because it's called either
           from the scheduler thread or from spu_deactivate */
        mutex_lock(&ctx->state_mutex);
-       __spu_schedule(spu, ctx);
+       if (ctx->state == SPU_STATE_SAVED)
+               __spu_schedule(spu, ctx);
        spu_release(ctx);
 }
 
-static void spu_unschedule(struct spu *spu, struct spu_context *ctx)
+/**
+ * spu_unschedule - remove a context from a spu, and possibly release it.
+ * @spu:       The SPU to unschedule from
+ * @ctx:       The context currently scheduled on the SPU
+ * @free_spu   Whether to free the SPU for other contexts
+ *
+ * Unbinds the context @ctx from the SPU @spu. If @free_spu is non-zero, the
+ * SPU is made available for other contexts (ie, may be returned by
+ * spu_get_idle). If this is zero, the caller is expected to schedule another
+ * context to this spu.
+ *
+ * Should be called with ctx->state_mutex held.
+ */
+static void spu_unschedule(struct spu *spu, struct spu_context *ctx,
+               int free_spu)
 {
        int node = spu->node;
 
        mutex_lock(&cbe_spu_info[node].list_mutex);
        cbe_spu_info[node].nr_active--;
-       spu->alloc_state = SPU_FREE;
+       if (free_spu)
+               spu->alloc_state = SPU_FREE;
        spu_unbind_context(spu, ctx);
        ctx->stats.invol_ctx_switch++;
        spu->stats.invol_ctx_switch++;
@@ -837,7 +854,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
        if (spu) {
                new = grab_runnable_context(max_prio, spu->node);
                if (new || force) {
-                       spu_unschedule(spu, ctx);
+                       spu_unschedule(spu, ctx, new == NULL);
                        if (new) {
                                if (new->flags & SPU_CREATE_NOSCHED)
                                        wake_up(&new->stop_wq);
@@ -910,7 +927,7 @@ static noinline void spusched_tick(struct spu_context *ctx)
 
        new = grab_runnable_context(ctx->prio + 1, spu->node);
        if (new) {
-               spu_unschedule(spu, ctx);
+               spu_unschedule(spu, ctx, 0);
                if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags))
                        spu_add_to_rq(ctx);
        } else {
index 58ecdd72630fb1e3eb772df368b500cd672d0e8b..be60d64be7ad92a11046bbf0fbbcd12b79e1a43b 100644 (file)
@@ -2,7 +2,7 @@ CFLAGS_bootx_init.o             += -fPIC
 
 ifdef CONFIG_FTRACE
 # Do not trace early boot code
-CFLAGS_REMOVE_bootx_init.o = -pg
+CFLAGS_REMOVE_bootx_init.o = -pg -mno-sched-epilog
 endif
 
 obj-y                          += pic.o setup.o time.o feature.o pci.o \
index cde81fa64f89bf17bc586dce3f973e77f55985e8..a2be3a978d5c43281e3cf3115e2dfb19d473307f 100644 (file)
@@ -42,6 +42,7 @@ struct user_regs_struct32
        u32 gprs[NUM_GPRS];
        u32 acrs[NUM_ACRS];
        u32 orig_gpr2;
+       /* nb: there's a 4-byte hole here */
        s390_fp_regs fp_regs;
        /*
         * These per registers are in here so that gdb can modify them
index 2815bfe348a6f92e67b64e04e0b70cbecde6bc58..c8b08289eb87e1d78c9c92996fe7bbfe30c16645 100644 (file)
@@ -170,6 +170,13 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
                 */
                tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
 
+       } else if (addr < (addr_t) &dummy->regs.fp_regs) {
+               /*
+                * prevent reads of padding hole between
+                * orig_gpr2 and fp_regs on s390.
+                */
+               tmp = 0;
+
        } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
                /* 
                 * floating point regs. are stored in the thread structure
@@ -270,6 +277,13 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
                 */
                task_pt_regs(child)->orig_gpr2 = data;
 
+       } else if (addr < (addr_t) &dummy->regs.fp_regs) {
+               /*
+                * prevent writes of padding hole between
+                * orig_gpr2 and fp_regs on s390.
+                */
+               return 0;
+
        } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
                /*
                 * floating point regs. are stored in the thread structure
@@ -428,6 +442,13 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
                 */
                tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
 
+       } else if (addr < (addr_t) &dummy32->regs.fp_regs) {
+               /*
+                * prevent reads of padding hole between
+                * orig_gpr2 and fp_regs on s390.
+                */
+               tmp = 0;
+
        } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
                /*
                 * floating point regs. are stored in the thread structure 
@@ -514,6 +535,13 @@ static int __poke_user_compat(struct task_struct *child,
                 */
                *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
 
+       } else if (addr < (addr_t) &dummy32->regs.fp_regs) {
+               /*
+                * prevent writess of padding hole between
+                * orig_gpr2 and fp_regs on s390.
+                */
+               return 0;
+
        } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
                /*
                 * floating point regs. are stored in the thread structure 
index 29926a9b9ce2248a3f8cb03feee5d38ea75a86c0..851c870adf3b0a1447270f9cd5033fe49e8bd45c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26
-# Wed Jul 30 01:18:59 2008
+# Linux kernel version: 2.6.27-rc4
+# Tue Aug 26 14:21:17 2008
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
@@ -11,6 +11,7 @@ CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
@@ -20,7 +21,6 @@ CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -58,7 +58,6 @@ CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_KALLSYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
@@ -89,6 +88,7 @@ CONFIG_HAVE_OPROFILE=y
 # CONFIG_USE_GENERIC_SMP_HELPERS is not set
 CONFIG_HAVE_CLK=y
 CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
@@ -261,9 +261,10 @@ CONFIG_HZ_250=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
-# CONFIG_SCHED_HRTICK is not set
+CONFIG_SCHED_HRTICK=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_SECCOMP=y
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
@@ -289,10 +290,6 @@ CONFIG_CMDLINE="console=tty1 console=ttySC5,38400 root=/dev/nfs ip=dhcp"
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
@@ -647,6 +644,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
 
 #
 # Multimedia devices
@@ -690,7 +688,10 @@ CONFIG_DUMMY_CONSOLE=y
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
-# CONFIG_UIO is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
 
 #
 # File systems
@@ -854,6 +855,7 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_SAMPLES is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
index c4b3e1d8950d9bac9766e56e560231ab6ff11024..4f8b1974f2c7a5b3d4ba66b5daf962992519ed6b 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26
-# Wed Jul 30 01:44:41 2008
+# Linux kernel version: 2.6.27-rc4
+# Tue Aug 26 14:18:17 2008
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
@@ -11,6 +11,7 @@ CONFIG_GENERIC_BUG=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
@@ -21,7 +22,6 @@ CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -87,6 +87,7 @@ CONFIG_HAVE_OPROFILE=y
 # CONFIG_USE_GENERIC_SMP_HELPERS is not set
 CONFIG_HAVE_CLK=y
 CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
@@ -270,6 +271,7 @@ CONFIG_HZ=250
 # CONFIG_SCHED_HRTICK is not set
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_SECCOMP=y
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -294,10 +296,6 @@ CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ip=on"
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
@@ -649,6 +647,7 @@ CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
 
 #
 # I2C Hardware Bus support
@@ -709,6 +708,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
 
 #
 # Multimedia devices
@@ -755,6 +755,8 @@ CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB is not set
 # CONFIG_USB_OTG_WHITELIST is not set
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -842,7 +844,10 @@ CONFIG_RTC_DRV_RS5C372=y
 #
 CONFIG_RTC_DRV_SH=y
 # CONFIG_DMADEVICES is not set
-# CONFIG_UIO is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
 
 #
 # File systems
index 81b3d515fcb36920938de61b13412a0d75e95fe4..5580fd471003e156b843df49f3eec236471e7335 100644 (file)
@@ -76,4 +76,6 @@ extern long __put_user_asm_l(void *, long);
 extern long __put_user_asm_q(void *, long);
 extern void __put_user_unknown(void);
 
+extern long __strnlen_user(const char *__s, long __n);
+
 #endif /* __ASM_SH_UACCESS_64_H */
index 04c7da968146636084c58bef6639907093d60368..e640c63d58113046e422e30f9a1b6e6475087700 100644 (file)
@@ -2,7 +2,7 @@
  * arch/sh/kernel/cpu/sh5/entry.S
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2004 - 2007  Paul Mundt
+ * Copyright (C) 2004 - 2008  Paul Mundt
  * Copyright (C) 2003, 2004  Richard Curnow
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -923,6 +923,8 @@ ret_from_exception:
        blink   tr0, ZERO
 
 resume_kernel:
+       CLI()
+
        pta     restore_all, tr0
 
        getcon  KCR0, r6
@@ -939,19 +941,11 @@ need_resched:
        andi    r7, 0xf0, r7
        bne     r7, ZERO, tr0
 
-       movi    ((PREEMPT_ACTIVE >> 16) & 65535), r8
-       shori   (PREEMPT_ACTIVE & 65535), r8
-       st.l    r6, TI_PRE_COUNT, r8
-
-       STI()
-       movi    schedule, r7
+       movi    preempt_schedule_irq, r7
        ori     r7, 1, r7
        ptabs   r7, tr1
        blink   tr1, LINK
 
-       st.l    r6, TI_PRE_COUNT, ZERO
-       CLI()
-
        pta     need_resched, tr1
        blink   tr1, ZERO
 #endif
index 0bc17def55a70ae6bc0d7398d92ffd826f005a14..efbb4268875e3a2b1fc43de0789b08b834cf2b3e 100644 (file)
@@ -92,6 +92,7 @@ ENTRY(ret_from_irq)
        bra     resume_userspace
         nop
 ENTRY(resume_kernel)
+       cli
        mov.l   @(TI_PRE_COUNT,r8), r0  ! current_thread_info->preempt_count
        tst     r0, r0
        bf      noresched
@@ -105,28 +106,9 @@ need_resched:
        and     #0xf0, r0               ! interrupts off (exception path)?
        cmp/eq  #0xf0, r0
        bt      noresched
-
-       mov.l   1f, r0
-       mov.l   r0, @(TI_PRE_COUNT,r8)
-
-#ifdef CONFIG_TRACE_IRQFLAGS
        mov.l   3f, r0
-       jsr     @r0
-        nop
-#endif
-       sti
-       mov.l   2f, r0
-       jsr     @r0
-        nop
-       mov     #0, r0
-       mov.l   r0, @(TI_PRE_COUNT,r8)
-       cli
-#ifdef CONFIG_TRACE_IRQFLAGS
-       mov.l   4f, r0
-       jsr     @r0
+       jsr     @r0                     ! call preempt_schedule_irq
         nop
-#endif
-
        bra     need_resched
         nop
 
@@ -137,10 +119,7 @@ noresched:
        .align 2
 1:     .long   PREEMPT_ACTIVE
 2:     .long   schedule
-#ifdef CONFIG_TRACE_IRQFLAGS
-3:     .long   trace_hardirqs_on
-4:     .long   trace_hardirqs_off
-#endif
+3:     .long   preempt_schedule_irq
 #endif
 
 ENTRY(resume_userspace)
index 4703dff174d59bb7084c832f92a1c364d6ff77df..94df56b0d1f65612d76196ec8ef1bfbb1fb4eeae 100644 (file)
@@ -102,7 +102,7 @@ void machine_kexec(struct kimage *image)
 
        /* now call it */
        rnk = (relocate_new_kernel_t) reboot_code_buffer;
-       (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
+       (*rnk)(page_list, reboot_code_buffer, P2SEGADDR(image->start), vbr_reg);
 }
 
 void arch_crash_save_vmcoreinfo(void)
index 5922edd416dbc2b049063d58248fc75132a25fb8..9c6424892bd37fcca32ae16e02e8691198c6c788 100644 (file)
@@ -131,6 +131,8 @@ void user_enable_single_step(struct task_struct *child)
 
 void user_disable_single_step(struct task_struct *child)
 {
+       struct pt_regs *regs = child->thread.uregs;
+
        regs->sr &= ~SR_SSTEP;
 }
 
index a35207655e7b64fba60f4dee70a2fc682b716932..de832056bf1b28ae1196633d0bf23633144f8f26 100644 (file)
@@ -171,6 +171,7 @@ static void __init reserve_crashkernel(void)
                                (unsigned long)(free_mem >> 20));
                crashk_res.start = crash_base;
                crashk_res.end   = crash_base + crash_size - 1;
+               insert_resource(&iomem_resource, &crashk_res);
        }
 }
 #else
@@ -204,11 +205,6 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
        request_resource(res, &data_resource);
        request_resource(res, &bss_resource);
 
-#ifdef CONFIG_KEXEC
-       if (crashk_res.start != crashk_res.end)
-               request_resource(res, &crashk_res);
-#endif
-
        add_active_range(nid, start_pfn, end_pfn);
 }
 
index 59cd2859ce9b247e70c27728dd029eaba0fb370f..9061b86d73fadefef5b20d7834a6c25299fcc289 100644 (file)
@@ -170,7 +170,7 @@ asmlinkage int sys_ipc(uint call, int first, int second,
        version = call >> 16; /* hack for backward compatibility */
        call &= 0xffff;
 
-       if (call <= SEMCTL)
+       if (call <= SEMTIMEDOP)
                switch (call) {
                case SEMOP:
                        return sys_semtimedop(first,
index 895bb3f335c77f39481191e54739e8871674f7a1..64b8f7f96f9aed038e87be11ee374d5b0797f239 100644 (file)
@@ -101,7 +101,7 @@ static int __init memchunk_setup(char *str)
 }
 __setup("memchunk.", memchunk_setup);
 
-static void memchunk_cmdline_override(char *name, unsigned long *sizep)
+static void __init memchunk_cmdline_override(char *name, unsigned long *sizep)
 {
        char *p = boot_command_line;
        int k = strlen(name);
@@ -118,8 +118,8 @@ static void memchunk_cmdline_override(char *name, unsigned long *sizep)
        }
 }
 
-int platform_resource_setup_memory(struct platform_device *pdev,
-                                  char *name, unsigned long memsize)
+int __init platform_resource_setup_memory(struct platform_device *pdev,
+                                         char *name, unsigned long memsize)
 {
        struct resource *r;
        dma_addr_t dma_handle;
index 7201752cf93418fba65af3dbcdaef246f8a627a7..a8180e546a48f87a6d5b9a7123d9ed91a3b51a56 100644 (file)
@@ -50,27 +50,24 @@ struct seq_file;
 void smp_bogo(struct seq_file *);
 void smp_info(struct seq_file *);
 
-BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
+BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, cpumask_t, unsigned long, unsigned long, unsigned long, unsigned long)
 BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
 BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
 BTFIXUPDEF_BLACKBOX(load_current)
 
-#define smp_cross_call(func,arg1,arg2,arg3,arg4,arg5) BTFIXUP_CALL(smp_cross_call)(func,arg1,arg2,arg3,arg4,arg5)
+#define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4)
 
-static inline void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); }
+static inline void xc0(smpfunc_t func) { smp_cross_call(func, cpu_online_map, 0, 0, 0, 0); }
 static inline void xc1(smpfunc_t func, unsigned long arg1)
-{ smp_cross_call(func, arg1, 0, 0, 0, 0); }
+{ smp_cross_call(func, cpu_online_map, arg1, 0, 0, 0); }
 static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2)
-{ smp_cross_call(func, arg1, arg2, 0, 0, 0); }
+{ smp_cross_call(func, cpu_online_map, arg1, arg2, 0, 0); }
 static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2,
                           unsigned long arg3)
-{ smp_cross_call(func, arg1, arg2, arg3, 0, 0); }
+{ smp_cross_call(func, cpu_online_map, arg1, arg2, arg3, 0); }
 static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2,
                           unsigned long arg3, unsigned long arg4)
-{ smp_cross_call(func, arg1, arg2, arg3, arg4, 0); }
-static inline void xc5(smpfunc_t func, unsigned long arg1, unsigned long arg2,
-                          unsigned long arg3, unsigned long arg4, unsigned long arg5)
-{ smp_cross_call(func, arg1, arg2, arg3, arg4, arg5); }
+{ smp_cross_call(func, cpu_online_map, arg1, arg2, arg3, arg4); }
 
 static inline int smp_call_function(void (*func)(void *info), void *info, int wait)
 {
@@ -78,6 +75,14 @@ static inline int smp_call_function(void (*func)(void *info), void *info, int wa
        return 0;
 }
 
+static inline int smp_call_function_single(int cpuid, void (*func) (void *info),
+                                          void *info, int wait)
+{
+       smp_cross_call((smpfunc_t)func, cpumask_of_cpu(cpuid),
+                      (unsigned long) info, 0, 0, 0);
+       return 0;
+}
+
 static inline int cpu_logical_map(int cpu)
 {
        return cpu;
index cc4c235c4f592e5e193429bfb346656287c8092f..c481d45f97b748a3748c8fcc813be7d7965555e6 100644 (file)
@@ -70,7 +70,7 @@ struct of_bus {
                                       int *addrc, int *sizec);
        int             (*map)(u32 *addr, const u32 *range,
                               int na, int ns, int pna);
-       unsigned int    (*get_flags)(const u32 *addr);
+       unsigned long   (*get_flags)(const u32 *addr, unsigned long);
 };
 
 /*
@@ -130,8 +130,10 @@ static int of_bus_default_map(u32 *addr, const u32 *range,
        return 0;
 }
 
-static unsigned int of_bus_default_get_flags(const u32 *addr)
+static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
 {
+       if (flags)
+               return flags;
        return IORESOURCE_MEM;
 }
 
@@ -194,17 +196,21 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
        return 0;
 }
 
-static unsigned int of_bus_pci_get_flags(const u32 *addr)
+static unsigned long of_bus_pci_get_flags(const u32 *addr, unsigned long flags)
 {
-       unsigned int flags = 0;
        u32 w = addr[0];
 
+       /* For PCI, we override whatever child busses may have used.  */
+       flags = 0;
        switch((w >> 24) & 0x03) {
        case 0x01:
                flags |= IORESOURCE_IO;
+               break;
+
        case 0x02: /* 32 bits */
        case 0x03: /* 64 bits */
                flags |= IORESOURCE_MEM;
+               break;
        }
        if (w & 0x40000000)
                flags |= IORESOURCE_PREFETCH;
@@ -362,10 +368,11 @@ static void __init build_device_resources(struct of_device *op,
                int pna, pns;
 
                size = of_read_addr(reg + na, ns);
-               flags = bus->get_flags(reg);
 
                memcpy(addr, reg, na * 4);
 
+               flags = bus->get_flags(reg, 0);
+
                /* If the immediate parent has no ranges property to apply,
                 * just use a 1<->1 mapping.
                 */
@@ -393,6 +400,8 @@ static void __init build_device_resources(struct of_device *op,
                                               dna, dns, pna))
                                break;
 
+                       flags = pbus->get_flags(addr, flags);
+
                        dna = pna;
                        dns = pns;
                        dbus = pbus;
index dfde77ff084870810b3a8e94e40f089b796418be..69596402a500092c562b3ec97e7269efcc8981ec 100644 (file)
@@ -262,8 +262,9 @@ static struct smp_funcall {
 static DEFINE_SPINLOCK(cross_call_lock);
 
 /* Cross calls must be serialized, at least currently. */
-void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
-                   unsigned long arg3, unsigned long arg4, unsigned long arg5)
+static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
+                            unsigned long arg2, unsigned long arg3,
+                            unsigned long arg4)
 {
        if(smp_processors_ready) {
                register int high = smp_highest_cpu;
@@ -278,7 +279,7 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
                        register unsigned long a2 asm("i2") = arg2;
                        register unsigned long a3 asm("i3") = arg3;
                        register unsigned long a4 asm("i4") = arg4;
-                       register unsigned long a5 asm("i5") = arg5;
+                       register unsigned long a5 asm("i5") = 0;
 
                        __asm__ __volatile__(
                                "std %0, [%6]\n\t"
@@ -290,11 +291,10 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
 
                /* Init receive/complete mapping, plus fire the IPI's off. */
                {
-                       cpumask_t mask;
                        register int i;
 
-                       mask = cpumask_of_cpu(hard_smp4d_processor_id());
-                       cpus_andnot(mask, cpu_online_map, mask);
+                       cpu_clear(smp_processor_id(), mask);
+                       cpus_and(mask, cpu_online_map, mask);
                        for(i = 0; i <= high; i++) {
                                if (cpu_isset(i, mask)) {
                                        ccall_info.processors_in[i] = 0;
@@ -309,12 +309,16 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
 
                        i = 0;
                        do {
+                               if (!cpu_isset(i, mask))
+                                       continue;
                                while(!ccall_info.processors_in[i])
                                        barrier();
                        } while(++i <= high);
 
                        i = 0;
                        do {
+                               if (!cpu_isset(i, mask))
+                                       continue;
                                while(!ccall_info.processors_out[i])
                                        barrier();
                        } while(++i <= high);
index 406ac1abc83a8645f559b435690b5f12594f6e5a..a14a76ac7f36464642ea95f397326c29d3967002 100644 (file)
@@ -244,9 +244,9 @@ static struct smp_funcall {
 static DEFINE_SPINLOCK(cross_call_lock);
 
 /* Cross calls must be serialized, at least currently. */
-static void smp4m_cross_call(smpfunc_t func, unsigned long arg1,
+static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
                             unsigned long arg2, unsigned long arg3,
-                            unsigned long arg4, unsigned long arg5)
+                            unsigned long arg4)
 {
                register int ncpus = SUN4M_NCPUS;
                unsigned long flags;
@@ -259,14 +259,14 @@ static void smp4m_cross_call(smpfunc_t func, unsigned long arg1,
                ccall_info.arg2 = arg2;
                ccall_info.arg3 = arg3;
                ccall_info.arg4 = arg4;
-               ccall_info.arg5 = arg5;
+               ccall_info.arg5 = 0;
 
                /* Init receive/complete mapping, plus fire the IPI's off. */
                {
-                       cpumask_t mask = cpu_online_map;
                        register int i;
 
                        cpu_clear(smp_processor_id(), mask);
+                       cpus_and(mask, cpu_online_map, mask);
                        for(i = 0; i < ncpus; i++) {
                                if (cpu_isset(i, mask)) {
                                        ccall_info.processors_in[i] = 0;
@@ -284,12 +284,16 @@ static void smp4m_cross_call(smpfunc_t func, unsigned long arg1,
 
                        i = 0;
                        do {
+                               if (!cpu_isset(i, mask))
+                                       continue;
                                while(!ccall_info.processors_in[i])
                                        barrier();
                        } while(++i < ncpus);
 
                        i = 0;
                        do {
+                               if (!cpu_isset(i, mask))
+                                       continue;
                                while(!ccall_info.processors_out[i])
                                        barrier();
                        } while(++i < ncpus);
index 9b6689d9d57097239641d51653dc921e2607b997..23963882bc18f203cd27850300cbb80755df025e 100644 (file)
@@ -792,6 +792,8 @@ void fixup_irqs(void)
                }
                spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
        }
+
+       tick_ops->disable_irq();
 }
 #endif
 
index f8b50cbf4bf711658ef3ad742270da424cbf4294..f845f150f565b26a019dea86afa7a6b9d2970ce7 100644 (file)
@@ -96,7 +96,7 @@ struct of_bus {
                                       int *addrc, int *sizec);
        int             (*map)(u32 *addr, const u32 *range,
                               int na, int ns, int pna);
-       unsigned int    (*get_flags)(const u32 *addr);
+       unsigned long   (*get_flags)(const u32 *addr, unsigned long);
 };
 
 /*
@@ -156,8 +156,10 @@ static int of_bus_default_map(u32 *addr, const u32 *range,
        return 0;
 }
 
-static unsigned int of_bus_default_get_flags(const u32 *addr)
+static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
 {
+       if (flags)
+               return flags;
        return IORESOURCE_MEM;
 }
 
@@ -249,17 +251,21 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
        return 0;
 }
 
-static unsigned int of_bus_pci_get_flags(const u32 *addr)
+static unsigned long of_bus_pci_get_flags(const u32 *addr, unsigned long flags)
 {
-       unsigned int flags = 0;
        u32 w = addr[0];
 
+       /* For PCI, we override whatever child busses may have used.  */
+       flags = 0;
        switch((w >> 24) & 0x03) {
        case 0x01:
                flags |= IORESOURCE_IO;
+               break;
+
        case 0x02: /* 32 bits */
        case 0x03: /* 64 bits */
                flags |= IORESOURCE_MEM;
+               break;
        }
        if (w & 0x40000000)
                flags |= IORESOURCE_PREFETCH;
@@ -478,10 +484,10 @@ static void __init build_device_resources(struct of_device *op,
                int pna, pns;
 
                size = of_read_addr(reg + na, ns);
-               flags = bus->get_flags(reg);
-
                memcpy(addr, reg, na * 4);
 
+               flags = bus->get_flags(addr, 0);
+
                if (use_1to1_mapping(pp)) {
                        result = of_read_addr(addr, na);
                        goto build_res;
@@ -506,6 +512,8 @@ static void __init build_device_resources(struct of_device *op,
                                               dna, dns, pna))
                                break;
 
+                       flags = pbus->get_flags(addr, flags);
+
                        dna = pna;
                        dns = pns;
                        dbus = pbus;
index 743ccad61c60921b36c9bf42a556dac79ac4e23c..2be166c544ca42a27222325cc61001b5190e368c 100644 (file)
@@ -80,8 +80,6 @@ void smp_bogo(struct seq_file *m)
                           i, cpu_data(i).clock_tick);
 }
 
-static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
-
 extern void setup_sparc64_timer(void);
 
 static volatile unsigned long callin_flag = 0;
@@ -120,9 +118,9 @@ void __cpuinit smp_callin(void)
        while (!cpu_isset(cpuid, smp_commenced_mask))
                rmb();
 
-       spin_lock(&call_lock);
+       ipi_call_lock();
        cpu_set(cpuid, cpu_online_map);
-       spin_unlock(&call_lock);
+       ipi_call_unlock();
 
        /* idle thread is expected to have preempt disabled */
        preempt_disable();
@@ -1305,10 +1303,6 @@ int __cpu_disable(void)
        c->core_id = 0;
        c->proc_id = -1;
 
-       spin_lock(&call_lock);
-       cpu_clear(cpu, cpu_online_map);
-       spin_unlock(&call_lock);
-
        smp_wmb();
 
        /* Make sure no interrupts point to this cpu.  */
@@ -1318,6 +1312,10 @@ int __cpu_disable(void)
        mdelay(1);
        local_irq_disable();
 
+       ipi_call_lock();
+       cpu_clear(cpu, cpu_online_map);
+       ipi_call_unlock();
+
        return 0;
 }
 
index b4aeb0f696dc4330e837d7e5b085ba0d2fbf4a7f..a41df7bef0356eef702e247f7ef2bb05a8679acb 100644 (file)
@@ -1843,7 +1843,7 @@ static int pavail_rescan_ents __initdata;
  * memory list again, and make sure it provides at least as much
  * memory as 'pavail' does.
  */
-static void setup_valid_addr_bitmap_from_pavail(void)
+static void __init setup_valid_addr_bitmap_from_pavail(void)
 {
        int i;
 
index 2c518fbc52ece13221e587ee71f11c81a4d5cec7..b225219c448ca4cc44c7de2402b8c894e8b5da3e 100644 (file)
@@ -382,14 +382,17 @@ config X86_OOSTORE
 # P6_NOPs are a relatively minor optimization that require a family >=
 # 6 processor, except that it is broken on certain VIA chips.
 # Furthermore, AMD chips prefer a totally different sequence of NOPs
-# (which work on all CPUs).  As a result, disallow these if we're
-# compiling X86_GENERIC but not X86_64 (these NOPs do work on all
-# x86-64 capable chips); the list of processors in the right-hand clause
-# are the cores that benefit from this optimization.
+# (which work on all CPUs).  In addition, it looks like Virtual PC
+# does not understand them.
+#
+# As a result, disallow these if we're not compiling for X86_64 (these
+# NOPs do work on all x86-64 capable chips); the list of processors in
+# the right-hand clause are the cores that benefit from this optimization.
 #
 config X86_P6_NOP
        def_bool y
-       depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4 || MPSC)
+       depends on X86_64
+       depends on (MCORE2 || MPENTIUM4 || MPSC)
 
 config X86_TSC
        def_bool y
index 4b9ae7c567480658ff1e83333a2f8137c887579b..4d3ff037201ffbee0bb468e04d069b02909d094d 100644 (file)
@@ -38,12 +38,12 @@ static const u32 req_flags[NCAPINTS] =
 {
        REQUIRED_MASK0,
        REQUIRED_MASK1,
-       REQUIRED_MASK2,
-       REQUIRED_MASK3,
+       0, /* REQUIRED_MASK2 not implemented in this file */
+       0, /* REQUIRED_MASK3 not implemented in this file */
        REQUIRED_MASK4,
-       REQUIRED_MASK5,
+       0, /* REQUIRED_MASK5 not implemented in this file */
        REQUIRED_MASK6,
-       REQUIRED_MASK7,
+       0, /* REQUIRED_MASK7 not implemented in this file */
 };
 
 #define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
index 2763cb37b553e5780c9dc080311022e3b4339092..65a0c1b4869636122fc22dec84de26788662a2d4 100644 (file)
@@ -145,35 +145,25 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = {
 extern char __vsyscall_0;
 const unsigned char *const *find_nop_table(void)
 {
-       return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-              boot_cpu_data.x86 < 6 ? k8_nops : p6_nops;
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+           boot_cpu_has(X86_FEATURE_NOPL))
+               return p6_nops;
+       else
+               return k8_nops;
 }
 
 #else /* CONFIG_X86_64 */
 
-static const struct nop {
-       int cpuid;
-       const unsigned char *const *noptable;
-} noptypes[] = {
-       { X86_FEATURE_K8, k8_nops },
-       { X86_FEATURE_K7, k7_nops },
-       { X86_FEATURE_P4, p6_nops },
-       { X86_FEATURE_P3, p6_nops },
-       { -1, NULL }
-};
-
 const unsigned char *const *find_nop_table(void)
 {
-       const unsigned char *const *noptable = intel_nops;
-       int i;
-
-       for (i = 0; noptypes[i].cpuid >= 0; i++) {
-               if (boot_cpu_has(noptypes[i].cpuid)) {
-                       noptable = noptypes[i].noptable;
-                       break;
-               }
-       }
-       return noptable;
+       if (boot_cpu_has(X86_FEATURE_K8))
+               return k8_nops;
+       else if (boot_cpu_has(X86_FEATURE_K7))
+               return k7_nops;
+       else if (boot_cpu_has(X86_FEATURE_NOPL))
+               return p6_nops;
+       else
+               return intel_nops;
 }
 
 #endif /* CONFIG_X86_64 */
index cae9cabc3031f1e3a2a3d6f8085d20b557026ac3..18514ed261047b057104b6bc4384d0ab18908cfd 100644 (file)
@@ -31,6 +31,11 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
                if (c->x86_power & (1<<8))
                        set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
        }
+
+       /*  Set MTRR capability flag if appropriate */
+       if (c->x86_model == 13 || c->x86_model == 9 ||
+          (c->x86_model == 8 && c->x86_mask >= 8))
+               set_cpu_cap(c, X86_FEATURE_K6_MTRR);
 }
 
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -166,10 +171,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                                                mbytes);
                                }
 
-                               /*  Set MTRR capability flag if appropriate */
-                               if (c->x86_model == 13 || c->x86_model == 9 ||
-                                  (c->x86_model == 8 && c->x86_mask >= 8))
-                                       set_cpu_cap(c, X86_FEATURE_K6_MTRR);
                                break;
                        }
 
index e0f45edd6a5591498aca154243bd234e11973609..a0534c04d38a5d385072b869903eea4339553293 100644 (file)
@@ -314,6 +314,16 @@ enum {
                EAMD3D          = 1<<20,
 };
 
+static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
+{
+       switch (c->x86) {
+       case 5:
+               /* Emulate MTRRs using Centaur's MCR. */
+               set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
+               break;
+       }
+}
+
 static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
 {
 
@@ -462,6 +472,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
 static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
        .c_vendor       = "Centaur",
        .c_ident        = { "CentaurHauls" },
+       .c_early_init   = early_init_centaur,
        .c_init         = init_centaur,
        .c_size_cache   = centaur_size_cache,
 };
index 80ab20d4fa39913ce2a7b4ea5676883bb6f9d96f..8aab8517642e7ba34c3c91da7403c4892b01b53d 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/mtrr.h>
 #include <asm/mce.h>
 #include <asm/pat.h>
+#include <asm/asm.h>
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/mpspec.h>
 #include <asm/apic.h>
@@ -334,11 +335,40 @@ static void __init early_cpu_detect(void)
 
        get_cpu_vendor(c, 1);
 
+       early_get_cap(c);
+
        if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
            cpu_devs[c->x86_vendor]->c_early_init)
                cpu_devs[c->x86_vendor]->c_early_init(c);
+}
 
-       early_get_cap(c);
+/*
+ * The NOPL instruction is supposed to exist on all CPUs with
+ * family >= 6, unfortunately, that's not true in practice because
+ * of early VIA chips and (more importantly) broken virtualizers that
+ * are not easy to detect.  Hence, probe for it based on first
+ * principles.
+ */
+static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
+{
+       const u32 nopl_signature = 0x888c53b1; /* Random number */
+       u32 has_nopl = nopl_signature;
+
+       clear_cpu_cap(c, X86_FEATURE_NOPL);
+       if (c->x86 >= 6) {
+               asm volatile("\n"
+                            "1:      .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
+                            "2:\n"
+                            "        .section .fixup,\"ax\"\n"
+                            "3:      xor %0,%0\n"
+                            "        jmp 2b\n"
+                            "        .previous\n"
+                            _ASM_EXTABLE(1b,3b)
+                            : "+a" (has_nopl));
+
+               if (has_nopl == nopl_signature)
+                       set_cpu_cap(c, X86_FEATURE_NOPL);
+       }
 }
 
 static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
@@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
                }
 
                init_scattered_cpuid_features(c);
+               detect_nopl(c);
        }
-
 }
 
 static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
index dd6e3f15017eb87b04885fd5164681bbdd9a3073..a11f5d4477cd797432d8a54df202dd558bdec5d5 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mtrr.h>
 #include <asm/mce.h>
 #include <asm/pat.h>
+#include <asm/asm.h>
 #include <asm/numa.h>
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/mpspec.h>
@@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void)
        }
 }
 
+/*
+ * The NOPL instruction is supposed to exist on all CPUs with
+ * family >= 6, unfortunately, that's not true in practice because
+ * of early VIA chips and (more importantly) broken virtualizers that
+ * are not easy to detect.  Hence, probe for it based on first
+ * principles.
+ *
+ * Note: no 64-bit chip is known to lack these, but put the code here
+ * for consistency with 32 bits, and to make it utterly trivial to
+ * diagnose the problem should it ever surface.
+ */
+static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
+{
+       const u32 nopl_signature = 0x888c53b1; /* Random number */
+       u32 has_nopl = nopl_signature;
+
+       clear_cpu_cap(c, X86_FEATURE_NOPL);
+       if (c->x86 >= 6) {
+               asm volatile("\n"
+                            "1:      .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
+                            "2:\n"
+                            "        .section .fixup,\"ax\"\n"
+                            "3:      xor %0,%0\n"
+                            "        jmp 2b\n"
+                            "        .previous\n"
+                            _ASM_EXTABLE(1b,3b)
+                            : "+a" (has_nopl));
+
+               if (has_nopl == nopl_signature)
+                       set_cpu_cap(c, X86_FEATURE_NOPL);
+       }
+}
+
 static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
 
 void __init early_cpu_init(void)
@@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
                c->x86_phys_bits = eax & 0xff;
        }
 
+       detect_nopl(c);
+
        if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
            cpu_devs[c->x86_vendor]->c_early_init)
                cpu_devs[c->x86_vendor]->c_early_init(c);
@@ -493,17 +529,20 @@ void pda_init(int cpu)
                /* others are initialized in smpboot.c */
                pda->pcurrent = &init_task;
                pda->irqstackptr = boot_cpu_stack;
+               pda->irqstackptr += IRQSTACKSIZE - 64;
        } else {
-               pda->irqstackptr = (char *)
-                       __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
-               if (!pda->irqstackptr)
-                       panic("cannot allocate irqstack for cpu %d", cpu);
+               if (!pda->irqstackptr) {
+                       pda->irqstackptr = (char *)
+                               __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
+                       if (!pda->irqstackptr)
+                               panic("cannot allocate irqstack for cpu %d",
+                                     cpu);
+                       pda->irqstackptr += IRQSTACKSIZE - 64;
+               }
 
                if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
                        pda->nodenumber = cpu_to_node(cpu);
        }
-
-       pda->irqstackptr += IRQSTACKSIZE-64;
 }
 
 char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
@@ -601,19 +640,22 @@ void __cpuinit cpu_init(void)
        /*
         * set up and load the per-CPU TSS
         */
-       for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+       if (!orig_ist->ist[0]) {
                static const unsigned int order[N_EXCEPTION_STACKS] = {
-                       [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
-                       [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+                 [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+                 [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
                };
-               if (cpu) {
-                       estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
-                       if (!estacks)
-                               panic("Cannot allocate exception stack %ld %d\n",
-                                     v, cpu);
+               for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+                       if (cpu) {
+                               estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
+                               if (!estacks)
+                                       panic("Cannot allocate exception "
+                                             "stack %ld %d\n", v, cpu);
+                       }
+                       estacks += PAGE_SIZE << order[v];
+                       orig_ist->ist[v] = t->x86_tss.ist[v] =
+                                       (unsigned long)estacks;
                }
-               estacks += PAGE_SIZE << order[v];
-               orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks;
        }
 
        t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
index e710a21bb6e8dc0dd9d83a7bd49df69135cbcf7b..898a5a2002ed64e391d45a24d5e6a7103d6397a9 100644 (file)
 /*
  * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
  */
-static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
 {
        unsigned char ccr2, ccr3;
-       unsigned long flags;
 
        /* we test for DEVID by checking whether CCR3 is writable */
-       local_irq_save(flags);
        ccr3 = getCx86(CX86_CCR3);
        setCx86(CX86_CCR3, ccr3 ^ 0x80);
        getCx86(0xc0);   /* dummy to change bus */
@@ -44,9 +42,16 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
                *dir0 = getCx86(CX86_DIR0);
                *dir1 = getCx86(CX86_DIR1);
        }
-       local_irq_restore(flags);
 }
 
+static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __do_cyrix_devid(dir0, dir1);
+       local_irq_restore(flags);
+}
 /*
  * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
  * order to identify the Cyrix CPU model after we're out of setup.c
@@ -161,6 +166,24 @@ static void __cpuinit geode_configure(void)
        local_irq_restore(flags);
 }
 
+static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c)
+{
+       unsigned char dir0, dir0_msn, dir1 = 0;
+
+       __do_cyrix_devid(&dir0, &dir1);
+       dir0_msn = dir0 >> 4; /* identifies CPU "family"   */
+
+       switch (dir0_msn) {
+       case 3: /* 6x86/6x86L */
+               /* Emulate MTRRs using Cyrix's ARRs. */
+               set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
+               break;
+       case 5: /* 6x86MX/M II */
+               /* Emulate MTRRs using Cyrix's ARRs. */
+               set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
+               break;
+       }
+}
 
 static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
 {
@@ -416,6 +439,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c)
 static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
        .c_vendor       = "Cyrix",
        .c_ident        = { "CyrixInstead" },
+       .c_early_init   = early_init_cyrix,
        .c_init         = init_cyrix,
        .c_identify     = cyrix_identify,
 };
index e43ad4ad4cbae8b75561f67ec1da51628c568491..c9017799497c5f99db3df1ce96d010b6ea5e3230 100644 (file)
@@ -39,7 +39,8 @@ const char * const x86_cap_flags[NCAPINTS*32] = {
        NULL, NULL, NULL, NULL,
        "constant_tsc", "up", NULL, "arch_perfmon",
        "pebs", "bts", NULL, NULL,
-       "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       "rep_good", NULL, NULL, NULL,
+       "nopl", NULL, NULL, NULL,
        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
        /* Intel-defined (#2) */
index 9af89078f7bb0cb2b6ce7ed958c9483b24d4402e..66e48aa2dd1b4dae8739f69841337386cc670889 100644 (file)
@@ -1203,7 +1203,7 @@ static int __init parse_memmap_opt(char *p)
        if (!p)
                return -EINVAL;
 
-       if (!strcmp(p, "exactmap")) {
+       if (!strncmp(p, "exactmap", 8)) {
 #ifdef CONFIG_CRASH_DUMP
                /*
                 * If we are doing a crash dump, we still need to know
index 59fd3b6b13036e1e279e54d0e1e3d3f5ebb55166..73deaffadd036a578984bb8ad6e0455f1044558a 100644 (file)
@@ -210,8 +210,8 @@ static void hpet_legacy_clockevent_register(void)
        /* Calculate the min / max delta */
        hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
                                                           &hpet_clockevent);
-       hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30,
-                                                          &hpet_clockevent);
+       /* 5 usec minimum reprogramming delta. */
+       hpet_clockevent.min_delta_ns = 5000;
 
        /*
         * Start hpet with the boot cpu mask and make it
@@ -270,15 +270,22 @@ static void hpet_legacy_set_mode(enum clock_event_mode mode,
 }
 
 static int hpet_legacy_next_event(unsigned long delta,
-                          struct clock_event_device *evt)
+                                 struct clock_event_device *evt)
 {
-       unsigned long cnt;
+       u32 cnt;
 
        cnt = hpet_readl(HPET_COUNTER);
-       cnt += delta;
+       cnt += (u32) delta;
        hpet_writel(cnt, HPET_T0_CMP);
 
-       return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0;
+       /*
+        * We need to read back the CMP register to make sure that
+        * what we wrote hit the chip before we compare it to the
+        * counter.
+        */
+       WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt);
+
+       return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
 }
 
 /*
index 1c3a66a67f83d3bb6d7eec2d5e4cfb1560660720..720d2607aacbc2bee985b00289b8bc5c70cb4fb5 100644 (file)
@@ -92,6 +92,14 @@ static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "30BF")
                }
        },
+       {
+               .callback       = dmi_io_delay_0xed_port,
+               .ident          = "Presario F700",
+               .matches        = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+                       DMI_MATCH(DMI_BOARD_NAME, "30D3")
+               }
+       },
        { }
 };
 
index 8e786b0d665a42e1f24dc7a068ec21fa0a654eeb..8f98e9de1b82f5f6a13015bd34fe428187e79c38 100644 (file)
@@ -122,80 +122,216 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet)
        return ULLONG_MAX;
 }
 
-/**
- * native_calibrate_tsc - calibrate the tsc on boot
+/*
+ * Try to calibrate the TSC against the Programmable
+ * Interrupt Timer and return the frequency of the TSC
+ * in kHz.
+ *
+ * Return ULONG_MAX on failure to calibrate.
  */
-unsigned long native_calibrate_tsc(void)
+static unsigned long pit_calibrate_tsc(void)
 {
-       unsigned long flags;
-       u64 tsc1, tsc2, tr1, tr2, delta, pm1, pm2, hpet1, hpet2;
-       int hpet = is_hpet_enabled();
-       unsigned int tsc_khz_val = 0;
-
-       local_irq_save(flags);
-
-       tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL);
+       u64 tsc, t1, t2, delta;
+       unsigned long tscmin, tscmax;
+       int pitcnt;
 
+       /* Set the Gate high, disable speaker */
        outb((inb(0x61) & ~0x02) | 0x01, 0x61);
 
+       /*
+        * Setup CTC channel 2* for mode 0, (interrupt on terminal
+        * count mode), binary count. Set the latch register to 50ms
+        * (LSB then MSB) to begin countdown.
+        */
        outb(0xb0, 0x43);
        outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
        outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42);
-       tr1 = get_cycles();
-       while ((inb(0x61) & 0x20) == 0);
-       tr2 = get_cycles();
 
-       tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL);
+       tsc = t1 = t2 = get_cycles();
 
-       local_irq_restore(flags);
+       pitcnt = 0;
+       tscmax = 0;
+       tscmin = ULONG_MAX;
+       while ((inb(0x61) & 0x20) == 0) {
+               t2 = get_cycles();
+               delta = t2 - tsc;
+               tsc = t2;
+               if ((unsigned long) delta < tscmin)
+                       tscmin = (unsigned int) delta;
+               if ((unsigned long) delta > tscmax)
+                       tscmax = (unsigned int) delta;
+               pitcnt++;
+       }
 
        /*
-        * Preset the result with the raw and inaccurate PIT
-        * calibration value
+        * Sanity checks:
+        *
+        * If we were not able to read the PIT more than 5000
+        * times, then we have been hit by a massive SMI
+        *
+        * If the maximum is 10 times larger than the minimum,
+        * then we got hit by an SMI as well.
         */
-       delta = (tr2 - tr1);
+       if (pitcnt < 5000 || tscmax > 10 * tscmin)
+               return ULONG_MAX;
+
+       /* Calculate the PIT value */
+       delta = t2 - t1;
        do_div(delta, 50);
-       tsc_khz_val = delta;
+       return delta;
+}
+
+
+/**
+ * native_calibrate_tsc - calibrate the tsc on boot
+ */
+unsigned long native_calibrate_tsc(void)
+{
+       u64 tsc1, tsc2, delta, pm1, pm2, hpet1, hpet2;
+       unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
+       unsigned long flags;
+       int hpet = is_hpet_enabled(), i;
 
-       /* hpet or pmtimer available ? */
+       /*
+        * Run 5 calibration loops to get the lowest frequency value
+        * (the best estimate). We use two different calibration modes
+        * here:
+        *
+        * 1) PIT loop. We set the PIT Channel 2 to oneshot mode and
+        * load a timeout of 50ms. We read the time right after we
+        * started the timer and wait until the PIT count down reaches
+        * zero. In each wait loop iteration we read the TSC and check
+        * the delta to the previous read. We keep track of the min
+        * and max values of that delta. The delta is mostly defined
+        * by the IO time of the PIT access, so we can detect when a
+        * SMI/SMM disturbance happend between the two reads. If the
+        * maximum time is significantly larger than the minimum time,
+        * then we discard the result and have another try.
+        *
+        * 2) Reference counter. If available we use the HPET or the
+        * PMTIMER as a reference to check the sanity of that value.
+        * We use separate TSC readouts and check inside of the
+        * reference read for a SMI/SMM disturbance. We dicard
+        * disturbed values here as well. We do that around the PIT
+        * calibration delay loop as we have to wait for a certain
+        * amount of time anyway.
+        */
+       for (i = 0; i < 5; i++) {
+               unsigned long tsc_pit_khz;
+
+               /*
+                * Read the start value and the reference count of
+                * hpet/pmtimer when available. Then do the PIT
+                * calibration, which will take at least 50ms, and
+                * read the end value.
+                */
+               local_irq_save(flags);
+               tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL);
+               tsc_pit_khz = pit_calibrate_tsc();
+               tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL);
+               local_irq_restore(flags);
+
+               /* Pick the lowest PIT TSC calibration so far */
+               tsc_pit_min = min(tsc_pit_min, tsc_pit_khz);
+
+               /* hpet or pmtimer available ? */
+               if (!hpet && !pm1 && !pm2)
+                       continue;
+
+               /* Check, whether the sampling was disturbed by an SMI */
+               if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX)
+                       continue;
+
+               tsc2 = (tsc2 - tsc1) * 1000000LL;
+
+               if (hpet) {
+                       if (hpet2 < hpet1)
+                               hpet2 += 0x100000000ULL;
+                       hpet2 -= hpet1;
+                       tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
+                       do_div(tsc1, 1000000);
+               } else {
+                       if (pm2 < pm1)
+                               pm2 += (u64)ACPI_PM_OVRRUN;
+                       pm2 -= pm1;
+                       tsc1 = pm2 * 1000000000LL;
+                       do_div(tsc1, PMTMR_TICKS_PER_SEC);
+               }
+
+               do_div(tsc2, tsc1);
+               tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2);
+       }
+
+       /*
+        * Now check the results.
+        */
+       if (tsc_pit_min == ULONG_MAX) {
+               /* PIT gave no useful value */
+               printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n");
+
+               /* We don't have an alternative source, disable TSC */
+               if (!hpet && !pm1 && !pm2) {
+                       printk("TSC: No reference (HPET/PMTIMER) available\n");
+                       return 0;
+               }
+
+               /* The alternative source failed as well, disable TSC */
+               if (tsc_ref_min == ULONG_MAX) {
+                       printk(KERN_WARNING "TSC: HPET/PMTIMER calibration "
+                              "failed due to SMI disturbance.\n");
+                       return 0;
+               }
+
+               /* Use the alternative source */
+               printk(KERN_INFO "TSC: using %s reference calibration\n",
+                      hpet ? "HPET" : "PMTIMER");
+
+               return tsc_ref_min;
+       }
+
+       /* We don't have an alternative source, use the PIT calibration value */
        if (!hpet && !pm1 && !pm2) {
-               printk(KERN_INFO "TSC calibrated against PIT\n");
-               goto out;
+               printk(KERN_INFO "TSC: Using PIT calibration value\n");
+               return tsc_pit_min;
        }
 
-       /* Check, whether the sampling was disturbed by an SMI */
-       if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX) {
-               printk(KERN_WARNING "TSC calibration disturbed by SMI, "
-                               "using PIT calibration result\n");
-               goto out;
+       /* The alternative source failed, use the PIT calibration value */
+       if (tsc_ref_min == ULONG_MAX) {
+               printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed due "
+                      "to SMI disturbance. Using PIT calibration\n");
+               return tsc_pit_min;
        }
 
-       tsc2 = (tsc2 - tsc1) * 1000000LL;
-
-       if (hpet) {
-               printk(KERN_INFO "TSC calibrated against HPET\n");
-               if (hpet2 < hpet1)
-                       hpet2 += 0x100000000ULL;
-               hpet2 -= hpet1;
-               tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
-               do_div(tsc1, 1000000);
-       } else {
-               printk(KERN_INFO "TSC calibrated against PM_TIMER\n");
-               if (pm2 < pm1)
-                       pm2 += (u64)ACPI_PM_OVRRUN;
-               pm2 -= pm1;
-               tsc1 = pm2 * 1000000000LL;
-               do_div(tsc1, PMTMR_TICKS_PER_SEC);
+       /* Check the reference deviation */
+       delta = ((u64) tsc_pit_min) * 100;
+       do_div(delta, tsc_ref_min);
+
+       /*
+        * If both calibration results are inside a 5% window, the we
+        * use the lower frequency of those as it is probably the
+        * closest estimate.
+        */
+       if (delta >= 95 && delta <= 105) {
+               printk(KERN_INFO "TSC: PIT calibration confirmed by %s.\n",
+                      hpet ? "HPET" : "PMTIMER");
+               printk(KERN_INFO "TSC: using %s calibration value\n",
+                      tsc_pit_min <= tsc_ref_min ? "PIT" :
+                      hpet ? "HPET" : "PMTIMER");
+               return tsc_pit_min <= tsc_ref_min ? tsc_pit_min : tsc_ref_min;
        }
 
-       do_div(tsc2, tsc1);
-       tsc_khz_val = tsc2;
+       printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
+              hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
 
-out:
-       return tsc_khz_val;
+       /*
+        * The calibration values differ too much. In doubt, we use
+        * the PIT value as we know that there are PMTIMERs around
+        * running at double speed.
+        */
+       printk(KERN_INFO "TSC: Using PIT calibration value\n");
+       return tsc_pit_min;
 }
 
-
 #ifdef CONFIG_X86_32
 /* Only called from the Powernow K7 cpu freq driver */
 int recalibrate_cpu_khz(void)
index 5807d1bc73f74639c81cf4dec9255ec26e076c73..8791fc55e7154484700cbd2253de3026053b96ae 100644 (file)
@@ -128,8 +128,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
                                pr = pci_find_parent_resource(dev, r);
                                if (!r->start || !pr ||
                                    request_resource(pr, r) < 0) {
-                                       dev_err(&dev->dev, "BAR %d: can't "
-                                               "allocate resource\n", idx);
+                                       dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx);
                                        /*
                                         * Something is wrong with the region.
                                         * Invalidate the resource to prevent
@@ -164,15 +163,13 @@ static void __init pcibios_allocate_resources(int pass)
                        else
                                disabled = !(command & PCI_COMMAND_MEMORY);
                        if (pass == disabled) {
-                               dev_dbg(&dev->dev, "resource %#08llx-%#08llx "
-                                       "(f=%lx, d=%d, p=%d)\n",
+                               dev_dbg(&dev->dev, "resource %#08llx-%#08llx (f=%lx, d=%d, p=%d)\n",
                                        (unsigned long long) r->start,
                                        (unsigned long long) r->end,
                                        r->flags, disabled, pass);
                                pr = pci_find_parent_resource(dev, r);
                                if (!pr || request_resource(pr, r) < 0) {
-                                       dev_err(&dev->dev, "BAR %d: can't "
-                                               "allocate resource\n", idx);
+                                       dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx);
                                        /* We'll assign a new address later */
                                        r->end -= r->start;
                                        r->start = 0;
index 9ff6e3cbf08feaf41c36d9a48c46ae45a105174e..a4e201b47f64ec1fbaf5075da3254c6b72f109b1 100644 (file)
@@ -1324,7 +1324,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
        .ptep_modify_prot_commit = __ptep_modify_prot_commit,
 
        .pte_val = xen_pte_val,
-       .pte_flags = native_pte_val,
+       .pte_flags = native_pte_flags,
        .pgd_val = xen_pgd_val,
 
        .make_pte = xen_make_pte,
index 1d4026206ac2717b6f29826d3fcf014a68c0a127..228b6447e89f295346bcb2d07e295f467bc10f35 100644 (file)
@@ -223,6 +223,7 @@ int blk_register_filter(struct gendisk *disk)
 
        return 0;
 }
+EXPORT_SYMBOL(blk_register_filter);
 
 void blk_unregister_filter(struct gendisk *disk)
 {
@@ -231,4 +232,4 @@ void blk_unregister_filter(struct gendisk *disk)
        kobject_put(&filter->kobj);
        kobject_put(disk->holder_dir->parent);
 }
-
+EXPORT_SYMBOL(blk_unregister_filter);
index 656c2c7abf999628e1232024b71c4af2f22a1ac9..e0ce23ac2ece84b24a283f9ae9203ec3291f2f78 100644 (file)
@@ -190,7 +190,6 @@ void add_disk(struct gendisk *disk)
                            disk->minors, NULL, exact_match, exact_lock, disk);
        register_disk(disk);
        blk_register_queue(disk);
-       blk_register_filter(disk);
 
        bdi = &disk->queue->backing_dev_info;
        bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor));
@@ -203,7 +202,6 @@ EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */
 
 void unlink_gendisk(struct gendisk *disk)
 {
-       blk_unregister_filter(disk);
        sysfs_remove_link(&disk->dev.kobj, "bdi");
        bdi_unregister(&disk->queue->backing_dev_info);
        blk_unregister_queue(disk);
@@ -309,7 +307,7 @@ static void *part_start(struct seq_file *part, loff_t *pos)
        loff_t k = *pos;
 
        if (!k)
-               seq_puts(part, "major minor  #blocks  name\n\n");
+               part->private = (void *)1LU;    /* tell show to print header */
 
        mutex_lock(&block_class_lock);
        dev = class_find_device(&block_class, NULL, &k, find_start);
@@ -351,6 +349,17 @@ static int show_partition(struct seq_file *part, void *v)
        int n;
        char buf[BDEVNAME_SIZE];
 
+       /*
+        * Print header if start told us to do.  This is to preserve
+        * the original behavior of not printing header if no
+        * partition exists.  This hackery will be removed later with
+        * class iteration clean up.
+        */
+       if (part->private) {
+               seq_puts(part, "major minor  #blocks  name\n\n");
+               part->private = NULL;
+       }
+
        /* Don't show non-partitionable removeable devices or empty devices */
        if (!get_capacity(sgp) ||
                        (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE)))
index 85eaf7b1c53153ef07bdc33efa3a9d9c6cdff839..e8362c1efa309f8e0242a255235650d953aeca51 100644 (file)
@@ -137,7 +137,8 @@ async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
                spin_lock_bh(&next->lock);
                next->parent = NULL;
                _next = next->next;
-               next->next = NULL;
+               if (_next && _next->chan == chan)
+                       next->next = NULL;
                spin_unlock_bh(&next->lock);
 
                next->tx_submit(next);
index b1cc4de6493cfa7604187e4f05429d84f6ad2e58..493fee7e0a8b46bbd9933d92681e0a7c16d0ab81 100644 (file)
@@ -35,8 +35,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/bitops.h>
-#include <asm/unaligned.h>
 
 static const u32 camellia_sp1110[256] = {
        0x70707000,0x82828200,0x2c2c2c00,0xececec00,
@@ -337,6 +335,20 @@ static const u32 camellia_sp4404[256] = {
 /*
  *  macros
  */
+#define GETU32(v, pt) \
+    do { \
+       /* latest breed of gcc is clever enough to use move */ \
+       memcpy(&(v), (pt), 4); \
+       (v) = be32_to_cpu(v); \
+    } while(0)
+
+/* rotation right shift 1byte */
+#define ROR8(x) (((x) >> 8) + ((x) << 24))
+/* rotation left shift 1bit */
+#define ROL1(x) (((x) << 1) + ((x) >> 31))
+/* rotation left shift 1byte */
+#define ROL8(x) (((x) << 8) + ((x) >> 24))
+
 #define ROLDQ(ll, lr, rl, rr, w0, w1, bits)            \
     do {                                               \
        w0 = ll;                                        \
@@ -371,7 +383,7 @@ static const u32 camellia_sp4404[256] = {
           ^ camellia_sp3033[(u8)(il >> 8)]                     \
           ^ camellia_sp4404[(u8)(il     )];                    \
        yl ^= yr;                                               \
-       yr = ror32(yr, 8);                                      \
+       yr = ROR8(yr);                                          \
        yr ^= yl;                                               \
     } while(0)
 
@@ -393,7 +405,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        subL[7] ^= subL[1]; subR[7] ^= subR[1];
        subL[1] ^= subR[1] & ~subR[9];
        dw = subL[1] & subL[9],
-               subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl2) */
+               subR[1] ^= ROL1(dw); /* modified for FLinv(kl2) */
        /* round 8 */
        subL[11] ^= subL[1]; subR[11] ^= subR[1];
        /* round 10 */
@@ -402,7 +414,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        subL[15] ^= subL[1]; subR[15] ^= subR[1];
        subL[1] ^= subR[1] & ~subR[17];
        dw = subL[1] & subL[17],
-               subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl4) */
+               subR[1] ^= ROL1(dw); /* modified for FLinv(kl4) */
        /* round 14 */
        subL[19] ^= subL[1]; subR[19] ^= subR[1];
        /* round 16 */
@@ -418,7 +430,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        } else {
                subL[1] ^= subR[1] & ~subR[25];
                dw = subL[1] & subL[25],
-                       subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl6) */
+                       subR[1] ^= ROL1(dw); /* modified for FLinv(kl6) */
                /* round 20 */
                subL[27] ^= subL[1]; subR[27] ^= subR[1];
                /* round 22 */
@@ -438,7 +450,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
                subL[26] ^= kw4l; subR[26] ^= kw4r;
                kw4l ^= kw4r & ~subR[24];
                dw = kw4l & subL[24],
-                       kw4r ^= rol32(dw, 1); /* modified for FL(kl5) */
+                       kw4r ^= ROL1(dw); /* modified for FL(kl5) */
        }
        /* round 17 */
        subL[22] ^= kw4l; subR[22] ^= kw4r;
@@ -448,7 +460,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        subL[18] ^= kw4l; subR[18] ^= kw4r;
        kw4l ^= kw4r & ~subR[16];
        dw = kw4l & subL[16],
-               kw4r ^= rol32(dw, 1); /* modified for FL(kl3) */
+               kw4r ^= ROL1(dw); /* modified for FL(kl3) */
        /* round 11 */
        subL[14] ^= kw4l; subR[14] ^= kw4r;
        /* round 9 */
@@ -457,7 +469,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        subL[10] ^= kw4l; subR[10] ^= kw4r;
        kw4l ^= kw4r & ~subR[8];
        dw = kw4l & subL[8],
-               kw4r ^= rol32(dw, 1); /* modified for FL(kl1) */
+               kw4r ^= ROL1(dw); /* modified for FL(kl1) */
        /* round 5 */
        subL[6] ^= kw4l; subR[6] ^= kw4r;
        /* round 3 */
@@ -482,7 +494,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        SUBKEY_R(6) = subR[5] ^ subR[7];
        tl = subL[10] ^ (subR[10] & ~subR[8]);
        dw = tl & subL[8],  /* FL(kl1) */
-               tr = subR[10] ^ rol32(dw, 1);
+               tr = subR[10] ^ ROL1(dw);
        SUBKEY_L(7) = subL[6] ^ tl; /* round 6 */
        SUBKEY_R(7) = subR[6] ^ tr;
        SUBKEY_L(8) = subL[8];       /* FL(kl1) */
@@ -491,7 +503,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        SUBKEY_R(9) = subR[9];
        tl = subL[7] ^ (subR[7] & ~subR[9]);
        dw = tl & subL[9],  /* FLinv(kl2) */
-               tr = subR[7] ^ rol32(dw, 1);
+               tr = subR[7] ^ ROL1(dw);
        SUBKEY_L(10) = tl ^ subL[11]; /* round 7 */
        SUBKEY_R(10) = tr ^ subR[11];
        SUBKEY_L(11) = subL[10] ^ subL[12]; /* round 8 */
@@ -504,7 +516,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        SUBKEY_R(14) = subR[13] ^ subR[15];
        tl = subL[18] ^ (subR[18] & ~subR[16]);
        dw = tl & subL[16], /* FL(kl3) */
-               tr = subR[18] ^ rol32(dw, 1);
+               tr = subR[18] ^ ROL1(dw);
        SUBKEY_L(15) = subL[14] ^ tl; /* round 12 */
        SUBKEY_R(15) = subR[14] ^ tr;
        SUBKEY_L(16) = subL[16];     /* FL(kl3) */
@@ -513,7 +525,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        SUBKEY_R(17) = subR[17];
        tl = subL[15] ^ (subR[15] & ~subR[17]);
        dw = tl & subL[17], /* FLinv(kl4) */
-               tr = subR[15] ^ rol32(dw, 1);
+               tr = subR[15] ^ ROL1(dw);
        SUBKEY_L(18) = tl ^ subL[19]; /* round 13 */
        SUBKEY_R(18) = tr ^ subR[19];
        SUBKEY_L(19) = subL[18] ^ subL[20]; /* round 14 */
@@ -532,7 +544,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        } else {
                tl = subL[26] ^ (subR[26] & ~subR[24]);
                dw = tl & subL[24], /* FL(kl5) */
-                       tr = subR[26] ^ rol32(dw, 1);
+                       tr = subR[26] ^ ROL1(dw);
                SUBKEY_L(23) = subL[22] ^ tl; /* round 18 */
                SUBKEY_R(23) = subR[22] ^ tr;
                SUBKEY_L(24) = subL[24];     /* FL(kl5) */
@@ -541,7 +553,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
                SUBKEY_R(25) = subR[25];
                tl = subL[23] ^ (subR[23] & ~subR[25]);
                dw = tl & subL[25], /* FLinv(kl6) */
-                       tr = subR[23] ^ rol32(dw, 1);
+                       tr = subR[23] ^ ROL1(dw);
                SUBKEY_L(26) = tl ^ subL[27]; /* round 19 */
                SUBKEY_R(26) = tr ^ subR[27];
                SUBKEY_L(27) = subL[26] ^ subL[28]; /* round 20 */
@@ -561,17 +573,17 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        /* apply the inverse of the last half of P-function */
        i = 2;
        do {
-               dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = rol32(dw, 8);/* round 1 */
+               dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = ROL8(dw);/* round 1 */
                SUBKEY_R(i + 0) = SUBKEY_L(i + 0) ^ dw; SUBKEY_L(i + 0) = dw;
-               dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = rol32(dw, 8);/* round 2 */
+               dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = ROL8(dw);/* round 2 */
                SUBKEY_R(i + 1) = SUBKEY_L(i + 1) ^ dw; SUBKEY_L(i + 1) = dw;
-               dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = rol32(dw, 8);/* round 3 */
+               dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = ROL8(dw);/* round 3 */
                SUBKEY_R(i + 2) = SUBKEY_L(i + 2) ^ dw; SUBKEY_L(i + 2) = dw;
-               dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = rol32(dw, 8);/* round 4 */
+               dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = ROL8(dw);/* round 4 */
                SUBKEY_R(i + 3) = SUBKEY_L(i + 3) ^ dw; SUBKEY_L(i + 3) = dw;
-               dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = rol32(dw, 9);/* round 5 */
+               dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = ROL8(dw);/* round 5 */
                SUBKEY_R(i + 4) = SUBKEY_L(i + 4) ^ dw; SUBKEY_L(i + 4) = dw;
-               dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = rol32(dw, 8);/* round 6 */
+               dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = ROL8(dw);/* round 6 */
                SUBKEY_R(i + 5) = SUBKEY_L(i + 5) ^ dw; SUBKEY_L(i + 5) = dw;
                i += 8;
        } while (i < max);
@@ -587,10 +599,10 @@ static void camellia_setup128(const unsigned char *key, u32 *subkey)
        /**
         *  k == kll || klr || krl || krr (|| is concatenation)
         */
-       kll = get_unaligned_be32(key);
-       klr = get_unaligned_be32(key + 4);
-       krl = get_unaligned_be32(key + 8);
-       krr = get_unaligned_be32(key + 12);
+       GETU32(kll, key     );
+       GETU32(klr, key +  4);
+       GETU32(krl, key +  8);
+       GETU32(krr, key + 12);
 
        /* generate KL dependent subkeys */
        /* kw1 */
@@ -695,14 +707,14 @@ static void camellia_setup256(const unsigned char *key, u32 *subkey)
         *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
         *  (|| is concatenation)
         */
-       kll = get_unaligned_be32(key);
-       klr = get_unaligned_be32(key + 4);
-       krl = get_unaligned_be32(key + 8);
-       krr = get_unaligned_be32(key + 12);
-       krll = get_unaligned_be32(key + 16);
-       krlr = get_unaligned_be32(key + 20);
-       krrl = get_unaligned_be32(key + 24);
-       krrr = get_unaligned_be32(key + 28);
+       GETU32(kll,  key     );
+       GETU32(klr,  key +  4);
+       GETU32(krl,  key +  8);
+       GETU32(krr,  key + 12);
+       GETU32(krll, key + 16);
+       GETU32(krlr, key + 20);
+       GETU32(krrl, key + 24);
+       GETU32(krrr, key + 28);
 
        /* generate KL dependent subkeys */
        /* kw1 */
@@ -858,13 +870,13 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey)
        t0 &= ll;                                                       \
        t2 |= rr;                                                       \
        rl ^= t2;                                                       \
-       lr ^= rol32(t0, 1);                                             \
+       lr ^= ROL1(t0);                                                 \
        t3 = krl;                                                       \
        t1 = klr;                                                       \
        t3 &= rl;                                                       \
        t1 |= lr;                                                       \
        ll ^= t1;                                                       \
-       rr ^= rol32(t3, 1);                                             \
+       rr ^= ROL1(t3);                                                 \
     } while(0)
 
 #define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir)               \
@@ -880,7 +892,7 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey)
        il ^= kl;                                                       \
        ir ^= il ^ kr;                                                  \
        yl ^= ir;                                                       \
-       yr ^= ror32(il, 8) ^ ir;                                                \
+       yr ^= ROR8(il) ^ ir;                                            \
     } while(0)
 
 /* max = 24: 128bit encrypt, max = 32: 256bit encrypt */
index 1022e38994c2bffcdd8a52d676e9ecf951cc49f7..0f280589921025c5e8f9f4e8caebc3ea5efc21b0 100644 (file)
@@ -496,7 +496,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
                        arg = arg->common.next;
                }
 
-               ACPI_ERROR((AE_INFO,
+               ACPI_WARNING((AE_INFO,
                            "Package List length (%X) larger than NumElements count (%X), truncated\n",
                            i, element_count));
        } else if (i < element_count) {
index d3f0a62efcc1afaf61418a0bee4a7d0ac1b8d161..ee68ac54c0d412996aebefc58b6c51c1363da5af 100644 (file)
@@ -138,7 +138,7 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
        {
        set_no_mwait, "Extensa 5220", {
        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-       DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
        DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
        DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
        {},
index 80e32093e977c6a3c5427e0746c1732a2282e017..80c251ec6d2aac7dff658a9c6df5fec5733bc168 100644 (file)
@@ -71,7 +71,7 @@ static DEFINE_MUTEX(performance_mutex);
  *  1 -> ignore _PPC totally -> forced by user through boot param
  */
 static int ignore_ppc = -1;
-module_param(ignore_ppc, uint, 0644);
+module_param(ignore_ppc, int, 0644);
 MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
                 "limited by BIOS, this should help");
 
index bcf2c70fca87f498b9a3c5af5e0037248c488b37..a4e3767b8c64241c6bd1c11010f0c2001fd7e7c1 100644 (file)
@@ -107,6 +107,13 @@ static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
        if (wait_event_timeout(hc->wait, smb_check_done(hc),
                               msecs_to_jiffies(timeout)))
                return 0;
+       /*
+        * After the timeout happens, OS will try to check the status of SMbus.
+        * If the status is what OS expected, it will be regarded as the bogus
+        * timeout.
+        */
+       if (smb_check_done(hc))
+               return 0;
        else
                return -ETIME;
 }
index c3419182c9a72fd033b765f1d48e4ea14c11256c..775c97a282bd0d036bdcee72e192d502e8ba08ea 100644 (file)
@@ -300,6 +300,8 @@ int __init acpi_table_init(void)
 
 static int __init acpi_parse_apic_instance(char *str)
 {
+       if (!str)
+               return -EINVAL;
 
        acpi_apic_instance = simple_strtoul(str, NULL, 0);
 
index ae8494944c45dd54eb92f57f9651b86b6679f361..11c8c19f0fb7107acfd0c9189c70aeffc5dfba06 100644 (file)
@@ -448,8 +448,10 @@ config PATA_MARVELL
        tristate "Marvell PATA support via legacy mode"
        depends on PCI
        help
-         This option enables limited support for the Marvell 88SE6145 ATA
-         controller.
+         This option enables limited support for the Marvell 88SE61xx ATA
+         controllers. If you wish to use only the SATA ports then select
+         the AHCI driver alone. If you wish to the use the PATA port or
+         both SATA and PATA include this driver.
 
          If unsure, say N.
 
index c729e6988bbb17db928de1cd903682cfc3dc2802..2e1a7cb2ed5f91553ef9d2a39326233197eae7bd 100644 (file)
@@ -420,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = {
        /* board_ahci_mv */
        {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
-                                AHCI_HFLAG_MV_PATA),
+                                AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
                .pio_mask       = 0x1f, /* pio0-4 */
@@ -487,7 +487,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
        { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
        { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
+       { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
+       { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -610,6 +612,15 @@ module_param(ahci_em_messages, int, 0444);
 MODULE_PARM_DESC(ahci_em_messages,
        "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
 
+#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
+static int marvell_enable;
+#else
+static int marvell_enable = 1;
+#endif
+module_param(marvell_enable, int, 0644);
+MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
+
+
 static inline int ahci_nr_ports(u32 cap)
 {
        return (cap & 0x1f) + 1;
@@ -732,6 +743,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
                           "MV_AHCI HACK: port_map %x -> %x\n",
                           port_map,
                           port_map & mv);
+               dev_printk(KERN_ERR, &pdev->dev,
+                         "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
 
                port_map &= mv;
        }
@@ -2533,6 +2546,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
+       /* The AHCI driver can only drive the SATA ports, the PATA driver
+          can drive them all so if both drivers are selected make sure
+          AHCI stays out of the way */
+       if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
+               return -ENODEV;
+
        /* acquire resources */
        rc = pcim_enable_device(pdev);
        if (rc)
index 304fdc6f1dc2c8bce53e7e4e1fca18d982762f31..2a4c516894f0018c7c370168b4ae004f25598546 100644 (file)
@@ -1315,11 +1315,6 @@ fsm_start:
                break;
 
        case HSM_ST_ERR:
-               /* make sure qc->err_mask is available to
-                * know what's wrong and recover
-                */
-               WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
-
                ap->hsm_task_state = HSM_ST_IDLE;
 
                /* complete taskfile transaction */
index 24a011b25024abf4f0da6c8032262934d76db81e..0d87eec849665fe3fac8b276ba6b40009cd129e7 100644 (file)
 #include <linux/ata.h>
 
 #define DRV_NAME       "pata_marvell"
-#define DRV_VERSION    "0.1.4"
+#define DRV_VERSION    "0.1.6"
 
 /**
- *     marvell_pre_reset       -       check for 40/80 pin
- *     @link: link
- *     @deadline: deadline jiffies for the operation
+ *     marvell_pata_active     -       check if PATA is active
+ *     @pdev: PCI device
  *
- *     Perform the PATA port setup we need.
+ *     Returns 1 if the PATA port may be active. We know how to check this
+ *     for the 6145 but not the other devices
  */
 
-static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+static int marvell_pata_active(struct pci_dev *pdev)
 {
-       struct ata_port *ap = link->ap;
-       struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+       int i;
        u32 devices;
        void __iomem *barp;
-       int i;
 
-       /* Check if our port is enabled */
+       /* We don't yet know how to do this for other devices */
+       if (pdev->device != 0x6145)
+               return 1;       
 
        barp = pci_iomap(pdev, 5, 0x10);
        if (barp == NULL)
                return -ENOMEM;
+
        printk("BAR5:");
        for(i = 0; i <= 0x0F; i++)
                printk("%02X:%02X ", i, ioread8(barp + i));
@@ -51,9 +52,27 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
        devices = ioread32(barp + 0x0C);
        pci_iounmap(pdev, barp);
 
-       if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
-           (!(devices & 0x10)))        /* PATA enable ? */
-               return -ENOENT;
+       if (devices & 0x10)
+               return 1;
+       return 0;
+}
+
+/**
+ *     marvell_pre_reset       -       check for 40/80 pin
+ *     @link: link
+ *     @deadline: deadline jiffies for the operation
+ *
+ *     Perform the PATA port setup we need.
+ */
+
+static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+{
+       struct ata_port *ap = link->ap;
+       struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+       if (pdev->device == 0x6145 && ap->port_no == 0 &&
+               !marvell_pata_active(pdev))     /* PATA enable ? */
+                       return -ENOENT;
 
        return ata_sff_prereset(link, deadline);
 }
@@ -128,6 +147,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
        if (pdev->device == 0x6101)
                ppi[1] = &ata_dummy_port_info;
 
+#if defined(CONFIG_AHCI) || defined(CONFIG_AHCI_MODULE)
+       if (!marvell_pata_active(pdev)) {
+               printk(KERN_INFO DRV_NAME ": PATA port not active, deferring to AHCI driver.\n");
+               return -ENODEV;
+       }
+#endif
        return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
 }
 
index 720b8645f58a3121d96112f60e03625fd12de8bc..e970b227fbce39037b4f14879eb4152056df59a5 100644 (file)
@@ -322,9 +322,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
        /* Try to acquire MMIO resources and fallback to PIO if
         * that fails
         */
-       rc = pcim_enable_device(pdev);
-       if (rc)
-               return rc;
        rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME);
        if (rc)
                goto use_ioports;
index 13c1d2af18ac3e0ff02ef35b926df40955ac3006..c815f8ecf6e64c758eb2a43deebc5c20f259ab03 100644 (file)
@@ -667,7 +667,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
        { PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
        { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
        { PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
-       /* RocketRAID 1740/174x have different identifiers */
+       /* RocketRAID 1720/174x have different identifiers */
+       { PCI_VDEVICE(TTI, 0x1720), chip_6042 },
        { PCI_VDEVICE(TTI, 0x1740), chip_508x },
        { PCI_VDEVICE(TTI, 0x1742), chip_508x },
 
index 858f70610edaa8370a6b79b2367147cf3d69dba9..1e1f3f3757ae7bf98fd7ce2d39cfafdc644095f0 100644 (file)
@@ -309,8 +309,6 @@ static void nv_nf2_freeze(struct ata_port *ap);
 static void nv_nf2_thaw(struct ata_port *ap);
 static void nv_ck804_freeze(struct ata_port *ap);
 static void nv_ck804_thaw(struct ata_port *ap);
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
-                       unsigned long deadline);
 static int nv_adma_slave_config(struct scsi_device *sdev);
 static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
@@ -407,7 +405,7 @@ static struct scsi_host_template nv_swncq_sht = {
 
 static struct ata_port_operations nv_generic_ops = {
        .inherits               = &ata_bmdma_port_ops,
-       .hardreset              = nv_hardreset,
+       .hardreset              = ATA_OP_NULL,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
 };
@@ -1588,21 +1586,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
        ata_sff_thaw(ap);
 }
 
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
-                       unsigned long deadline)
-{
-       int rc;
-
-       /* SATA hardreset fails to retrieve proper device signature on
-        * some controllers.  Request follow up SRST.  For more info,
-        * see http://bugzilla.kernel.org/show_bug.cgi?id=3352
-        */
-       rc = sata_sff_hardreset(link, class, deadline);
-       if (rc)
-               return rc;
-       return -EAGAIN;
-}
-
 static void nv_adma_error_handler(struct ata_port *ap)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
index 1838aa3d24feac6a09b9516acbb1ffd623e7f2db..7ce1ac4baa6d81feccad163cb9c476edfb7278c9 100644 (file)
@@ -407,7 +407,7 @@ struct entropy_store {
        /* read-write data: */
        spinlock_t lock;
        unsigned add_ptr;
-       int entropy_count;
+       int entropy_count;      /* Must at no time exceed ->POOLBITS! */
        int input_rotate;
 };
 
@@ -520,6 +520,7 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
 static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
        unsigned long flags;
+       int entropy_count;
 
        if (!nbits)
                return;
@@ -527,20 +528,20 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
        spin_lock_irqsave(&r->lock, flags);
 
        DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
-       r->entropy_count += nbits;
-       if (r->entropy_count < 0) {
+       entropy_count = r->entropy_count;
+       entropy_count += nbits;
+       if (entropy_count < 0) {
                DEBUG_ENT("negative entropy/overflow\n");
-               r->entropy_count = 0;
-       } else if (r->entropy_count > r->poolinfo->POOLBITS)
-               r->entropy_count = r->poolinfo->POOLBITS;
+               entropy_count = 0;
+       } else if (entropy_count > r->poolinfo->POOLBITS)
+               entropy_count = r->poolinfo->POOLBITS;
+       r->entropy_count = entropy_count;
 
        /* should we wake readers? */
-       if (r == &input_pool &&
-           r->entropy_count >= random_read_wakeup_thresh) {
+       if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
                wake_up_interruptible(&random_read_wait);
                kill_fasync(&fasync, SIGIO, POLL_IN);
        }
-
        spin_unlock_irqrestore(&r->lock, flags);
 }
 
index 5ca1d80de182bfa3bb333f0aeca907f7929ed26c..4eee533f3f4af7e8f5c9d811c7ac671d95d05083 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 
 /*
@@ -151,13 +152,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
  */
 static int verify_pmtmr_rate(void)
 {
-       u32 value1, value2;
+       cycle_t value1, value2;
        unsigned long count, delta;
 
        mach_prepare_counter();
-       value1 = read_pmtmr();
+       value1 = clocksource_acpi_pm.read();
        mach_countup(&count);
-       value2 = read_pmtmr();
+       value2 = clocksource_acpi_pm.read();
        delta = (value2 - value1) & ACPI_PM_MASK;
 
        /* Check that the PMTMR delta is within 5% of what we expect */
@@ -175,10 +176,13 @@ static int verify_pmtmr_rate(void)
 #define verify_pmtmr_rate() (0)
 #endif
 
+/* Number of monotonicity checks to perform during initialization */
+#define ACPI_PM_MONOTONICITY_CHECKS 10
+
 static int __init init_acpi_pm_clocksource(void)
 {
-       u32 value1, value2;
-       unsigned int i;
+       cycle_t value1, value2;
+       unsigned int i, j, good = 0;
 
        if (!pmtmr_ioport)
                return -ENODEV;
@@ -187,24 +191,32 @@ static int __init init_acpi_pm_clocksource(void)
                                                clocksource_acpi_pm.shift);
 
        /* "verify" this timing source: */
-       value1 = read_pmtmr();
-       for (i = 0; i < 10000; i++) {
-               value2 = read_pmtmr();
-               if (value2 == value1)
-                       continue;
-               if (value2 > value1)
-                       goto pm_good;
-               if ((value2 < value1) && ((value2) < 0xFFF))
-                       goto pm_good;
-               printk(KERN_INFO "PM-Timer had inconsistent results:"
-                       " 0x%#x, 0x%#x - aborting.\n", value1, value2);
-               return -EINVAL;
+       for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
+               value1 = clocksource_acpi_pm.read();
+               for (i = 0; i < 10000; i++) {
+                       value2 = clocksource_acpi_pm.read();
+                       if (value2 == value1)
+                               continue;
+                       if (value2 > value1)
+                               good++;
+                               break;
+                       if ((value2 < value1) && ((value2) < 0xFFF))
+                               good++;
+                               break;
+                       printk(KERN_INFO "PM-Timer had inconsistent results:"
+                              " 0x%#llx, 0x%#llx - aborting.\n",
+                              value1, value2);
+                       return -EINVAL;
+               }
+               udelay(300 * i);
+       }
+
+       if (good != ACPI_PM_MONOTONICITY_CHECKS) {
+               printk(KERN_INFO "PM-Timer failed consistency check "
+                      " (0x%#llx) - aborting.\n", value1);
+               return -ENODEV;
        }
-       printk(KERN_INFO "PM-Timer had no reasonable result:"
-                       " 0x%#x - aborting.\n", value1);
-       return -ENODEV;
 
-pm_good:
        if (verify_pmtmr_rate() != 0)
                return -ENODEV;
 
index 8024e3bfd8774e4c52383cc7918eb46781fc0ffd..b91ef63126ede7decff0bdbbbd475f03a07bd219 100644 (file)
@@ -669,8 +669,7 @@ static int __init ibft_register_kobjects(struct ibft_table_header *header,
 
        control = (void *)header + sizeof(*header);
        end = (void *)control + control->hdr.length;
-       eot_offset = (void *)header + header->length -
-                    (void *)control - sizeof(*header);
+       eot_offset = (void *)header + header->length - (void *)control;
        rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control,
                             sizeof(*control));
 
index 3331f88dcfb641a4d1d54addc68744ebac2e2646..248ab4a7d39fdb42a1073f48cceca3ed237d28ce 100644 (file)
@@ -223,7 +223,7 @@ static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
                        return 0;
                DRM_UDELAY(1);
        }
-       DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n",
+       DRM_DEBUG("wait for fifo failed status : 0x%08X 0x%08X\n",
                 RADEON_READ(RADEON_RBBM_STATUS),
                 RADEON_READ(R300_VAP_CNTL_STATUS));
 
@@ -252,7 +252,7 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
                }
                DRM_UDELAY(1);
        }
-       DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n",
+       DRM_DEBUG("wait idle failed status : 0x%08X 0x%08X\n",
                 RADEON_READ(RADEON_RBBM_STATUS),
                 RADEON_READ(R300_VAP_CNTL_STATUS));
 
index 840e634fa31f82286d2ff1be195847a598c0fc58..640cbb237328196b1b3b22a91fea4b9ee42bf3b1 100644 (file)
 #include <linux/clk.h>
 #include <linux/io.h>
 
+/* Transmit operation:                                                      */
+/*                                                                          */
+/* 0 byte transmit                                                          */
+/* BUS:     S     A8     ACK   P                                            */
+/* IRQ:       DTE   WAIT                                                    */
+/* ICIC:                                                                    */
+/* ICCR: 0x94 0x90                                                          */
+/* ICDR:      A8                                                            */
+/*                                                                          */
+/* 1 byte transmit                                                          */
+/* BUS:     S     A8     ACK   D8(1)   ACK   P                              */
+/* IRQ:       DTE   WAIT         WAIT                                       */
+/* ICIC:      -DTE                                                          */
+/* ICCR: 0x94       0x90                                                    */
+/* ICDR:      A8    D8(1)                                                   */
+/*                                                                          */
+/* 2 byte transmit                                                          */
+/* BUS:     S     A8     ACK   D8(1)   ACK   D8(2)   ACK   P                */
+/* IRQ:       DTE   WAIT         WAIT          WAIT                         */
+/* ICIC:      -DTE                                                          */
+/* ICCR: 0x94                    0x90                                       */
+/* ICDR:      A8    D8(1)        D8(2)                                      */
+/*                                                                          */
+/* 3 bytes or more, +---------+ gets repeated                               */
+/*                                                                          */
+/*                                                                          */
+/* Receive operation:                                                       */
+/*                                                                          */
+/* 0 byte receive - not supported since slave may hold SDA low              */
+/*                                                                          */
+/* 1 byte receive       [TX] | [RX]                                         */
+/* BUS:     S     A8     ACK | D8(1)   ACK   P                              */
+/* IRQ:       DTE   WAIT     |   WAIT     DTE                               */
+/* ICIC:      -DTE           |   +DTE                                       */
+/* ICCR: 0x94       0x81     |   0xc0                                       */
+/* ICDR:      A8             |            D8(1)                             */
+/*                                                                          */
+/* 2 byte receive        [TX]| [RX]                                         */
+/* BUS:     S     A8     ACK | D8(1)   ACK   D8(2)   ACK   P                */
+/* IRQ:       DTE   WAIT     |   WAIT          WAIT     DTE                 */
+/* ICIC:      -DTE           |                 +DTE                         */
+/* ICCR: 0x94       0x81     |                 0xc0                         */
+/* ICDR:      A8             |                 D8(1)    D8(2)               */
+/*                                                                          */
+/* 3 byte receive       [TX] | [RX]                                         */
+/* BUS:     S     A8     ACK | D8(1)   ACK   D8(2)   ACK   D8(3)   ACK    P */
+/* IRQ:       DTE   WAIT     |   WAIT          WAIT         WAIT      DTE   */
+/* ICIC:      -DTE           |                              +DTE            */
+/* ICCR: 0x94       0x81     |                              0xc0            */
+/* ICDR:      A8             |                 D8(1)        D8(2)     D8(3) */
+/*                                                                          */
+/* 4 bytes or more, this part is repeated    +---------+                    */
+/*                                                                          */
+/*                                                                          */
+/* Interrupt order and BUSY flag                                            */
+/*     ___                                                 _                */
+/* SDA ___\___XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAA___/                 */
+/* SCL      \_/1\_/2\_/3\_/4\_/5\_/6\_/7\_/8\___/9\_____/                   */
+/*                                                                          */
+/*        S   D7  D6  D5  D4  D3  D2  D1  D0              P                 */
+/*                                           ___                            */
+/* WAIT IRQ ________________________________/   \___________                */
+/* TACK IRQ ____________________________________/   \_______                */
+/* DTE  IRQ __________________________________________/   \_                */
+/* AL   IRQ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                */
+/*         _______________________________________________                  */
+/* BUSY __/                                               \_                */
+/*                                                                          */
+
 enum sh_mobile_i2c_op {
        OP_START = 0,
-       OP_TX_ONLY,
+       OP_TX_FIRST,
+       OP_TX,
        OP_TX_STOP,
        OP_TX_TO_RX,
-       OP_RX_ONLY,
+       OP_RX,
        OP_RX_STOP,
+       OP_RX_STOP_DATA,
 };
 
 struct sh_mobile_i2c_data {
@@ -127,25 +198,34 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
        spin_lock_irqsave(&pd->lock, flags);
 
        switch (op) {
-       case OP_START:
+       case OP_START: /* issue start and trigger DTE interrupt */
                iowrite8(0x94, ICCR(pd));
                break;
-       case OP_TX_ONLY:
+       case OP_TX_FIRST: /* disable DTE interrupt and write data */
+               iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd));
                iowrite8(data, ICDR(pd));
                break;
-       case OP_TX_STOP:
+       case OP_TX: /* write data */
                iowrite8(data, ICDR(pd));
-               iowrite8(0x90, ICCR(pd));
-               iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd));
                break;
-       case OP_TX_TO_RX:
+       case OP_TX_STOP: /* write data and issue a stop afterwards */
                iowrite8(data, ICDR(pd));
+               iowrite8(0x90, ICCR(pd));
+               break;
+       case OP_TX_TO_RX: /* select read mode */
                iowrite8(0x81, ICCR(pd));
                break;
-       case OP_RX_ONLY:
+       case OP_RX: /* just read data */
                ret = ioread8(ICDR(pd));
                break;
-       case OP_RX_STOP:
+       case OP_RX_STOP: /* enable DTE interrupt, issue stop */
+               iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE,
+                        ICIC(pd));
+               iowrite8(0xc0, ICCR(pd));
+               break;
+       case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */
+               iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE,
+                        ICIC(pd));
                ret = ioread8(ICDR(pd));
                iowrite8(0xc0, ICCR(pd));
                break;
@@ -157,58 +237,120 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
        return ret;
 }
 
+static int sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd)
+{
+       if (pd->pos == -1)
+               return 1;
+
+       return 0;
+}
+
+static int sh_mobile_i2c_is_last_byte(struct sh_mobile_i2c_data *pd)
+{
+       if (pd->pos == (pd->msg->len - 1))
+               return 1;
+
+       return 0;
+}
+
+static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd,
+                                  unsigned char *buf)
+{
+       switch (pd->pos) {
+       case -1:
+               *buf = (pd->msg->addr & 0x7f) << 1;
+               *buf |= (pd->msg->flags & I2C_M_RD) ? 1 : 0;
+               break;
+       default:
+               *buf = pd->msg->buf[pd->pos];
+       }
+}
+
+static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd)
+{
+       unsigned char data;
+
+       if (pd->pos == pd->msg->len)
+               return 1;
+
+       sh_mobile_i2c_get_data(pd, &data);
+
+       if (sh_mobile_i2c_is_last_byte(pd))
+               i2c_op(pd, OP_TX_STOP, data);
+       else if (sh_mobile_i2c_is_first_byte(pd))
+               i2c_op(pd, OP_TX_FIRST, data);
+       else
+               i2c_op(pd, OP_TX, data);
+
+       pd->pos++;
+       return 0;
+}
+
+static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd)
+{
+       unsigned char data;
+       int real_pos;
+
+       do {
+               if (pd->pos <= -1) {
+                       sh_mobile_i2c_get_data(pd, &data);
+
+                       if (sh_mobile_i2c_is_first_byte(pd))
+                               i2c_op(pd, OP_TX_FIRST, data);
+                       else
+                               i2c_op(pd, OP_TX, data);
+                       break;
+               }
+
+               if (pd->pos == 0) {
+                       i2c_op(pd, OP_TX_TO_RX, 0);
+                       break;
+               }
+
+               real_pos = pd->pos - 2;
+
+               if (pd->pos == pd->msg->len) {
+                       if (real_pos < 0) {
+                               i2c_op(pd, OP_RX_STOP, 0);
+                               break;
+                       }
+                       data = i2c_op(pd, OP_RX_STOP_DATA, 0);
+               } else
+                       data = i2c_op(pd, OP_RX, 0);
+
+               pd->msg->buf[real_pos] = data;
+       } while (0);
+
+       pd->pos++;
+       return pd->pos == (pd->msg->len + 2);
+}
+
 static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
 {
        struct platform_device *dev = dev_id;
        struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
-       struct i2c_msg *msg = pd->msg;
-       unsigned char data, sr;
-       int wakeup = 0;
+       unsigned char sr;
+       int wakeup;
 
        sr = ioread8(ICSR(pd));
-       pd->sr |= sr;
+       pd->sr |= sr; /* remember state */
 
        dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
-              (msg->flags & I2C_M_RD) ? "read" : "write",
-              pd->pos, msg->len);
+              (pd->msg->flags & I2C_M_RD) ? "read" : "write",
+              pd->pos, pd->msg->len);
 
        if (sr & (ICSR_AL | ICSR_TACK)) {
-               iowrite8(0, ICIC(pd)); /* disable interrupts */
-               wakeup = 1;
-               goto do_wakeup;
-       }
+               /* don't interrupt transaction - continue to issue stop */
+               iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd));
+               wakeup = 0;
+       } else if (pd->msg->flags & I2C_M_RD)
+               wakeup = sh_mobile_i2c_isr_rx(pd);
+       else
+               wakeup = sh_mobile_i2c_isr_tx(pd);
 
-       if (pd->pos == msg->len) {
-               i2c_op(pd, OP_RX_ONLY, 0);
-               wakeup = 1;
-               goto do_wakeup;
-       }
+       if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */
+               iowrite8(sr & ~ICSR_WAIT, ICSR(pd));
 
-       if (pd->pos == -1) {
-               data = (msg->addr & 0x7f) << 1;
-               data |= (msg->flags & I2C_M_RD) ? 1 : 0;
-       } else
-               data = msg->buf[pd->pos];
-
-       if ((pd->pos == -1) || !(msg->flags & I2C_M_RD)) {
-               if (msg->flags & I2C_M_RD)
-                       i2c_op(pd, OP_TX_TO_RX, data);
-               else if (pd->pos == (msg->len - 1)) {
-                       i2c_op(pd, OP_TX_STOP, data);
-                       wakeup = 1;
-               } else
-                       i2c_op(pd, OP_TX_ONLY, data);
-       } else {
-               if (pd->pos == (msg->len - 1))
-                       data = i2c_op(pd, OP_RX_STOP, 0);
-               else
-                       data = i2c_op(pd, OP_RX_ONLY, 0);
-
-               msg->buf[pd->pos] = data;
-       }
-       pd->pos++;
-
- do_wakeup:
        if (wakeup) {
                pd->sr |= SW_DONE;
                wake_up(&pd->wait);
@@ -219,6 +361,11 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
 
 static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
 {
+       if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) {
+               dev_err(pd->dev, "Unsupported zero length i2c read\n");
+               return -EIO;
+       }
+
        /* Initialize channel registers */
        iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
 
@@ -233,9 +380,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
        pd->pos = -1;
        pd->sr = 0;
 
-       /* Enable all interrupts except wait */
-       iowrite8(ioread8(ICIC(pd)) | ICIC_ALE | ICIC_TACKE | ICIC_DTEE,
-                ICIC(pd));
+       /* Enable all interrupts to begin with */
+       iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd));
        return 0;
 }
 
@@ -268,25 +414,18 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
                if (!k)
                        dev_err(pd->dev, "Transfer request timed out\n");
 
-               retry_count = 10;
+               retry_count = 1000;
 again:
                val = ioread8(ICSR(pd));
 
                dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
 
-               if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
-                       err = -EIO;
-                       break;
-               }
-
                /* the interrupt handler may wake us up before the
                 * transfer is finished, so poll the hardware
                 * until we're done.
                 */
-
-               if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) &&
-                     (val & ICSR_SDAM))) {
-                       msleep(1);
+               if (val & ICSR_BUSY) {
+                       udelay(10);
                        if (retry_count--)
                                goto again;
 
@@ -294,6 +433,12 @@ again:
                        dev_err(pd->dev, "Polling timed out\n");
                        break;
                }
+
+               /* handle missing acknowledge and arbitration lost */
+               if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
+                       err = -EIO;
+                       break;
+               }
        }
 
        deactivate_ch(pd);
index a34758d29516c3aff28958582a915b5b664ec72e..fc735ab08ff4f8f3f80c82e911242a2f54f84758 100644 (file)
@@ -242,7 +242,7 @@ config BLK_DEV_IDEFLOPPY
          module will be called ide-floppy.
 
 config BLK_DEV_IDESCSI
-       tristate "SCSI emulation support"
+       tristate "SCSI emulation support (DEPRECATED)"
        depends on SCSI
        select IDE_ATAPI
        ---help---
@@ -255,20 +255,6 @@ config BLK_DEV_IDESCSI
          and will allow you to use a SCSI device driver instead of a native
          ATAPI driver.
 
-         This is useful if you have an ATAPI device for which no native
-         driver has been written (for example, an ATAPI PD-CD drive);
-         you can then use this emulation together with an appropriate SCSI
-         device driver. In order to do this, say Y here and to "SCSI support"
-         and "SCSI generic support", below. You must then provide the kernel
-         command line "hdx=ide-scsi" (try "man bootparam" or see the
-         documentation of your boot loader (lilo or loadlin) about how to
-         pass options to the kernel at boot time) for devices if you want the
-         native EIDE sub-drivers to skip over the native support, so that
-         this SCSI emulation can be used instead.
-
-         Note that this option does NOT allow you to attach SCSI devices to a
-         box that doesn't have a SCSI host adapter installed.
-
          If both this SCSI emulation and native ATAPI support are compiled
          into the kernel, the native support will be used.
 
index f788fa5a977b54f4606ff09d306475fd5c435cd9..4fd91dcf1dc2e516f7ba499938aed124a887d13c 100644 (file)
@@ -343,11 +343,10 @@ static struct ide_port_info __devinitdata palm_bk3710_port_info = {
        .mwdma_mask             = ATA_MWDMA2,
 };
 
-static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+static int __init palm_bk3710_probe(struct platform_device *pdev)
 {
        struct clk *clk;
        struct resource *mem, *irq;
-       struct ide_host *host;
        unsigned long base, rate;
        int i, rc;
        hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
@@ -390,6 +389,7 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
                hw.io_ports_array[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i;
        hw.io_ports.ctl_addr = base + IDE_PALM_ATA_PRI_CTL_OFFSET;
        hw.irq = irq->start;
+       hw.dev = &pdev->dev;
        hw.chipset = ide_palm3710;
 
        palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
@@ -413,13 +413,11 @@ static struct platform_driver platform_bk_driver = {
                .name = "palm_bk3710",
                .owner = THIS_MODULE,
        },
-       .probe = palm_bk3710_probe,
-       .remove = NULL,
 };
 
 static int __init palm_bk3710_init(void)
 {
-       return platform_driver_register(&platform_bk_driver);
+       return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe);
 }
 
 module_init(palm_bk3710_init);
index 49a8c589e346c15982e158e5116c9fd930aa9b46..f1489999cf916a53f222a9c71d9e518be9f69c20 100644 (file)
@@ -1933,6 +1933,7 @@ static void ide_cd_remove(ide_drive_t *drive)
 
        ide_proc_unregister_driver(drive, info->driver);
 
+       blk_unregister_filter(info->disk);
        del_gendisk(info->disk);
 
        ide_cd_put(info);
@@ -2158,6 +2159,7 @@ static int ide_cd_probe(ide_drive_t *drive)
        g->fops = &idecd_ops;
        g->flags |= GENHD_FL_REMOVABLE;
        add_disk(g);
+       blk_register_filter(g);
        return 0;
 
 out_free_cd:
index 68b9cf0138b05f017427b24c958750bd77356ee8..07ef88bd109b69a04c0addfcac588024ea7286dd 100644 (file)
@@ -445,20 +445,6 @@ static void idedisk_check_hpa(ide_drive_t *drive)
        }
 }
 
-/*
- * Compute drive->capacity, the full capacity of the drive
- * Called with drive->id != NULL.
- *
- * To compute capacity, this uses either of
- *
- *    1. CHS value set by user       (whatever user sets will be trusted)
- *    2. LBA value from target drive (require new ATA feature)
- *    3. LBA value from system BIOS  (new one is OK, old one may break)
- *    4. CHS value from system BIOS  (traditional style)
- *
- * in above order (i.e., if value of higher priority is available,
- * reset will be ignored).
- */
 static void init_idedisk_capacity(ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
index 2ec921bf3c6016b6dc19e5999e3ccf6682e209bf..18f4d7f6ce6d0d3b983d34fffc7b6da437679cc7 100644 (file)
@@ -63,7 +63,7 @@
 }
 
 /* table of devices that work with this driver */
-static const struct usb_device_id bcm5974_table [] = {
+static const struct usb_device_id bcm5974_table[] = {
        /* MacbookAir1.1 */
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
@@ -105,7 +105,7 @@ struct tp_header {
 
 /* trackpad finger structure */
 struct tp_finger {
-       __le16 origin;          /* left/right origin? */
+       __le16 origin;          /* zero when switching track finger */
        __le16 abs_x;           /* absolute x coodinate */
        __le16 abs_y;           /* absolute y coodinate */
        __le16 rel_x;           /* relative x coodinate */
@@ -159,6 +159,7 @@ struct bcm5974 {
        struct bt_data *bt_data;        /* button transferred data */
        struct urb *tp_urb;             /* trackpad usb request block */
        struct tp_data *tp_data;        /* trackpad transferred data */
+       int fingers;                    /* number of fingers on trackpad */
 };
 
 /* logical dimensions */
@@ -172,6 +173,10 @@ struct bcm5974 {
 #define SN_WIDTH       100             /* width signal-to-noise ratio */
 #define SN_COORD       250             /* coordinate signal-to-noise ratio */
 
+/* pressure thresholds */
+#define PRESSURE_LOW   (2 * DIM_PRESSURE / SN_PRESSURE)
+#define PRESSURE_HIGH  (3 * PRESSURE_LOW)
+
 /* device constants */
 static const struct bcm5974_config bcm5974_config_table[] = {
        {
@@ -248,6 +253,7 @@ static void setup_events_to_report(struct input_dev *input_dev,
                                0, cfg->y.dim, cfg->y.fuzz, 0);
 
        __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
        __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
        __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
@@ -273,32 +279,66 @@ static int report_tp_state(struct bcm5974 *dev, int size)
        const struct tp_finger *f = dev->tp_data->finger;
        struct input_dev *input = dev->input;
        const int fingers = (size - 26) / 28;
-       int p = 0, w, x, y, n = 0;
+       int raw_p, raw_w, raw_x, raw_y;
+       int ptest = 0, origin = 0, nmin = 0, nmax = 0;
+       int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
 
        if (size < 26 || (size - 26) % 28 != 0)
                return -EIO;
 
+       /* always track the first finger; when detached, start over */
        if (fingers) {
-               p = raw2int(f->force_major);
-               w = raw2int(f->size_major);
-               x = raw2int(f->abs_x);
-               y = raw2int(f->abs_y);
-               n = p > 0 ? fingers : 0;
+               raw_p = raw2int(f->force_major);
+               raw_w = raw2int(f->size_major);
+               raw_x = raw2int(f->abs_x);
+               raw_y = raw2int(f->abs_y);
 
                dprintk(9,
-                       "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
-                       p, w, x, y, n);
+                       "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
+                       raw_p, raw_w, raw_x, raw_y);
+
+               ptest = int2bound(&c->p, raw_p);
+               origin = raw2int(f->origin);
+       }
 
-               input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w));
-               input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin));
-               input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y));
+       /* while tracking finger still valid, count all fingers */
+       if (ptest > PRESSURE_LOW && origin) {
+               abs_p = ptest;
+               abs_w = int2bound(&c->w, raw_w);
+               abs_x = int2bound(&c->x, raw_x - c->x.devmin);
+               abs_y = int2bound(&c->y, c->y.devmax - raw_y);
+               for (; f != dev->tp_data->finger + fingers; f++) {
+                       ptest = int2bound(&c->p, raw2int(f->force_major));
+                       if (ptest > PRESSURE_LOW)
+                               nmax++;
+                       if (ptest > PRESSURE_HIGH)
+                               nmin++;
+               }
        }
 
-       input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p));
+       if (dev->fingers < nmin)
+               dev->fingers = nmin;
+       if (dev->fingers > nmax)
+               dev->fingers = nmax;
+
+       input_report_key(input, BTN_TOUCH, dev->fingers > 0);
+       input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
+       input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
+       input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
 
-       input_report_key(input, BTN_TOOL_FINGER, n == 1);
-       input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
-       input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2);
+       input_report_abs(input, ABS_PRESSURE, abs_p);
+       input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
+
+       if (abs_p) {
+               input_report_abs(input, ABS_X, abs_x);
+               input_report_abs(input, ABS_Y, abs_y);
+
+               dprintk(8,
+                       "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
+                       "nmin: %d nmax: %d n: %d\n",
+                       abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
+
+       }
 
        input_sync(input);
 
index 3282b741e2460ed20d30ef4fd3a5f655fc228f5c..5aafe24984c598236efdd54dde31e8db9ec6cc60 100644 (file)
@@ -305,7 +305,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                .ident = "Lenovo 3000 n100",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
                },
        },
        {
index 7e65bad522cb26456b4b1909d69b7c72e52efb3d..ac89a5deaca2e12fa62ccb78f1d62b088039675c 100644 (file)
@@ -238,15 +238,47 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
 
 }
 
+static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+{
+       /* Iterate the disks of an mddev, using rcu to protect access to the
+        * linked list, and raising the refcount of devices we return to ensure
+        * they don't disappear while in use.
+        * As devices are only added or removed when raid_disk is < 0 and
+        * nr_pending is 0 and In_sync is clear, the entries we return will
+        * still be in the same position on the list when we re-enter
+        * list_for_each_continue_rcu.
+        */
+       struct list_head *pos;
+       rcu_read_lock();
+       if (rdev == NULL)
+               /* start at the beginning */
+               pos = &mddev->disks;
+       else {
+               /* release the previous rdev and start from there. */
+               rdev_dec_pending(rdev, mddev);
+               pos = &rdev->same_set;
+       }
+       list_for_each_continue_rcu(pos, &mddev->disks) {
+               rdev = list_entry(pos, mdk_rdev_t, same_set);
+               if (rdev->raid_disk >= 0 &&
+                   test_bit(In_sync, &rdev->flags) &&
+                   !test_bit(Faulty, &rdev->flags)) {
+                       /* this is a usable devices */
+                       atomic_inc(&rdev->nr_pending);
+                       rcu_read_unlock();
+                       return rdev;
+               }
+       }
+       rcu_read_unlock();
+       return NULL;
+}
+
 static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
 {
-       mdk_rdev_t *rdev;
+       mdk_rdev_t *rdev = NULL;
        mddev_t *mddev = bitmap->mddev;
 
-       rcu_read_lock();
-       rdev_for_each_rcu(rdev, mddev)
-               if (test_bit(In_sync, &rdev->flags)
-                   && !test_bit(Faulty, &rdev->flags)) {
+       while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
                        int size = PAGE_SIZE;
                        if (page->index == bitmap->file_pages-1)
                                size = roundup(bitmap->last_page_size,
@@ -281,8 +313,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
                                       + page->index * (PAGE_SIZE/512),
                                       size,
                                       page);
-               }
-       rcu_read_unlock();
+       }
 
        if (wait)
                md_super_wait(mddev);
index 8cfadc5bd2ba54f858c8f28c8f17c5db40942891..4790c83d78d0cd52adbfb4d4c394eb9d7ec4c691 100644 (file)
@@ -3841,8 +3841,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 
                del_timer_sync(&mddev->safemode_timer);
 
-               invalidate_partition(disk, 0);
-
                switch(mode) {
                case 1: /* readonly */
                        err  = -ENXIO;
index e8bc7abf24097d93b6b0b2135c72a2c3c9b198fd..99be9e5c85f78c5221a4107ff06233e70a36e242 100644 (file)
@@ -1068,7 +1068,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
        {
                v4l2_std_id *id = arg;
                int found = 0;
-               int i, err;
+               int i;
 
                DEB_EE(("VIDIOC_S_STD\n"));
 
@@ -1116,7 +1116,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
        case VIDIOC_OVERLAY:
        {
                int on = *(int *)arg;
-               int err = 0;
 
                DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
                if (on != 0) {
@@ -1192,7 +1191,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
        case VIDIOCGMBUF:
        {
                struct video_mbuf *mbuf = arg;
-               struct videobuf_queue *q;
                int i;
 
                /* fixme: number of capture buffers and sizes for v4l apps */
index e254bcfc2efb77df010cdae10d482eaeb884afb4..e8d3c48f86059d13aab958f0465346413439b2b8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index cd8376f6f7b48ac3fd812e7ee7f06eb8cf037a3e..6632de640df0d9eb8c84ab2368371d01d26ea8b6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e930759c2c006d06f1ddaecea370d83cae14cc71..4e05a67e88c1419580fe410450c07bf00c66f8e4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0dc2bef9f6a3b9acd59c7c4c75439d3782ce0192..227642b044ae6b35f43aa902531911dc81ef1fa5 100644 (file)
@@ -2,7 +2,7 @@
     MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
 
     Copyright (C) 2008 MaxLinear
-    Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2006 Steven Toth <stoth@linuxtv.org>
       Functions:
        mxl5005s_reset()
        mxl5005s_writereg()
@@ -3837,7 +3837,7 @@ static u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
 /* ----------------------------------------------------------------
  * Begin: Everything after here is new code to adapt the
  * proprietary Realtek driver into a Linux API tuner.
- * Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ * Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
  */
 static int mxl5005s_reset(struct dvb_frontend *fe)
 {
index 396db150bf0c7a3ca9d294a8eb6c1e7ee26559cb..7ac6815b30aaf84b70ddafe9768fd46d99c2b6da 100644 (file)
@@ -2,7 +2,7 @@
     MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
 
     Copyright (C) 2008 MaxLinear
-    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index 597e47f5d69cde232fbf03bc52c685785ab72fc9..aa773a658a2a3e3c0d7caae7cb2d3b783ff8b10d 100644 (file)
@@ -253,7 +253,7 @@ static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
 
 static int simple_config_lookup(struct dvb_frontend *fe,
                                struct tuner_params *t_params,
-                               int *frequency, u8 *config, u8 *cb)
+                               unsigned *frequency, u8 *config, u8 *cb)
 {
        struct tuner_simple_priv *priv = fe->tuner_priv;
        int i;
@@ -587,45 +587,45 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
        priv->last_div = div;
        if (t_params->has_tda9887) {
                struct v4l2_priv_tun_config tda9887_cfg;
-               int config = 0;
+               int tda_config = 0;
                int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
                                                 V4L2_STD_SECAM_LC)) &&
                        !(params->std & ~(V4L2_STD_SECAM_L |
                                          V4L2_STD_SECAM_LC));
 
                tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv  = &config;
+               tda9887_cfg.priv  = &tda_config;
 
                if (params->std == V4L2_STD_SECAM_LC) {
                        if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
-                               config |= TDA9887_PORT1_ACTIVE;
+                               tda_config |= TDA9887_PORT1_ACTIVE;
                        if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
-                               config |= TDA9887_PORT2_ACTIVE;
+                               tda_config |= TDA9887_PORT2_ACTIVE;
                } else {
                        if (t_params->port1_active)
-                               config |= TDA9887_PORT1_ACTIVE;
+                               tda_config |= TDA9887_PORT1_ACTIVE;
                        if (t_params->port2_active)
-                               config |= TDA9887_PORT2_ACTIVE;
+                               tda_config |= TDA9887_PORT2_ACTIVE;
                }
                if (t_params->intercarrier_mode)
-                       config |= TDA9887_INTERCARRIER;
+                       tda_config |= TDA9887_INTERCARRIER;
                if (is_secam_l) {
                        if (i == 0 && t_params->default_top_secam_low)
-                               config |= TDA9887_TOP(t_params->default_top_secam_low);
+                               tda_config |= TDA9887_TOP(t_params->default_top_secam_low);
                        else if (i == 1 && t_params->default_top_secam_mid)
-                               config |= TDA9887_TOP(t_params->default_top_secam_mid);
+                               tda_config |= TDA9887_TOP(t_params->default_top_secam_mid);
                        else if (t_params->default_top_secam_high)
-                               config |= TDA9887_TOP(t_params->default_top_secam_high);
+                               tda_config |= TDA9887_TOP(t_params->default_top_secam_high);
                } else {
                        if (i == 0 && t_params->default_top_low)
-                               config |= TDA9887_TOP(t_params->default_top_low);
+                               tda_config |= TDA9887_TOP(t_params->default_top_low);
                        else if (i == 1 && t_params->default_top_mid)
-                               config |= TDA9887_TOP(t_params->default_top_mid);
+                               tda_config |= TDA9887_TOP(t_params->default_top_mid);
                        else if (t_params->default_top_high)
-                               config |= TDA9887_TOP(t_params->default_top_high);
+                               tda_config |= TDA9887_TOP(t_params->default_top_high);
                }
                if (t_params->default_pll_gating_18)
-                       config |= TDA9887_GATING_18;
+                       tda_config |= TDA9887_GATING_18;
                i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
                                    &tda9887_cfg);
        }
@@ -813,7 +813,8 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
        static struct tuner_params *t_params;
        u8 config, cb;
        u32 div;
-       int ret, frequency = params->frequency / 62500;
+       int ret;
+       unsigned frequency = params->frequency / 62500;
 
        t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
        ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
index 5f99de0ad61252545567b5bfa01a38ff9ff92ede..dcddfa803a75597b00d97e40f734203a4fdc8952 100644 (file)
@@ -2,7 +2,7 @@
  *  Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
  *
  *  Copyright (c) 2007 Xceive Corporation
- *  Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index c910715addc97bdac548c89a563e2600ffa11b0e..5389f740945ae82133bf3f53d07872a13d7b59e6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
  *
- *  Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index a72a9887fe7ffeab488da51193be130ba7d98767..b2a0074c99c946a7c77a71aeb10451f2fc933f1b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
  *
- *  Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index f9d087669d5db3dce7de713182e50eec8bdcc6d6..4eed783f4bce0daaa4e724e20bfbfe21f80cdef9 100644 (file)
@@ -137,7 +137,8 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un
                        flexcop_diseqc_send_byte(fe, 0xff);
                else {
                        flexcop_set_tone(fe, SEC_TONE_ON);
-                       udelay(12500);
+                       mdelay(12);
+                       udelay(500);
                        flexcop_set_tone(fe, SEC_TONE_OFF);
                }
                msleep(20);
index 55973eaf371180d90534bced637142582e5373bc..43a112ec6d44f146b260c64cf12446d036e1283a 100644 (file)
@@ -221,12 +221,12 @@ int flexcop_i2c_init(struct flexcop_device *fc)
        fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
        fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
 
-       strncpy(fc->fc_i2c_adap[0].i2c_adap.name,
-               "B2C2 FlexCop I2C to demod", I2C_NAME_SIZE);
-       strncpy(fc->fc_i2c_adap[1].i2c_adap.name,
-               "B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE);
-       strncpy(fc->fc_i2c_adap[2].i2c_adap.name,
-               "B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE);
+       strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",
+               sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
+       strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
+               sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
+       strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",
+               sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
 
        i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
        i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
index a7637562e74200943bb846dddf81a8318b8b9dc4..aa3db57d32d94ce7ac01abb81b3ab41bbb501e2a 100644 (file)
@@ -1244,7 +1244,7 @@ static int dst_command(struct dst_state *state, u8 *data, u8 len)
                goto error;
        }
        if (state->type_flags & DST_TYPE_HAS_FW_1)
-               udelay(3000);
+               mdelay(3);
        if (read_dst(state, &reply, GET_ACK)) {
                dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
                if ((dst_error_recovery(state)) < 0) {
@@ -1260,7 +1260,7 @@ static int dst_command(struct dst_state *state, u8 *data, u8 len)
        if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
                goto error;
        if (state->type_flags & DST_TYPE_HAS_FW_1)
-               udelay(3000);
+               mdelay(3);
        else
                udelay(2000);
        if (!dst_wait_dst_ready(state, NO_DELAY))
index 1cf9fcb6f5149ff882af75cc54b0a5225656ac74..069d847ba887c39e2f1f83eafdf7c06a07b838a7 100644 (file)
@@ -641,7 +641,6 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
                struct timespec timeout = { 0 };
                struct dmx_pes_filter_params *para = &filter->params.pes;
                dmx_output_t otype;
-               int ret;
                int ts_type;
                enum dmx_ts_pes ts_pes;
                struct dmx_ts_feed **tsfeed = &filter->feed.ts;
index 8e5dd7b1f034b052b8401ad1f6c646707a7127b9..98ee16773ff2e204e82f3501f0f0ed45d123b844 100644 (file)
@@ -1032,7 +1032,7 @@ static int dvb_ca_en50221_thread(void *data)
                                        /* we need this extra check for annoying interfaces like the budget-av */
                                        if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
                                            (ca->pub->poll_slot_status)) {
-                                               int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+                                               status = ca->pub->poll_slot_status(ca->pub, slot, 0);
                                                if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
                                                        ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
                                                        dvb_ca_en50221_thread_update_delay(ca);
@@ -1089,7 +1089,7 @@ static int dvb_ca_en50221_thread(void *data)
                                        /* we need this extra check for annoying interfaces like the budget-av */
                                        if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
                                            (ca->pub->poll_slot_status)) {
-                                               int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+                                               status = ca->pub->poll_slot_status(ca->pub, slot, 0);
                                                if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
                                                        ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
                                                        dvb_ca_en50221_thread_update_delay(ca);
index 8cbdb218952f768fc9128552e64c8a3327370132..3526e3ee9487747788e00ac66b0c978af36a3ad2 100644 (file)
@@ -889,13 +889,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                         * initialization, so parg is 8 bits and does not
                         * include the initialization or start bit
                         */
-                       unsigned long cmd = ((unsigned long) parg) << 1;
+                       unsigned long swcmd = ((unsigned long) parg) << 1;
                        struct timeval nexttime;
                        struct timeval tv[10];
                        int i;
                        u8 last = 1;
                        if (dvb_frontend_debug)
-                               printk("%s switch command: 0x%04lx\n", __func__, cmd);
+                               printk("%s switch command: 0x%04lx\n", __func__, swcmd);
                        do_gettimeofday(&nexttime);
                        if (dvb_frontend_debug)
                                memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -908,12 +908,12 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        for (i = 0; i < 9; i++) {
                                if (dvb_frontend_debug)
                                        do_gettimeofday(&tv[i + 1]);
-                               if ((cmd & 0x01) != last) {
+                               if ((swcmd & 0x01) != last) {
                                        /* set voltage to (last ? 13V : 18V) */
                                        fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
                                        last = (last) ? 0 : 1;
                                }
-                               cmd = cmd >> 1;
+                               swcmd = swcmd >> 1;
                                if (i != 8)
                                        dvb_frontend_sleep_until(&nexttime, 8000);
                        }
index aaa0b6f0b5218711136bdaa0b57189c5a73f1373..563400277a426a5455e0d9036fdb5d608a0e416e 100644 (file)
@@ -210,7 +210,7 @@ static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff)
        if (d->state == DVB_USB_STATE_INIT &&
            usb_set_interface(d->udev, 0, 0) < 0)
                err("set interface failed");
-       do; while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
+       do {} while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
                   !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) &&
                   !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0);
        if (!ret) {
index 3dd20bfbed326f7d573f6861a0c1757adf9e6b47..6c0e5c5f4362fbed72c8ccdd3d10c7a0098bf056 100644 (file)
@@ -1117,7 +1117,8 @@ struct usb_device_id dib0700_usb_id_table[] = {
        { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
        { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_T_XXS) },
        { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
-       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
+/* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) },
        { 0 }           /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1373,7 +1374,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        }
                },
 
-               .num_device_descs = 3,
+               .num_device_descs = 4,
                .devices = {
                        {   "DiBcom STK7070PD reference design",
                                { &dib0700_usb_id_table[17], NULL },
@@ -1386,6 +1387,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        {   "Hauppauge Nova-TD Stick (52009)",
                                { &dib0700_usb_id_table[35], NULL },
                                { NULL },
+                       },
+                       {   "Hauppauge Nova-TD-500 (84xxx)",
+                               { &dib0700_usb_id_table[36], NULL },
+                               { NULL },
                        }
                }
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
index 029b437caf9a11d20896df531762e279d7378858..03dfb9f2fe30eacd73aadbcf01b8aa9c5230ccd5 100644 (file)
 #define USB_PID_WINTV_NOVA_T_USB2_WARM                 0x9301
 #define USB_PID_HAUPPAUGE_NOVA_T_500                   0x9941
 #define USB_PID_HAUPPAUGE_NOVA_T_500_2                 0x9950
+#define USB_PID_HAUPPAUGE_NOVA_T_500_3                 0x8400
 #define USB_PID_HAUPPAUGE_NOVA_T_STICK                 0x7050
 #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2               0x7060
 #define USB_PID_HAUPPAUGE_NOVA_T_STICK_3               0x7070
index f7b71657f0f6324f57891d470faf1d2a4f30275f..0b82cc2a1e161c7603e900ab6bff8d4ffc9effee 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Auvitek AU8522 QAM/8VSB demodulator driver
 
-    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -304,6 +304,43 @@ static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
        return ret;
 }
 
+static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       u8 r0b5, r0b6, r0b7;
+       char *ifmhz;
+
+       switch (if_freq) {
+       case AU8522_IF_3_25MHZ:
+               ifmhz = "3.25";
+               r0b5 = 0x00;
+               r0b6 = 0x3d;
+               r0b7 = 0xa0;
+               break;
+       case AU8522_IF_4MHZ:
+               ifmhz = "4.00";
+               r0b5 = 0x00;
+               r0b6 = 0x4b;
+               r0b7 = 0xd9;
+               break;
+       case AU8522_IF_6MHZ:
+               ifmhz = "6.00";
+               r0b5 = 0xfb;
+               r0b6 = 0x8e;
+               r0b7 = 0x39;
+               break;
+       default:
+               dprintk("%s() IF Frequency not supported\n", __func__);
+               return -EINVAL;
+       }
+       dprintk("%s() %s MHz\n", __func__, ifmhz);
+       au8522_writereg(state, 0x80b5, r0b5);
+       au8522_writereg(state, 0x80b6, r0b6);
+       au8522_writereg(state, 0x80b7, r0b7);
+
+       return 0;
+}
+
 /* VSB Modulation table */
 static struct {
        u16 reg;
@@ -334,9 +371,6 @@ static struct {
        { 0x80af, 0x66 },
        { 0x821b, 0xcc },
        { 0x821d, 0x80 },
-       { 0x80b5, 0xfb },
-       { 0x80b6, 0x8e },
-       { 0x80b7, 0x39 },
        { 0x80a4, 0xe8 },
        { 0x8231, 0x13 },
 };
@@ -350,9 +384,6 @@ static struct {
        { 0x80a4, 0x00 },
        { 0x8081, 0xc4 },
        { 0x80a5, 0x40 },
-       { 0x80b5, 0xfb },
-       { 0x80b6, 0x8e },
-       { 0x80b7, 0x39 },
        { 0x80aa, 0x77 },
        { 0x80ad, 0x77 },
        { 0x80a6, 0x67 },
@@ -438,6 +469,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
                        au8522_writereg(state,
                                VSB_mod_tab[i].reg,
                                VSB_mod_tab[i].data);
+               au8522_set_if(fe, state->config->vsb_if);
                break;
        case QAM_64:
        case QAM_256:
@@ -446,6 +478,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
                        au8522_writereg(state,
                                QAM_mod_tab[i].reg,
                                QAM_mod_tab[i].data);
+               au8522_set_if(fe, state->config->qam_if);
                break;
        default:
                dprintk("%s() Invalid modulation\n", __func__);
index d7affa3cdb27536190d24293ca658729740b95e5..595915ade8c3681b5158e0ed0bf56da36ab25d4f 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Auvitek AU8522 QAM/8VSB demodulator driver
 
-    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
 #include <linux/dvb/frontend.h>
 
+enum au8522_if_freq {
+       AU8522_IF_6MHZ = 0,
+       AU8522_IF_4MHZ,
+       AU8522_IF_3_25MHZ,
+};
+
 struct au8522_config {
        /* the demodulator's i2c address */
        u8 demod_address;
@@ -32,6 +38,9 @@ struct au8522_config {
 #define AU8522_TUNERLOCKING 0
 #define AU8522_DEMODLOCKING 1
        u8 status_mode;
+
+       enum au8522_if_freq vsb_if;
+       enum au8522_if_freq qam_if;
 };
 
 #if defined(CONFIG_DVB_AU8522) ||                              \
index cc1db4e371c360c6365ea3ae1b49b91f85d6ab48..9430e03dba6c3fef4b744e28d7930b8ca0df09dd 100644 (file)
@@ -7,7 +7,7 @@
     Copyright (C) 2001-2002 Convergence Integrated Media GmbH
          Holger Waechtler <holger@convergence.de>
 
-    Copyright (C) 2004 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2004 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index 8af766a315520b882aa7c62adb1f0507d9b6fb69..b1e465c6c2cec362c989f7a17a41e6c5c03a05f4 100644 (file)
@@ -7,7 +7,7 @@
     Copyright (C) 2001-2002 Convergence Integrated Media GmbH
          Holger Waechtler <holger@convergence.de>
 
-    Copyright (C) 2004 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2004 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index 7f68d78c6558eb962ba2b74dbae4b8537faa1825..7156157cb34b2ec9f06c9af3b17e14e84d460f82 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
  *
- *   Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+ *   Copyright (C) 2005 Steven Toth <stoth@linuxtv.org>
  *
  *   Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
  *
@@ -1072,8 +1072,8 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
     if (config->dont_use_pll)
        cx24123_repeater_mode(state, 1, 0);
 
-       strncpy(state->tuner_i2c_adapter.name,
-               "CX24123 tuner I2C bus", I2C_NAME_SIZE);
+       strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus",
+               sizeof(state->tuner_i2c_adapter.name));
        state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
        state->tuner_i2c_adapter.algo      = &cx24123_tuner_i2c_algo;
        state->tuner_i2c_adapter.algo_data = NULL;
index 81ebc3d2f19f07353278f00ee82537e48e484c48..cc6b411d6d20ba76da2a535ad103f854eec71690 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
 
-    Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2005 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index 5ddb2dca305c9970e5a4ba315fbaed844b8f2754..7500a1c53e68b50cef235c1e1ef1d73b21836f84 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Samsung S5H1409 VSB/QAM demodulator driver
 
-    Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2006 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -404,6 +404,7 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
                break;
        case QAM_64:
        case QAM_256:
+       case QAM_AUTO:
                dprintk("%s() QAM_AUTO (64/256)\n", __func__);
                if (state->if_freq != S5H1409_QAM_IF_FREQ)
                        s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
index 59f4335964c6625a78ccba31e2db6ce24855466c..d1a1d2eb8e111247c06eee1f5d38e41e817a6322 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Samsung S5H1409 VSB/QAM demodulator driver
 
-    Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2006 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index cff360ce1ba3f22bddbd4e051c51ae997a8bb595..2da1a3763de93ce16eba814d3ee8ff5a6ffc0d1e 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Samsung S5H1411 VSB/QAM demodulator driver
 
-    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -488,6 +488,7 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe,
                break;
        case QAM_64:
        case QAM_256:
+       case QAM_AUTO:
                dprintk("%s() QAM_AUTO (64/256)\n", __func__);
                s5h1411_set_if_freq(fe, state->config->qam_if);
                s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
index 1855f64ed4d81bdd80cadf007b47348fd536abb2..7d542bc00c487e9ad9c27e92d2c2f12e9e3d9642 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Samsung S5H1411 VSB/QAM demodulator driver
 
-    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index 720ed9ff7c5fda6a43b0b5074e16ee28c487eaf0..747d3fa2e5e5c47721a187858bb79c629aea9387 100644 (file)
@@ -915,7 +915,8 @@ struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
        state->frontend.demodulator_priv = state;
 
        /* create tuner i2c adapter */
-       strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE);
+       strlcpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus",
+               sizeof(state->tuner_i2c_adapter.name));
        state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
        state->tuner_i2c_adapter.algo      = &s5h1420_tuner_i2c_algo;
        state->tuner_i2c_adapter.algo_data = NULL;
index 0ab8d86b3ae3e4d859d51c54e87febef04c62c06..04e7f1cc1403ef1fb6f197f18cec99827e6d3453 100644 (file)
@@ -1,7 +1,7 @@
 /*
     NXP TDA10048HN DVB OFDM demodulator driver
 
-    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -303,7 +303,7 @@ static int tda10048_firmware_upload(struct dvb_frontend *fe)
 
        if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
                printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
-               return -EIO;
+               ret = -EIO;
        } else {
                printk(KERN_INFO "%s: firmware uploading\n", __func__);
 
index 2b5c78e62c860c7fee60101cb3055b64eda9aa48..0457b24601fa1239d34935811bbe165bf47428d3 100644 (file)
@@ -1,7 +1,7 @@
 /*
     NXP TDA10048HN DVB OFDM demodulator driver
 
-    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index e7a8ac0c4049d1de1f225df6d3b764f00f43c510..cc5efb643f33eb9de793843888cea0ee1a747a28 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 3 as
+ *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation;
  *
  *  Software distributed under the License is distributed on an "AS IS"
index 83b39bc203fea8f5ba2d4eefaef0734e2994113e..c8f3da6f9bc1021b60b2db3469a71989b6ab1415 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 3 as
+ *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation;
  *
  *  Software distributed under the License is distributed on an "AS IS"
index c5f45fed69dc41290a2300a5a90dfea701f87cdb..6576fbb40fc67eb8fcfce1205873f0051ce68fd7 100644 (file)
@@ -8,7 +8,7 @@
  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 3 as
+ *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation;
  *
  *  Software distributed under the License is distributed on an "AS IS"
index c1f8f1dccb111bd654ff141bb111fbc4e93b53d9..8d973f726fb835c565b30a827828372d8e4eeedc 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 3 as
+ *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation;
  *
  *  Software distributed under the License is distributed on an "AS IS"
index 229274a14110515a8c00f020162c0310d1ab4d53..8d490e133f350aa3c41c346b8c1fb2b397488d99 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 3 as
+ *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation;
  *
  *  Software distributed under the License is distributed on an "AS IS"
index c10b1849c6a348c6928ca39aa7438d3aab6abc21..87a3c24454b9903e5ad0fdc6aba160cf512091d6 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 3 as
+ *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation;
  *
  *  Software distributed under the License is distributed on an "AS IS"
index 39bd0a20f53a41f4d8cf51ecdc41644abb039994..aa5ed4ef19f24cfcf68eb8282cb369317c9478d3 100644 (file)
@@ -116,7 +116,8 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
                        DiseqcSendByte(budget, 0xff);
                else {
                        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
-                       udelay(12500);
+                       mdelay(12);
+                       udelay(500);
                        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
                }
                msleep(20);
index 2293d80c6e5131fcad7feed54d7823581571ac65..f0068996ac07eb907e4042ed01be74e5c0bdd462 100644 (file)
@@ -108,7 +108,8 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
                        DiseqcSendByte(budget, 0xff);
                else {
                        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
-                       udelay(12500);
+                       mdelay(12);
+                       udelay(500);
                        saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
                }
                msleep(20);
index a30159f6fa428808ff88b76f497a5421b3fd71cc..7ca71ab96b43021d5edd3080f118b7fe2f072f44 100644 (file)
@@ -2,8 +2,6 @@
 # Makefile for the kernel character device drivers.
 #
 
-miropcm20-objs := miropcm20-rds-core.o miropcm20-radio.o
-
 obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
 obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
 obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o
@@ -14,8 +12,6 @@ obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o
 obj-$(CONFIG_RADIO_MAXIRADIO) += radio-maxiradio.o
 obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
 obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
-obj-$(CONFIG_RADIO_MIROPCM20) += miropcm20.o
-obj-$(CONFIG_RADIO_MIROPCM20_RDS) += miropcm20-rds.o
 obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
 obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
index 1ed88f3abe61084cc661a188afd829e2f54e0d79..70c65a745923f088b96e2e8d0da59e3f7865ef25 100644 (file)
@@ -493,7 +493,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
        radio->usbdev = interface_to_usbdev(intf);
        radio->curfreq = FREQ_MIN*FREQ_MUL;
        video_set_drvdata(radio->videodev, radio);
-       if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) {
+       if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) {
                warn("Could not register video device");
                video_device_release(radio->videodev);
                kfree(radio->transfer_buffer);
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
deleted file mode 100644 (file)
index 7fd7ee2..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/* Miro PCM20 radio driver for Linux radio support
- * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- * Thanks to Norberto Pellici for the ACI device interface specification
- * The API part is based on the radiotrack driver by M. Kirkwood
- * This driver relies on the aci mixer (drivers/sound/aci.c)
- * Look there for further info...
- */
-
-/* Revision history:
- *
- *   1998        Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- *   2000-09-05  Robert Siemer <Robert.Siemer@gmx.de>
- *        removed unfinished volume control (maybe adding it later again)
- *        use OSS-mixer; added stereo control
- */
-
-/* What ever you think about the ACI, version 0x07 is not very well!
- * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
- * conditions...                Robert
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include "oss/aci.h"
-#include "miropcm20-rds-core.h"
-
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
-
-struct pcm20_device {
-       unsigned long freq;
-       int muted;
-       int stereo;
-};
-
-
-static int pcm20_mute(struct pcm20_device *dev, unsigned char mute)
-{
-       dev->muted = mute;
-       return aci_write_cmd(ACI_SET_TUNERMUTE, mute);
-}
-
-static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo)
-{
-       dev->stereo = stereo;
-       return aci_write_cmd(ACI_SET_TUNERMONO, !stereo);
-}
-
-static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
-{
-       unsigned char freql;
-       unsigned char freqh;
-
-       dev->freq=freq;
-
-       freq /= 160;
-       if (!(aci_version==0x07 || aci_version>=0xb0))
-               freq /= 10;  /* I don't know exactly which version
-                             * needs this hack */
-       freql = freq & 0xff;
-       freqh = freq >> 8;
-
-       aci_rds_cmd(RDS_RESET, NULL, 0);
-       pcm20_stereo(dev, 1);
-
-       return aci_rw_cmd(ACI_WRITE_TUNE, freql, freqh);
-}
-
-static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
-{
-       /* okay, check for signal, stereo and rds here... */
-       int i;
-       unsigned char buf;
-
-       if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0)
-               return i;
-       pr_debug("check_sig: 0x%x\n", i);
-       if (i & 0x80) {
-               /* no signal from tuner */
-               *flags=0;
-               *signal=0;
-               return 0;
-       } else
-               *signal=0xffff;
-
-       if ((i=aci_rw_cmd(ACI_READ_TUNERSTEREO, -1, -1))<0)
-               return i;
-       if (i & 0x40) {
-               *flags=0;
-       } else {
-               /* stereo */
-               *flags=VIDEO_TUNER_STEREO_ON;
-               /* I can't see stereo, when forced to mono */
-               dev->stereo=1;
-       }
-
-       if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0)
-               return i;
-       if (buf & 1)
-               /* RDS available */
-               *flags|=VIDEO_TUNER_RDS_ON;
-       else
-               return 0;
-
-       if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
-               return i;
-       pr_debug("rds-signal: %d\n", buf);
-       if (buf > 15) {
-               printk("miropcm20-radio: RX strengths unexpected high...\n");
-               buf=15;
-       }
-       /* refine signal */
-       if ((*signal=SCALE(15, 0xffff, buf))==0)
-               *signal = 1;
-
-       return 0;
-}
-
-static int pcm20_do_ioctl(struct inode *inode, struct file *file,
-                         unsigned int cmd, void *arg)
-{
-       struct video_device *dev = video_devdata(file);
-       struct pcm20_device *pcm20 = dev->priv;
-       int i;
-
-       switch(cmd)
-       {
-               case VIDIOCGCAP:
-               {
-                       struct video_capability *v = arg;
-                       memset(v,0,sizeof(*v));
-                       v->type=VID_TYPE_TUNER;
-                       strcpy(v->name, "Miro PCM20");
-                       v->channels=1;
-                       v->audios=1;
-                       return 0;
-               }
-               case VIDIOCGTUNER:
-               {
-                       struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */
-                               return -EINVAL;
-                       v->rangelow=87*16000;
-                       v->rangehigh=108*16000;
-                       pcm20_getflags(pcm20, &v->flags, &v->signal);
-                       v->flags|=VIDEO_TUNER_LOW;
-                       v->mode=VIDEO_MODE_AUTO;
-                       strcpy(v->name, "FM");
-                       return 0;
-               }
-               case VIDIOCSTUNER:
-               {
-                       struct video_tuner *v = arg;
-                       if(v->tuner!=0)
-                               return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
-                       return 0;
-               }
-               case VIDIOCGFREQ:
-               {
-                       unsigned long *freq = arg;
-                       *freq = pcm20->freq;
-                       return 0;
-               }
-               case VIDIOCSFREQ:
-               {
-                       unsigned long *freq = arg;
-                       pcm20->freq = *freq;
-                       i=pcm20_setfreq(pcm20, pcm20->freq);
-                       pr_debug("First view (setfreq): 0x%x\n", i);
-                       return i;
-               }
-               case VIDIOCGAUDIO:
-               {
-                       struct video_audio *v = arg;
-                       memset(v,0, sizeof(*v));
-                       v->flags=VIDEO_AUDIO_MUTABLE;
-                       if (pcm20->muted)
-                               v->flags|=VIDEO_AUDIO_MUTE;
-                       v->mode=VIDEO_SOUND_STEREO;
-                       if (pcm20->stereo)
-                               v->mode|=VIDEO_SOUND_MONO;
-                       /* v->step=2048; */
-                       strcpy(v->name, "Radio");
-                       return 0;
-               }
-               case VIDIOCSAUDIO:
-               {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
-
-                       pcm20_mute(pcm20, !!(v->flags&VIDEO_AUDIO_MUTE));
-                       if(v->flags&VIDEO_SOUND_MONO)
-                               pcm20_stereo(pcm20, 0);
-                       if(v->flags&VIDEO_SOUND_STEREO)
-                               pcm20_stereo(pcm20, 1);
-
-                       return 0;
-               }
-               default:
-                       return -ENOIOCTLCMD;
-       }
-}
-
-static int pcm20_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, unsigned long arg)
-{
-       return video_usercopy(inode, file, cmd, arg, pcm20_do_ioctl);
-}
-
-static struct pcm20_device pcm20_unit = {
-       .freq   = 87*16000,
-       .muted  = 1,
-};
-
-static const struct file_operations pcm20_fops = {
-       .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
-       .ioctl          = pcm20_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
-};
-
-static struct video_device pcm20_radio = {
-       .name           = "Miro PCM 20 radio",
-       .fops           = &pcm20_fops,
-       .priv           = &pcm20_unit
-};
-
-static int __init pcm20_init(void)
-{
-       if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1)
-               goto video_register_device;
-
-       if(attach_aci_rds()<0)
-               goto attach_aci_rds;
-
-       printk(KERN_INFO "Miro PCM20 radio card driver.\n");
-
-       return 0;
-
- attach_aci_rds:
-       video_unregister_device(&pcm20_radio);
- video_register_device:
-       return -EINVAL;
-}
-
-MODULE_AUTHOR("Ruurd Reitsma");
-MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
-MODULE_LICENSE("GPL");
-
-static void __exit pcm20_cleanup(void)
-{
-       unload_aci_rds();
-       video_unregister_device(&pcm20_radio);
-}
-
-module_init(pcm20_init);
-module_exit(pcm20_cleanup);
diff --git a/drivers/media/radio/miropcm20-rds-core.c b/drivers/media/radio/miropcm20-rds-core.c
deleted file mode 100644 (file)
index 9428d8b..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *  Many thanks to Fred Seidel <seidel@metabox.de>, the
- *  designer of the RDS decoder hardware. With his help
- *  I was able to code this driver.
- *  Thanks also to Norberto Pellicci, Dominic Mounteney
- *  <DMounteney@pinnaclesys.com> and www.teleauskunft.de
- *  for good hints on finding Fred. It was somewhat hard
- *  to locate him here in Germany... [:
- *
- * Revision history:
- *
- *   2000-08-09  Robert Siemer <Robert.Siemer@gmx.de>
- *        RDS support for MiroSound PCM20 radio
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include "oss/aci.h"
-#include "miropcm20-rds-core.h"
-
-#define DEBUG 0
-
-static struct mutex aci_rds_mutex;
-
-#define RDS_DATASHIFT          2   /* Bit 2 */
-#define RDS_DATAMASK        (1 << RDS_DATASHIFT)
-#define RDS_BUSYMASK        0x10   /* Bit 4 */
-#define RDS_CLOCKMASK       0x08   /* Bit 3 */
-
-#define RDS_DATA(x)         (((x) >> RDS_DATASHIFT) & 1)
-
-
-#if DEBUG
-static void print_matrix(char array[], unsigned int length)
-{
-       int i, j;
-
-       for (i=0; i<length; i++) {
-               printk(KERN_DEBUG "aci-rds: ");
-               for (j=7; j>=0; j--) {
-                       printk("%d", (array[i] >> j) & 0x1);
-               }
-               if (i%8 == 0)
-                       printk(" byte-border\n");
-               else
-                       printk("\n");
-       }
-}
-#endif /* DEBUG */
-
-static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size)
-{
-       int i;
-
-       if (size != 8)
-               return -1;
-       for (i = 7; i >= 0; i--)
-               sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
-       sendbuffer[0] |= RDS_CLOCKMASK;
-
-       return 0;
-}
-
-static int rds_waitread(void)
-{
-       unsigned char byte;
-       int i=2000;
-
-       do {
-               byte=inb(RDS_REGISTER);
-               i--;
-       }
-       while ((byte & RDS_BUSYMASK) && i);
-
-       if (i) {
-               #if DEBUG
-               printk(KERN_DEBUG "rds_waitread()");
-               print_matrix(&byte, 1);
-               #endif
-               return (byte);
-       } else {
-               printk(KERN_WARNING "aci-rds: rds_waitread() timeout...\n");
-               return -1;
-       }
-}
-
-/* don't use any ..._nowait() function if you are not sure what you do... */
-
-static inline void rds_rawwrite_nowait(unsigned char byte)
-{
-       #if DEBUG
-       printk(KERN_DEBUG "rds_rawwrite()");
-       print_matrix(&byte, 1);
-       #endif
-       outb(byte, RDS_REGISTER);
-}
-
-static int rds_rawwrite(unsigned char byte)
-{
-       if (rds_waitread() >= 0) {
-               rds_rawwrite_nowait(byte);
-               return 0;
-       } else
-               return -1;
-}
-
-static int rds_write(unsigned char cmd)
-{
-       unsigned char sendbuffer[8];
-       int i;
-
-       if (byte2trans(cmd, sendbuffer, 8) != 0){
-               return -1;
-       } else {
-               for (i=0; i<8; i++) {
-                       rds_rawwrite(sendbuffer[i]);
-               }
-       }
-       return 0;
-}
-
-static int rds_readcycle_nowait(void)
-{
-       rds_rawwrite_nowait(0);
-       return rds_waitread();
-}
-
-static int rds_readcycle(void)
-{
-       if (rds_rawwrite(0) < 0)
-               return -1;
-       return rds_waitread();
-}
-
-static int rds_read(unsigned char databuffer[], int datasize)
-{
-       #define READSIZE (8*datasize)
-
-       int i,j;
-
-       if (datasize < 1)  /* nothing to read */
-               return 0;
-
-       /* to be able to use rds_readcycle_nowait()
-          I have to waitread() here */
-       if (rds_waitread() < 0)
-               return -1;
-
-       memset(databuffer, 0, datasize);
-
-       for (i=0; i< READSIZE; i++)
-               if((j=rds_readcycle_nowait()) < 0) {
-                       return -1;
-               } else {
-                       databuffer[i/8]|=(RDS_DATA(j) << (7-(i%8)));
-               }
-
-       return 0;
-}
-
-static int rds_ack(void)
-{
-       int i=rds_readcycle();
-
-       if (i < 0)
-               return -1;
-       if (i & RDS_DATAMASK) {
-               return 0;  /* ACK  */
-       } else {
-               printk(KERN_DEBUG "aci-rds: NACK\n");
-               return 1;  /* NACK */
-       }
-}
-
-int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize)
-{
-       int ret;
-
-       if (mutex_lock_interruptible(&aci_rds_mutex))
-               return -EINTR;
-
-       rds_write(cmd);
-
-       /* RDS_RESET doesn't need further processing */
-       if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize)))
-               ret = -1;
-       else
-               ret = 0;
-
-       mutex_unlock(&aci_rds_mutex);
-
-       return ret;
-}
-EXPORT_SYMBOL(aci_rds_cmd);
-
-int __init attach_aci_rds(void)
-{
-       mutex_init(&aci_rds_mutex);
-       return 0;
-}
-
-void __exit unload_aci_rds(void)
-{
-}
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/radio/miropcm20-rds-core.h b/drivers/media/radio/miropcm20-rds-core.h
deleted file mode 100644 (file)
index aeb5761..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _MIROPCM20_RDS_CORE_H_
-#define _MIROPCM20_RDS_CORE_H_
-
-extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize);
-
-#define RDS_STATUS      0x01
-#define RDS_STATIONNAME 0x02
-#define RDS_TEXT        0x03
-#define RDS_ALTFREQ     0x04
-#define RDS_TIMEDATE    0x05
-#define RDS_PI_CODE     0x06
-#define RDS_PTYTATP     0x07
-#define RDS_RESET       0x08
-#define RDS_RXVALUE     0x09
-
-extern void __exit unload_aci_rds(void);
-extern int __init attach_aci_rds(void);
-
-#endif /* _MIROPCM20_RDS_CORE_H_ */
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
deleted file mode 100644 (file)
index 3e840f7..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/* MiroSOUND PCM20 radio rds interface driver
- * (c) 2001 Robert Siemer <Robert.Siemer@gmx.de>
- * Thanks to Fred Seidel. See miropcm20-rds-core.c for further information.
- */
-
-/* Revision history:
- *
- *   2001-04-18  Robert Siemer <Robert.Siemer@gmx.de>
- *        separate file for user interface driver
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include "miropcm20-rds-core.h"
-
-static char * text_buffer;
-static int rds_users;
-
-
-static int rds_f_open(struct inode *in, struct file *fi)
-{
-       if (rds_users)
-               return -EBUSY;
-
-       lock_kernel();
-       rds_users++;
-       if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) {
-               rds_users--;
-               printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n");
-               unlock_kernel();
-               return -ENOMEM;
-       }
-
-       unlock_kernel();
-       return 0;
-}
-
-static int rds_f_release(struct inode *in, struct file *fi)
-{
-       kfree(text_buffer);
-
-       rds_users--;
-       return 0;
-}
-
-static void print_matrix(char *ch, char out[])
-{
-       int j;
-
-       for (j=7; j>=0; j--) {
-                out[7-j] = ((*ch >> j) & 0x1) + '0';
-       }
-}
-
-static ssize_t rds_f_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
-{
-//     i = sprintf(text_buffer, "length: %d, offset: %d\n", length, *offset);
-
-       char c;
-       char bits[8];
-
-       msleep(2000);
-       aci_rds_cmd(RDS_STATUS, &c, 1);
-       print_matrix(&c, bits);
-       if (copy_to_user(buffer, bits, 8))
-               return -EFAULT;
-
-/*     if ((c >> 3) & 1) {
-               aci_rds_cmd(RDS_STATIONNAME, text_buffer+1, 8);
-               text_buffer[0]  = ' ' ;
-               text_buffer[9]  = '\n';
-               return copy_to_user(buffer+8, text_buffer, 10) ? -EFAULT: 18;
-       }
-*/
-/*     if ((c >> 6) & 1) {
-               aci_rds_cmd(RDS_PTYTATP, &c, 1);
-               if ( c & 1)
-                       sprintf(text_buffer, " M");
-               else
-                       sprintf(text_buffer, " S");
-               if ((c >> 1) & 1)
-                       sprintf(text_buffer+2, " TA");
-               else
-                       sprintf(text_buffer+2, " --");
-               if ((c >> 7) & 1)
-                       sprintf(text_buffer+5, " TP");
-               else
-                       sprintf(text_buffer+5, " --");
-               sprintf(text_buffer+8, " %2d\n", (c >> 2) & 0x1f);
-               return copy_to_user(buffer+8, text_buffer, 12) ? -EFAULT: 20;
-       }
-*/
-
-       if ((c >> 4) & 1) {
-               aci_rds_cmd(RDS_TEXT, text_buffer, 65);
-               text_buffer[0]  = ' ' ;
-               text_buffer[65] = '\n';
-               return copy_to_user(buffer+8, text_buffer,66) ? -EFAULT : 66+8;
-       } else {
-               put_user('\n', buffer+8);
-               return 9;
-       }
-}
-
-static const struct file_operations rds_fops = {
-       .owner          = THIS_MODULE,
-       .read           = rds_f_read,
-       .open           = rds_f_open,
-       .release        = rds_f_release
-};
-
-static struct miscdevice rds_miscdev = {
-       .minor          = MISC_DYNAMIC_MINOR,
-       .name           = "radiotext",
-       .fops           = &rds_fops,
-};
-
-static int __init miropcm20_rds_init(void)
-{
-       return misc_register(&rds_miscdev);
-}
-
-static void __exit miropcm20_rds_cleanup(void)
-{
-       misc_deregister(&rds_miscdev);
-}
-
-module_init(miropcm20_rds_init);
-module_exit(miropcm20_rds_cleanup);
-MODULE_LICENSE("GPL");
index eba9209b30240a3212d707da8bb3e79f54d67f9f..1f064f4b32df6945c0d20262471784ddb94f7204 100644 (file)
@@ -426,8 +426,7 @@ static int __init rtrack_init(void)
 
        rtrack_radio.priv=&rtrack_unit;
 
-       if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr)==-1)
-       {
+       if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 2);
                return -EINVAL;
        }
index 3fe5504428c5b0099fa7aeba0a99bf91c509a4b8..628c689e3ffe1779c422bdbc11883207a15d7c9e 100644 (file)
@@ -394,8 +394,7 @@ static int __init aztech_init(void)
        mutex_init(&lock);
        aztech_radio.priv=&aztech_unit;
 
-       if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1)
-       {
+       if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io,2);
                return -EINVAL;
        }
index 6166e726ed7203908adcd908be14199452c744aa..04c3698d32e4b77e3b28f81d104b0dcbe23dfe59 100644 (file)
@@ -682,7 +682,7 @@ static int __init cadet_init(void)
        }
        if (!request_region(io,2,"cadet"))
                goto fail;
-       if(video_register_device(&cadet_radio,VFL_TYPE_RADIO,radio_nr)==-1) {
+       if (video_register_device(&cadet_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io,2);
                goto fail;
        }
index 36e754e3ffb2011cbdba08e88cdfce11cab7ec0f..5cd7f032298d28e1af01a35342b9f332f8e9faa7 100644 (file)
@@ -425,7 +425,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
        }
        *devradio = vdev_template;
 
-       if ( video_register_device( devradio, VFL_TYPE_RADIO , nr_radio) == -1 ) {
+       if (video_register_device(devradio, VFL_TYPE_RADIO, nr_radio) < 0) {
                kfree( devradio );
                goto err_video;
        }
index 2b1a6221de6d5f2108ff8ad0aaab04e515082002..0a0f956bb308387dc7c9334f150bef5b855448b9 100644 (file)
@@ -612,8 +612,7 @@ static int __init gemtek_init(void)
 
        gemtek_radio.priv = &gemtek_unit;
 
-       if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO,
-               radio_nr) == -1) {
+       if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 1);
                return -EBUSY;
        }
index 0ada1c697e8a4834690ee2b442dcb87128f694fc..9ef0a763eeb72a54570324a7b3112a549cdfdcb6 100644 (file)
@@ -409,8 +409,7 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
        video_set_drvdata(maestro_radio_inst, radio_unit);
        pci_set_drvdata(pdev, maestro_radio_inst);
 
-       retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO,
-               radio_nr);
+       retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO, radio_nr);
        if (retval) {
                printk(KERN_ERR "can't register video device!\n");
                goto errfr1;
index 43c75497dc499ea02fdeebabfd0d57568458e896..0cc6fcb041fd9773c56088ed50de1406f8030a27 100644 (file)
@@ -156,28 +156,28 @@ static void set_freq(__u16 io, __u32 freq)
 {
        unsigned long int si;
        int bl;
-       int data = FREQ2BITS(freq);
+       int val = FREQ2BITS(freq);
 
        /* TEA5757 shift register bits (see pdf) */
 
-       outbit(0,io); // 24  search
-       outbit(1,io); // 23  search up/down
+       outbit(0, io); /* 24  search */
+       outbit(1, io); /* 23  search up/down */
 
-       outbit(0,io); // 22  stereo/mono
+       outbit(0, io); /* 22  stereo/mono */
 
-       outbit(0,io); // 21  band
-       outbit(0,io); // 20  band (only 00=FM works I think)
+       outbit(0, io); /* 21  band */
+       outbit(0, io); /* 20  band (only 00=FM works I think) */
 
-       outbit(0,io); // 19  port ?
-       outbit(0,io); // 18  port ?
+       outbit(0, io); /* 19  port ? */
+       outbit(0, io); /* 18  port ? */
 
-       outbit(0,io); // 17  search level
-       outbit(0,io); // 16  search level
+       outbit(0, io); /* 17  search level */
+       outbit(0, io); /* 16  search level */
 
        si = 0x8000;
-       for (bl = 1; bl <= 16 ; bl++) {
-               outbit(data & si,io);
-               si >>=1;
+       for (bl = 1; bl <= 16; bl++) {
+               outbit(val & si, io);
+               si >>= 1;
        }
 
        dprintk(1, "Radio freq set to %d.%02d MHz\n",
@@ -410,7 +410,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d
        mutex_init(&radio_unit.lock);
        maxiradio_radio.priv = &radio_unit;
 
-       if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
+       if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                printk("radio-maxiradio: can't register device!");
                goto err_out_free_region;
        }
index e2dde0807268374f404db090b6c0b412548d0b40..6d820e2481e7cc0e9e8b1d02a93f974289e35ce5 100644 (file)
@@ -332,8 +332,7 @@ static int __init rtrack2_init(void)
        rtrack2_radio.priv=&rtrack2_unit;
 
        spin_lock_init(&lock);
-       if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr)==-1)
-       {
+       if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 4);
                return -EINVAL;
        }
index bb5d92f104af000177afab5c202652adafc7a0f8..0d478f54a90770810198a3e14551ac287b807353 100644 (file)
@@ -377,7 +377,7 @@ static int __init fmi_init(void)
 
        mutex_init(&lock);
 
-       if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) == -1) {
+       if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 2);
                return -EINVAL;
        }
index a4984ff87c9c8328bd7e59b92022adf994d74430..16c7ef20265c4c34e3782baead264700797923dd 100644 (file)
@@ -1694,8 +1694,8 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
        INIT_DELAYED_WORK(&radio->work, si470x_work);
 
        /* register video device */
-       if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
-               retval = -EIO;
+       retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+       if (retval) {
                printk(KERN_WARNING DRIVER_NAME
                                ": Could not register video device\n");
                goto err_all;
index cefa44fc5aed84a42900591d99ac40a0878012fc..0876fecc5f275de8bf61bf1ab5d3713c90349c0f 100644 (file)
@@ -405,8 +405,7 @@ static int __init terratec_init(void)
 
        spin_lock_init(&lock);
 
-       if(video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr)==-1)
-       {
+       if (video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io,2);
                return -EINVAL;
        }
index d70172d23edb431f0460dbecd2a562a740a28e9e..193161956253422121f906d46729013c114716a4 100644 (file)
@@ -378,8 +378,7 @@ static int __init trust_init(void)
                printk(KERN_ERR "trust: port 0x%x already in use\n", io);
                return -EBUSY;
        }
-       if(video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr)==-1)
-       {
+       if (video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 2);
                return -EINVAL;
        }
index 9f17a332fa1173b5efa41dd298b84d614d6216e6..51d57ed3b3e12a5db805f09cb93acc9c39560e7c 100644 (file)
@@ -446,8 +446,7 @@ static int __init zoltrix_init(void)
                return -EBUSY;
        }
 
-       if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) == -1)
-       {
+       if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 2);
                return -EINVAL;
        }
index bbc6f8b82297e7a62dfc7d1e6ada130dff48d2d0..ef7c8d3ffb18bba4e3930668285a30883fc1fc10 100644 (file)
@@ -20,6 +20,8 @@ ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
   obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o
 endif
 
+obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+
 obj-$(CONFIG_VIDEO_BT848) += bt8xx/
 obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
 obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
@@ -85,8 +87,6 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
 obj-$(CONFIG_VIDEO_DPC) += dpc7146.o
 obj-$(CONFIG_TUNER_3036) += tuner-3036.o
 
-obj-$(CONFIG_VIDEO_TUNER) += tuner.o
-
 obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
 obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
 obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
index ed9a50f189fc8325cfd52f470997c55d10b69a16..018f72b8e3e201cf45c2abb07d41c8aa6ec7a0cb 100644 (file)
@@ -7,6 +7,7 @@ config VIDEO_AU0828
        select DVB_AU8522 if !DVB_FE_CUSTOMIZE
        select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
        select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
        ---help---
          This is a video4linux driver for Auvitek's USB device.
 
index 443e590097628873a7f6ad490ecbcb15a97dbce4..ed48908a90340666f0726a77fc8b59c48e3e758f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Auvitek USB bridge
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -38,6 +38,9 @@ struct au0828_board au0828_boards[] = {
        [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
                .name   = "DViCO FusionHDTV USB",
        },
+       [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
+               .name = "Hauppauge Woodbury",
+       },
 };
 
 /* Tuner callback function for au0828 boards. Currently only needed
@@ -115,6 +118,7 @@ void au0828_card_setup(struct au0828_dev *dev)
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
                if (dev->i2c_rc == 0)
                        hauppauge_eeprom(dev, eeprom+0xa0);
                break;
@@ -134,6 +138,7 @@ void au0828_gpio_setup(struct au0828_dev *dev)
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
                /* GPIO's
                 * 4 - CS5340
                 * 5 - AU8522 Demodulator
@@ -205,6 +210,8 @@ struct usb_device_id au0828_usb_id_table [] = {
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
        { USB_DEVICE(0x2040, 0x7281),
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+       { USB_DEVICE(0x2040, 0x8200),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
        { },
 };
 
index c37f5fd0fa801b2f0932258687dd8bc62ab5df77..48a1882c2b6bec47464cb48992d3b3af3081a6ea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Auvitek USB bridge
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -24,3 +24,4 @@
 #define AU0828_BOARD_HAUPPAUGE_HVR850  2
 #define AU0828_BOARD_DVICO_FUSIONHDTV7 3
 #define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL     4
+#define AU0828_BOARD_HAUPPAUGE_WOODBURY        5
index 54bfc0f05295571eca21b3d8595c7443e940ca0f..d856de9f742f03521d62af59f0b91d0e441089e6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Auvitek USB bridge
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -252,5 +252,5 @@ module_init(au0828_init);
 module_exit(au0828_exit);
 
 MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
-MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
index 584a83a94a2a276501f77864321c67f1ce065ca2..ba94be7e0ac1cdc65fb767d28cb8466e85cf9767 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Auvitek USB bridge
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
 #include "au8522.h"
 #include "xc5000.h"
 #include "mxl5007t.h"
+#include "tda18271.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -38,6 +39,15 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 static struct au8522_config hauppauge_hvr950q_config = {
        .demod_address = 0x8e >> 1,
        .status_mode   = AU8522_DEMODLOCKING,
+       .qam_if        = AU8522_IF_6MHZ,
+       .vsb_if        = AU8522_IF_6MHZ,
+};
+
+static struct au8522_config hauppauge_woodbury_config = {
+       .demod_address = 0x8e >> 1,
+       .status_mode   = AU8522_DEMODLOCKING,
+       .qam_if        = AU8522_IF_4MHZ,
+       .vsb_if        = AU8522_IF_3_25MHZ,
 };
 
 static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
@@ -51,6 +61,10 @@ static struct mxl5007t_config mxl5007t_hvr950q_config = {
        .if_freq_hz = MxL_IF_6_MHZ,
 };
 
+static struct tda18271_config hauppauge_woodbury_tunerconfig = {
+       .gate    = TDA18271_GATE_DIGITAL,
+};
+
 /*-------------------------------------------------------------------*/
 static void urb_completion(struct urb *purb)
 {
@@ -357,6 +371,15 @@ int au0828_dvb_register(struct au0828_dev *dev)
                                   &dev->i2c_adap, 0x60,
                                   &mxl5007t_hvr950q_config);
                break;
+       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &hauppauge_woodbury_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL)
+                       dvb_attach(tda18271_attach, dvb->frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &hauppauge_woodbury_tunerconfig);
+               break;
        default:
                printk(KERN_WARNING "The frontend of your DVB/ATSC card "
                       "isn't supported yet\n");
index 741a4937b050c05ae92e2eee1a534f89414f3d1f..d618fbaade1bcc3d31828e32d65e7cff310049be 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Auvitek AU0828 USB bridge
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 39827550891c744ba87f1b7fb7d84513fc0be5e2..1e87fa0c684261db53f58702a5a94a1a299a8532 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Auvitek USB bridge
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 7beb571798e5d04de72ad9ce45f55d6ed8aa0b55..4f10ff300135fcedec9f9c5d5362bc2b7ec0cb65 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Auvitek AU0828 USB bridge
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 1c56ae92ce7482c68cb6445031458a71332906b9..6081edc362df4fb8adad2d87794cc2ba8990bb21 100644 (file)
@@ -3144,8 +3144,9 @@ static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
 
 static void flyvideo_gpio(struct bttv *btv)
 {
-       int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821;
-       int tuner=UNSET,ttype;
+       int gpio, has_remote, has_radio, is_capture_only;
+       int is_lr90, has_tda9820_tda9821;
+       int tuner_type = UNSET, ttype;
 
        gpio_inout(0xffffff, 0);
        udelay(8);  /* without this we would see the 0x1800 mask */
@@ -3163,20 +3164,26 @@ static void flyvideo_gpio(struct bttv *btv)
         * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
         * Note: Some bits are Audio_Mask !
         */
-       ttype=(gpio&0x0f0000)>>16;
-       switch(ttype) {
-       case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */
+       ttype = (gpio & 0x0f0000) >> 16;
+       switch (ttype) {
+       case 0x0:
+               tuner_type = 2;  /* NTSC, e.g. TPI8NSR11P */
                break;
-       case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */
+       case 0x2:
+               tuner_type = 39; /* LG NTSC (newer TAPC series) TAPC-H701P */
                break;
-       case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
+       case 0x4:
+               tuner_type = 5;  /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
                break;
-       case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */
+       case 0x6:
+               tuner_type = 37; /* LG PAL (newer TAPC series) TAPC-G702P */
                break;
-               case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
+       case 0xC:
+               tuner_type = 3;  /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
                break;
        default:
                printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
+               break;
        }
 
        has_remote          =   gpio & 0x800000;
@@ -3189,23 +3196,26 @@ static void flyvideo_gpio(struct bttv *btv)
        /*
         * gpio & 0x001000    output bit for audio routing */
 
-       if(is_capture_only)
-               tuner = TUNER_ABSENT; /* No tuner present */
+       if (is_capture_only)
+               tuner_type = TUNER_ABSENT; /* No tuner present */
 
        printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
-              btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio);
+               btv->c.nr, has_radio ? "yes" : "no ",
+               has_remote ? "yes" : "no ", tuner_type, gpio);
        printk(KERN_INFO "bttv%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
-               btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
-               is_capture_only?"yes":"no ");
+               btv->c.nr, is_lr90 ? "yes" : "no ",
+               has_tda9820_tda9821 ? "yes" : "no ",
+               is_capture_only ? "yes" : "no ");
 
-       if (tuner != UNSET) /* only set if known tuner autodetected, else let insmod option through */
-               btv->tuner_type = tuner;
+       if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
+               btv->tuner_type = tuner_type;
        btv->has_radio = has_radio;
 
        /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
         * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
         * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
-       if(has_tda9820_tda9821) btv->audio_mode_gpio = lt9415_audio;
+       if (has_tda9820_tda9821)
+               btv->audio_mode_gpio = lt9415_audio;
        /* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */
 }
 
@@ -3962,7 +3972,7 @@ static int tuner_1_table[] = {
 
 static void __devinit avermedia_eeprom(struct bttv *btv)
 {
-       int tuner_make,tuner_tv_fm,tuner_format,tuner=0;
+       int tuner_make, tuner_tv_fm, tuner_format, tuner_type = 0;
 
        tuner_make      = (eeprom_data[0x41] & 0x7);
        tuner_tv_fm     = (eeprom_data[0x41] & 0x18) >> 3;
@@ -3970,24 +3980,24 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
        btv->has_remote = (eeprom_data[0x42] & 0x01);
 
        if (tuner_make == 0 || tuner_make == 2)
-               if(tuner_format <=0x0a)
-                       tuner = tuner_0_table[tuner_format];
+               if (tuner_format <= 0x0a)
+                       tuner_type = tuner_0_table[tuner_format];
        if (tuner_make == 1)
-               if(tuner_format <=9)
-                       tuner = tuner_1_table[tuner_format];
+               if (tuner_format <= 9)
+                       tuner_type = tuner_1_table[tuner_format];
 
        if (tuner_make == 4)
-               if(tuner_format == 0x09)
-                       tuner = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
+               if (tuner_format == 0x09)
+                       tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
 
        printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
-               btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]);
-       if(tuner) {
-               btv->tuner_type=tuner;
-               printk("%d",tuner);
+               btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
+       if (tuner_type) {
+               btv->tuner_type = tuner_type;
+               printk(KERN_CONT "%d", tuner_type);
        } else
-               printk("Unknown type");
-       printk(" radio:%s remote control:%s\n",
+               printk(KERN_CONT "Unknown type");
+       printk(KERN_CONT " radio:%s remote control:%s\n",
               tuner_tv_fm     ? "yes" : "no",
               btv->has_remote ? "yes" : "no");
 }
@@ -4029,7 +4039,8 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin)
 
        gpio_inout(mask,mask);
        gpio_bits(mask,0);
-       udelay(2500);
+       mdelay(2);
+       udelay(500);
        gpio_bits(mask,mask);
 
        if (bttv_gpio)
index 85bf31ab8789db097df2f29b0aaf77f8578b86f8..6ae4cc860efedebdfdfc66babb7c683908417bd8 100644 (file)
@@ -96,7 +96,6 @@ static unsigned int irq_iswitch;
 static unsigned int uv_ratio    = 50;
 static unsigned int full_luma_range;
 static unsigned int coring;
-extern int no_overlay;
 
 /* API features (turn on/off stuff for testing) */
 static unsigned int v4l2        = 1;
index 649682aac1acebf4ff3a4bc45033f897258f875f..5b1b8e4c78baf602b3c84511b506db451a0f5aad 100644 (file)
@@ -244,7 +244,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
                  const struct bttv_format *fmt, struct bttv_overlay *ov,
                  int skip_even, int skip_odd)
 {
-       int dwords,rc,line,maxy,start,end,skip,nskips;
+       int dwords, rc, line, maxy, start, end;
+       unsigned skip, nskips;
        struct btcx_skiplist *skips;
        __le32 *rp;
        u32 ri,ra;
index 08ef54a22c9e7e843be5b8d8faa5a9789aa4235e..b4d940b2e44744777fa43a30d0d1f0fc4911b9bd 100644 (file)
@@ -266,6 +266,11 @@ extern struct bus_type bttv_sub_bus_type;
 int bttv_sub_add_device(struct bttv_core *core, char *name);
 int bttv_sub_del_devices(struct bttv_core *core);
 
+/* ---------------------------------------------------------- */
+/* bttv-cards.c                                               */
+
+extern int no_overlay;
+
 /* ---------------------------------------------------------- */
 /* bttv-driver.c                                              */
 
index f42701f82e7fe72009bd8391672bbb40d80d306b..3324ab38f58c3b395f617e00c9a9c4bd957ff820 100644 (file)
@@ -184,12 +184,12 @@ btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
 }
 
 void
-btcx_calc_skips(int line, int width, unsigned int *maxy,
+btcx_calc_skips(int line, int width, int *maxy,
                struct btcx_skiplist *skips, unsigned int *nskips,
                const struct v4l2_clip *clips, unsigned int nclips)
 {
        unsigned int clip,skip;
-       int end,maxline;
+       int end, maxline;
 
        skip=0;
        maxline = 9999;
index 861bc8112824959298bf40c422b3782984f2deee..f8bc6e8e7b5198d1bb8dade28f803fc75a2e161f 100644 (file)
@@ -23,7 +23,7 @@ int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
 int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
               unsigned int n, int mask);
 void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
-void btcx_calc_skips(int line, int width, unsigned int *maxy,
+void btcx_calc_skips(int line, int width, int *maxy,
                     struct btcx_skiplist *skips, unsigned int *nskips,
                     const struct v4l2_clip *clips, unsigned int nclips);
 
index d3b3268bace8795dcde4e8d6f1e002d61fa24b7f..6e39e253ce5361a5d99644e7b93d96474759b966 100644 (file)
@@ -946,8 +946,7 @@ static int init_bwqcam(struct parport *port)
 
        printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
 
-       if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
-       {
+       if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                parport_unregister_device(qcam->pdev);
                kfree(qcam);
                return -ENODEV;
index fe9379b282d36b10e7b3043ab46f1f243a2fa8ed..7f6c6b4bec10e7f3470d8452e1ee71b9cd90ab0e 100644 (file)
@@ -787,8 +787,7 @@ static int init_cqcam(struct parport *port)
 
        parport_release(qcam->pdev);
 
-       if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
-       {
+       if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
                       qcam->pport->name);
                parport_unregister_device(qcam->pdev);
index dc8cc6115e2f13f1eea59c69d177afd5d051ecdd..a661800b0e69fdefec154a23b69462fc448da2c1 100644 (file)
@@ -3955,7 +3955,7 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve
        camera->lowlevel_data = lowlevel;
 
        /* register v4l device */
-       if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+       if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                kfree(camera);
                printk(KERN_DEBUG "video_register_device failed\n");
                return NULL;
index 515c8b57a60d8772c7b156fb1e0fd11c02f9d2d3..eb9f15cd4c45c9884170fb9599e99f6544e4e288 100644 (file)
@@ -1024,7 +1024,6 @@ static int ioctl_queryctrl(void *arg,struct camera_data *cam)
                if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&
                   cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){
                        // Maximum 15fps
-                       int i;
                        for(i=0; i<c->maximum; ++i) {
                                if(framerate_controls[i].value ==
                                   CPIA2_VP_FRAMERATE_15) {
@@ -1959,8 +1958,7 @@ int cpia2_register_camera(struct camera_data *cam)
        reset_camera_struct_v4l(cam);
 
        /* register v4l device */
-       if (video_register_device
-           (cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+       if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                ERR("video_register_device failed\n");
                video_device_release(cam->vdev);
                return -ENODEV;
index 834b9248242ecc51e3526c526ccc3f153a45aca8..e996a4e3123a3a01a2cae74a152d6131f79e594a 100644 (file)
@@ -32,7 +32,7 @@ int cx18_av_loadfw(struct cx18 *cx)
        u32 v;
        const u8 *ptr;
        int i;
-       int retries = 0;
+       int retries1 = 0;
 
        if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
                CX18_ERR("unable to open firmware %s\n", FWFILE);
@@ -41,7 +41,7 @@ int cx18_av_loadfw(struct cx18 *cx)
 
        /* The firmware load often has byte errors, so allow for several
           retries, both at byte level and at the firmware load level. */
-       while (retries < 5) {
+       while (retries1 < 5) {
                cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
                cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
 
@@ -57,9 +57,9 @@ int cx18_av_loadfw(struct cx18 *cx)
                for (i = 0; i < size; i++) {
                        u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
                        u32 value = 0;
-                       int retries;
+                       int retries2;
 
-                       for (retries = 0; retries < 5; retries++) {
+                       for (retries2 = 0; retries2 < 5; retries2++) {
                                cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
                                udelay(10);
                                value = cx18_av_read4(cx, CXADEC_DL_CTL);
@@ -69,18 +69,18 @@ int cx18_av_loadfw(struct cx18 *cx)
                                   the address.  We can only write the lower
                                   address byte of the address. */
                                if ((value & 0x3F00) != (dl_control & 0x3F00)) {
-                                       retries = 5;
+                                       retries2 = 5;
                                        break;
                                }
                        }
-                       if (retries >= 5)
+                       if (retries2 >= 5)
                                break;
                }
                if (i == size)
                        break;
-               retries++;
+               retries1++;
        }
-       if (retries >= 5) {
+       if (retries1 >= 5) {
                CX18_ERR("unable to load firmware %s\n", FWFILE);
                release_firmware(fw);
                return -EIO;
index 22434aadde316183afcf0165d659361befda60eb..bd18afebbf860565292b212bde83361486761d8e 100644 (file)
@@ -74,9 +74,9 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
                                     -1, -1, -1, -1, -1, -1, -1, -1,
                                     -1, -1, -1, -1, -1, -1, -1, -1 };
 
-static int cardtype_c = 1;
-static int tuner_c = 1;
-static int radio_c = 1;
+static unsigned cardtype_c = 1;
+static unsigned tuner_c = 1;
+static unsigned radio_c = 1;
 static char pal[] = "--";
 static char secam[] = "--";
 static char ntsc[] = "-";
index cae38985b1313a306f4dedbe8c656f6208b737ca..1e420a804fc96ddf24c3632b83e136d8755dc163 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  cx18 functions for DVB support
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index d6a6ccda79a9067f2040e90a782c2265a0babfd7..bf8d8f6f54558ab3264dd783ad13dc9246632b40 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  cx18 functions for DVB support
  *
- *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 25114a5cbd57d0f58c19c7461b269421717a61c5..ab218315c84bb384fd71865392254c54fe9f9fbb 100644 (file)
@@ -61,7 +61,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
                CX18_WARN("Ack struct = %d for %s\n",
                        mb->args[2], s->name);
        id = read_enc(off);
-       buf = cx18_queue_find_buf(s, id, read_enc(off + 4));
+       buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4));
        CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
        if (buf) {
                cx18_buf_sync_for_cpu(s, buf);
index 6990b77c6200ab57ab29bb1a2962a67930ff1392..dbe792ac30015d68c760a1d42b2731f7a043042e 100644 (file)
@@ -78,12 +78,13 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
        return buf;
 }
 
-struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
        u32 bytesused)
 {
        struct cx18 *cx = s->cx;
        struct list_head *p;
 
+       spin_lock(&s->qlock);
        list_for_each(p, &s->q_free.list) {
                struct cx18_buffer *buf =
                        list_entry(p, struct cx18_buffer, list);
@@ -92,114 +93,48 @@ struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
                        continue;
                buf->bytesused = bytesused;
                /* the transport buffers are handled differently,
-                  so there is no need to move them to the full queue */
-               if (s->type == CX18_ENC_STREAM_TYPE_TS)
-                       return buf;
-               s->q_free.buffers--;
-               s->q_free.length -= s->buf_size;
-               s->q_full.buffers++;
-               s->q_full.length += s->buf_size;
-               s->q_full.bytesused += buf->bytesused;
-               list_move_tail(&buf->list, &s->q_full.list);
+                  they are not moved to the full queue */
+               if (s->type != CX18_ENC_STREAM_TYPE_TS) {
+                       s->q_free.buffers--;
+                       s->q_free.length -= s->buf_size;
+                       s->q_full.buffers++;
+                       s->q_full.length += s->buf_size;
+                       s->q_full.bytesused += buf->bytesused;
+                       list_move_tail(&buf->list, &s->q_full.list);
+               }
+               spin_unlock(&s->qlock);
                return buf;
        }
+       spin_unlock(&s->qlock);
        CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name);
        return NULL;
 }
 
-static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from,
-               struct cx18_queue *to, int clear, int full)
-{
-       struct cx18_buffer *buf =
-               list_entry(from->list.next, struct cx18_buffer, list);
-
-       list_move_tail(from->list.next, &to->list);
-       from->buffers--;
-       from->length -= s->buf_size;
-       from->bytesused -= buf->bytesused - buf->readpos;
-       /* special handling for q_free */
-       if (clear)
-               buf->bytesused = buf->readpos = buf->b_flags = 0;
-       else if (full) {
-               /* special handling for stolen buffers, assume
-                  all bytes are used. */
-               buf->bytesused = s->buf_size;
-               buf->readpos = buf->b_flags = 0;
-       }
-       to->buffers++;
-       to->length += s->buf_size;
-       to->bytesused += buf->bytesused - buf->readpos;
-}
-
-/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
-   If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
-   If 'steal' != NULL, then buffers may also taken from that queue if
-   needed.
-
-   The buffer is automatically cleared if it goes to the free queue. It is
-   also cleared if buffers need to be taken from the 'steal' queue and
-   the 'from' queue is the free queue.
-
-   When 'from' is q_free, then needed_bytes is compared to the total
-   available buffer length, otherwise needed_bytes is compared to the
-   bytesused value. For the 'steal' queue the total available buffer
-   length is always used.
-
-   -ENOMEM is returned if the buffers could not be obtained, 0 if all
-   buffers where obtained from the 'from' list and if non-zero then
-   the number of stolen buffers is returned. */
-static int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from,
-                          struct cx18_queue *steal, struct cx18_queue *to,
-                          int needed_bytes)
+/* Move all buffers of a queue to q_free, while flushing the buffers */
+static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q)
 {
        unsigned long flags;
-       int rc = 0;
-       int from_free = from == &s->q_free;
-       int to_free = to == &s->q_free;
-       int bytes_available;
-
-       spin_lock_irqsave(&s->qlock, flags);
-       if (needed_bytes == 0) {
-               from_free = 1;
-               needed_bytes = from->length;
-       }
-
-       bytes_available = from_free ? from->length : from->bytesused;
-       bytes_available += steal ? steal->length : 0;
+       struct cx18_buffer *buf;
 
-       if (bytes_available < needed_bytes) {
-               spin_unlock_irqrestore(&s->qlock, flags);
-               return -ENOMEM;
-       }
-       if (from_free) {
-               u32 old_length = to->length;
+       if (q == &s->q_free)
+               return;
 
-               while (to->length - old_length < needed_bytes) {
-                       if (list_empty(&from->list))
-                               from = steal;
-                       if (from == steal)
-                               rc++;   /* keep track of 'stolen' buffers */
-                       cx18_queue_move_buf(s, from, to, 1, 0);
-               }
-       } else {
-               u32 old_bytesused = to->bytesused;
-
-               while (to->bytesused - old_bytesused < needed_bytes) {
-                       if (list_empty(&from->list))
-                               from = steal;
-                       if (from == steal)
-                               rc++;   /* keep track of 'stolen' buffers */
-                       cx18_queue_move_buf(s, from, to, to_free, rc);
-               }
+       spin_lock_irqsave(&s->qlock, flags);
+       while (!list_empty(&q->list)) {
+               buf = list_entry(q->list.next, struct cx18_buffer, list);
+               list_move_tail(q->list.next, &s->q_free.list);
+               buf->bytesused = buf->readpos = buf->b_flags = 0;
+               s->q_free.buffers++;
+               s->q_free.length += s->buf_size;
        }
+       cx18_queue_init(q);
        spin_unlock_irqrestore(&s->qlock, flags);
-       return rc;
 }
 
 void cx18_flush_queues(struct cx18_stream *s)
 {
-       cx18_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
-       cx18_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
+       cx18_queue_flush(s, &s->q_io);
+       cx18_queue_flush(s, &s->q_full);
 }
 
 int cx18_stream_alloc(struct cx18_stream *s)
@@ -214,10 +149,10 @@ int cx18_stream_alloc(struct cx18_stream *s)
                s->name, s->buffers, s->buf_size,
                s->buffers * s->buf_size / 1024);
 
-       if (((char *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
-                               (char *)cx->scb) > SCB_RESERVED_SIZE) {
-               unsigned bufsz = (((char *)cx->scb) + SCB_RESERVED_SIZE -
-                                       ((char *)cx->scb->cpu_mdl));
+       if (((char __iomem *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
+                               (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) {
+               unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE -
+                                       ((char __iomem *)cx->scb->cpu_mdl));
 
                CX18_ERR("Too many buffers, cannot fit in SCB area\n");
                CX18_ERR("Max buffers = %zd\n",
index 91423b9863a43a402d6fe7c6efe5b347d059d355..7f93bb13c09f6b53de8848451475e00c5ea6b8c1 100644 (file)
@@ -46,7 +46,7 @@ void cx18_queue_init(struct cx18_queue *q);
 void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
        struct cx18_queue *q);
 struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
-struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
        u32 bytesused);
 void cx18_flush_queues(struct cx18_stream *s);
 
index 8118091568fc62ee711bc88d06c5c193751df4a7..7b0e8c01692efab12f289c2fc3f843cdff733548 100644 (file)
@@ -4,7 +4,7 @@
  *
  *    (c) 2004 Jelle Foks <jelle@foks.8m.com>
  *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
- *    (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *    (c) 2008 Steven Toth <stoth@linuxtv.org>
  *      - CX23885/7/8 support
  *
  *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
index a19de850955dbacb9c69fa1d1592ed9f1d959291..c36d3f632104a22c37b408805f056ccddec936c8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Conexant CX23885 PCIe bridge
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 6286a9cf957ef5751492ccf8d8ca8e902a8c8f53..25fb09938744b67fdcece9661983e827daeda1db 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Conexant CX23885 PCIe bridge
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
 #include "cx23885.h"
 
 MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
-MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
 
 static unsigned int debug;
index 0a2e6558cd669aee9377cd68567fe246eb53cdff..291b9d008da87f17897390b09cbcbf785201d5a1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Conexant CX23885 PCIe bridge
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index c6bb0a05bc1c147fd61527ab3a47bdf790577924..f98e476e96172c9aa8b3865e437b07d98d7fa548 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Conexant CX23885 PCIe bridge
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index bdd11bc513adc3d07c66547ec871c666af0180a3..20b68a23626064ccea4a5f94db8c68beff4fd6c0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Conexant CX23885 PCIe bridge
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e36e3fcae2fbfb21b5de18d562193668fa4babbc..35e61cd112fc8c09be763df9b14eca51ff26e2ad 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Conexant CX23885 PCIe bridge
  *
- *  Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index ad2235dab5b1450c1f958973556bce77faf5febf..6047c78d84bf5c2b26576e734e73e04f2724eb6c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Conexant CX23885 PCIe bridge
  *
- *  Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -41,7 +41,7 @@
 #endif
 
 MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
-MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
 
 /* ------------------------------------------------------------------ */
index 00dfdc89d64128f26b21f79999743a614c2141b5..e23d97c071e05d49c2ad15dafc10cc33e15d636a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Conexant CX23885 PCIe bridge
  *
- *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 209d3bcb5dbb9a3de89978117aeaf336862ae111..4da8cd74f00e6e17b6301a03d0c9a31f873a587e 100644 (file)
@@ -13,7 +13,7 @@
  * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca>
  * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>.
  *
- * CX23885 support by Steven Toth <stoth@hauppauge.com>.
+ * CX23885 support by Steven Toth <stoth@linuxtv.org>.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 48f4b92a8f8b09a2f6b07418660ce2d7ce02e64f..79faedf585217f0e5cda3ac6902ce567dc9918c7 100644 (file)
@@ -403,6 +403,7 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
        ret = request_firmware(&fw, "dabusb/bitstream.bin", &s->usbdev->dev);
        if (ret) {
                err("Failed to load \"dabusb/bitstream.bin\": %d\n", ret);
+               kfree(b);
                return ret;
        }
 
index 2d170d101c2197f348f1e2c2a111891144b46bd2..8db2a05bf9c542544b3a3bf9bc1c4fdd5cc217bf 100644 (file)
@@ -2588,6 +2588,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        cam->v4ldev->fops = &et61x251_fops;
        cam->v4ldev->minor = video_nr[dev_nr];
        cam->v4ldev->release = video_device_release;
+       cam->v4ldev->parent = &udev->dev;
        video_set_drvdata(cam->v4ldev, cam);
 
        init_completion(&cam->probe);
index cd3a3f5829b273d17a277e7f9134f3e0cf54cc44..4d9f4cc255a9540fe13e1fb36806f36cd7af6f7e 100644 (file)
@@ -124,7 +124,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
        struct usb_device *dev = gspca_dev->dev;
 
 #ifdef GSPCA_DEBUG
-       if (len > sizeof gspca_dev->usb_buf) {
+       if (len > USB_BUF_SZ) {
                err("reg_r: buffer overflow");
                return;
        }
@@ -164,7 +164,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
        struct usb_device *dev = gspca_dev->dev;
 
 #ifdef GSPCA_DEBUG
-       if (len > sizeof gspca_dev->usb_buf) {
+       if (len > USB_BUF_SZ) {
                err("reg_w: buffer overflow");
                return;
        }
@@ -731,13 +731,13 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
        reg_w_val(gspca_dev, 0x0000, 0x00);
        /* wait for completion */
        retry = 50;
-       while (retry--) {
+       do {
                reg_r(gspca_dev, 0x0002, 1);
                                                        /* 0x07 until 0x00 */
                if (gspca_dev->usb_buf[0] == 0x00)
                        break;
                reg_w_val(gspca_dev, 0x0053, 0x00);
-       }
+       } while (--retry);
        if (retry == 0)
                PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
        /* send the qtable now */
@@ -826,8 +826,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        cx11646_init1(gspca_dev);
        cx11646_initsize(gspca_dev);
@@ -845,10 +845,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
        cx11646_jpeg(gspca_dev);
 }
 
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
        int retry = 50;
@@ -871,10 +867,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
        reg_w_val(gspca_dev, 0x00fc, 0xe0);
 }
 
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -998,11 +990,9 @@ static struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
-       .stopN = sd_stopN,
        .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -1026,6 +1016,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 1dbe92d01e6a7ce941abec7a9d79780d8fbf5752..4ff0e386914baf87d37482f0abdb7611c66720a2 100644 (file)
@@ -81,6 +81,7 @@ static struct ctrl sd_ctrls[] = {
         .set = sd_setcontrast,
         .get = sd_getcontrast,
         },
+#define COLOR_IDX 2
        {
         {
          .id = V4L2_CID_SATURATION,
@@ -234,7 +235,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
        struct usb_device *dev = gspca_dev->dev;
 
 #ifdef GSPCA_DEBUG
-       if (len > sizeof gspca_dev->usb_buf) {
+       if (len > USB_BUF_SZ) {
                err("reg_r: buffer overflow");
                return;
        }
@@ -272,7 +273,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
        struct usb_device *dev = gspca_dev->dev;
 
 #ifdef GSPCA_DEBUG
-       if (len > sizeof gspca_dev->usb_buf) {
+       if (len > USB_BUF_SZ) {
                err("reg_w: buffer overflow");
                return;
        }
@@ -665,6 +666,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        } else {
                cam->cam_mode = vga_mode;
                cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+               gspca_dev->ctrl_dis = (1 << COLOR_IDX);
        }
        sd->brightness = BRIGHTNESS_DEF;
        sd->contrast = CONTRAST_DEF;
@@ -674,8 +676,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
@@ -709,14 +711,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        et_video(gspca_dev, 0);         /* video off */
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -893,21 +887,19 @@ static struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .dq_callback = do_autogain,
 };
 
 /* -- module initialisation -- */
 static __devinitdata struct usb_device_id device_table[] = {
-#ifndef CONFIG_USB_ET61X251
        {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
-#endif
+#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
        {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
+#endif
        {}
 };
 
@@ -926,6 +918,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 15d302b28b795d7d5e727a1e1091964dbb1e651f..7be69284da035b0475eb1f7bdb1b6c4cabf3ecaf 100644 (file)
@@ -114,7 +114,10 @@ static void fill_frame(struct gspca_dev *gspca_dev,
        cam_pkt_op pkt_scan;
 
        if (urb->status != 0) {
-               PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+#ifdef CONFIG_PM
+               if (!gspca_dev->frozen)
+#endif
+                       PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
                return;         /* disconnection ? */
        }
        pkt_scan = gspca_dev->sd_desc->pkt_scan;
@@ -555,10 +558,12 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
        gspca_dev->streaming = 0;
        atomic_set(&gspca_dev->nevent, 0);
        if (gspca_dev->present) {
-               gspca_dev->sd_desc->stopN(gspca_dev);
+               if (gspca_dev->sd_desc->stopN)
+                       gspca_dev->sd_desc->stopN(gspca_dev);
                destroy_urbs(gspca_dev);
                gspca_set_alt0(gspca_dev);
-               gspca_dev->sd_desc->stop0(gspca_dev);
+               if (gspca_dev->sd_desc->stop0)
+                       gspca_dev->sd_desc->stop0(gspca_dev);
                PDEBUG(D_STREAM, "stream off OK");
        }
 }
@@ -767,19 +772,7 @@ static int dev_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       /* if not done yet, initialize the sensor */
-       if (gspca_dev->users == 0) {
-               if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
-                       ret = -ERESTARTSYS;
-                       goto out;
-               }
-               ret = gspca_dev->sd_desc->open(gspca_dev);
-               mutex_unlock(&gspca_dev->usb_lock);
-               if (ret != 0) {
-                       PDEBUG(D_ERR|D_CONF, "init device failed %d", ret);
-                       goto out;
-               }
-       } else if (gspca_dev->users > 4) {      /* (arbitrary value) */
+       if (gspca_dev->users > 4) {     /* (arbitrary value) */
                ret = -EBUSY;
                goto out;
        }
@@ -792,6 +785,7 @@ static int dev_open(struct inode *inode, struct file *file)
        else
                gspca_dev->vdev.debug &= ~3;
 #endif
+       ret = 0;
 out:
        mutex_unlock(&gspca_dev->queue_lock);
        if (ret != 0)
@@ -812,11 +806,11 @@ static int dev_close(struct inode *inode, struct file *file)
 
        /* if the file did the capture, free the streaming resources */
        if (gspca_dev->capt_file == file) {
-               mutex_lock(&gspca_dev->usb_lock);
-               if (gspca_dev->streaming)
+               if (gspca_dev->streaming) {
+                       mutex_lock(&gspca_dev->usb_lock);
                        gspca_stream_off(gspca_dev);
-               gspca_dev->sd_desc->close(gspca_dev);
-               mutex_unlock(&gspca_dev->usb_lock);
+                       mutex_unlock(&gspca_dev->usb_lock);
+               }
                frame_free(gspca_dev);
                gspca_dev->capt_file = NULL;
                gspca_dev->memory = GSPCA_MEMORY_NO;
@@ -853,42 +847,44 @@ static int vidioc_querycap(struct file *file, void  *priv,
        return 0;
 }
 
-/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
 static int vidioc_queryctrl(struct file *file, void *priv,
                           struct v4l2_queryctrl *q_ctrl)
 {
        struct gspca_dev *gspca_dev = priv;
-       int i;
+       int i, ix;
        u32 id;
 
+       ix = -1;
        id = q_ctrl->id;
        if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
                id &= V4L2_CTRL_ID_MASK;
                id++;
                for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
-                       if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
-                               memcpy(q_ctrl,
-                                       &gspca_dev->sd_desc->ctrls[i].qctrl,
-                                       sizeof *q_ctrl);
-                               return 0;
+                       if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
+                               continue;
+                       if (ix < 0) {
+                               ix = i;
+                               continue;
                        }
+                       if (gspca_dev->sd_desc->ctrls[i].qctrl.id
+                                   > gspca_dev->sd_desc->ctrls[ix].qctrl.id)
+                               continue;
+                       ix = i;
                }
-               return -EINVAL;
        }
        for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
                if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
-                       memcpy(q_ctrl,
-                               &gspca_dev->sd_desc->ctrls[i].qctrl,
-                               sizeof *q_ctrl);
-                       return 0;
+                       ix = i;
+                       break;
                }
        }
-       if (id >= V4L2_CID_BASE
-           && id <= V4L2_CID_LASTP1) {
+       if (ix < 0)
+               return -EINVAL;
+       memcpy(q_ctrl, &gspca_dev->sd_desc->ctrls[ix].qctrl,
+               sizeof *q_ctrl);
+       if (gspca_dev->ctrl_dis & (1 << ix))
                q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
-               return 0;
-       }
-       return -EINVAL;
+       return 0;
 }
 
 static int vidioc_s_ctrl(struct file *file, void *priv,
@@ -903,6 +899,8 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
             i++, ctrls++) {
                if (ctrl->id != ctrls->qctrl.id)
                        continue;
+               if (gspca_dev->ctrl_dis & (1 << i))
+                       return -EINVAL;
                if (ctrl->value < ctrls->qctrl.minimum
                    || ctrl->value > ctrls->qctrl.maximum)
                        return -ERANGE;
@@ -929,6 +927,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
             i++, ctrls++) {
                if (ctrl->id != ctrls->qctrl.id)
                        continue;
+               if (gspca_dev->ctrl_dis & (1 << i))
+                       return -EINVAL;
                if (mutex_lock_interruptible(&gspca_dev->usb_lock))
                        return -ERESTARTSYS;
                ret = ctrls->get(gspca_dev, &ctrl->value);
@@ -1403,7 +1403,7 @@ static int vidioc_dqbuf(struct file *file, void *priv,
        i = ret;                                /* frame index */
        frame = &gspca_dev->frame[i];
        if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
-               if (copy_to_user((__u8 *) frame->v4l2_buf.m.userptr,
+               if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
                                 frame->data,
                                 frame->v4l2_buf.bytesused)) {
                        PDEBUG(D_ERR|D_STREAM,
@@ -1731,6 +1731,12 @@ int gspca_dev_probe(struct usb_interface *intf,
                err("couldn't kzalloc gspca struct");
                return -EIO;
        }
+       gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
+       if (!gspca_dev->usb_buf) {
+               err("out of memory");
+               ret = -EIO;
+               goto out;
+       }
        gspca_dev->dev = dev;
        gspca_dev->iface = interface->bInterfaceNumber;
        gspca_dev->nbalt = intf->num_altsetting;
@@ -1738,8 +1744,11 @@ int gspca_dev_probe(struct usb_interface *intf,
 /*     gspca_dev->users = 0;                   (done by kzalloc) */
        gspca_dev->nbufread = 2;
 
-       /* configure the subdriver */
+       /* configure the subdriver and initialize the USB device */
        ret = gspca_dev->sd_desc->config(gspca_dev, id);
+       if (ret < 0)
+               goto out;
+       ret = gspca_dev->sd_desc->init(gspca_dev);
        if (ret < 0)
                goto out;
        ret = gspca_set_alt0(gspca_dev);
@@ -1771,6 +1780,7 @@ int gspca_dev_probe(struct usb_interface *intf,
        PDEBUG(D_PROBE, "probe ok");
        return 0;
 out:
+       kfree(gspca_dev->usb_buf);
        kfree(gspca_dev);
        return ret;
 }
@@ -1803,11 +1813,42 @@ void gspca_disconnect(struct usb_interface *intf)
 /* We don't want people trying to open up the device */
        video_unregister_device(&gspca_dev->vdev);
 /* Free the memory */
+       kfree(gspca_dev->usb_buf);
        kfree(gspca_dev);
        PDEBUG(D_PROBE, "disconnect complete");
 }
 EXPORT_SYMBOL(gspca_disconnect);
 
+#ifdef CONFIG_PM
+int gspca_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+       if (!gspca_dev->streaming)
+               return 0;
+       gspca_dev->frozen = 1;          /* avoid urb error messages */
+       if (gspca_dev->sd_desc->stopN)
+               gspca_dev->sd_desc->stopN(gspca_dev);
+       destroy_urbs(gspca_dev);
+       gspca_set_alt0(gspca_dev);
+       if (gspca_dev->sd_desc->stop0)
+               gspca_dev->sd_desc->stop0(gspca_dev);
+       return 0;
+}
+EXPORT_SYMBOL(gspca_suspend);
+
+int gspca_resume(struct usb_interface *intf)
+{
+       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+       gspca_dev->frozen = 0;
+       gspca_dev->sd_desc->init(gspca_dev);
+       if (gspca_dev->streaming)
+               return gspca_init_transfer(gspca_dev);
+       return 0;
+}
+EXPORT_SYMBOL(gspca_resume);
+#endif
 /* -- cam driver utility functions -- */
 
 /* auto gain and exposure algorithm based on the knee algorithm described here:
index 67e448940eaa300bc8507b6a5afd9eee4451784f..c17625cff9ba2dbf35003ab4220363441fe6585d 100644 (file)
@@ -56,7 +56,6 @@ extern int gspca_debug;
 
 /* device information - set at probe time */
 struct cam {
-       char *dev_name;
        struct v4l2_pix_format *cam_mode;       /* size nmodes */
        char nmodes;
        __u8 epaddr;
@@ -91,15 +90,14 @@ struct sd_desc {
 /* controls */
        const struct ctrl *ctrls;
        int nctrls;
-/* operations */
+/* mandatory operations */
        cam_cf_op config;       /* called on probe */
-       cam_op open;            /* called on open */
+       cam_op init;            /* called on probe and resume */
        cam_v_op start;         /* called on stream on */
-       cam_v_op stopN;         /* called on stream off - main alt */
-       cam_v_op stop0;         /* called on stream off - alt 0 */
-       cam_v_op close;         /* called on close */
        cam_pkt_op pkt_scan;
 /* optional operations */
+       cam_v_op stopN;         /* called on stream off - main alt */
+       cam_v_op stop0;         /* called on stream off - alt 0 */
        cam_v_op dq_callback;   /* called when a frame has been dequeued */
        cam_jpg_op get_jcomp;
        cam_jpg_op set_jcomp;
@@ -127,8 +125,10 @@ struct gspca_dev {
 
        struct cam cam;                         /* device information */
        const struct sd_desc *sd_desc;          /* subdriver description */
+       unsigned ctrl_dis;              /* disabled controls (bit map) */
 
-       __u8 usb_buf[8];                        /* buffer for USB exchanges */
+#define USB_BUF_SZ 64
+       __u8 *usb_buf;                          /* buffer for USB exchanges */
        struct urb *urb[MAX_NURBS];
 
        __u8 *frbuf;                            /* buffer for nframes */
@@ -155,6 +155,9 @@ struct gspca_dev {
        struct mutex queue_lock;        /* ISOC queue protection */
        __u32 sequence;                 /* frame sequence number */
        char streaming;
+#ifdef CONFIG_PM
+       char frozen;                    /* suspend - resume */
+#endif
        char users;                     /* number of opens */
        char present;                   /* device connected */
        char nbufread;                  /* number of buffers for read() */
@@ -174,6 +177,10 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
                                    struct gspca_frame *frame,
                                    const __u8 *data,
                                    int len);
+#ifdef CONFIG_PM
+int gspca_suspend(struct usb_interface *intf, pm_message_t message);
+int gspca_resume(struct usb_interface *intf);
+#endif
 int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
        int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
 #endif /* GSPCAV2_H */
index 21c4ee56a10aaef3702d8b3a79cce7ddda884c5a..4d5db47ba8cbf3564d9287a86153e4f46733f2e8 100644 (file)
@@ -100,22 +100,6 @@ static int reg_w(struct gspca_dev *gspca_dev,
        return rc;
 }
 
-static int reg_w_buf(struct gspca_dev *gspca_dev,
-                       __u16 index, __u8 *buf, int len)
-{
-       int rc;
-
-       rc = usb_control_msg(gspca_dev->dev,
-                        usb_sndbulkpipe(gspca_dev->dev, 4),
-                        0x12,
-                        0xc8,          /* ?? */
-                        0,             /* value */
-                        index, buf, len, 500);
-       if (rc < 0)
-               PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
-       return rc;
-}
-
 static void bulk_w(struct gspca_dev *gspca_dev,
                   __u16 *pch,
                   __u16 Address)
@@ -144,8 +128,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        return 0;
 }
@@ -175,7 +159,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
        /*
           Initialize the MR97113 chip register
         */
-       data = kmalloc(16, GFP_KERNEL);
        data[0] = 0x00;         /* address */
        data[1] = 0x0c | 0x01;  /* reg 0 */
        data[2] = 0x01;         /* reg 1 */
@@ -195,12 +178,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
        data[10] = 0x5d;        /* reg 9, I2C device address
                                 *      [for PAS5101 (0x40)] [for MI (0x5d)] */
 
-       err_code = reg_w_buf(gspca_dev, data[0], data, 11);
-       kfree(data);
+       err_code = reg_w(gspca_dev, data[0], 11);
        if (err_code < 0)
                return;
 
-       data = gspca_dev->usb_buf;
        data[0] = 0x23;         /* address */
        data[1] = 0x09;         /* reg 35, append frame header */
 
@@ -358,14 +339,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                PDEBUG(D_ERR, "Camera Stop failed");
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -411,11 +384,9 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -439,6 +410,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index b4f00ec0885cc0ec6600f52f362cd2c16d21b2ff..4df4eec9f7e71163fe35950bf02a303ca5a3272c 100644 (file)
@@ -63,11 +63,10 @@ struct sd {
 #define SEN_OV6630 2
 #define SEN_OV7610 3
 #define SEN_OV7620 4
-#define SEN_OV7630 5
-#define SEN_OV7640 6
-#define SEN_OV7670 7
-#define SEN_OV76BE 8
-#define SEN_OV8610 9
+#define SEN_OV7640 5
+#define SEN_OV7670 6
+#define SEN_OV76BE 7
+#define SEN_OV8610 8
 
 };
 
@@ -127,6 +126,7 @@ static struct ctrl sd_ctrls[] = {
            .get = sd_getcolors,
        },
 /* next controls work with ov7670 only */
+#define HFLIP_IDX 3
        {
            {
                .id      = V4L2_CID_HFLIP,
@@ -141,6 +141,7 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_sethflip,
            .get = sd_gethflip,
        },
+#define VFLIP_IDX 4
        {
            {
                .id      = V4L2_CID_VFLIP,
@@ -293,6 +294,541 @@ static struct v4l2_pix_format sif_mode[] = {
 #define OV7670_REG_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
 #define OV7670_REG_BD60MAX     0xab    /* 60hz banding step limit */
 
+struct ov_regvals {
+       __u8 reg;
+       __u8 val;
+};
+struct ov_i2c_regvals {
+       __u8 reg;
+       __u8 val;
+};
+
+static const struct ov_i2c_regvals norm_6x20[] = {
+       { 0x12, 0x80 }, /* reset */
+       { 0x11, 0x01 },
+       { 0x03, 0x60 },
+       { 0x05, 0x7f }, /* For when autoadjust is off */
+       { 0x07, 0xa8 },
+       /* The ratio of 0x0c and 0x0d  controls the white point */
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+       { 0x0f, 0x15 }, /* COMS */
+       { 0x10, 0x75 }, /* AEC Exposure time */
+       { 0x12, 0x24 }, /* Enable AGC */
+       { 0x14, 0x04 },
+       /* 0x16: 0x06 helps frame stability with moving objects */
+       { 0x16, 0x06 },
+/*     { 0x20, 0x30 },  * Aperture correction enable */
+       { 0x26, 0xb2 }, /* BLC enable */
+       /* 0x28: 0x05 Selects RGB format if RGB on */
+       { 0x28, 0x05 },
+       { 0x2a, 0x04 }, /* Disable framerate adjust */
+/*     { 0x2b, 0xac },  * Framerate; Set 2a[7] first */
+       { 0x2d, 0x99 },
+       { 0x33, 0xa0 }, /* Color Processing Parameter */
+       { 0x34, 0xd2 }, /* Max A/D range */
+       { 0x38, 0x8b },
+       { 0x39, 0x40 },
+
+       { 0x3c, 0x39 }, /* Enable AEC mode changing */
+       { 0x3c, 0x3c }, /* Change AEC mode */
+       { 0x3c, 0x24 }, /* Disable AEC mode changing */
+
+       { 0x3d, 0x80 },
+       /* These next two registers (0x4a, 0x4b) are undocumented.
+        * They control the color balance */
+       { 0x4a, 0x80 },
+       { 0x4b, 0x80 },
+       { 0x4d, 0xd2 }, /* This reduces noise a bit */
+       { 0x4e, 0xc1 },
+       { 0x4f, 0x04 },
+/* Do 50-53 have any effect? */
+/* Toggle 0x12[2] off and on here? */
+};
+
+static const struct ov_i2c_regvals norm_6x30[] = {
+       { 0x12, 0x80 }, /* Reset */
+       { 0x00, 0x1f }, /* Gain */
+       { 0x01, 0x99 }, /* Blue gain */
+       { 0x02, 0x7c }, /* Red gain */
+       { 0x03, 0xc0 }, /* Saturation */
+       { 0x05, 0x0a }, /* Contrast */
+       { 0x06, 0x95 }, /* Brightness */
+       { 0x07, 0x2d }, /* Sharpness */
+       { 0x0c, 0x20 },
+       { 0x0d, 0x20 },
+       { 0x0e, 0x20 },
+       { 0x0f, 0x05 },
+       { 0x10, 0x9a },
+       { 0x11, 0x00 }, /* Pixel clock = fastest */
+       { 0x12, 0x24 }, /* Enable AGC and AWB */
+       { 0x13, 0x21 },
+       { 0x14, 0x80 },
+       { 0x15, 0x01 },
+       { 0x16, 0x03 },
+       { 0x17, 0x38 },
+       { 0x18, 0xea },
+       { 0x19, 0x04 },
+       { 0x1a, 0x93 },
+       { 0x1b, 0x00 },
+       { 0x1e, 0xc4 },
+       { 0x1f, 0x04 },
+       { 0x20, 0x20 },
+       { 0x21, 0x10 },
+       { 0x22, 0x88 },
+       { 0x23, 0xc0 }, /* Crystal circuit power level */
+       { 0x25, 0x9a }, /* Increase AEC black ratio */
+       { 0x26, 0xb2 }, /* BLC enable */
+       { 0x27, 0xa2 },
+       { 0x28, 0x00 },
+       { 0x29, 0x00 },
+       { 0x2a, 0x84 }, /* 60 Hz power */
+       { 0x2b, 0xa8 }, /* 60 Hz power */
+       { 0x2c, 0xa0 },
+       { 0x2d, 0x95 }, /* Enable auto-brightness */
+       { 0x2e, 0x88 },
+       { 0x33, 0x26 },
+       { 0x34, 0x03 },
+       { 0x36, 0x8f },
+       { 0x37, 0x80 },
+       { 0x38, 0x83 },
+       { 0x39, 0x80 },
+       { 0x3a, 0x0f },
+       { 0x3b, 0x3c },
+       { 0x3c, 0x1a },
+       { 0x3d, 0x80 },
+       { 0x3e, 0x80 },
+       { 0x3f, 0x0e },
+       { 0x40, 0x00 }, /* White bal */
+       { 0x41, 0x00 }, /* White bal */
+       { 0x42, 0x80 },
+       { 0x43, 0x3f }, /* White bal */
+       { 0x44, 0x80 },
+       { 0x45, 0x20 },
+       { 0x46, 0x20 },
+       { 0x47, 0x80 },
+       { 0x48, 0x7f },
+       { 0x49, 0x00 },
+       { 0x4a, 0x00 },
+       { 0x4b, 0x80 },
+       { 0x4c, 0xd0 },
+       { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
+       { 0x4e, 0x40 },
+       { 0x4f, 0x07 }, /* UV avg., col. killer: max */
+       { 0x50, 0xff },
+       { 0x54, 0x23 }, /* Max AGC gain: 18dB */
+       { 0x55, 0xff },
+       { 0x56, 0x12 },
+       { 0x57, 0x81 },
+       { 0x58, 0x75 },
+       { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
+       { 0x5a, 0x2c },
+       { 0x5b, 0x0f }, /* AWB chrominance levels */
+       { 0x5c, 0x10 },
+       { 0x3d, 0x80 },
+       { 0x27, 0xa6 },
+       { 0x12, 0x20 }, /* Toggle AWB */
+       { 0x12, 0x24 },
+};
+
+/* Lawrence Glaister <lg@jfm.bc.ca> reports:
+ *
+ * Register 0x0f in the 7610 has the following effects:
+ *
+ * 0x85 (AEC method 1): Best overall, good contrast range
+ * 0x45 (AEC method 2): Very overexposed
+ * 0xa5 (spec sheet default): Ok, but the black level is
+ *     shifted resulting in loss of contrast
+ * 0x05 (old driver setting): very overexposed, too much
+ *     contrast
+ */
+static const struct ov_i2c_regvals norm_7610[] = {
+       { 0x10, 0xff },
+       { 0x16, 0x06 },
+       { 0x28, 0x24 },
+       { 0x2b, 0xac },
+       { 0x12, 0x00 },
+       { 0x38, 0x81 },
+       { 0x28, 0x24 }, /* 0c */
+       { 0x0f, 0x85 }, /* lg's setting */
+       { 0x15, 0x01 },
+       { 0x20, 0x1c },
+       { 0x23, 0x2a },
+       { 0x24, 0x10 },
+       { 0x25, 0x8a },
+       { 0x26, 0xa2 },
+       { 0x27, 0xc2 },
+       { 0x2a, 0x04 },
+       { 0x2c, 0xfe },
+       { 0x2d, 0x93 },
+       { 0x30, 0x71 },
+       { 0x31, 0x60 },
+       { 0x32, 0x26 },
+       { 0x33, 0x20 },
+       { 0x34, 0x48 },
+       { 0x12, 0x24 },
+       { 0x11, 0x01 },
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+};
+
+static const struct ov_i2c_regvals norm_7620[] = {
+       { 0x00, 0x00 },         /* gain */
+       { 0x01, 0x80 },         /* blue gain */
+       { 0x02, 0x80 },         /* red gain */
+       { 0x03, 0xc0 },         /* OV7670_REG_VREF */
+       { 0x06, 0x60 },
+       { 0x07, 0x00 },
+       { 0x0c, 0x24 },
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+       { 0x11, 0x01 },
+       { 0x12, 0x24 },
+       { 0x13, 0x01 },
+       { 0x14, 0x84 },
+       { 0x15, 0x01 },
+       { 0x16, 0x03 },
+       { 0x17, 0x2f },
+       { 0x18, 0xcf },
+       { 0x19, 0x06 },
+       { 0x1a, 0xf5 },
+       { 0x1b, 0x00 },
+       { 0x20, 0x18 },
+       { 0x21, 0x80 },
+       { 0x22, 0x80 },
+       { 0x23, 0x00 },
+       { 0x26, 0xa2 },
+       { 0x27, 0xea },
+       { 0x28, 0x20 },
+       { 0x29, 0x00 },
+       { 0x2a, 0x10 },
+       { 0x2b, 0x00 },
+       { 0x2c, 0x88 },
+       { 0x2d, 0x91 },
+       { 0x2e, 0x80 },
+       { 0x2f, 0x44 },
+       { 0x60, 0x27 },
+       { 0x61, 0x02 },
+       { 0x62, 0x5f },
+       { 0x63, 0xd5 },
+       { 0x64, 0x57 },
+       { 0x65, 0x83 },
+       { 0x66, 0x55 },
+       { 0x67, 0x92 },
+       { 0x68, 0xcf },
+       { 0x69, 0x76 },
+       { 0x6a, 0x22 },
+       { 0x6b, 0x00 },
+       { 0x6c, 0x02 },
+       { 0x6d, 0x44 },
+       { 0x6e, 0x80 },
+       { 0x6f, 0x1d },
+       { 0x70, 0x8b },
+       { 0x71, 0x00 },
+       { 0x72, 0x14 },
+       { 0x73, 0x54 },
+       { 0x74, 0x00 },
+       { 0x75, 0x8e },
+       { 0x76, 0x00 },
+       { 0x77, 0xff },
+       { 0x78, 0x80 },
+       { 0x79, 0x80 },
+       { 0x7a, 0x80 },
+       { 0x7b, 0xe2 },
+       { 0x7c, 0x00 },
+};
+
+/* 7640 and 7648. The defaults should be OK for most registers. */
+static const struct ov_i2c_regvals norm_7640[] = {
+       { 0x12, 0x80 },
+       { 0x12, 0x14 },
+};
+
+/* 7670. Defaults taken from OmniVision provided data,
+*  as provided by Jonathan Corbet of OLPC              */
+static const struct ov_i2c_regvals norm_7670[] = {
+       { OV7670_REG_COM7, OV7670_COM7_RESET },
+       { OV7670_REG_TSLB, 0x04 },              /* OV */
+       { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
+       { OV7670_REG_CLKRC, 0x01 },
+/*
+ * Set the hardware window.  These values from OV don't entirely
+ * make sense - hstop is less than hstart.  But they work...
+ */
+       { OV7670_REG_HSTART, 0x13 },
+       { OV7670_REG_HSTOP, 0x01 },
+       { OV7670_REG_HREF, 0xb6 },
+       { OV7670_REG_VSTART, 0x02 },
+       { OV7670_REG_VSTOP, 0x7a },
+       { OV7670_REG_VREF, 0x0a },
+
+       { OV7670_REG_COM3, 0 },
+       { OV7670_REG_COM14, 0 },
+/* Mystery scaling numbers */
+       { 0x70, 0x3a },
+       { 0x71, 0x35 },
+       { 0x72, 0x11 },
+       { 0x73, 0xf0 },
+       { 0xa2, 0x02 },
+/*     { OV7670_REG_COM10, 0x0 }, */
+
+/* Gamma curve values */
+       { 0x7a, 0x20 },
+       { 0x7b, 0x10 },
+       { 0x7c, 0x1e },
+       { 0x7d, 0x35 },
+       { 0x7e, 0x5a },
+       { 0x7f, 0x69 },
+       { 0x80, 0x76 },
+       { 0x81, 0x80 },
+       { 0x82, 0x88 },
+       { 0x83, 0x8f },
+       { 0x84, 0x96 },
+       { 0x85, 0xa3 },
+       { 0x86, 0xaf },
+       { 0x87, 0xc4 },
+       { 0x88, 0xd7 },
+       { 0x89, 0xe8 },
+
+/* AGC and AEC parameters.  Note we start by disabling those features,
+   then turn them only after tweaking the values. */
+       { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+                        | OV7670_COM8_AECSTEP
+                        | OV7670_COM8_BFILT },
+       { OV7670_REG_GAIN, 0 },
+       { OV7670_REG_AECH, 0 },
+       { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
+       { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
+       { OV7670_REG_BD50MAX, 0x05 },
+       { OV7670_REG_BD60MAX, 0x07 },
+       { OV7670_REG_AEW, 0x95 },
+       { OV7670_REG_AEB, 0x33 },
+       { OV7670_REG_VPT, 0xe3 },
+       { OV7670_REG_HAECC1, 0x78 },
+       { OV7670_REG_HAECC2, 0x68 },
+       { 0xa1, 0x03 }, /* magic */
+       { OV7670_REG_HAECC3, 0xd8 },
+       { OV7670_REG_HAECC4, 0xd8 },
+       { OV7670_REG_HAECC5, 0xf0 },
+       { OV7670_REG_HAECC6, 0x90 },
+       { OV7670_REG_HAECC7, 0x94 },
+       { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+                       | OV7670_COM8_AECSTEP
+                       | OV7670_COM8_BFILT
+                       | OV7670_COM8_AGC
+                       | OV7670_COM8_AEC },
+
+/* Almost all of these are magic "reserved" values.  */
+       { OV7670_REG_COM5, 0x61 },
+       { OV7670_REG_COM6, 0x4b },
+       { 0x16, 0x02 },
+       { OV7670_REG_MVFP, 0x07 },
+       { 0x21, 0x02 },
+       { 0x22, 0x91 },
+       { 0x29, 0x07 },
+       { 0x33, 0x0b },
+       { 0x35, 0x0b },
+       { 0x37, 0x1d },
+       { 0x38, 0x71 },
+       { 0x39, 0x2a },
+       { OV7670_REG_COM12, 0x78 },
+       { 0x4d, 0x40 },
+       { 0x4e, 0x20 },
+       { OV7670_REG_GFIX, 0 },
+       { 0x6b, 0x4a },
+       { 0x74, 0x10 },
+       { 0x8d, 0x4f },
+       { 0x8e, 0 },
+       { 0x8f, 0 },
+       { 0x90, 0 },
+       { 0x91, 0 },
+       { 0x96, 0 },
+       { 0x9a, 0 },
+       { 0xb0, 0x84 },
+       { 0xb1, 0x0c },
+       { 0xb2, 0x0e },
+       { 0xb3, 0x82 },
+       { 0xb8, 0x0a },
+
+/* More reserved magic, some of which tweaks white balance */
+       { 0x43, 0x0a },
+       { 0x44, 0xf0 },
+       { 0x45, 0x34 },
+       { 0x46, 0x58 },
+       { 0x47, 0x28 },
+       { 0x48, 0x3a },
+       { 0x59, 0x88 },
+       { 0x5a, 0x88 },
+       { 0x5b, 0x44 },
+       { 0x5c, 0x67 },
+       { 0x5d, 0x49 },
+       { 0x5e, 0x0e },
+       { 0x6c, 0x0a },
+       { 0x6d, 0x55 },
+       { 0x6e, 0x11 },
+       { 0x6f, 0x9f },
+                                       /* "9e for advance AWB" */
+       { 0x6a, 0x40 },
+       { OV7670_REG_BLUE, 0x40 },
+       { OV7670_REG_RED, 0x60 },
+       { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+                       | OV7670_COM8_AECSTEP
+                       | OV7670_COM8_BFILT
+                       | OV7670_COM8_AGC
+                       | OV7670_COM8_AEC
+                       | OV7670_COM8_AWB },
+
+/* Matrix coefficients */
+       { 0x4f, 0x80 },
+       { 0x50, 0x80 },
+       { 0x51, 0 },
+       { 0x52, 0x22 },
+       { 0x53, 0x5e },
+       { 0x54, 0x80 },
+       { 0x58, 0x9e },
+
+       { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
+       { OV7670_REG_EDGE, 0 },
+       { 0x75, 0x05 },
+       { 0x76, 0xe1 },
+       { 0x4c, 0 },
+       { 0x77, 0x01 },
+       { OV7670_REG_COM13, OV7670_COM13_GAMMA
+                         | OV7670_COM13_UVSAT
+                         | 2},         /* was 3 */
+       { 0x4b, 0x09 },
+       { 0xc9, 0x60 },
+       { OV7670_REG_COM16, 0x38 },
+       { 0x56, 0x40 },
+
+       { 0x34, 0x11 },
+       { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
+       { 0xa4, 0x88 },
+       { 0x96, 0 },
+       { 0x97, 0x30 },
+       { 0x98, 0x20 },
+       { 0x99, 0x30 },
+       { 0x9a, 0x84 },
+       { 0x9b, 0x29 },
+       { 0x9c, 0x03 },
+       { 0x9d, 0x4c },
+       { 0x9e, 0x3f },
+       { 0x78, 0x04 },
+
+/* Extra-weird stuff.  Some sort of multiplexor register */
+       { 0x79, 0x01 },
+       { 0xc8, 0xf0 },
+       { 0x79, 0x0f },
+       { 0xc8, 0x00 },
+       { 0x79, 0x10 },
+       { 0xc8, 0x7e },
+       { 0x79, 0x0a },
+       { 0xc8, 0x80 },
+       { 0x79, 0x0b },
+       { 0xc8, 0x01 },
+       { 0x79, 0x0c },
+       { 0xc8, 0x0f },
+       { 0x79, 0x0d },
+       { 0xc8, 0x20 },
+       { 0x79, 0x09 },
+       { 0xc8, 0x80 },
+       { 0x79, 0x02 },
+       { 0xc8, 0xc0 },
+       { 0x79, 0x03 },
+       { 0xc8, 0x40 },
+       { 0x79, 0x05 },
+       { 0xc8, 0x30 },
+       { 0x79, 0x26 },
+};
+
+static const struct ov_i2c_regvals norm_8610[] = {
+       { 0x12, 0x80 },
+       { 0x00, 0x00 },
+       { 0x01, 0x80 },
+       { 0x02, 0x80 },
+       { 0x03, 0xc0 },
+       { 0x04, 0x30 },
+       { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
+       { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
+       { 0x0a, 0x86 },
+       { 0x0b, 0xb0 },
+       { 0x0c, 0x20 },
+       { 0x0d, 0x20 },
+       { 0x11, 0x01 },
+       { 0x12, 0x25 },
+       { 0x13, 0x01 },
+       { 0x14, 0x04 },
+       { 0x15, 0x01 }, /* Lin and Win think different about UV order */
+       { 0x16, 0x03 },
+       { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
+       { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
+       { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
+       { 0x1a, 0xf5 },
+       { 0x1b, 0x00 },
+       { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
+       { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
+       { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
+       { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
+       { 0x26, 0xa2 },
+       { 0x27, 0xea },
+       { 0x28, 0x00 },
+       { 0x29, 0x00 },
+       { 0x2a, 0x80 },
+       { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
+       { 0x2c, 0xac },
+       { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
+       { 0x2e, 0x80 },
+       { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
+       { 0x4c, 0x00 },
+       { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
+       { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
+       { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
+       { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
+       { 0x63, 0xff },
+       { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
+                        * maybe thats wrong */
+       { 0x65, 0x00 },
+       { 0x66, 0x55 },
+       { 0x67, 0xb0 },
+       { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
+       { 0x69, 0x02 },
+       { 0x6a, 0x22 },
+       { 0x6b, 0x00 },
+       { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
+                        * deleting bit7 colors the first images red */
+       { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
+       { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
+       { 0x6f, 0x01 },
+       { 0x70, 0x8b },
+       { 0x71, 0x00 },
+       { 0x72, 0x14 },
+       { 0x73, 0x54 },
+       { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
+       { 0x75, 0x0e },
+       { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
+       { 0x77, 0xff },
+       { 0x78, 0x80 },
+       { 0x79, 0x80 },
+       { 0x7a, 0x80 },
+       { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
+       { 0x7c, 0x00 },
+       { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
+       { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
+       { 0x7f, 0xfb },
+       { 0x80, 0x28 },
+       { 0x81, 0x00 },
+       { 0x82, 0x23 },
+       { 0x83, 0x0b },
+       { 0x84, 0x00 },
+       { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
+       { 0x86, 0xc9 },
+       { 0x87, 0x00 },
+       { 0x88, 0x00 },
+       { 0x89, 0x01 },
+       { 0x12, 0x20 },
+       { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
+};
+
 static unsigned char ov7670_abs_to_sm(unsigned char v)
 {
        if (v > 127)
@@ -537,18 +1073,10 @@ static int ov51x_set_slave_ids(struct sd *sd,
        rc = reg_w(sd, R51x_I2C_W_SID, slave);
        if (rc < 0)
                return rc;
+       sd->primary_i2c_slave = slave;
        return reg_w(sd, R51x_I2C_R_SID, slave + 1);
 }
 
-struct ov_regvals {
-       __u8 reg;
-       __u8 val;
-};
-struct ov_i2c_regvals {
-       __u8 reg;
-       __u8 val;
-};
-
 static int write_regvals(struct sd *sd,
                         const struct ov_regvals *regvals,
                         int n)
@@ -591,101 +1119,9 @@ static int write_i2c_regvals(struct sd *sd,
 static int ov8xx0_configure(struct sd *sd)
 {
        int rc;
-       static const struct ov_i2c_regvals norm_8610[] = {
-               { 0x12, 0x80 },
-               { 0x00, 0x00 },
-               { 0x01, 0x80 },
-               { 0x02, 0x80 },
-               { 0x03, 0xc0 },
-               { 0x04, 0x30 },
-               { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
-               { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
-               { 0x0a, 0x86 },
-               { 0x0b, 0xb0 },
-               { 0x0c, 0x20 },
-               { 0x0d, 0x20 },
-               { 0x11, 0x01 },
-               { 0x12, 0x25 },
-               { 0x13, 0x01 },
-               { 0x14, 0x04 },
-               { 0x15, 0x01 }, /* Lin and Win think different about UV order */
-               { 0x16, 0x03 },
-               { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
-               { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
-               { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
-               { 0x1a, 0xf5 },
-               { 0x1b, 0x00 },
-               { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
-               { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
-               { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
-               { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
-               { 0x26, 0xa2 },
-               { 0x27, 0xea },
-               { 0x28, 0x00 },
-               { 0x29, 0x00 },
-               { 0x2a, 0x80 },
-               { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
-               { 0x2c, 0xac },
-               { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
-               { 0x2e, 0x80 },
-               { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
-               { 0x4c, 0x00 },
-               { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
-               { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
-               { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
-               { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
-               { 0x63, 0xff },
-               { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
-                                * maybe thats wrong */
-               { 0x65, 0x00 },
-               { 0x66, 0x55 },
-               { 0x67, 0xb0 },
-               { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
-               { 0x69, 0x02 },
-               { 0x6a, 0x22 },
-               { 0x6b, 0x00 },
-               { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
-                                  deleting bit7 colors the first images red */
-               { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
-               { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
-               { 0x6f, 0x01 },
-               { 0x70, 0x8b },
-               { 0x71, 0x00 },
-               { 0x72, 0x14 },
-               { 0x73, 0x54 },
-               { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
-               { 0x75, 0x0e },
-               { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
-               { 0x77, 0xff },
-               { 0x78, 0x80 },
-               { 0x79, 0x80 },
-               { 0x7a, 0x80 },
-               { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
-               { 0x7c, 0x00 },
-               { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
-               { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
-               { 0x7f, 0xfb },
-               { 0x80, 0x28 },
-               { 0x81, 0x00 },
-               { 0x82, 0x23 },
-               { 0x83, 0x0b },
-               { 0x84, 0x00 },
-               { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
-               { 0x86, 0xc9 },
-               { 0x87, 0x00 },
-               { 0x88, 0x00 },
-               { 0x89, 0x01 },
-               { 0x12, 0x20 },
-               { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
-       };
 
        PDEBUG(D_PROBE, "starting ov8xx0 configuration");
 
-       if (init_ov_sensor(sd) < 0)
-               PDEBUG(D_ERR|D_PROBE, "Failed to read sensor ID");
-       else
-               PDEBUG(D_PROBE, "OV86x0 initialized");
-
        /* Detect sensor (sub)type */
        rc = i2c_r(sd, OV7610_REG_COM_I);
        if (rc < 0) {
@@ -698,9 +1134,6 @@ static int ov8xx0_configure(struct sd *sd)
                PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
                return -1;
        }
-       PDEBUG(D_PROBE, "Writing 8610 registers");
-       if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
-               return -1;
 
        /* Set sensor-specific vars */
 /*     sd->sif = 0;            already done */
@@ -714,252 +1147,6 @@ static int ov7xx0_configure(struct sd *sd)
 {
        int rc, high, low;
 
-       /* Lawrence Glaister <lg@jfm.bc.ca> reports:
-        *
-        * Register 0x0f in the 7610 has the following effects:
-        *
-        * 0x85 (AEC method 1): Best overall, good contrast range
-        * 0x45 (AEC method 2): Very overexposed
-        * 0xa5 (spec sheet default): Ok, but the black level is
-        *      shifted resulting in loss of contrast
-        * 0x05 (old driver setting): very overexposed, too much
-        *      contrast
-        */
-       static const struct ov_i2c_regvals norm_7610[] = {
-               { 0x10, 0xff },
-               { 0x16, 0x06 },
-               { 0x28, 0x24 },
-               { 0x2b, 0xac },
-               { 0x12, 0x00 },
-               { 0x38, 0x81 },
-               { 0x28, 0x24 }, /* 0c */
-               { 0x0f, 0x85 }, /* lg's setting */
-               { 0x15, 0x01 },
-               { 0x20, 0x1c },
-               { 0x23, 0x2a },
-               { 0x24, 0x10 },
-               { 0x25, 0x8a },
-               { 0x26, 0xa2 },
-               { 0x27, 0xc2 },
-               { 0x2a, 0x04 },
-               { 0x2c, 0xfe },
-               { 0x2d, 0x93 },
-               { 0x30, 0x71 },
-               { 0x31, 0x60 },
-               { 0x32, 0x26 },
-               { 0x33, 0x20 },
-               { 0x34, 0x48 },
-               { 0x12, 0x24 },
-               { 0x11, 0x01 },
-               { 0x0c, 0x24 },
-               { 0x0d, 0x24 },
-       };
-
-       static const struct ov_i2c_regvals norm_7620[] = {
-               { 0x00, 0x00 },         /* gain */
-               { 0x01, 0x80 },         /* blue gain */
-               { 0x02, 0x80 },         /* red gain */
-               { 0x03, 0xc0 },         /* OV7670_REG_VREF */
-               { 0x06, 0x60 },
-               { 0x07, 0x00 },
-               { 0x0c, 0x24 },
-               { 0x0c, 0x24 },
-               { 0x0d, 0x24 },
-               { 0x11, 0x01 },
-               { 0x12, 0x24 },
-               { 0x13, 0x01 },
-               { 0x14, 0x84 },
-               { 0x15, 0x01 },
-               { 0x16, 0x03 },
-               { 0x17, 0x2f },
-               { 0x18, 0xcf },
-               { 0x19, 0x06 },
-               { 0x1a, 0xf5 },
-               { 0x1b, 0x00 },
-               { 0x20, 0x18 },
-               { 0x21, 0x80 },
-               { 0x22, 0x80 },
-               { 0x23, 0x00 },
-               { 0x26, 0xa2 },
-               { 0x27, 0xea },
-               { 0x28, 0x20 },
-               { 0x29, 0x00 },
-               { 0x2a, 0x10 },
-               { 0x2b, 0x00 },
-               { 0x2c, 0x88 },
-               { 0x2d, 0x91 },
-               { 0x2e, 0x80 },
-               { 0x2f, 0x44 },
-               { 0x60, 0x27 },
-               { 0x61, 0x02 },
-               { 0x62, 0x5f },
-               { 0x63, 0xd5 },
-               { 0x64, 0x57 },
-               { 0x65, 0x83 },
-               { 0x66, 0x55 },
-               { 0x67, 0x92 },
-               { 0x68, 0xcf },
-               { 0x69, 0x76 },
-               { 0x6a, 0x22 },
-               { 0x6b, 0x00 },
-               { 0x6c, 0x02 },
-               { 0x6d, 0x44 },
-               { 0x6e, 0x80 },
-               { 0x6f, 0x1d },
-               { 0x70, 0x8b },
-               { 0x71, 0x00 },
-               { 0x72, 0x14 },
-               { 0x73, 0x54 },
-               { 0x74, 0x00 },
-               { 0x75, 0x8e },
-               { 0x76, 0x00 },
-               { 0x77, 0xff },
-               { 0x78, 0x80 },
-               { 0x79, 0x80 },
-               { 0x7a, 0x80 },
-               { 0x7b, 0xe2 },
-               { 0x7c, 0x00 },
-       };
-
-       /* 7640 and 7648. The defaults should be OK for most registers. */
-       static const struct ov_i2c_regvals norm_7640[] = {
-               { 0x12, 0x80 },
-               { 0x12, 0x14 },
-       };
-
-       /* 7670. Defaults taken from OmniVision provided data,
-       *  as provided by Jonathan Corbet of OLPC               */
-       static const struct ov_i2c_regvals norm_7670[] = {
-               { OV7670_REG_COM7, OV7670_COM7_RESET },
-               { OV7670_REG_TSLB, 0x04 },              /* OV */
-               { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
-               { OV7670_REG_CLKRC, 0x01 },
-       /*
-        * Set the hardware window.  These values from OV don't entirely
-        * make sense - hstop is less than hstart.  But they work...
-        */
-               { OV7670_REG_HSTART, 0x13 },    { OV7670_REG_HSTOP, 0x01 },
-               { OV7670_REG_HREF, 0xb6 },      { OV7670_REG_VSTART, 0x02 },
-               { OV7670_REG_VSTOP, 0x7a },     { OV7670_REG_VREF, 0x0a },
-
-               { OV7670_REG_COM3, 0 }, { OV7670_REG_COM14, 0 },
-       /* Mystery scaling numbers */
-               { 0x70, 0x3a },         { 0x71, 0x35 },
-               { 0x72, 0x11 },         { 0x73, 0xf0 },
-               { 0xa2, 0x02 },
-/*             { OV7670_REG_COM10, 0x0 }, */
-
-       /* Gamma curve values */
-               { 0x7a, 0x20 },
-               { 0x7b, 0x10 },
-               { 0x7c, 0x1e },
-               { 0x7d, 0x35 },
-               { 0x7e, 0x5a },         { 0x7f, 0x69 },
-               { 0x80, 0x76 },         { 0x81, 0x80 },
-               { 0x82, 0x88 },         { 0x83, 0x8f },
-               { 0x84, 0x96 },         { 0x85, 0xa3 },
-               { 0x86, 0xaf },         { 0x87, 0xc4 },
-               { 0x88, 0xd7 },         { 0x89, 0xe8 },
-
-       /* AGC and AEC parameters.  Note we start by disabling those features,
-          then turn them only after tweaking the values. */
-               { OV7670_REG_COM8, OV7670_COM8_FASTAEC
-                                | OV7670_COM8_AECSTEP
-                                | OV7670_COM8_BFILT },
-               { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 },
-               { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
-               { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
-               { OV7670_REG_BD50MAX, 0x05 },   { OV7670_REG_BD60MAX, 0x07 },
-               { OV7670_REG_AEW, 0x95 },       { OV7670_REG_AEB, 0x33 },
-               { OV7670_REG_VPT, 0xe3 },       { OV7670_REG_HAECC1, 0x78 },
-               { OV7670_REG_HAECC2, 0x68 },
-               { 0xa1, 0x03 }, /* magic */
-               { OV7670_REG_HAECC3, 0xd8 },    { OV7670_REG_HAECC4, 0xd8 },
-               { OV7670_REG_HAECC5, 0xf0 },    { OV7670_REG_HAECC6, 0x90 },
-               { OV7670_REG_HAECC7, 0x94 },
-               { OV7670_REG_COM8, OV7670_COM8_FASTAEC
-                               | OV7670_COM8_AECSTEP
-                               | OV7670_COM8_BFILT
-                               | OV7670_COM8_AGC
-                               | OV7670_COM8_AEC },
-
-       /* Almost all of these are magic "reserved" values.  */
-               { OV7670_REG_COM5, 0x61 },      { OV7670_REG_COM6, 0x4b },
-               { 0x16, 0x02 },
-               { OV7670_REG_MVFP, 0x07 },
-               { 0x21, 0x02 },         { 0x22, 0x91 },
-               { 0x29, 0x07 },         { 0x33, 0x0b },
-               { 0x35, 0x0b },         { 0x37, 0x1d },
-               { 0x38, 0x71 },         { 0x39, 0x2a },
-               { OV7670_REG_COM12, 0x78 },     { 0x4d, 0x40 },
-               { 0x4e, 0x20 },         { OV7670_REG_GFIX, 0 },
-               { 0x6b, 0x4a },         { 0x74, 0x10 },
-               { 0x8d, 0x4f },         { 0x8e, 0 },
-               { 0x8f, 0 },            { 0x90, 0 },
-               { 0x91, 0 },            { 0x96, 0 },
-               { 0x9a, 0 },            { 0xb0, 0x84 },
-               { 0xb1, 0x0c },         { 0xb2, 0x0e },
-               { 0xb3, 0x82 },         { 0xb8, 0x0a },
-
-       /* More reserved magic, some of which tweaks white balance */
-               { 0x43, 0x0a },         { 0x44, 0xf0 },
-               { 0x45, 0x34 },         { 0x46, 0x58 },
-               { 0x47, 0x28 },         { 0x48, 0x3a },
-               { 0x59, 0x88 },         { 0x5a, 0x88 },
-               { 0x5b, 0x44 },         { 0x5c, 0x67 },
-               { 0x5d, 0x49 },         { 0x5e, 0x0e },
-               { 0x6c, 0x0a },         { 0x6d, 0x55 },
-               { 0x6e, 0x11 },         { 0x6f, 0x9f },
-                                               /* "9e for advance AWB" */
-               { 0x6a, 0x40 },         { OV7670_REG_BLUE, 0x40 },
-               { OV7670_REG_RED, 0x60 },
-               { OV7670_REG_COM8, OV7670_COM8_FASTAEC
-                               | OV7670_COM8_AECSTEP
-                               | OV7670_COM8_BFILT
-                               | OV7670_COM8_AGC
-                               | OV7670_COM8_AEC
-                               | OV7670_COM8_AWB },
-
-       /* Matrix coefficients */
-               { 0x4f, 0x80 },         { 0x50, 0x80 },
-               { 0x51, 0 },            { 0x52, 0x22 },
-               { 0x53, 0x5e },         { 0x54, 0x80 },
-               { 0x58, 0x9e },
-
-               { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
-               { OV7670_REG_EDGE, 0 },
-               { 0x75, 0x05 },         { 0x76, 0xe1 },
-               { 0x4c, 0 },            { 0x77, 0x01 },
-               { OV7670_REG_COM13, OV7670_COM13_GAMMA
-                                 | OV7670_COM13_UVSAT
-                                 | 2},         /* was 3 */
-               { 0x4b, 0x09 },
-               { 0xc9, 0x60 },         { OV7670_REG_COM16, 0x38 },
-               { 0x56, 0x40 },
-
-               { 0x34, 0x11 },
-               { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
-               { 0xa4, 0x88 },         { 0x96, 0 },
-               { 0x97, 0x30 },         { 0x98, 0x20 },
-               { 0x99, 0x30 },         { 0x9a, 0x84 },
-               { 0x9b, 0x29 },         { 0x9c, 0x03 },
-               { 0x9d, 0x4c },         { 0x9e, 0x3f },
-               { 0x78, 0x04 },
-
-       /* Extra-weird stuff.  Some sort of multiplexor register */
-               { 0x79, 0x01 },         { 0xc8, 0xf0 },
-               { 0x79, 0x0f },         { 0xc8, 0x00 },
-               { 0x79, 0x10 },         { 0xc8, 0x7e },
-               { 0x79, 0x0a },         { 0xc8, 0x80 },
-               { 0x79, 0x0b },         { 0xc8, 0x01 },
-               { 0x79, 0x0c },         { 0xc8, 0x0f },
-               { 0x79, 0x0d },         { 0xc8, 0x20 },
-               { 0x79, 0x09 },         { 0xc8, 0x80 },
-               { 0x79, 0x02 },         { 0xc8, 0xc0 },
-               { 0x79, 0x03 },         { 0xc8, 0x40 },
-               { 0x79, 0x05 },         { 0xc8, 0x30 },
-               { 0x79, 0x26 },
-       };
 
        PDEBUG(D_PROBE, "starting OV7xx0 configuration");
 
@@ -1011,8 +1198,9 @@ static int ov7xx0_configure(struct sd *sd)
                        switch (low) {
                        case 0x30:
                                PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635");
-                               sd->sensor = SEN_OV7630;
-                               break;
+                               PDEBUG(D_ERR,
+                                     "7630 is not supported by this driver");
+                               return -1;
                        case 0x40:
                                PDEBUG(D_PROBE, "Sensor is an OV7645");
                                sd->sensor = SEN_OV7640; /* FIXME */
@@ -1038,32 +1226,6 @@ static int ov7xx0_configure(struct sd *sd)
                return -1;
        }
 
-       switch (sd->sensor) {
-       case SEN_OV7620:
-               PDEBUG(D_PROBE, "Writing 7620 registers");
-               if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
-                       return -1;
-               break;
-       case SEN_OV7630:
-               PDEBUG(D_ERR, "7630 is not supported by this driver version");
-               return -1;
-       case SEN_OV7640:
-               PDEBUG(D_PROBE, "Writing 7640 registers");
-               if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
-                       return -1;
-               break;
-       case SEN_OV7670:
-               PDEBUG(D_PROBE, "Writing 7670 registers");
-               if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
-                       return -1;
-               break;
-       default:
-               PDEBUG(D_PROBE, "Writing 7610 registers");
-               if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
-                       return -1;
-               break;
-       }
-
        /* Set sensor-specific vars */
 /*     sd->sif = 0;            already done */
        return 0;
@@ -1073,141 +1235,7 @@ static int ov7xx0_configure(struct sd *sd)
 static int ov6xx0_configure(struct sd *sd)
 {
        int rc;
-       static const struct ov_i2c_regvals norm_6x20[] = {
-               { 0x12, 0x80 }, /* reset */
-               { 0x11, 0x01 },
-               { 0x03, 0x60 },
-               { 0x05, 0x7f }, /* For when autoadjust is off */
-               { 0x07, 0xa8 },
-               /* The ratio of 0x0c and 0x0d  controls the white point */
-               { 0x0c, 0x24 },
-               { 0x0d, 0x24 },
-               { 0x0f, 0x15 }, /* COMS */
-               { 0x10, 0x75 }, /* AEC Exposure time */
-               { 0x12, 0x24 }, /* Enable AGC */
-               { 0x14, 0x04 },
-               /* 0x16: 0x06 helps frame stability with moving objects */
-               { 0x16, 0x06 },
-/*             { 0x20, 0x30 },  * Aperture correction enable */
-               { 0x26, 0xb2 }, /* BLC enable */
-               /* 0x28: 0x05 Selects RGB format if RGB on */
-               { 0x28, 0x05 },
-               { 0x2a, 0x04 }, /* Disable framerate adjust */
-/*             { 0x2b, 0xac },  * Framerate; Set 2a[7] first */
-               { 0x2d, 0x99 },
-               { 0x33, 0xa0 }, /* Color Processing Parameter */
-               { 0x34, 0xd2 }, /* Max A/D range */
-               { 0x38, 0x8b },
-               { 0x39, 0x40 },
-
-               { 0x3c, 0x39 }, /* Enable AEC mode changing */
-               { 0x3c, 0x3c }, /* Change AEC mode */
-               { 0x3c, 0x24 }, /* Disable AEC mode changing */
-
-               { 0x3d, 0x80 },
-               /* These next two registers (0x4a, 0x4b) are undocumented.
-                * They control the color balance */
-               { 0x4a, 0x80 },
-               { 0x4b, 0x80 },
-               { 0x4d, 0xd2 }, /* This reduces noise a bit */
-               { 0x4e, 0xc1 },
-               { 0x4f, 0x04 },
-/* Do 50-53 have any effect? */
-/* Toggle 0x12[2] off and on here? */
-       };
-
-       static const struct ov_i2c_regvals norm_6x30[] = {
-               { 0x12, 0x80 }, /* Reset */
-               { 0x00, 0x1f }, /* Gain */
-               { 0x01, 0x99 }, /* Blue gain */
-               { 0x02, 0x7c }, /* Red gain */
-               { 0x03, 0xc0 }, /* Saturation */
-               { 0x05, 0x0a }, /* Contrast */
-               { 0x06, 0x95 }, /* Brightness */
-               { 0x07, 0x2d }, /* Sharpness */
-               { 0x0c, 0x20 },
-               { 0x0d, 0x20 },
-               { 0x0e, 0x20 },
-               { 0x0f, 0x05 },
-               { 0x10, 0x9a },
-               { 0x11, 0x00 }, /* Pixel clock = fastest */
-               { 0x12, 0x24 }, /* Enable AGC and AWB */
-               { 0x13, 0x21 },
-               { 0x14, 0x80 },
-               { 0x15, 0x01 },
-               { 0x16, 0x03 },
-               { 0x17, 0x38 },
-               { 0x18, 0xea },
-               { 0x19, 0x04 },
-               { 0x1a, 0x93 },
-               { 0x1b, 0x00 },
-               { 0x1e, 0xc4 },
-               { 0x1f, 0x04 },
-               { 0x20, 0x20 },
-               { 0x21, 0x10 },
-               { 0x22, 0x88 },
-               { 0x23, 0xc0 }, /* Crystal circuit power level */
-               { 0x25, 0x9a }, /* Increase AEC black ratio */
-               { 0x26, 0xb2 }, /* BLC enable */
-               { 0x27, 0xa2 },
-               { 0x28, 0x00 },
-               { 0x29, 0x00 },
-               { 0x2a, 0x84 }, /* 60 Hz power */
-               { 0x2b, 0xa8 }, /* 60 Hz power */
-               { 0x2c, 0xa0 },
-               { 0x2d, 0x95 }, /* Enable auto-brightness */
-               { 0x2e, 0x88 },
-               { 0x33, 0x26 },
-               { 0x34, 0x03 },
-               { 0x36, 0x8f },
-               { 0x37, 0x80 },
-               { 0x38, 0x83 },
-               { 0x39, 0x80 },
-               { 0x3a, 0x0f },
-               { 0x3b, 0x3c },
-               { 0x3c, 0x1a },
-               { 0x3d, 0x80 },
-               { 0x3e, 0x80 },
-               { 0x3f, 0x0e },
-               { 0x40, 0x00 }, /* White bal */
-               { 0x41, 0x00 }, /* White bal */
-               { 0x42, 0x80 },
-               { 0x43, 0x3f }, /* White bal */
-               { 0x44, 0x80 },
-               { 0x45, 0x20 },
-               { 0x46, 0x20 },
-               { 0x47, 0x80 },
-               { 0x48, 0x7f },
-               { 0x49, 0x00 },
-               { 0x4a, 0x00 },
-               { 0x4b, 0x80 },
-               { 0x4c, 0xd0 },
-               { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
-               { 0x4e, 0x40 },
-               { 0x4f, 0x07 }, /* UV avg., col. killer: max */
-               { 0x50, 0xff },
-               { 0x54, 0x23 }, /* Max AGC gain: 18dB */
-               { 0x55, 0xff },
-               { 0x56, 0x12 },
-               { 0x57, 0x81 },
-               { 0x58, 0x75 },
-               { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
-               { 0x5a, 0x2c },
-               { 0x5b, 0x0f }, /* AWB chrominance levels */
-               { 0x5c, 0x10 },
-               { 0x3d, 0x80 },
-               { 0x27, 0xa6 },
-               { 0x12, 0x20 }, /* Toggle AWB */
-               { 0x12, 0x24 },
-       };
-
-       PDEBUG(D_PROBE, "starting sensor configuration");
-
-       if (init_ov_sensor(sd) < 0) {
-               PDEBUG(D_ERR, "Failed to read sensor ID.");
-               return -1;
-       }
-       PDEBUG(D_PROBE, "OV6xx0 sensor detected");
+       PDEBUG(D_PROBE, "starting OV6xx0 configuration");
 
        /* Detect sensor (sub)type */
        rc = i2c_r(sd, OV7610_REG_COM_I);
@@ -1251,15 +1279,6 @@ static int ov6xx0_configure(struct sd *sd)
        /* Set sensor-specific vars */
        sd->sif = 1;
 
-       if (sd->sensor == SEN_OV6620) {
-               PDEBUG(D_PROBE, "Writing 6x20 registers");
-               if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
-                       return -1;
-       } else {
-               PDEBUG(D_PROBE, "Writing 6x30 registers");
-               if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
-                       return -1;
-       }
        return 0;
 }
 
@@ -1298,22 +1317,31 @@ static int sd_config(struct gspca_dev *gspca_dev,
        ov51x_led_control(sd, 0);       /* turn LED off */
 
        /* Test for 76xx */
-       sd->primary_i2c_slave = OV7xx0_SID;
        if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0)
                goto error;
 
        /* The OV519 must be more aggressive about sensor detection since
         * I2C write will never fail if the sensor is not present. We have
         * to try to initialize the sensor to detect its presence */
-       if (init_ov_sensor(sd) < 0) {
+       if (init_ov_sensor(sd) >= 0) {
+               if (ov7xx0_configure(sd) < 0) {
+                       PDEBUG(D_ERR, "Failed to configure OV7xx0");
+                       goto error;
+               }
+       } else {
+
                /* Test for 6xx0 */
-               sd->primary_i2c_slave = OV6xx0_SID;
                if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0)
                        goto error;
 
-               if (init_ov_sensor(sd) < 0) {
+               if (init_ov_sensor(sd) >= 0) {
+                       if (ov6xx0_configure(sd) < 0) {
+                               PDEBUG(D_ERR, "Failed to configure OV6xx0");
+                               goto error;
+                       }
+               } else {
+
                        /* Test for 8xx0 */
-                       sd->primary_i2c_slave = OV8xx0_SID;
                        if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0)
                                goto error;
 
@@ -1321,24 +1349,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
                                PDEBUG(D_ERR,
                                        "Can't determine sensor slave IDs");
                                goto error;
-                       } else {
-                               if (ov8xx0_configure(sd) < 0) {
-                                       PDEBUG(D_ERR,
-                                          "Failed to configure OV8xx0 sensor");
-                                       goto error;
-                               }
                        }
-               } else {
-                       if (ov6xx0_configure(sd) < 0) {
-                               PDEBUG(D_ERR, "Failed to configure OV6xx0");
+                       if (ov8xx0_configure(sd) < 0) {
+                               PDEBUG(D_ERR,
+                                  "Failed to configure OV8xx0 sensor");
                                goto error;
                        }
                }
-       } else {
-               if (ov7xx0_configure(sd) < 0) {
-                       PDEBUG(D_ERR, "Failed to configure OV7xx0");
-                       goto error;
-               }
        }
 
        cam = &gspca_dev->cam;
@@ -1355,15 +1372,53 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->colors = COLOR_DEF;
        sd->hflip = HFLIP_DEF;
        sd->vflip = VFLIP_DEF;
+       if (sd->sensor != SEN_OV7670)
+               gspca_dev->ctrl_dis = (1 << HFLIP_IDX)
+                                       | (1 << VFLIP_IDX);
        return 0;
 error:
        PDEBUG(D_ERR, "OV519 Config failed");
        return -EBUSY;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* initialize the sensor */
+       switch (sd->sensor) {
+       case SEN_OV6620:
+               if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
+                       return -EIO;
+               break;
+       case SEN_OV6630:
+               if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
+                       return -EIO;
+               break;
+       default:
+/*     case SEN_OV7610: */
+/*     case SEN_OV76BE: */
+               if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
+                       return -EIO;
+               break;
+       case SEN_OV7620:
+               if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
+                       return -EIO;
+               break;
+       case SEN_OV7640:
+               if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
+                       return -EIO;
+               break;
+       case SEN_OV7670:
+               if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
+                       return -EIO;
+               break;
+       case SEN_OV8610:
+               if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
+                       return -EIO;
+               break;
+       }
        return 0;
 }
 
@@ -1827,14 +1882,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        ov51x_led_control((struct sd *) gspca_dev, 0);
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -2091,11 +2138,9 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -2132,6 +2177,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 7ef18d57881156de5cd5f125d410e9632e7112b3..83b5f740c9470960b3bf42aef54472726bbce098 100644 (file)
@@ -56,12 +56,6 @@ MODULE_LICENSE("GPL");
 #define PAC207_GAIN_KNEE               20
 
 #define PAC207_AUTOGAIN_DEADZONE       30
-/* We calculating the autogain at the end of the transfer of a frame, at this
-   moment a frame with the old settings is being transmitted, and a frame is
-   being captured with the old settings. So if we adjust the autogain we must
-   ignore atleast the 2 next frames for the new settings to come into effect
-   before doing any other adjustments */
-#define PAC207_AUTOGAIN_IGNORE_FRAMES  3
 
 /* specific webcam descriptor */
 struct sd {
@@ -131,7 +125,8 @@ static struct ctrl sd_ctrls[] = {
                .minimum = 0,
                .maximum = 1,
                .step   = 1,
-               .default_value = 1,
+#define AUTOGAIN_DEF 1
+               .default_value = AUTOGAIN_DEF,
                .flags = 0,
            },
            .set = sd_setautogain,
@@ -181,9 +176,6 @@ static const __u8 pac207_sensor_init[][8] = {
                        /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
 static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
 
-static const unsigned char pac207_sof_marker[5] =
-               { 0xff, 0xff, 0x00, 0xff, 0x96 };
-
 static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
        const u8 *buffer, u16 length)
 {
@@ -259,35 +251,32 @@ static int sd_config(struct gspca_dev *gspca_dev,
                return -ENODEV;
        }
 
-       pac207_write_reg(gspca_dev, 0x41, 0x00);
-                               /* Bit_0=Image Format,
-                                * Bit_1=LED,
-                                * Bit_2=Compression test mode enable */
-       pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
-       pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
-
        PDEBUG(D_PROBE,
                "Pixart PAC207BCA Image Processor and Control Chip detected"
                " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x05;
        cam->cam_mode = sif_mode;
        cam->nmodes = ARRAY_SIZE(sif_mode);
        sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
        sd->exposure = PAC207_EXPOSURE_DEFAULT;
        sd->gain = PAC207_GAIN_DEFAULT;
+       sd->autogain = AUTOGAIN_DEF;
 
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
-       struct sd *sd = (struct sd *) gspca_dev;
+       pac207_write_reg(gspca_dev, 0x41, 0x00);
+                               /* Bit_0=Image Format,
+                                * Bit_1=LED,
+                                * Bit_2=Compression test mode enable */
+       pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
+       pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
 
-       sd->autogain = 1;
        return 0;
 }
 
@@ -343,14 +332,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
+/* Include pac common sof detection functions */
+#include "pac_common.h"
 
 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
 {
@@ -365,33 +348,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
        else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
                        100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
                        PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
-               sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
-}
-
-static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
-                                       unsigned char *m, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-
-       /* Search for the SOF marker (fixed part) in the header */
-       for (i = 0; i < len; i++) {
-               if (m[i] == pac207_sof_marker[sd->sof_read]) {
-                       sd->sof_read++;
-                       if (sd->sof_read == sizeof(pac207_sof_marker)) {
-                               PDEBUG(D_STREAM,
-                                       "SOF found, bytes to analyze: %u."
-                                       " Frame starts at byte #%u",
-                                       len, i + 1);
-                               sd->sof_read = 0;
-                               return m + i + 1;
-                       }
-               } else {
-                       sd->sof_read = 0;
-               }
-       }
-
-       return NULL;
+               sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -402,14 +359,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
        struct sd *sd = (struct sd *) gspca_dev;
        unsigned char *sof;
 
-       sof = pac207_find_sof(gspca_dev, data, len);
+       sof = pac_find_sof(gspca_dev, data, len);
        if (sof) {
                int n;
 
                /* finish decoding current frame */
                n = sof - data;
-               if (n > sizeof pac207_sof_marker)
-                       n -= sizeof pac207_sof_marker;
+               if (n > sizeof pac_sof_marker)
+                       n -= sizeof pac_sof_marker;
                else
                        n = 0;
                frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
@@ -537,7 +494,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
                sd->gain = PAC207_GAIN_DEFAULT;
                if (gspca_dev->streaming) {
                        sd->autogain_ignore_frames =
-                               PAC207_AUTOGAIN_IGNORE_FRAMES;
+                               PAC_AUTOGAIN_IGNORE_FRAMES;
                        setexposure(gspca_dev);
                        setgain(gspca_dev);
                }
@@ -560,11 +517,9 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .dq_callback = pac207_do_auto_gain,
        .pkt_scan = sd_pkt_scan,
 };
@@ -597,6 +552,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 815bea6edc448f989ac9a8f4df41ea7067b1dc29..d4be51843286dccc0f5af80502e96ca89e42eb19 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+/* Some documentation about various registers as determined by trial and error.
+   When the register addresses differ between the 7202 and the 7311 the 2
+   different addresses are written as 7302addr/7311addr, when one of the 2
+   addresses is a - sign that register description is not valid for the
+   matching IC.
+
+   Register page 1:
+
+   Address     Description
+   -/0x08      Unknown compressor related, must always be 8 except when not
+               in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
+   -/0x1b      Auto white balance related, bit 0 is AWB enable (inverted)
+               bits 345 seem to toggle per color gains on/off (inverted)
+   0x78                Global control, bit 6 controls the LED (inverted)
+   -/0x80      JPEG compression ratio ? Best not touched
+
+   Register page 3/4:
+
+   Address     Description
+   0x02                Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
+               the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
+   -/0x0f      Master gain 1-245, low value = high gain
+   0x10/-      Master gain 0-31
+   -/0x10      Another gain 0-15, limited influence (1-2x gain I guess)
+   0x21                Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
+   -/0x27      Seems to toggle various gains on / off, Setting bit 7 seems to
+               completely disable the analog amplification block. Set to 0x68
+               for max gain, 0x14 for minimal gain.
+*/
+
 #define MODULE_NAME "pac7311"
 
 #include "gspca.h"
@@ -31,18 +61,23 @@ MODULE_LICENSE("GPL");
 struct sd {
        struct gspca_dev gspca_dev;             /* !! must be the first item */
 
-       int lum_sum;
-       atomic_t avg_lum;
-       atomic_t do_gain;
-
        unsigned char brightness;
        unsigned char contrast;
        unsigned char colors;
+       unsigned char gain;
+       unsigned char exposure;
        unsigned char autogain;
+       __u8 hflip;
+       __u8 vflip;
+
+       __u8 sensor;
+#define SENSOR_PAC7302 0
+#define SENSOR_PAC7311 1
 
-       char ffseq;
-       signed char ag_cnt;
-#define AG_CNT_START 13
+       u8 sof_read;
+       u8 autogain_ignore_frames;
+
+       atomic_t avg_lum;
 };
 
 /* V4L2 controls supported by the driver */
@@ -54,8 +89,18 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
+/* This control is pac7302 only */
+#define BRIGHTNESS_IDX 0
        {
            {
                .id      = V4L2_CID_BRIGHTNESS,
@@ -71,13 +116,15 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setbrightness,
            .get = sd_getbrightness,
        },
+/* This control is for both the 7302 and the 7311 */
        {
            {
                .id      = V4L2_CID_CONTRAST,
                .type    = V4L2_CTRL_TYPE_INTEGER,
                .name    = "Contrast",
                .minimum = 0,
-               .maximum = 255,
+#define CONTRAST_MAX 255
+               .maximum = CONTRAST_MAX,
                .step    = 1,
 #define CONTRAST_DEF 127
                .default_value = CONTRAST_DEF,
@@ -85,13 +132,16 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setcontrast,
            .get = sd_getcontrast,
        },
+/* This control is pac7302 only */
+#define SATURATION_IDX 2
        {
            {
                .id      = V4L2_CID_SATURATION,
                .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Color",
+               .name    = "Saturation",
                .minimum = 0,
-               .maximum = 255,
+#define COLOR_MAX 255
+               .maximum = COLOR_MAX,
                .step    = 1,
 #define COLOR_DEF 127
                .default_value = COLOR_DEF,
@@ -99,6 +149,39 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setcolors,
            .get = sd_getcolors,
        },
+/* All controls below are for both the 7302 and the 7311 */
+       {
+           {
+               .id      = V4L2_CID_GAIN,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Gain",
+               .minimum = 0,
+#define GAIN_MAX 255
+               .maximum = GAIN_MAX,
+               .step    = 1,
+#define GAIN_DEF 127
+#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
+               .default_value = GAIN_DEF,
+           },
+           .set = sd_setgain,
+           .get = sd_getgain,
+       },
+       {
+           {
+               .id      = V4L2_CID_EXPOSURE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Exposure",
+               .minimum = 0,
+#define EXPOSURE_MAX 255
+               .maximum = EXPOSURE_MAX,
+               .step    = 1,
+#define EXPOSURE_DEF  16 /*  32 ms / 30 fps */
+#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
+               .default_value = EXPOSURE_DEF,
+           },
+           .set = sd_setexposure,
+           .get = sd_getexposure,
+       },
        {
            {
                .id      = V4L2_CID_AUTOGAIN,
@@ -113,101 +196,207 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setautogain,
            .get = sd_getautogain,
        },
+       {
+           {
+               .id      = V4L2_CID_HFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Mirror",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+#define HFLIP_DEF 0
+               .default_value = HFLIP_DEF,
+           },
+           .set = sd_sethflip,
+           .get = sd_gethflip,
+       },
+       {
+           {
+               .id      = V4L2_CID_VFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Vflip",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+#define VFLIP_DEF 0
+               .default_value = VFLIP_DEF,
+           },
+           .set = sd_setvflip,
+           .get = sd_getvflip,
+       },
 };
 
 static struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+       {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
                .bytesperline = 160,
                .sizeimage = 160 * 120 * 3 / 8 + 590,
                .colorspace = V4L2_COLORSPACE_JPEG,
                .priv = 2},
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+       {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
                .bytesperline = 320,
                .sizeimage = 320 * 240 * 3 / 8 + 590,
                .colorspace = V4L2_COLORSPACE_JPEG,
                .priv = 1},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+       {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
                .bytesperline = 640,
                .sizeimage = 640 * 480 * 3 / 8 + 590,
                .colorspace = V4L2_COLORSPACE_JPEG,
                .priv = 0},
 };
 
-#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header)  /* (594) */
-
-static const __u8 pac7311_jpeg_header[] = {
-       0xff, 0xd8,
-       0xff, 0xe0, 0x00, 0x03, 0x20,
-       0xff, 0xc0, 0x00, 0x11, 0x08,
-               0x01, 0xe0,                     /* 12: height */
-               0x02, 0x80,                     /* 14: width */
-               0x03,                           /* 16 */
-                       0x01, 0x21, 0x00,
-                       0x02, 0x11, 0x01,
-                       0x03, 0x11, 0x01,
-       0xff, 0xdb, 0x00, 0x84,
-       0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
-       0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
-       0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
-       0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
-       0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
-       0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
-       0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
-       0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-       0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
-       0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
-       0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
-       0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
-       0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
-       0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
-       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
-       0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
-       0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
-       0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
-       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
-       0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
-       0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
-       0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-       0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
-       0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
-       0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-       0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
-       0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
-       0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
-       0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
-       0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
-       0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
-       0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
-       0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
-       0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-       0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
-       0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
-       0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
-       0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
-       0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-       0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
-       0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-       0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
-       0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
-       0x11, 0x00, 0x3f, 0x00
+/* pac 7302 */
+static const __u8 init_7302[] = {
+/*     index,value */
+       0xff, 0x01,             /* page 1 */
+       0x78, 0x00,             /* deactivate */
+       0xff, 0x01,
+       0x78, 0x40,             /* led off */
+};
+static const __u8 start_7302[] = {
+/*     index, len, [value]* */
+       0xff, 1,        0x00,           /* page 0 */
+       0x00, 12,       0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
+                       0x00, 0x00, 0x00, 0x00,
+       0x0d, 24,       0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
+                       0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
+                       0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
+       0x26, 2,        0xaa, 0xaa,
+       0x2e, 1,        0x31,
+       0x38, 1,        0x01,
+       0x3a, 3,        0x14, 0xff, 0x5a,
+       0x43, 11,       0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
+                       0x00, 0x54, 0x11,
+       0x55, 1,        0x00,
+       0x62, 4,        0x10, 0x1e, 0x1e, 0x18,
+       0x6b, 1,        0x00,
+       0x6e, 3,        0x08, 0x06, 0x00,
+       0x72, 3,        0x00, 0xff, 0x00,
+       0x7d, 23,       0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
+                       0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
+                       0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
+       0xa2, 10,       0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
+                       0xd2, 0xeb,
+       0xaf, 1,        0x02,
+       0xb5, 2,        0x08, 0x08,
+       0xb8, 2,        0x08, 0x88,
+       0xc4, 4,        0xae, 0x01, 0x04, 0x01,
+       0xcc, 1,        0x00,
+       0xd1, 11,       0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
+                       0xc1, 0xd7, 0xec,
+       0xdc, 1,        0x01,
+       0xff, 1,        0x01,           /* page 1 */
+       0x12, 3,        0x02, 0x00, 0x01,
+       0x3e, 2,        0x00, 0x00,
+       0x76, 5,        0x01, 0x20, 0x40, 0x00, 0xf2,
+       0x7c, 1,        0x00,
+       0x7f, 10,       0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
+                       0x02, 0x00,
+       0x96, 5,        0x01, 0x10, 0x04, 0x01, 0x04,
+       0xc8, 14,       0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+                       0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
+       0xd8, 1,        0x01,
+       0xdb, 2,        0x00, 0x01,
+       0xde, 7,        0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
+       0xe6, 4,        0x00, 0x00, 0x00, 0x01,
+       0xeb, 1,        0x00,
+       0xff, 1,        0x02,           /* page 2 */
+       0x22, 1,        0x00,
+       0xff, 1,        0x03,           /* page 3 */
+       0x00, 255,                      /* load the page 3 */
+       0x11, 1,        0x01,
+       0xff, 1,        0x02,           /* page 2 */
+       0x13, 1,        0x00,
+       0x22, 4,        0x1f, 0xa4, 0xf0, 0x96,
+       0x27, 2,        0x14, 0x0c,
+       0x2a, 5,        0xc8, 0x00, 0x18, 0x12, 0x22,
+       0x64, 8,        0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
+       0x6e, 1,        0x08,
+       0xff, 1,        0x01,           /* page 1 */
+       0x78, 1,        0x00,
+       0, 0                            /* end of sequence */
+};
+
+/* page 3 - the value 0xaa says skip the index - see reg_w_page() */
+static const __u8 page3_7302[] = {
+       0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
+       0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
+       0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
+       0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
+       0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
+       0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
+       0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
+       0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
+       0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+       0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
+       0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
+       0x00
+};
+
+/* pac 7311 */
+static const __u8 init_7311[] = {
+       0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
+       0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
+       0x78, 0x44,     /* Bit_0=start stream, Bit_6=LED */
+       0xff, 0x04,
+       0x27, 0x80,
+       0x28, 0xca,
+       0x29, 0x53,
+       0x2a, 0x0e,
+       0xff, 0x01,
+       0x3e, 0x20,
+};
+
+static const __u8 start_7311[] = {
+/*     index, len, [value]* */
+       0xff, 1,        0x01,           /* page 1 */
+       0x02, 43,       0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
+                       0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
+                       0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
+                       0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00,
+       0x3e, 42,       0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
+                       0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
+                       0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
+                       0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
+                       0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
+                       0xd0, 0xff,
+       0x78, 6,        0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
+       0x7f, 18,       0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
+                       0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
+                       0x18, 0x20,
+       0x96, 3,        0x01, 0x08, 0x04,
+       0xa0, 4,        0x44, 0x44, 0x44, 0x04,
+       0xf0, 13,       0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
+                       0x3f, 0x00, 0x0a, 0x01, 0x00,
+       0xff, 1,        0x04,           /* page 4 */
+       0x00, 254,                      /* load the page 4 */
+       0x11, 1,        0x01,
+       0, 0                            /* end of sequence */
+};
+
+/* page 4 - the value 0xaa says skip the index - see reg_w_page() */
+static const __u8 page4_7311[] = {
+       0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
+       0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
+       0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
+       0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68,
+       0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
+       0x23, 0x28, 0x04, 0x11, 0x00, 0x00
 };
 
 static void reg_w_buf(struct gspca_dev *gspca_dev,
-                 __u16 index,
-                 const char *buffer, __u16 len)
+                 __u8 index,
+                 const char *buffer, int len)
 {
        memcpy(gspca_dev->usb_buf, buffer, len);
        usb_control_msg(gspca_dev->dev,
@@ -219,21 +408,9 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
                        500);
 }
 
-static __u8 reg_r(struct gspca_dev *gspca_dev,
-                            __u16 index)
-{
-       usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0,                      /* request */
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,                      /* value */
-                       index, gspca_dev->usb_buf, 1,
-                       500);
-       return gspca_dev->usb_buf[0];
-}
 
 static void reg_w(struct gspca_dev *gspca_dev,
-                 __u16 index,
+                 __u8 index,
                  __u8 value)
 {
        gspca_dev->usb_buf[0] = value;
@@ -241,10 +418,78 @@ static void reg_w(struct gspca_dev *gspca_dev,
                        usb_sndctrlpipe(gspca_dev->dev, 0),
                        0,                      /* request */
                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, gspca_dev->usb_buf, 1,
+                       0, index, gspca_dev->usb_buf, 1,
                        500);
 }
 
+static void reg_w_seq(struct gspca_dev *gspca_dev,
+               const __u8 *seq, int len)
+{
+       while (--len >= 0) {
+               reg_w(gspca_dev, seq[0], seq[1]);
+               seq += 2;
+       }
+}
+
+/* load the beginning of a page */
+static void reg_w_page(struct gspca_dev *gspca_dev,
+                       const __u8 *page, int len)
+{
+       int index;
+
+       for (index = 0; index < len; index++) {
+               if (page[index] == 0xaa)                /* skip this index */
+                       continue;
+               gspca_dev->usb_buf[0] = page[index];
+               usb_control_msg(gspca_dev->dev,
+                               usb_sndctrlpipe(gspca_dev->dev, 0),
+                               0,                      /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               0, index, gspca_dev->usb_buf, 1,
+                               500);
+       }
+}
+
+/* output a variable sequence */
+static void reg_w_var(struct gspca_dev *gspca_dev,
+                       const __u8 *seq)
+{
+       int index, len;
+
+       for (;;) {
+               index = *seq++;
+               len = *seq++;
+               switch (len) {
+               case 0:
+                       return;
+               case 254:
+                       reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
+                       break;
+               case 255:
+                       reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
+                       break;
+               default:
+                       if (len > 64) {
+                               PDEBUG(D_ERR|D_STREAM,
+                                       "Incorrect variable sequence");
+                               return;
+                       }
+                       while (len > 0) {
+                               if (len < 8) {
+                                       reg_w_buf(gspca_dev, index, seq, len);
+                                       seq += len;
+                                       break;
+                               }
+                               reg_w_buf(gspca_dev, index, seq, 8);
+                               seq += 8;
+                               index += 8;
+                               len -= 8;
+                       }
+               }
+       }
+       /* not reached */
+}
+
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
                        const struct usb_device_id *id)
@@ -252,203 +497,245 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
 
-       PDEBUG(D_CONF, "Find Sensor PAC7311");
-       reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
-       reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
-       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
-       reg_w(gspca_dev, 0xff, 0x04);
-       reg_w(gspca_dev, 0x27, 0x80);
-       reg_w(gspca_dev, 0x28, 0xca);
-       reg_w(gspca_dev, 0x29, 0x53);
-       reg_w(gspca_dev, 0x2a, 0x0e);
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x3e, 0x20);
-
        cam = &gspca_dev->cam;
        cam->epaddr = 0x05;
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
+
+       sd->sensor = id->driver_info;
+       if (sd->sensor == SENSOR_PAC7302) {
+               PDEBUG(D_CONF, "Find Sensor PAC7302");
+               cam->cam_mode = &vga_mode[2];   /* only 640x480 */
+               cam->nmodes = 1;
+       } else {
+               PDEBUG(D_CONF, "Find Sensor PAC7311");
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+               gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX)
+                               | (1 << SATURATION_IDX);
+       }
 
        sd->brightness = BRIGHTNESS_DEF;
        sd->contrast = CONTRAST_DEF;
        sd->colors = COLOR_DEF;
+       sd->gain = GAIN_DEF;
+       sd->exposure = EXPOSURE_DEF;
        sd->autogain = AUTOGAIN_DEF;
-       sd->ag_cnt = -1;
+       sd->hflip = HFLIP_DEF;
+       sd->vflip = VFLIP_DEF;
        return 0;
 }
 
-static void setbrightness(struct gspca_dev *gspca_dev)
+/* This function is used by pac7302 only */
+static void setbrightcont(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, v;
+       static const __u8 max[10] =
+               {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
+                0xd4, 0xec};
+       static const __u8 delta[10] =
+               {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
+                0x11, 0x0b};
+
+       reg_w(gspca_dev, 0xff, 0x00);   /* page 0 */
+       for (i = 0; i < 10; i++) {
+               v = max[i];
+               v += (sd->brightness - BRIGHTNESS_MAX)
+                       * 150 / BRIGHTNESS_MAX;         /* 200 ? */
+               v -= delta[i] * sd->contrast / CONTRAST_MAX;
+               if (v < 0)
+                       v = 0;
+               else if (v > 0xff)
+                       v = 0xff;
+               reg_w(gspca_dev, 0xa2 + i, v);
+       }
+       reg_w(gspca_dev, 0xdc, 0x01);
+}
+
+/* This function is used by pac7311 only */
+static void setcontrast(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       int brightness;
 
-/*jfm: inverted?*/
-       brightness = BRIGHTNESS_MAX - sd->brightness;
        reg_w(gspca_dev, 0xff, 0x04);
-/*     reg_w(gspca_dev, 0x0e, 0x00); */
-       reg_w(gspca_dev, 0x0f, brightness);
+       reg_w(gspca_dev, 0x10, sd->contrast >> 4);
        /* load registers to sensor (Bit 0, auto clear) */
        reg_w(gspca_dev, 0x11, 0x01);
-       PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
 }
 
-static void setcontrast(struct gspca_dev *gspca_dev)
+/* This function is used by pac7302 only */
+static void setcolors(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
+       int i, v;
+       static const int a[9] =
+               {217, -212, 0, -101, 170, -67, -38, -315, 355};
+       static const int b[9] =
+               {19, 106, 0, 19, 106, 1, 19, 106, 1};
 
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x80, sd->contrast);
-       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0xff, 0x03);   /* page 3 */
        reg_w(gspca_dev, 0x11, 0x01);
-       PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
+       reg_w(gspca_dev, 0xff, 0x00);   /* page 0 */
+       reg_w(gspca_dev, 0xff, 0x00);   /* page 0 */
+       for (i = 0; i < 9; i++) {
+               v = a[i] * sd->colors / COLOR_MAX + b[i];
+               reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
+               reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
+       }
+       reg_w(gspca_dev, 0xdc, 0x01);
+       PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
 }
 
-static void setcolors(struct gspca_dev *gspca_dev)
+static void setgain(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x10, sd->colors);
+       if (sd->sensor == SENSOR_PAC7302) {
+               reg_w(gspca_dev, 0xff, 0x03);           /* page 3 */
+               reg_w(gspca_dev, 0x10, sd->gain >> 3);
+       } else {
+               int gain = GAIN_MAX - sd->gain;
+               if (gain < 1)
+                       gain = 1;
+               else if (gain > 245)
+                       gain = 245;
+               reg_w(gspca_dev, 0xff, 0x04);           /* page 4 */
+               reg_w(gspca_dev, 0x0e, 0x00);
+               reg_w(gspca_dev, 0x0f, gain);
+       }
        /* load registers to sensor (Bit 0, auto clear) */
        reg_w(gspca_dev, 0x11, 0x01);
-       PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
 }
 
-static void setautogain(struct gspca_dev *gspca_dev)
+static void setexposure(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
+       __u8 reg;
+
+       /* register 2 of frame 3/4 contains the clock divider configuring the
+          no fps according to the formula: 60 / reg. sd->exposure is the
+          desired exposure time in ms. */
+       reg = 120 * sd->exposure / 1000;
+       if (reg < 2)
+               reg = 2;
+       else if (reg > 63)
+               reg = 63;
+
+       if (sd->sensor == SENSOR_PAC7302) {
+               /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
+                  the nearest multiple of 3, except when between 6 and 12? */
+               if (reg < 6 || reg > 12)
+                       reg = ((reg + 1) / 3) * 3;
+               reg_w(gspca_dev, 0xff, 0x03);           /* page 3 */
+               reg_w(gspca_dev, 0x02, reg);
+       } else {
+               reg_w(gspca_dev, 0xff, 0x04);           /* page 4 */
+               reg_w(gspca_dev, 0x02, reg);
+               /* Page 1 register 8 must always be 0x08 except when not in
+                  640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
+               reg_w(gspca_dev, 0xff, 0x01);
+               if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
+                               reg <= 3)
+                       reg_w(gspca_dev, 0x08, 0x09);
+               else
+                       reg_w(gspca_dev, 0x08, 0x08);
+       }
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+}
 
-       if (sd->autogain) {
-               sd->lum_sum = 0;
-               sd->ag_cnt = AG_CNT_START;
+static void sethvflip(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u8 data;
+
+       if (sd->sensor == SENSOR_PAC7302) {
+               reg_w(gspca_dev, 0xff, 0x03);           /* page 3 */
+               data = (sd->hflip ? 0x08 : 0x00)
+                       | (sd->vflip ? 0x04 : 0x00);
        } else {
-               sd->ag_cnt = -1;
+               reg_w(gspca_dev, 0xff, 0x04);           /* page 4 */
+               data = (sd->hflip ? 0x04 : 0x00)
+                       | (sd->vflip ? 0x08 : 0x00);
        }
+       reg_w(gspca_dev, 0x21, data);
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
-       reg_w(gspca_dev, 0x78, 0x00);   /* Turn on LED */
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PAC7302)
+               reg_w_seq(gspca_dev, init_7302, sizeof init_7302);
+       else
+               reg_w_seq(gspca_dev, init_7311, sizeof init_7311);
+
        return 0;
 }
 
 static void sd_start(struct gspca_dev *gspca_dev)
 {
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
-       reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
-       reg_w_buf(gspca_dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
-       reg_w_buf(gspca_dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
-       reg_w_buf(gspca_dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
-       reg_w_buf(gspca_dev, 0x002a, "\x00\x00\x00", 3);
-       reg_w_buf(gspca_dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
-       reg_w_buf(gspca_dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
-       reg_w_buf(gspca_dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
-       reg_w_buf(gspca_dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
-       reg_w_buf(gspca_dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
-       reg_w_buf(gspca_dev, 0x0066, "\xd0\xff", 2);
-       reg_w_buf(gspca_dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
-       reg_w_buf(gspca_dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
-       reg_w_buf(gspca_dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
-       reg_w_buf(gspca_dev, 0x008f, "\x18\x20", 2);
-       reg_w_buf(gspca_dev, 0x0096, "\x01\x08\x04", 3);
-       reg_w_buf(gspca_dev, 0x00a0, "\x44\x44\x44\x04", 4);
-       reg_w_buf(gspca_dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
-       reg_w_buf(gspca_dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
+       struct sd *sd = (struct sd *) gspca_dev;
 
-       reg_w(gspca_dev, 0xff, 0x04);
-       reg_w(gspca_dev, 0x02, 0x04);
-       reg_w(gspca_dev, 0x03, 0x54);
-       reg_w(gspca_dev, 0x04, 0x07);
-       reg_w(gspca_dev, 0x05, 0x2b);
-       reg_w(gspca_dev, 0x06, 0x09);
-       reg_w(gspca_dev, 0x07, 0x0f);
-       reg_w(gspca_dev, 0x08, 0x09);
-       reg_w(gspca_dev, 0x09, 0x00);
-       reg_w(gspca_dev, 0x0c, 0x07);
-       reg_w(gspca_dev, 0x0d, 0x00);
-       reg_w(gspca_dev, 0x0e, 0x00);
-       reg_w(gspca_dev, 0x0f, 0x62);
-       reg_w(gspca_dev, 0x10, 0x08);
-       reg_w(gspca_dev, 0x12, 0x07);
-       reg_w(gspca_dev, 0x13, 0x00);
-       reg_w(gspca_dev, 0x14, 0x00);
-       reg_w(gspca_dev, 0x15, 0x00);
-       reg_w(gspca_dev, 0x16, 0x00);
-       reg_w(gspca_dev, 0x17, 0x00);
-       reg_w(gspca_dev, 0x18, 0x00);
-       reg_w(gspca_dev, 0x19, 0x00);
-       reg_w(gspca_dev, 0x1a, 0x00);
-       reg_w(gspca_dev, 0x1b, 0x03);
-       reg_w(gspca_dev, 0x1c, 0xa0);
-       reg_w(gspca_dev, 0x1d, 0x01);
-       reg_w(gspca_dev, 0x1e, 0xf4);
-       reg_w(gspca_dev, 0x21, 0x00);
-       reg_w(gspca_dev, 0x22, 0x08);
-       reg_w(gspca_dev, 0x24, 0x03);
-       reg_w(gspca_dev, 0x26, 0x00);
-       reg_w(gspca_dev, 0x27, 0x01);
-       reg_w(gspca_dev, 0x28, 0xca);
-       reg_w(gspca_dev, 0x29, 0x10);
-       reg_w(gspca_dev, 0x2a, 0x06);
-       reg_w(gspca_dev, 0x2b, 0x78);
-       reg_w(gspca_dev, 0x2c, 0x00);
-       reg_w(gspca_dev, 0x2d, 0x00);
-       reg_w(gspca_dev, 0x2e, 0x00);
-       reg_w(gspca_dev, 0x2f, 0x00);
-       reg_w(gspca_dev, 0x30, 0x23);
-       reg_w(gspca_dev, 0x31, 0x28);
-       reg_w(gspca_dev, 0x32, 0x04);
-       reg_w(gspca_dev, 0x33, 0x11);
-       reg_w(gspca_dev, 0x34, 0x00);
-       reg_w(gspca_dev, 0x35, 0x00);
-       reg_w(gspca_dev, 0x11, 0x01);
-       setcontrast(gspca_dev);
-       setbrightness(gspca_dev);
-       setcolors(gspca_dev);
-       setautogain(gspca_dev);
+       sd->sof_read = 0;
+
+       if (sd->sensor == SENSOR_PAC7302) {
+               reg_w_var(gspca_dev, start_7302);
+               setbrightcont(gspca_dev);
+               setcolors(gspca_dev);
+       } else {
+               reg_w_var(gspca_dev, start_7311);
+               setcontrast(gspca_dev);
+       }
+       setgain(gspca_dev);
+       setexposure(gspca_dev);
+       sethvflip(gspca_dev);
 
        /* set correct resolution */
        switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
-       case 2:                                 /* 160x120 */
-               reg_w(gspca_dev, 0xff, 0x04);
-               reg_w(gspca_dev, 0x02, 0x03);
+       case 2:                                 /* 160x120 pac7311 */
                reg_w(gspca_dev, 0xff, 0x01);
-               reg_w(gspca_dev, 0x08, 0x09);
                reg_w(gspca_dev, 0x17, 0x20);
-               reg_w(gspca_dev, 0x1b, 0x00);
-/*             reg_w(gspca_dev, 0x80, 0x69); */
                reg_w(gspca_dev, 0x87, 0x10);
                break;
-       case 1:                                 /* 320x240 */
-               reg_w(gspca_dev, 0xff, 0x04);
-               reg_w(gspca_dev, 0x02, 0x03);
+       case 1:                                 /* 320x240 pac7311 */
                reg_w(gspca_dev, 0xff, 0x01);
-               reg_w(gspca_dev, 0x08, 0x09);
                reg_w(gspca_dev, 0x17, 0x30);
-/*             reg_w(gspca_dev, 0x80, 0x3f); */
                reg_w(gspca_dev, 0x87, 0x11);
                break;
        case 0:                                 /* 640x480 */
-               reg_w(gspca_dev, 0xff, 0x04);
-               reg_w(gspca_dev, 0x02, 0x03);
+               if (sd->sensor == SENSOR_PAC7302)
+                       break;
                reg_w(gspca_dev, 0xff, 0x01);
-               reg_w(gspca_dev, 0x08, 0x08);
                reg_w(gspca_dev, 0x17, 0x00);
-/*             reg_w(gspca_dev, 0x80, 0x1c); */
                reg_w(gspca_dev, 0x87, 0x12);
                break;
        }
 
+       sd->sof_read = 0;
+       sd->autogain_ignore_frames = 0;
+       atomic_set(&sd->avg_lum, -1);
+
        /* start stream */
        reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x78, 0x04);
-       reg_w(gspca_dev, 0x78, 0x05);
+       if (sd->sensor == SENSOR_PAC7302)
+               reg_w(gspca_dev, 0x78, 0x01);
+       else
+               reg_w(gspca_dev, 0x78, 0x05);
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PAC7302) {
+               reg_w(gspca_dev, 0xff, 0x01);
+               reg_w(gspca_dev, 0x78, 0x00);
+               reg_w(gspca_dev, 0x78, 0x00);
+               return;
+       }
        reg_w(gspca_dev, 0xff, 0x04);
        reg_w(gspca_dev, 0x27, 0x80);
        reg_w(gspca_dev, 0x28, 0xca);
@@ -456,187 +743,147 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        reg_w(gspca_dev, 0x2a, 0x0e);
        reg_w(gspca_dev, 0xff, 0x01);
        reg_w(gspca_dev, 0x3e, 0x20);
-       reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
-       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
-       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
+       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
+       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
+       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
 }
 
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
-}
+       struct sd *sd = (struct sd *) gspca_dev;
 
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev, 0xff, 0x04);
-       reg_w(gspca_dev, 0x27, 0x80);
-       reg_w(gspca_dev, 0x28, 0xca);
-       reg_w(gspca_dev, 0x29, 0x53);
-       reg_w(gspca_dev, 0x2a, 0x0e);
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x3e, 0x20);
-       reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
-       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
-       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
+       if (sd->sensor == SENSOR_PAC7302) {
+               reg_w(gspca_dev, 0xff, 0x01);
+               reg_w(gspca_dev, 0x78, 0x40);
+       }
 }
 
+/* Include pac common sof detection functions */
+#include "pac_common.h"
+
 static void do_autogain(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       int luma;
-       int luma_mean = 128;
-       int luma_delta = 20;
-       __u8 spring = 5;
-       int Gbright;
+       int avg_lum = atomic_read(&sd->avg_lum);
+       int desired_lum, deadzone;
 
-       if (!atomic_read(&sd->do_gain))
+       if (avg_lum == -1)
                return;
-       atomic_set(&sd->do_gain, 0);
-
-       luma = atomic_read(&sd->avg_lum);
-       Gbright = reg_r(gspca_dev, 0x02);
-       PDEBUG(D_FRAM, "luma mean %d", luma);
-       if (luma < luma_mean - luma_delta ||
-           luma > luma_mean + luma_delta) {
-               Gbright += (luma_mean - luma) >> spring;
-               if (Gbright > 0x1a)
-                       Gbright = 0x1a;
-               else if (Gbright < 4)
-                       Gbright = 4;
-               PDEBUG(D_FRAM, "gbright %d", Gbright);
-               reg_w(gspca_dev, 0xff, 0x04);
-               reg_w(gspca_dev, 0x0f, Gbright);
-               /* load registers to sensor (Bit 0, auto clear) */
-               reg_w(gspca_dev, 0x11, 0x01);
+
+       if (sd->sensor == SENSOR_PAC7302) {
+               desired_lum = 270 + sd->brightness * 4;
+               /* Hack hack, with the 7202 the first exposure step is
+                  pretty large, so if we're about to make the first
+                  exposure increase make the deadzone large to avoid
+                  oscilating */
+               if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
+                               sd->exposure > EXPOSURE_DEF &&
+                               sd->exposure < 42)
+                       deadzone = 90;
+               else
+                       deadzone = 30;
+       } else {
+               desired_lum = 200;
+               deadzone = 20;
        }
+
+       if (sd->autogain_ignore_frames > 0)
+               sd->autogain_ignore_frames--;
+       else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
+                       deadzone, GAIN_KNEE, EXPOSURE_KNEE))
+               sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
 }
 
+static const unsigned char pac7311_jpeg_header1[] = {
+  0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08
+};
+
+static const unsigned char pac7311_jpeg_header2[] = {
+  0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda,
+  0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+};
+
+/* this function is run at interrupt level */
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
                        int len)                        /* iso packet length */
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       unsigned char tmpbuf[4];
-       int i, p, ffseq;
-
-/*     if (len < 5) { */
-       if (len < 6) {
-/*             gspca_dev->last_packet_type = DISCARD_PACKET; */
-               return;
-       }
-
-       ffseq = sd->ffseq;
-
-       for (p = 0; p < len - 6; p++) {
-               if ((data[0 + p] == 0xff)
-                   && (data[1 + p] == 0xff)
-                   && (data[2 + p] == 0x00)
-                   && (data[3 + p] == 0xff)
-                   && (data[4 + p] == 0x96)) {
-
-                       /* start of frame */
-                       if (sd->ag_cnt >= 0 && p > 28) {
-                               sd->lum_sum += data[p - 23];
-                               if (--sd->ag_cnt < 0) {
-                                       sd->ag_cnt = AG_CNT_START;
-                                       atomic_set(&sd->avg_lum,
-                                               sd->lum_sum / AG_CNT_START);
-                                       sd->lum_sum = 0;
-                                       atomic_set(&sd->do_gain, 1);
-                               }
-                       }
+       unsigned char *sof;
+
+       sof = pac_find_sof(gspca_dev, data, len);
+       if (sof) {
+               unsigned char tmpbuf[4];
+               int n, lum_offset, footer_length;
+
+               if (sd->sensor == SENSOR_PAC7302) {
+                 /* 6 bytes after the FF D9 EOF marker a number of lumination
+                    bytes are send corresponding to different parts of the
+                    image, the 14th and 15th byte after the EOF seem to
+                    correspond to the center of the image */
+                 lum_offset = 61 + sizeof pac_sof_marker;
+                 footer_length = 74;
+               } else {
+                 lum_offset = 24 + sizeof pac_sof_marker;
+                 footer_length = 26;
+               }
 
-                       /* copy the end of data to the current frame */
+               /* Finish decoding current frame */
+               n = (sof - data) - (footer_length + sizeof pac_sof_marker);
+               if (n < 0) {
+                       frame->data_end += n;
+                       n = 0;
+               }
+               frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+                                       data, n);
+               if (gspca_dev->last_packet_type != DISCARD_PACKET &&
+                               frame->data_end[-2] == 0xff &&
+                               frame->data_end[-1] == 0xd9)
                        frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
-                                               data, p);
-
-                       /* put the JPEG header in the new frame */
-                       gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
-                                       (unsigned char *) pac7311_jpeg_header,
-                                       12);
+                                               NULL, 0);
+
+               n = sof - data;
+               len -= n;
+               data = sof;
+
+               /* Get average lumination */
+               if (gspca_dev->last_packet_type == LAST_PACKET &&
+                               n >= lum_offset)
+                       atomic_set(&sd->avg_lum, data[-lum_offset] +
+                                               data[-lum_offset + 1]);
+               else
+                       atomic_set(&sd->avg_lum, -1);
+
+               /* Start the new frame with the jpeg header */
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                       pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1));
+               if (sd->sensor == SENSOR_PAC7302) {
+                       /* The PAC7302 has the image rotated 90 degrees */
+                       tmpbuf[0] = gspca_dev->width >> 8;
+                       tmpbuf[1] = gspca_dev->width & 0xff;
+                       tmpbuf[2] = gspca_dev->height >> 8;
+                       tmpbuf[3] = gspca_dev->height & 0xff;
+               } else {
                        tmpbuf[0] = gspca_dev->height >> 8;
                        tmpbuf[1] = gspca_dev->height & 0xff;
                        tmpbuf[2] = gspca_dev->width >> 8;
                        tmpbuf[3] = gspca_dev->width & 0xff;
-                       gspca_frame_add(gspca_dev, INTER_PACKET, frame,
-                                       tmpbuf, 4);
-                       gspca_frame_add(gspca_dev, INTER_PACKET, frame,
-                               (unsigned char *) &pac7311_jpeg_header[16],
-                               PAC7311_JPEG_HEADER_SIZE - 16);
-
-                       data += p + 7;
-                       len -= p + 7;
-                       ffseq = 0;
-                       break;
                }
+               gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4);
+               gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+                       pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2));
        }
-
-       /* remove the 'ff ff ff xx' sequences */
-       switch (ffseq) {
-       case 3:
-               data += 1;
-               len -= 1;
-               break;
-       case 2:
-               if (data[0] == 0xff) {
-                       data += 2;
-                       len -= 2;
-                       frame->data_end -= 2;
-               }
-               break;
-       case 1:
-               if (data[0] == 0xff
-                   && data[1] == 0xff) {
-                       data += 3;
-                       len -= 3;
-                       frame->data_end -= 1;
-               }
-               break;
-       }
-       for (i = 0; i < len - 4; i++) {
-               if (data[i] == 0xff
-                   && data[i + 1] == 0xff
-                   && data[i + 2] == 0xff) {
-                       memmove(&data[i], &data[i + 4], len - i - 4);
-                       len -= 4;
-               }
-       }
-       ffseq = 0;
-       if (data[len - 4] == 0xff) {
-               if (data[len - 3] == 0xff
-                   && data[len - 2] == 0xff) {
-                       len -= 4;
-               }
-       } else if (data[len - 3] == 0xff) {
-               if (data[len - 2] == 0xff
-                   && data[len - 1] == 0xff)
-                       ffseq = 3;
-       } else if (data[len - 2] == 0xff) {
-               if (data[len - 1] == 0xff)
-                       ffseq = 2;
-       } else if (data[len - 1] == 0xff)
-               ffseq = 1;
-       sd->ffseq = ffseq;
        gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-/*     sd->brightness = reg_r(gspca_dev, 0x08);
-       return sd->brightness;  */
-/*     PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
-}
-
-
-
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
        sd->brightness = val;
        if (gspca_dev->streaming)
-               setbrightness(gspca_dev);
+               setbrightcont(gspca_dev);
        return 0;
 }
 
@@ -644,7 +891,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       getbrightness(gspca_dev);
        *val = sd->brightness;
        return 0;
 }
@@ -654,8 +900,12 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
        struct sd *sd = (struct sd *) gspca_dev;
 
        sd->contrast = val;
-       if (gspca_dev->streaming)
-               setcontrast(gspca_dev);
+       if (gspca_dev->streaming) {
+               if (sd->sensor == SENSOR_PAC7302)
+                       setbrightcont(gspca_dev);
+               else
+                       setcontrast(gspca_dev);
+       }
        return 0;
 }
 
@@ -663,7 +913,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-/*     getcontrast(gspca_dev); */
        *val = sd->contrast;
        return 0;
 }
@@ -682,18 +931,66 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-/*     getcolors(gspca_dev); */
        *val = sd->colors;
        return 0;
 }
 
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->gain = val;
+       if (gspca_dev->streaming)
+               setgain(gspca_dev);
+       return 0;
+}
+
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->gain;
+       return 0;
+}
+
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->exposure = val;
+       if (gspca_dev->streaming)
+               setexposure(gspca_dev);
+       return 0;
+}
+
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->exposure;
+       return 0;
+}
+
 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
        sd->autogain = val;
-       if (gspca_dev->streaming)
-               setautogain(gspca_dev);
+       /* when switching to autogain set defaults to make sure
+          we are on a valid point of the autogain gain /
+          exposure knee graph, and give this change time to
+          take effect before doing autogain. */
+       if (sd->autogain) {
+               sd->exposure = EXPOSURE_DEF;
+               sd->gain = GAIN_DEF;
+               if (gspca_dev->streaming) {
+                       sd->autogain_ignore_frames =
+                               PAC_AUTOGAIN_IGNORE_FRAMES;
+                       setexposure(gspca_dev);
+                       setgain(gspca_dev);
+               }
+       }
+
        return 0;
 }
 
@@ -705,30 +1002,67 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
+static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->hflip = val;
+       if (gspca_dev->streaming)
+               sethvflip(gspca_dev);
+       return 0;
+}
+
+static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->hflip;
+       return 0;
+}
+
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->vflip = val;
+       if (gspca_dev->streaming)
+               sethvflip(gspca_dev);
+       return 0;
+}
+
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->vflip;
+       return 0;
+}
+
 /* sub-driver description */
 static struct sd_desc sd_desc = {
        .name = MODULE_NAME,
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
        .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .dq_callback = do_autogain,
 };
 
 /* -- module initialisation -- */
 static __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x093a, 0x2600)},
-       {USB_DEVICE(0x093a, 0x2601)},
-       {USB_DEVICE(0x093a, 0x2603)},
-       {USB_DEVICE(0x093a, 0x2608)},
-       {USB_DEVICE(0x093a, 0x260e)},
-       {USB_DEVICE(0x093a, 0x260f)},
-       {USB_DEVICE(0x093a, 0x2621)},
+       {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
+       {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
+       {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
+       {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
+       {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
+       {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
+       {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
+       {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
+       {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -746,6 +1080,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h
new file mode 100644 (file)
index 0000000..34d4b14
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Pixart PAC207BCA / PAC73xx common functions
+ *
+ * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+ * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
+ * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/* We calculate the autogain at the end of the transfer of a frame, at this
+   moment a frame with the old settings is being transmitted, and a frame is
+   being captured with the old settings. So if we adjust the autogain we must
+   ignore atleast the 2 next frames for the new settings to come into effect
+   before doing any other adjustments */
+#define PAC_AUTOGAIN_IGNORE_FRAMES     3
+
+static const unsigned char pac_sof_marker[5] =
+               { 0xff, 0xff, 0x00, 0xff, 0x96 };
+
+static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev,
+                                       unsigned char *m, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+
+       /* Search for the SOF marker (fixed part) in the header */
+       for (i = 0; i < len; i++) {
+               if (m[i] == pac_sof_marker[sd->sof_read]) {
+                       sd->sof_read++;
+                       if (sd->sof_read == sizeof(pac_sof_marker)) {
+                               PDEBUG(D_FRAM,
+                                       "SOF found, bytes to analyze: %u."
+                                       " Frame starts at byte #%u",
+                                       len, i + 1);
+                               sd->sof_read = 0;
+                               return m + i + 1;
+                       }
+               } else {
+                       sd->sof_read = 0;
+               }
+       }
+
+       return NULL;
+}
index 11210c71f66c38e6c673dc1709c712fe46e23c49..5dd78c6766eaf0745a52ad0c4e19d651421af524 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+/* Some documentation on known sonixb registers:
+
+Reg    Use
+0x10   high nibble red gain low nibble blue gain
+0x11   low nibble green gain
+0x12   hstart
+0x13   vstart
+0x15   hsize (hsize = register-value * 16)
+0x16   vsize (vsize = register-value * 16)
+0x17   bit 0 toggle compression quality (according to sn9c102 driver)
+0x18   bit 7 enables compression, bit 4-5 set image down scaling:
+       00 scale 1, 01 scale 1/2, 10, scale 1/4
+0x19   high-nibble is sensor clock divider, changes exposure on sensors which
+       use a clock generated by the bridge. Some sensors have their own clock.
+0x1c   auto_exposure area (for avg_lum) startx (startx = register-value * 32)
+0x1d   auto_exposure area (for avg_lum) starty (starty = register-value * 32)
+0x1e   auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
+0x1f   auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
+*/
+
 #define MODULE_NAME "sonixb"
 
 #include "gspca.h"
@@ -31,10 +51,8 @@ MODULE_LICENSE("GPL");
 /* specific webcam descriptor */
 struct sd {
        struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct sd_desc sd_desc;         /* our nctrls differ dependend upon the
-                                          sensor, so we use a per cam copy */
        atomic_t avg_lum;
+       int prev_avg_lum;
 
        unsigned char gain;
        unsigned char exposure;
@@ -44,8 +62,12 @@ struct sd {
        unsigned char frames_to_drop;
        unsigned char freq;             /* light freq filter setting */
 
-       unsigned char fr_h_sz;          /* size of frame header */
-       char sensor;                    /* Type of image sensor chip */
+       __u8 bridge;                    /* Type of bridge */
+#define BRIDGE_101 0
+#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
+#define BRIDGE_103 1
+
+       __u8 sensor;                    /* Type of image sensor chip */
 #define SENSOR_HV7131R 0
 #define SENSOR_OV6650 1
 #define SENSOR_OV7630 2
@@ -53,16 +75,35 @@ struct sd {
 #define SENSOR_PAS202 4
 #define SENSOR_TAS5110 5
 #define SENSOR_TAS5130CXX 6
-       char sensor_has_gain;
-       __u8 sensor_addr;
        __u8 reg11;
 };
 
-/* flags used in the device id table */
+typedef const __u8 sensor_init_t[8];
+
+struct sensor_data {
+       const __u8 *bridge_init[2];
+       int bridge_init_size[2];
+       sensor_init_t *sensor_init;
+       int sensor_init_size;
+       sensor_init_t *sensor_bridge_init[2];
+       int sensor_bridge_init_size[2];
+       int flags;
+       unsigned ctrl_dis;
+       __u8 sensor_addr;
+};
+
+/* sensor_data flags */
 #define F_GAIN 0x01            /* has gain */
-#define F_AUTO 0x02            /* has autogain */
-#define F_SIF  0x04            /* sif or vga */
-#define F_H18  0x08            /* long (18 b) or short (12 b) frame header */
+#define F_SIF  0x02            /* sif or vga */
+
+/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
+#define MODE_RAW 0x10          /* raw bayer mode */
+#define MODE_REDUCED_SIF 0x20  /* vga mode (320x240 / 160x120) on sif cam */
+
+/* ctrl_dis helper macros */
+#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
+#define NO_FREQ (1 << FREQ_IDX)
+#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
 
 #define COMP2 0x8f
 #define COMP 0xc7              /* 0x87 //0x07 */
@@ -73,6 +114,18 @@ struct sd {
 
 #define SYS_CLK 0x04
 
+#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
+       sensor_3, _flags, _ctrl_dis, _sensor_addr) \
+{ \
+       .bridge_init = { bridge_1, bridge_3 }, \
+       .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
+       .sensor_init = sensor, \
+       .sensor_init_size = sizeof(sensor), \
+       .sensor_bridge_init = { sensor_1, sensor_3,}, \
+       .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
+       .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
+}
+
 /* We calculate the autogain at the end of the transfer of a frame, at this
    moment a frame with the old settings is being transmitted, and a frame is
    being captured with the old settings. So if we adjust the autogain we must
@@ -95,6 +148,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
+#define BRIGHTNESS_IDX 0
        {
            {
                .id      = V4L2_CID_BRIGHTNESS,
@@ -109,6 +163,7 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setbrightness,
            .get = sd_getbrightness,
        },
+#define GAIN_IDX 1
        {
            {
                .id      = V4L2_CID_GAIN,
@@ -124,6 +179,7 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setgain,
            .get = sd_getgain,
        },
+#define EXPOSURE_IDX 2
        {
                {
                        .id = V4L2_CID_EXPOSURE,
@@ -140,6 +196,7 @@ static struct ctrl sd_ctrls[] = {
                .set = sd_setexposure,
                .get = sd_getexposure,
        },
+#define AUTOGAIN_IDX 3
        {
                {
                        .id = V4L2_CID_AUTOGAIN,
@@ -155,6 +212,7 @@ static struct ctrl sd_ctrls[] = {
                .set = sd_setautogain,
                .get = sd_getautogain,
        },
+#define FREQ_IDX 4
        {
                {
                        .id      = V4L2_CID_POWER_LINE_FREQUENCY,
@@ -172,31 +230,56 @@ static struct ctrl sd_ctrls[] = {
 };
 
 static struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2 | MODE_RAW},
        {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
                .bytesperline = 160,
-               .sizeimage = 160 * 120,
+               .sizeimage = 160 * 120 * 5 / 4,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 2},
        {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
                .bytesperline = 320,
-               .sizeimage = 320 * 240,
+               .sizeimage = 320 * 240 * 5 / 4,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 1},
        {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
                .bytesperline = 640,
-               .sizeimage = 640 * 480,
+               .sizeimage = 640 * 480 * 5 / 4,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 0},
 };
 static struct v4l2_pix_format sif_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
+       {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1 | MODE_REDUCED_SIF},
+       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1 | MODE_RAW},
        {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
                .bytesperline = 176,
-               .sizeimage = 176 * 144,
+               .sizeimage = 176 * 144 * 5 / 4,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 1},
+       {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0 | MODE_REDUCED_SIF},
        {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
                .bytesperline = 352,
-               .sizeimage = 352 * 288,
+               .sizeimage = 352 * 288 * 5 / 4,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 0},
 };
@@ -204,7 +287,7 @@ static struct v4l2_pix_format sif_mode[] = {
 static const __u8 initHv7131[] = {
        0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
        0x00, 0x00,
-       0x00, 0x00, 0x00, 0x03, 0x01, 0x00,     /* shift from 0x02 0x01 0x00 */
+       0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
        0x28, 0x1e, 0x60, 0x8a, 0x20,
        0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
 };
@@ -218,8 +301,8 @@ static const __u8 hv7131_sensor_init[][8] = {
 static const __u8 initOv6650[] = {
        0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
        0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
-       0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
+       0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
+       0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
 };
 static const __u8 ov6650_sensor_init[][8] =
 {
@@ -257,15 +340,15 @@ static const __u8 ov6650_sensor_init[][8] =
 static const __u8 initOv7630[] = {
        0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
        0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
-       0x00, 0x02, 0x01, 0x0a,                         /* r11 .. r14 */
+       0x00, 0x01, 0x01, 0x0a,                         /* r11 .. r14 */
        0x28, 0x1e,                     /* H & V sizes     r15 .. r16 */
-       0x68, COMP1, MCK_INIT1,                         /* r17 .. r19 */
+       0x68, COMP2, MCK_INIT1,                         /* r17 .. r19 */
        0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c              /* r1a .. r1f */
 };
 static const __u8 initOv7630_3[] = {
        0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
        0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
-       0x00, 0x01, 0x01, 0x0a,                         /* r11 .. r14 */
+       0x00, 0x02, 0x01, 0x0a,                         /* r11 .. r14 */
        0x28, 0x1e,                     /* H & V sizes     r15 .. r16 */
        0x68, 0x8f, MCK_INIT1,                          /* r17 .. r19 */
        0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00,       /* r1a .. r20 */
@@ -294,47 +377,65 @@ static const __u8 ov7630_sensor_init[][8] = {
        {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
 };
 
+static const __u8 ov7630_sensor_init_3[][8] = {
+       {0xa0, 0x21, 0x13, 0x80, 0x00,  0x00, 0x00, 0x10},
+};
+
 static const __u8 initPas106[] = {
        0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
        0x00, 0x00,
-       0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
-       0x16, 0x12, 0x28, COMP1, MCK_INIT1,
-       0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
+       0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
+       0x16, 0x12, 0x24, COMP1, MCK_INIT1,
+       0x18, 0x10, 0x02, 0x02, 0x09, 0x07
 };
 /* compression 0x86 mckinit1 0x2b */
-static const __u8 pas106_data[][2] = {
-       {0x02, 0x04},           /* Pixel Clock Divider 6 */
-       {0x03, 0x13},           /* Frame Time MSB */
-/*     {0x03, 0x12},            * Frame Time MSB */
-       {0x04, 0x06},           /* Frame Time LSB */
-/*     {0x04, 0x05},            * Frame Time LSB */
-       {0x05, 0x65},           /* Shutter Time Line Offset */
-/*     {0x05, 0x6d},            * Shutter Time Line Offset */
-/*     {0x06, 0xb1},            * Shutter Time Pixel Offset */
-       {0x06, 0xcd},           /* Shutter Time Pixel Offset */
-       {0x07, 0xc1},           /* Black Level Subtract Sign */
-/*     {0x07, 0x00},            * Black Level Subtract Sign */
-       {0x08, 0x06},           /* Black Level Subtract Level */
-       {0x08, 0x06},           /* Black Level Subtract Level */
-/*     {0x08, 0x01},            * Black Level Subtract Level */
-       {0x09, 0x05},           /* Color Gain B Pixel 5 a */
-       {0x0a, 0x04},           /* Color Gain G1 Pixel 1 5 */
-       {0x0b, 0x04},           /* Color Gain G2 Pixel 1 0 5 */
-       {0x0c, 0x05},           /* Color Gain R Pixel 3 1 */
-       {0x0d, 0x00},           /* Color GainH  Pixel */
-       {0x0e, 0x0e},           /* Global Gain */
-       {0x0f, 0x00},           /* Contrast */
-       {0x10, 0x06},           /* H&V synchro polarity */
-       {0x11, 0x06},           /* ?default */
-       {0x12, 0x06},           /* DAC scale */
-       {0x14, 0x02},           /* ?default */
-       {0x13, 0x01},           /* Validate Settings */
+static const __u8 pas106_sensor_init[][8] = {
+       /* Pixel Clock Divider 6 */
+       { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
+       /* Frame Time MSB (also seen as 0x12) */
+       { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
+       /* Frame Time LSB (also seen as 0x05) */
+       { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* Shutter Time Line Offset (also seen as 0x6d) */
+       { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
+       /* Shutter Time Pixel Offset (also seen as 0xb1) */
+       { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
+       /* Black Level Subtract Sign (also seen 0x00) */
+       { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
+       /* Black Level Subtract Level (also seen 0x01) */
+       { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* Color Gain B Pixel 5 a */
+       { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
+       /* Color Gain G1 Pixel 1 5 */
+       { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
+       /* Color Gain G2 Pixel 1 0 5 */
+       { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
+       /* Color Gain R Pixel 3 1 */
+       { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
+       /* Color GainH  Pixel */
+       { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
+       /* Global Gain */
+       { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
+       /* Contrast */
+       { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
+       /* H&V synchro polarity */
+       { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* ?default */
+       { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* DAC scale */
+       { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* ?default */
+       { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
+       /* Validate Settings */
+       { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
 };
+
 static const __u8 initPas202[] = {
        0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
        0x00, 0x00,
-       0x00, 0x00, 0x00, 0x07, 0x03, 0x0a,     /* 6 */
-       0x28, 0x1e, 0x28, 0x89, 0x30,
+       0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
+       0x28, 0x1e, 0x28, 0x89, 0x20,
        0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
 };
 static const __u8 pas202_sensor_init[][8] = {
@@ -364,7 +465,7 @@ static const __u8 pas202_sensor_init[][8] = {
 static const __u8 initTas5110[] = {
        0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
        0x00, 0x00,
-       0x00, 0x01, 0x00, 0x46, 0x09, 0x0a,     /* shift from 0x45 0x09 0x0a */
+       0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
        0x16, 0x12, 0x60, 0x86, 0x2b,
        0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
 };
@@ -377,7 +478,7 @@ static const __u8 tas5110_sensor_init[][8] = {
 static const __u8 initTas5130[] = {
        0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
        0x00, 0x00,
-       0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
+       0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
        0x28, 0x1e, 0x60, COMP, MCK_INIT,
        0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
 };
@@ -389,6 +490,21 @@ static const __u8 tas5130_sensor_init[][8] = {
        {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
 };
 
+struct sensor_data sensor_data[] = {
+SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
+SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
+SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
+       F_GAIN, 0, 0x21),
+SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
+       0),
+SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
+       NO_EXPO|NO_FREQ, 0),
+SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
+       NO_BRIGHTNESS|NO_FREQ, 0),
+SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
+       0),
+};
+
 /* get one byte in gspca_dev->usb_buf */
 static void reg_r(struct gspca_dev *gspca_dev,
                  __u16 value)
@@ -409,7 +525,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
                  int len)
 {
 #ifdef GSPCA_DEBUG
-       if (len > sizeof gspca_dev->usb_buf) {
+       if (len > USB_BUF_SZ) {
                PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
                return;
        }
@@ -425,26 +541,6 @@ static void reg_w(struct gspca_dev *gspca_dev,
                        500);
 }
 
-static void reg_w_big(struct gspca_dev *gspca_dev,
-                 __u16 value,
-                 const __u8 *buffer,
-                 int len)
-{
-       __u8 *tmpbuf;
-
-       tmpbuf = kmalloc(len, GFP_KERNEL);
-       memcpy(tmpbuf, buffer, len);
-       usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x08,                   /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       value,
-                       0,                      /* index */
-                       tmpbuf, len,
-                       500);
-       kfree(tmpbuf);
-}
-
 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
 {
        int retry = 60;
@@ -487,7 +583,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
                        {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
 
                /* change reg 0x06 */
-               i2cOV[1] = sd->sensor_addr;
+               i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
                i2cOV[3] = sd->brightness;
                if (i2c_w(gspca_dev, i2cOV) < 0)
                        goto err;
@@ -545,9 +641,6 @@ static void setbrightness(struct gspca_dev *gspca_dev)
                        goto err;
                break;
            }
-       case SENSOR_TAS5110:
-               /* FIXME figure out howto control brightness on TAS5110 */
-               break;
        }
        return;
 err:
@@ -577,7 +670,7 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
        case SENSOR_OV7630: {
                __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
 
-               i2c[1] = sd->sensor_addr;
+               i2c[1] = sensor_data[sd->sensor].sensor_addr;
                i2c[3] = gain >> 2;
                if (i2c_w(gspca_dev, i2c) < 0)
                        goto err;
@@ -604,7 +697,7 @@ static void setgain(struct gspca_dev *gspca_dev)
        rgb_value = gain;
        reg_w(gspca_dev, 0x11, &rgb_value, 1);
 
-       if (sd->sensor_has_gain)
+       if (sensor_data[sd->sensor].flags & F_GAIN)
                setsensorgain(gspca_dev);
 }
 
@@ -665,6 +758,11 @@ static void setexposure(struct gspca_dev *gspca_dev)
                else if (reg11 > 16)
                        reg11 = 16;
 
+               /* In 640x480, if the reg11 has less than 3, the image is
+                  unstable (not enough bandwidth). */
+               if (gspca_dev->width == 640 && reg11 < 3)
+                       reg11 = 3;
+
                /* frame exposure time in ms = 1000 * reg11 / 30    ->
                reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
                reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
@@ -678,13 +776,8 @@ static void setexposure(struct gspca_dev *gspca_dev)
                else if (reg10 > reg10_max)
                        reg10 = reg10_max;
 
-               /* In 640x480, if the reg11 has less than 3, the image is
-                  unstable (not enough bandwidth). */
-               if (gspca_dev->width == 640 && reg11 < 3)
-                       reg11 = 3;
-
                /* Write reg 10 and reg11 low nibble */
-               i2c[1] = sd->sensor_addr;
+               i2c[1] = sensor_data[sd->sensor].sensor_addr;
                i2c[3] = reg10;
                i2c[4] |= reg11 - 1;
 
@@ -724,7 +817,7 @@ static void setfreq(struct gspca_dev *gspca_dev)
                                        ? 0x4f : 0x8a;
                        break;
                }
-               i2c[1] = sd->sensor_addr;
+               i2c[1] = sensor_data[sd->sensor].sensor_addr;
                if (i2c_w(gspca_dev, i2c) < 0)
                        PDEBUG(D_ERR, "i2c error setfreq");
                break;
@@ -757,30 +850,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       int sif = 0;
 
-       /* nctrls depends upon the sensor, so we use a per cam copy */
-       memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
-       gspca_dev->sd_desc = &sd->sd_desc;
+       reg_r(gspca_dev, 0x00);
+       if (gspca_dev->usb_buf[0] != 0x10)
+               return -ENODEV;
 
        /* copy the webcam info from the device id */
-       sd->sensor = (id->driver_info >> 24) & 0xff;
-       if (id->driver_info & (F_GAIN << 16))
-               sd->sensor_has_gain = 1;
-       if (id->driver_info & (F_AUTO << 16))
-               sd->sd_desc.dq_callback = do_autogain;
-       if (id->driver_info & (F_SIF << 16))
-               sif = 1;
-       if (id->driver_info & (F_H18 << 16))
-               sd->fr_h_sz = 18;               /* size of frame header */
-       else
-               sd->fr_h_sz = 12;
-       sd->sd_desc.nctrls = (id->driver_info >> 8) & 0xff;
-       sd->sensor_addr = id->driver_info & 0xff;
+       sd->sensor = id->driver_info >> 8;
+       sd->bridge = id->driver_info & 0xff;
+       gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
 
        cam = &gspca_dev->cam;
        cam->epaddr = 0x01;
-       if (!sif) {
+       if (!(sensor_data[sd->sensor].flags & F_SIF)) {
                cam->cam_mode = vga_mode;
                cam->nmodes = ARRAY_SIZE(vga_mode);
        } else {
@@ -790,157 +872,98 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->brightness = BRIGHTNESS_DEF;
        sd->gain = GAIN_DEF;
        sd->exposure = EXPOSURE_DEF;
-       sd->autogain = AUTOGAIN_DEF;
+       if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
+               sd->autogain = 0; /* Disable do_autogain callback */
+       else
+               sd->autogain = AUTOGAIN_DEF;
        sd->freq = FREQ_DEF;
 
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
-       reg_r(gspca_dev, 0x00);
-       if (gspca_dev->usb_buf[0] != 0x10)
-               return -ENODEV;
-       return 0;
-}
+       const __u8 stop = 0x09; /* Disable stream turn of LED */
 
-static void pas106_i2cinit(struct gspca_dev *gspca_dev)
-{
-       int i;
-       const __u8 *data;
-       __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
-
-       i = ARRAY_SIZE(pas106_data);
-       data = pas106_data[0];
-       while (--i >= 0) {
-               memcpy(&i2c1[2], data, 2);
-                                       /* copy 2 bytes from the template */
-               if (i2c_w(gspca_dev, i2c1) < 0)
-                       PDEBUG(D_ERR, "i2c error pas106");
-               data += 2;
-       }
+       reg_w(gspca_dev, 0x01, &stop, 1);
+
+       return 0;
 }
 
 /* -- start the camera -- */
 static void sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       int mode, l = 0x1f;
+       struct cam *cam = &gspca_dev->cam;
+       int mode, l;
        const __u8 *sn9c10x;
-       __u8 reg17_19[3];
-
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       __u8 reg12_19[8];
+
+       mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
+       sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
+       l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
+       memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
+       reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
+       /* Special cases where reg 17 and or 19 value depends on mode */
        switch (sd->sensor) {
-       case SENSOR_HV7131R:
-               sn9c10x = initHv7131;
-               reg17_19[0] = 0x60;
-               reg17_19[1] = (mode << 4) | 0x8a;
-               reg17_19[2] = 0x20;
-               break;
-       case SENSOR_OV6650:
-               sn9c10x = initOv6650;
-               reg17_19[0] = 0x68;
-               reg17_19[1] = (mode << 4) | 0x8b;
-               reg17_19[2] = 0x20;
-               break;
-       case SENSOR_OV7630:
-               if (sd->fr_h_sz == 18) { /* SN9C103 */
-                       sn9c10x = initOv7630_3;
-                       l = sizeof initOv7630_3;
-               } else
-                       sn9c10x = initOv7630;
-               reg17_19[0] = 0x68;
-               reg17_19[1] = (mode << 4) | COMP2;
-               reg17_19[2] = MCK_INIT1;
-               break;
-       case SENSOR_PAS106:
-               sn9c10x = initPas106;
-               reg17_19[0] = 0x24;             /* 0x28 */
-               reg17_19[1] = (mode << 4) | COMP1;
-               reg17_19[2] = MCK_INIT1;
-               break;
        case SENSOR_PAS202:
-               sn9c10x = initPas202;
-               reg17_19[0] = mode ? 0x24 : 0x20;
-               reg17_19[1] = (mode << 4) | 0x89;
-               reg17_19[2] = 0x20;
+               reg12_19[5] = mode ? 0x24 : 0x20;
                break;
-       case SENSOR_TAS5110:
-               sn9c10x = initTas5110;
-               reg17_19[0] = 0x60;
-               reg17_19[1] = (mode << 4) | 0x86;
-               reg17_19[2] = 0x2b;             /* 0xf3; */
-               break;
-       default:
-/*     case SENSOR_TAS5130CXX: */
-               sn9c10x = initTas5130;
-               reg17_19[0] = 0x60;
-               reg17_19[1] = (mode << 4) | COMP;
-               reg17_19[2] = mode ? 0x23 : 0x43;
+       case SENSOR_TAS5130CXX:
+               /* probably not mode specific at all most likely the upper
+                  nibble of 0x19 is exposure (clock divider) just as with
+                  the tas5110, we need someone to test this. */
+               reg12_19[7] = mode ? 0x23 : 0x43;
                break;
        }
+       /* Disable compression when the raw bayer format has been selected */
+       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
+               reg12_19[6] &= ~0x80;
+
+       /* Vga mode emulation on SIF sensor? */
+       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
+               reg12_19[0] += 16; /* 0x12: hstart adjust */
+               reg12_19[1] += 24; /* 0x13: vstart adjust */
+               reg12_19[3] = 320 / 16; /* 0x15: hsize */
+               reg12_19[4] = 240 / 16; /* 0x16: vsize */
+       }
 
        /* reg 0x01 bit 2 video transfert on */
        reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
        /* reg 0x17 SensorClk enable inv Clk 0x60 */
        reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
        /* Set the registers from the template */
-       reg_w_big(gspca_dev, 0x01, sn9c10x, l);
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-               i2c_w_vector(gspca_dev, hv7131_sensor_init,
-                               sizeof hv7131_sensor_init);
-               break;
-       case SENSOR_OV6650:
-               i2c_w_vector(gspca_dev, ov6650_sensor_init,
-                               sizeof ov6650_sensor_init);
-               break;
-       case SENSOR_OV7630:
-               i2c_w_vector(gspca_dev, ov7630_sensor_init,
-                               sizeof ov7630_sensor_init);
-               if (sd->fr_h_sz == 18) { /* SN9C103 */
-                       const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
-                                               0x00, 0x00, 0x10 };
-                       i2c_w(gspca_dev, i2c);
-               }
-               break;
-       case SENSOR_PAS106:
-               pas106_i2cinit(gspca_dev);
-               break;
-       case SENSOR_PAS202:
-               i2c_w_vector(gspca_dev, pas202_sensor_init,
-                               sizeof pas202_sensor_init);
-               break;
-       case SENSOR_TAS5110:
-               i2c_w_vector(gspca_dev, tas5110_sensor_init,
-                               sizeof tas5110_sensor_init);
-               break;
-       default:
-/*     case SENSOR_TAS5130CXX: */
-               i2c_w_vector(gspca_dev, tas5130_sensor_init,
-                               sizeof tas5130_sensor_init);
-               break;
-       }
+       reg_w(gspca_dev, 0x01, sn9c10x, l);
+
+       /* Init the sensor */
+       i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
+                       sensor_data[sd->sensor].sensor_init_size);
+       if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
+               i2c_w_vector(gspca_dev,
+                       sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
+                       sensor_data[sd->sensor].sensor_bridge_init_size[
+                               sd->bridge]);
+
        /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
-       reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
+       reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
        /* compression register */
-       reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
+       reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
        /* H_start */
-       reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
+       reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
        /* V_START */
-       reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
+       reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
        /* reset 0x17 SensorClk enable inv Clk 0x60 */
                                /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
-       reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
+       reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
        /*MCKSIZE ->3 */        /*fixme: not ov7630*/
-       reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
+       reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
        /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
        reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
        /* Enable video transfert */
        reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
        /* Compression */
-       reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
+       reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
        msleep(20);
 
        sd->reg11 = -1;
@@ -957,18 +980,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
-       __u8 ByteSend;
-
-       ByteSend = 0x09;        /* 0X00 */
-       reg_w(gspca_dev, 0x01, &ByteSend, 1);
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
+       sd_init(gspca_dev);
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -978,6 +990,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 {
        int i;
        struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
 
        /* frames start with:
         *      ff ff 00 c4 c4 96       synchro
@@ -998,20 +1011,31 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                            && data[5 + i] == 0x96) {   /* start of frame */
                                int lum = -1;
                                int pkt_type = LAST_PACKET;
+                               int fr_h_sz = (sd->bridge == BRIDGE_103) ?
+                                       18 : 12;
 
-                               if (len - i < sd->fr_h_sz) {
+                               if (len - i < fr_h_sz) {
                                        PDEBUG(D_STREAM, "packet too short to"
                                                " get avg brightness");
-                               } else if (sd->fr_h_sz == 12) {
-                                       lum = data[i + 8] + (data[i + 9] << 8);
-                               } else {
+                               } else if (sd->bridge == BRIDGE_103) {
                                        lum = data[i + 9] +
                                                (data[i + 10] << 8);
+                               } else {
+                                       lum = data[i + 8] + (data[i + 9] << 8);
                                }
-                               if (lum == 0) {
+                               /* When exposure changes midway a frame we
+                                  get a lum of 0 in this case drop 2 frames
+                                  as the frames directly after an exposure
+                                  change have an unstable image. Sometimes lum
+                                  *really* is 0 (cam used in low light with
+                                  low exposure setting), so do not drop frames
+                                  if the previous lum was 0 too. */
+                               if (lum == 0 && sd->prev_avg_lum != 0) {
                                        lum = -1;
                                        sd->frames_to_drop = 2;
-                               }
+                                       sd->prev_avg_lum = 0;
+                               } else
+                                       sd->prev_avg_lum = lum;
                                atomic_set(&sd->avg_lum, lum);
 
                                if (sd->frames_to_drop) {
@@ -1021,14 +1045,25 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 
                                frame = gspca_frame_add(gspca_dev, pkt_type,
                                                        frame, data, 0);
-                               data += i + sd->fr_h_sz;
-                               len -= i + sd->fr_h_sz;
+                               data += i + fr_h_sz;
+                               len -= i + fr_h_sz;
                                gspca_frame_add(gspca_dev, FIRST_PACKET,
                                                frame, data, len);
                                return;
                        }
                }
        }
+
+       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
+               /* In raw mode we sometimes get some garbage after the frame
+                  ignore this */
+               int used = frame->data_end - frame->data;
+               int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
+
+               if (used + len > size)
+                       len = size - used;
+       }
+
        gspca_frame_add(gspca_dev, INTER_PACKET,
                        frame, data, len);
 }
@@ -1162,58 +1197,45 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .querymenu = sd_querymenu,
+       .dq_callback = do_autogain,
 };
 
 /* -- module initialisation -- */
-#define SFCI(sensor, flags, nctrls, i2c_addr) \
-       .driver_info = (SENSOR_ ## sensor << 24) \
-                       | ((flags) << 16) \
-                       | ((nctrls) << 8) \
-                       | (i2c_addr)
+#define SB(sensor, bridge) \
+       .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
+
+
 static __devinitdata struct usb_device_id device_table[] = {
-#ifndef CONFIG_USB_SN9C102
-       {USB_DEVICE(0x0c45, 0x6001),                    /* SN9C102 */
-                       SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
-       {USB_DEVICE(0x0c45, 0x6005),                    /* SN9C101 */
-                       SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
-       {USB_DEVICE(0x0c45, 0x6007),                    /* SN9C101 */
-                       SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
-       {USB_DEVICE(0x0c45, 0x6009),                    /* SN9C101 */
-                       SFCI(PAS106, F_SIF, 2, 0)},
-       {USB_DEVICE(0x0c45, 0x600d),                    /* SN9C101 */
-                       SFCI(PAS106, F_SIF, 2, 0)},
+       {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */
+       {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+       {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */
+       {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
+       {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
 #endif
-       {USB_DEVICE(0x0c45, 0x6011),            /* SN9C101 - SN9C101G */
-                       SFCI(OV6650, F_GAIN|F_AUTO|F_SIF, 5, 0x60)},
-#ifndef CONFIG_USB_SN9C102
-       {USB_DEVICE(0x0c45, 0x6019),                    /* SN9C101 */
-                       SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
-       {USB_DEVICE(0x0c45, 0x6024),                    /* SN9C102 */
-                       SFCI(TAS5130CXX, 0, 2, 0)},
-       {USB_DEVICE(0x0c45, 0x6025),                    /* SN9C102 */
-                       SFCI(TAS5130CXX, 0, 2, 0)},
-       {USB_DEVICE(0x0c45, 0x6028),                    /* SN9C102 */
-                       SFCI(PAS202, 0, 2, 0)},
-       {USB_DEVICE(0x0c45, 0x6029),                    /* SN9C101 */
-                       SFCI(PAS106, F_SIF, 2, 0)},
-       {USB_DEVICE(0x0c45, 0x602c),                    /* SN9C102 */
-                       SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
-       {USB_DEVICE(0x0c45, 0x602d),                    /* SN9C102 */
-                       SFCI(HV7131R, 0, 2, 0)},
-       {USB_DEVICE(0x0c45, 0x602e),                    /* SN9C102 */
-                       SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
-       {USB_DEVICE(0x0c45, 0x60af),                    /* SN9C103 */
-                       SFCI(PAS202, F_H18, 2, 0)},
-       {USB_DEVICE(0x0c45, 0x60b0),                    /* SN9C103 */
-                       SFCI(OV7630, F_GAIN|F_AUTO|F_H18, 5, 0x21)},
+       {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+       {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
+       {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
+       {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
+       {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
+       {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
+       {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
 #endif
+       {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+       {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
+#endif
+       {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+       {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
+#endif
+       {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1231,6 +1253,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 245a30ec5fb13438218e402259ac7ec19455c28b..d75b1d20b3180e8982db8ca196de42823d1b00c3 100644 (file)
@@ -54,8 +54,10 @@ struct sd {
 #define SENSOR_HV7131R 0
 #define SENSOR_MI0360 1
 #define SENSOR_MO4000 2
-#define SENSOR_OV7648 3
-#define SENSOR_OV7660 4
+#define SENSOR_OM6802 3
+#define SENSOR_OV7630 4
+#define SENSOR_OV7648 5
+#define SENSOR_OV7660 6
        unsigned char i2c_base;
 };
 
@@ -76,7 +78,8 @@ static struct ctrl sd_ctrls[] = {
                .type    = V4L2_CTRL_TYPE_INTEGER,
                .name    = "Brightness",
                .minimum = 0,
-               .maximum = 0xffff,
+#define BRIGHTNESS_MAX 0xffff
+               .maximum = BRIGHTNESS_MAX,
                .step    = 1,
 #define BRIGHTNESS_DEF 0x7fff
                .default_value = BRIGHTNESS_DEF,
@@ -90,7 +93,8 @@ static struct ctrl sd_ctrls[] = {
                .type    = V4L2_CTRL_TYPE_INTEGER,
                .name    = "Contrast",
                .minimum = 0,
-               .maximum = 127,
+#define CONTRAST_MAX 127
+               .maximum = CONTRAST_MAX,
                .step    = 1,
 #define CONTRAST_DEF 63
                .default_value = CONTRAST_DEF,
@@ -104,14 +108,15 @@ static struct ctrl sd_ctrls[] = {
                .type    = V4L2_CTRL_TYPE_INTEGER,
                .name    = "Color",
                .minimum = 0,
-               .maximum = 255,
+               .maximum = 64,
                .step    = 1,
-#define COLOR_DEF 127
+#define COLOR_DEF 32
                .default_value = COLOR_DEF,
            },
            .set = sd_setcolors,
            .get = sd_getcolors,
        },
+#define AUTOGAIN_IDX 3
        {
            {
                .id      = V4L2_CID_AUTOGAIN,
@@ -131,7 +136,7 @@ static struct ctrl sd_ctrls[] = {
 static struct v4l2_pix_format vga_mode[] = {
        {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
                .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 8 + 590,
+               .sizeimage = 160 * 120 * 4 / 8 + 590,
                .colorspace = V4L2_COLORSPACE_JPEG,
                .priv = 2},
        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -180,6 +185,31 @@ static const __u8 sn_mo4000[] = {
        0x08,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00
 };
 
+static const __u8 sn_om6802[] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x23,   0x72,   0x00,   0x1a,   0x34,   0x27,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x80,   0x34,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x51,   0x01,   0x00,   0x28,   0x1e,   0x40,
+/*     reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
+       0x05,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+       0x08,   0x22,   0x44,   0x63,   0x7d,   0x92,   0xa3,   0xaf,
+       0xbc,   0xc4,   0xcd,   0xd5,   0xdc,   0xe1,   0xe8,   0xef,
+       0xf7
+};
+
+static const __u8 sn_ov7630[] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x21,   0x40,   0x00,   0x1a,   0x20,   0x1f,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0xa1,   0x21,   0x76,   0x21,   0x00,   0x00,   0x00,   0x10,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x04,   0x01,   0x0a,   0x28,   0x1e,   0xc2,
+/*     reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
+       0x0b,   0x00,   0x00,   0x00,   0x00,   0x00
+};
+
 static const __u8 sn_ov7648[] = {
 /*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
        0x00,   0x21,   0x62,   0x00,   0x1a,   0x20,   0x20,   0x20,
@@ -207,31 +237,22 @@ static const __u8 *sn_tb[] = {
        sn_hv7131,
        sn_mi0360,
        sn_mo4000,
+       sn_om6802,
+       sn_ov7630,
        sn_ov7648,
        sn_ov7660
 };
 
-static const __u8 regsn20[] = {
+static const __u8 gamma_def[] = {
        0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
        0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
 };
-static const __u8 regsn20_sn9c325[] = {
-       0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
-       0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
-};
 
 static const __u8 reg84[] = {
        0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
        0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
-/*     0x00, 0x00, 0x00, 0x00, 0x00 */
-       0xf7, 0x0f, 0x0a, 0x00, 0x00
-};
-static const __u8 reg84_sn9c325[] = {
-       0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
-       0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
-       0xf8, 0x0f, 0x00, 0x00, 0x00
+       0xf7, 0x0f, 0x00, 0x00, 0x00
 };
-
 static const __u8 hv7131r_sensor_init[][8] = {
        {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
        {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
@@ -340,6 +361,92 @@ static const __u8 mo4000_sensor_init[][8] = {
        {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
        {}
 };
+static __u8 om6802_sensor_init[][8] = {
+       {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
+/*     {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
+       {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
+                                       /* white balance & auto-exposure */
+/*     {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
+                                                        * set color mode */
+/*     {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
+                                                * max AGC value in AE */
+/*     {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                                        * preset AGC */
+/*     {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                                * preset brightness */
+/*     {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                                        * preset contrast */
+/*     {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
+                                                        * preset gamma */
+       {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
+                                       /* luminance mode (0x4f = AE) */
+       {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
+                                                       /* preset shutter */
+/*     {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                                        * auto frame rate */
+/*     {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
+
+/*     {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
+/*     {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
+/*     {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
+/*     {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
+       {}
+};
+static const __u8 ov7630_sensor_init[][8] = {
+       {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
+/* win: delay 20ms */
+       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
+/* win: delay 20ms */
+       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+/* win: i2c_r from 00 to 80 */
+       {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
+       {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
+       {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
+       {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
+       {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
+       {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
+       {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
+       {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
+       {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
+       {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
+       {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
+       {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
+       {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
+       {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
+       {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
+       {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
+/* */
+       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+/*fixme: + 0x12, 0x04*/
+       {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
+/* */
+       {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
+/* */
+       {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
+/*     {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
+       {}
+};
 static const __u8 ov7660_sensor_init[][8] = {
        {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
 /*             (delay 20ms) */
@@ -506,10 +613,16 @@ static const __u8 qtable4[] = {
        0x29, 0x29, 0x29, 0x29
 };
 
-/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
+/* read <len> bytes to gspca_dev->usb_buf */
 static void reg_r(struct gspca_dev *gspca_dev,
                  __u16 value, int len)
 {
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               err("reg_r: buffer overflow");
+               return;
+       }
+#endif
        usb_control_msg(gspca_dev->dev,
                        usb_rcvctrlpipe(gspca_dev->dev, 0),
                        0,
@@ -542,29 +655,20 @@ static void reg_w(struct gspca_dev *gspca_dev,
 {
        PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
                value, buffer[0], buffer[1]);
-       if (len <= sizeof gspca_dev->usb_buf) {
-               memcpy(gspca_dev->usb_buf, buffer, len);
-               usb_control_msg(gspca_dev->dev,
-                               usb_sndctrlpipe(gspca_dev->dev, 0),
-                               0x08,
-                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                               value, 0,
-                               gspca_dev->usb_buf, len,
-                               500);
-       } else {
-               __u8 *tmpbuf;
-
-               tmpbuf = kmalloc(len, GFP_KERNEL);
-               memcpy(tmpbuf, buffer, len);
-               usb_control_msg(gspca_dev->dev,
-                               usb_sndctrlpipe(gspca_dev->dev, 0),
-                               0x08,
-                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                               value, 0,
-                               tmpbuf, len,
-                               500);
-               kfree(tmpbuf);
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               err("reg_w: buffer overflow");
+               return;
        }
+#endif
+       memcpy(gspca_dev->usb_buf, buffer, len);
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       value, 0,
+                       gspca_dev->usb_buf, len,
+                       500);
 }
 
 /* I2C write 1 byte */
@@ -665,7 +769,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
        static const __u8 regd4[] = {0x60, 0x00, 0x00};
 
        reg_w1(gspca_dev, 0xf1, 0x00);
-       reg_w1(gspca_dev, 0x01, 0x00);          /*jfm was sn9c1xx[1] in v1*/
+       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
 
        /* configure gpio */
        reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
@@ -685,21 +789,41 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
 
        reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
 
-       switch (sd->bridge) {
-       case BRIDGE_SN9C325:
+       switch (sd->sensor) {
+       case SENSOR_OM6802:
+               reg_w1(gspca_dev, 0x02, 0x71);
+               reg_w1(gspca_dev, 0x01, 0x42);
+               reg_w1(gspca_dev, 0x17, 0x64);
+               reg_w1(gspca_dev, 0x01, 0x42);
+               break;
+/*jfm: from win trace */
+       case SENSOR_OV7630:
+               reg_w1(gspca_dev, 0x01, 0x61);
+               reg_w1(gspca_dev, 0x17, 0xe2);
+               reg_w1(gspca_dev, 0x01, 0x60);
+               reg_w1(gspca_dev, 0x01, 0x40);
+               break;
+       case SENSOR_OV7648:
                reg_w1(gspca_dev, 0x01, 0x43);
                reg_w1(gspca_dev, 0x17, 0xae);
                reg_w1(gspca_dev, 0x01, 0x42);
                break;
+/*jfm: from win trace */
+       case SENSOR_OV7660:
+               reg_w1(gspca_dev, 0x01, 0x61);
+               reg_w1(gspca_dev, 0x17, 0x20);
+               reg_w1(gspca_dev, 0x01, 0x60);
+               reg_w1(gspca_dev, 0x01, 0x40);
+               break;
        default:
                reg_w1(gspca_dev, 0x01, 0x43);
                reg_w1(gspca_dev, 0x17, 0x61);
                reg_w1(gspca_dev, 0x01, 0x42);
-       }
-
-       if (sd->sensor == SENSOR_HV7131R) {
-               if (probesensor(gspca_dev) < 0)
-                       return -ENODEV;
+               if (sd->sensor == SENSOR_HV7131R) {
+                       if (probesensor(gspca_dev) < 0)
+                               return -ENODEV;
+               }
+               break;
        }
        return 0;
 }
@@ -737,6 +861,40 @@ static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
        }
 }
 
+static void om6802_InitSensor(struct gspca_dev *gspca_dev)
+{
+       int i = 0;
+
+       while (om6802_sensor_init[i][0]) {
+               i2c_w8(gspca_dev, om6802_sensor_init[i]);
+               i++;
+       }
+}
+
+static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
+{
+       int i = 0;
+
+       i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 76 01 */
+       i++;
+       i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 12 c8 (RGB+SRST) */
+       i++;
+       msleep(20);
+       i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 12 48 */
+       i++;
+       i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 12 c8 */
+       i++;
+       msleep(20);
+       i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 12 48 */
+       i++;
+/*jfm:win i2c_r from 00 to 80*/
+
+       while (ov7630_sensor_init[i][0]) {
+               i2c_w8(gspca_dev, ov7630_sensor_init[i]);
+               i++;
+       }
+}
+
 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
 {
        int i = 0;
@@ -783,11 +941,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->autogain = AUTOGAIN_DEF;
        sd->ag_cnt = -1;
 
+       switch (sd->sensor) {
+       case SENSOR_OV7630:
+       case SENSOR_OV7648:
+       case SENSOR_OV7660:
+               gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
+               break;
+       }
+
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 /*     const __u8 *sn9c1xx; */
@@ -891,16 +1057,53 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev,
                        | ((expoMo10[3] & 0x30) >> 4));
                break;
            }
+       case SENSOR_OM6802: {
+               __u8 gainOm[] =
+                       { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
+
+               if (expo > 0x03ff)
+                       expo = 0x03ff;
+                if (expo < 0x0001)
+                       expo = 0x0001;
+               gainOm[3] = expo >> 2;
+               i2c_w8(gspca_dev, gainOm);
+               reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
+               PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
+               break;
+           }
        }
        return expo;
 }
 
+/* this function is used for sensors o76xx only */
+static void setbrightcont(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       unsigned val;
+       __u8 reg84_full[0x15];
+
+       memset(reg84_full, 0, sizeof reg84_full);
+       val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10;        /* 10..30 */
+       reg84_full[2] = val;
+       reg84_full[0] = (val + 1) / 2;
+       reg84_full[4] = (val + 1) / 5;
+       if (val > BRIGHTNESS_DEF)
+               val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
+                       / BRIGHTNESS_MAX;
+       else
+               val = 0;
+       reg84_full[0x12] = val;                 /* 00..1f */
+       reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
+}
+
+/* sensor != ov76xx */
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        unsigned int expo;
        __u8 k2;
 
+       k2 = sd->brightness >> 10;
        switch (sd->sensor) {
        case SENSOR_HV7131R:
                expo = sd->brightness << 4;
@@ -915,12 +1118,17 @@ static void setbrightness(struct gspca_dev *gspca_dev)
                expo = sd->brightness >> 4;
                sd->exposure = setexposure(gspca_dev, expo);
                break;
+       case SENSOR_OM6802:
+               expo = sd->brightness >> 6;
+               sd->exposure = setexposure(gspca_dev, expo);
+               k2 = sd->brightness >> 11;
+               break;
        }
 
-       k2 = sd->brightness >> 10;
        reg_w1(gspca_dev, 0x96, k2);
 }
 
+/* sensor != ov76xx */
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -937,31 +1145,30 @@ static void setcontrast(struct gspca_dev *gspca_dev)
 static void setcolors(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       __u8 data;
-       int colour;
+       __u8 blue, red;
 
-       colour = sd->colors - 128;
-       if (colour > 0)
-               data = (colour + 32) & 0x7f;    /* blue */
-       else
-               data = (-colour + 32) & 0x7f;   /* red */
-       reg_w1(gspca_dev, 0x05, data);
+       if (sd->colors >= 32) {
+               red = 32 + (sd->colors - 32) / 2;
+               blue = 64 - sd->colors;
+       } else {
+               red = sd->colors;
+               blue = 32 + (32 - sd->colors) / 2;
+       }
+       reg_w1(gspca_dev, 0x05, red);
+/*     reg_w1(gspca_dev, 0x07, 32); */
+       reg_w1(gspca_dev, 0x06, blue);
 }
 
 static void setautogain(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-       case SENSOR_MO4000:
-       case SENSOR_MI0360:
-               if (sd->autogain)
-                       sd->ag_cnt = AG_CNT_START;
-               else
-                       sd->ag_cnt = -1;
-               break;
-       }
+       if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
+               return;
+       if (sd->autogain)
+               sd->ag_cnt = AG_CNT_START;
+       else
+               sd->ag_cnt = -1;
 }
 
 /* -- start the camera -- */
@@ -975,13 +1182,12 @@ static void sd_start(struct gspca_dev *gspca_dev)
        static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
        static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
        static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };    /* MI0360 */
-       static const __u8 CE_sn9c325[] =
-                       { 0x32, 0xdd, 0x32, 0xdd };     /* OV7648 - SN9C325 */
+       static const __u8 CE_ov76xx[] =
+                       { 0x32, 0xdd, 0x32, 0xdd };     /* OV7630/48 */
 
        sn9c1xx = sn_tb[(int) sd->sensor];
        configure_gpio(gspca_dev, sn9c1xx);
 
-/*     reg_w1(gspca_dev, 0x01, 0x44);          jfm from win trace*/
        reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
        reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
        reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
@@ -994,10 +1200,17 @@ static void sd_start(struct gspca_dev *gspca_dev)
        reg_w1(gspca_dev, 0xc8, 0x50);
        reg_w1(gspca_dev, 0xc9, 0x3c);
        reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
-       switch (sd->bridge) {
-       case BRIDGE_SN9C325:
+       switch (sd->sensor) {
+       case SENSOR_OV7630:
+               reg17 = 0xe2;
+               break;
+       case SENSOR_OV7648:
                reg17 = 0xae;
                break;
+/*jfm: from win trace */
+       case SENSOR_OV7660:
+               reg17 = 0xa0;
+               break;
        default:
                reg17 = 0x60;
                break;
@@ -1007,24 +1220,11 @@ static void sd_start(struct gspca_dev *gspca_dev)
        reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
        reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
        reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
-       switch (sd->bridge) {
-       case BRIDGE_SN9C325:
-               reg_w(gspca_dev, 0x20, regsn20_sn9c325,
-                               sizeof regsn20_sn9c325);
-               for (i = 0; i < 8; i++)
-                       reg_w(gspca_dev, 0x84, reg84_sn9c325,
-                                       sizeof reg84_sn9c325);
-               reg_w1(gspca_dev, 0x9a, 0x0a);
-               reg_w1(gspca_dev, 0x99, 0x60);
-               break;
-       default:
-               reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
-               for (i = 0; i < 8; i++)
-                       reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
+       reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
+       for (i = 0; i < 8; i++)
+               reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
                reg_w1(gspca_dev, 0x9a, 0x08);
                reg_w1(gspca_dev, 0x99, 0x59);
-               break;
-       }
 
        mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
        if (mode)
@@ -1049,6 +1249,15 @@ static void sd_start(struct gspca_dev *gspca_dev)
 /*                     reg1 = 0x06;     * 640 clk 24Mz (done) */
                }
                break;
+       case SENSOR_OM6802:
+               om6802_InitSensor(gspca_dev);
+               reg17 = 0x64;           /* 640 MCKSIZE */
+               break;
+       case SENSOR_OV7630:
+               ov7630_InitSensor(gspca_dev);
+               reg17 = 0xe2;
+               reg1 = 0x44;
+               break;
        case SENSOR_OV7648:
                ov7648_InitSensor(gspca_dev);
                reg17 = 0xa2;
@@ -1073,9 +1282,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
        }
        reg_w(gspca_dev, 0xc0, C0, 6);
        reg_w(gspca_dev, 0xca, CA, 4);
-       switch (sd->bridge) {
-       case BRIDGE_SN9C325:
-               reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
+       switch (sd->sensor) {
+       case SENSOR_OV7630:
+       case SENSOR_OV7648:
+               reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
                break;
        default:
                reg_w(gspca_dev, 0xce, CE, 4);
@@ -1093,10 +1303,20 @@ static void sd_start(struct gspca_dev *gspca_dev)
        reg_w1(gspca_dev, 0x18, reg18);
 
        reg_w1(gspca_dev, 0x17, reg17);
-       reg_w1(gspca_dev, 0x01, reg1);
-       setbrightness(gspca_dev);
-       setcontrast(gspca_dev);
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+       case SENSOR_MI0360:
+       case SENSOR_MO4000:
+       case SENSOR_OM6802:
+               setbrightness(gspca_dev);
+               setcontrast(gspca_dev);
+               break;
+       default:                        /* OV76xx */
+               setbrightcont(gspca_dev);
+               break;
+       }
        setautogain(gspca_dev);
+       reg_w1(gspca_dev, 0x01, reg1);
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1119,6 +1339,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                i2c_w8(gspca_dev, stopmi0360);
                data = 0x29;
                break;
+       case SENSOR_OV7630:
        case SENSOR_OV7648:
                data = 0x29;
                break;
@@ -1132,15 +1353,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
        reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
        reg_w1(gspca_dev, 0x01, data);
-       reg_w1(gspca_dev, 0xf1, 0x01);
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
+       reg_w1(gspca_dev, 0xf1, 0x00);
 }
 
 static void do_autogain(struct gspca_dev *gspca_dev)
@@ -1174,6 +1387,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
                default:
 /*             case SENSOR_MO4000: */
 /*             case SENSOR_MI0360: */
+/*             case SENSOR_OM6802: */
                        expotimes = sd->exposure;
                        expotimes += (luma_mean - delta) >> 6;
                        if (expotimes < 0)
@@ -1229,69 +1443,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
        gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
-static unsigned int getexposure(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u8 hexpo, mexpo, lexpo;
-
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-               /* read sensor exposure */
-               i2c_r5(gspca_dev, 0x25);
-               return (gspca_dev->usb_buf[0] << 16)
-                       | (gspca_dev->usb_buf[1] << 8)
-                       | gspca_dev->usb_buf[2];
-       case SENSOR_MI0360:
-               /* read sensor exposure */
-               i2c_r5(gspca_dev, 0x09);
-               return (gspca_dev->usb_buf[0] << 8)
-                       | gspca_dev->usb_buf[1];
-       case SENSOR_MO4000:
-               i2c_r5(gspca_dev, 0x0e);
-               hexpo = 0;              /* gspca_dev->usb_buf[1] & 0x07; */
-               mexpo = 0x40;           /* gspca_dev->usb_buf[2] & 0xff; */
-               lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
-               PDEBUG(D_CONF, "exposure %d",
-                       (hexpo << 10) | (mexpo << 2) | lexpo);
-               return (hexpo << 10) | (mexpo << 2) | lexpo;
-       default:
-/*     case SENSOR_OV7648:             * jfm: is it ok for 7648? */
-/*     case SENSOR_OV7660: */
-               /* read sensor exposure */
-               i2c_r5(gspca_dev, 0x04);
-               hexpo = gspca_dev->usb_buf[3] & 0x2f;
-               lexpo = gspca_dev->usb_buf[0] & 0x02;
-               i2c_r5(gspca_dev, 0x08);
-               mexpo = gspca_dev->usb_buf[2];
-               return (hexpo << 10) | (mexpo << 2) | lexpo;
-       }
-}
-
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* hardcoded registers seem not readable */
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-               sd->brightness = getexposure(gspca_dev) >> 4;
-               break;
-       case SENSOR_MI0360:
-               sd->brightness = getexposure(gspca_dev) << 4;
-               break;
-       case SENSOR_MO4000:
-               sd->brightness = getexposure(gspca_dev) << 4;
-               break;
-       }
-}
-
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
        sd->brightness = val;
-       if (gspca_dev->streaming)
-               setbrightness(gspca_dev);
+       if (gspca_dev->streaming) {
+               switch (sd->sensor) {
+               case SENSOR_HV7131R:
+               case SENSOR_MI0360:
+               case SENSOR_MO4000:
+               case SENSOR_OM6802:
+                       setbrightness(gspca_dev);
+                       break;
+               default:                        /* OV76xx */
+                       setbrightcont(gspca_dev);
+                       break;
+               }
+       }
        return 0;
 }
 
@@ -1299,7 +1468,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       getbrightness(gspca_dev);
        *val = sd->brightness;
        return 0;
 }
@@ -1309,8 +1477,19 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
        struct sd *sd = (struct sd *) gspca_dev;
 
        sd->contrast = val;
-       if (gspca_dev->streaming)
-               setcontrast(gspca_dev);
+       if (gspca_dev->streaming) {
+               switch (sd->sensor) {
+               case SENSOR_HV7131R:
+               case SENSOR_MI0360:
+               case SENSOR_MO4000:
+               case SENSOR_OM6802:
+                       setcontrast(gspca_dev);
+                       break;
+               default:                        /* OV76xx */
+                       setbrightcont(gspca_dev);
+                       break;
+               }
+       }
        return 0;
 }
 
@@ -1364,11 +1543,9 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .dq_callback = do_autogain,
 };
@@ -1379,7 +1556,7 @@ static const struct sd_desc sd_desc = {
                        | (SENSOR_ ## sensor << 8) \
                        | (i2c_addr)
 static const __devinitdata struct usb_device_id device_table[] = {
-#ifndef CONFIG_USB_SN9C102
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
        {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
        {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
@@ -1406,15 +1583,17 @@ static const __devinitdata struct usb_device_id device_table[] = {
 /*     {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
 /*     {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
 /*     {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
-       {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)},
-/* bw600.inf:
-       {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */
+       {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
+/*bw600.inf:*/
+       {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
        {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
-/*     {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */
+       {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
 /*     {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
-#ifndef CONFIG_USB_SN9C102
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
+#endif
        {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 /*     {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
        {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
        {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
@@ -1438,6 +1617,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 17fe2c2a440d8f222f434c4c2692db093ef4e50d..6e733901fcca24129457aba26946e4229af6ca0f 100644 (file)
@@ -645,8 +645,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
@@ -880,14 +880,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                gspca_dev->usb_buf[0]);
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -1051,11 +1043,9 @@ static struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -1093,6 +1083,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 51a3c3429ef0c26b2f71cb2e9439eec3d1b98921..e9eb59bae4fbf1b82effe0d21d5496213a86db80 100644 (file)
@@ -1953,8 +1953,8 @@ error:
        return -EINVAL;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
@@ -2022,11 +2022,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
 }
 
 static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
 {
        reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
 }
@@ -2120,11 +2115,10 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
        .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -2154,6 +2148,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index eda29d609359fdd2833cb31426e1e3620cc8639e..f601daf19ebeabacaf044af300f1914ed69caa61 100644 (file)
@@ -655,8 +655,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int ret;
@@ -742,11 +742,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
 }
 
 static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
 {
        /* This maybe reset or power control */
        reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
@@ -825,11 +820,10 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
        .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -855,6 +849,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index f622fa75766dfb0df3c47affed9efe8883f23282..195dce96ef068d5579b1cd896c623ed242619378 100644 (file)
@@ -313,8 +313,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        struct usb_device *dev = gspca_dev->dev;
 
@@ -560,14 +560,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        reg_w(dev, 0x03, 0x00, 0x0003);
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -740,11 +732,9 @@ static struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -772,6 +762,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 699340c17deabbcd548b0606e6d0bc86b206be75..281ce02103a336ced7a1d10042b3c830fdcf1155 100644 (file)
@@ -1521,8 +1521,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;                       /* success */
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
 /*     write_vector(gspca_dev, spca508_open_data); */
        return 0;
@@ -1554,15 +1554,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        reg_write(gspca_dev->dev, 0x8112, 0x20);
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -1633,11 +1624,9 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -1667,6 +1656,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 1073ac3d2ec64c1bbe4649fe65c5f9347f527f16..cfbc9ebc5c5d8f6bb6518bc352a1c0a69afe530b 100644 (file)
@@ -32,69 +32,48 @@ MODULE_LICENSE("GPL");
 struct sd {
        struct gspca_dev gspca_dev;     /* !! must be the first item */
 
-       unsigned short contrast;
-       __u8 brightness;
+       __u16 contrast;                 /* rev72a only */
+#define CONTRAST_MIN 0x0000
+#define CONTRAST_DEF 0x2000
+#define CONTRAST_MAX 0x3fff
+
+       __u16 exposure;                 /* rev12a only */
+#define EXPOSURE_MIN 1
+#define EXPOSURE_DEF 200
+#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */
+
+       __u8 brightness;                /* rev72a only */
+#define BRIGHTNESS_MIN 0
+#define BRIGHTNESS_DEF 32
+#define BRIGHTNESS_MAX 63
+
+       __u8 white;                     /* rev12a only */
+#define WHITE_MIN 1
+#define WHITE_DEF 0x40
+#define WHITE_MAX 0x7f
+
        __u8 autogain;
+#define AUTOGAIN_MIN 0
+#define AUTOGAIN_DEF 1
+#define AUTOGAIN_MAX 1
+
+       __u8 gain;                      /* rev12a only */
+#define GAIN_MIN 0x0
+#define GAIN_DEF 0x24
+#define GAIN_MAX 0x24
+
+#define EXPO12A_DEF 3
+       __u8 expo12a;           /* expo/gain? for rev 12a */
 
        __u8 chip_revision;
+#define Rev012A 0
+#define Rev072A 1
+
        signed char ag_cnt;
 #define AG_CNT_START 13
 };
 
-/* V4L2 controls supported by the driver */
-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
-
-static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
-       {
-        {
-         .id = V4L2_CID_BRIGHTNESS,
-         .type = V4L2_CTRL_TYPE_INTEGER,
-         .name = "Brightness",
-         .minimum = 0,
-         .maximum = 63,
-         .step = 1,
-         .default_value = 32,
-         },
-        .set = sd_setbrightness,
-        .get = sd_getbrightness,
-        },
-#define SD_CONTRAST 1
-       {
-        {
-         .id = V4L2_CID_CONTRAST,
-         .type = V4L2_CTRL_TYPE_INTEGER,
-         .name = "Contrast",
-         .minimum = 0,
-         .maximum = 0x3fff,
-         .step = 1,
-         .default_value = 0x2000,
-         },
-        .set = sd_setcontrast,
-        .get = sd_getcontrast,
-        },
-#define SD_AUTOGAIN 2
-       {
-        {
-         .id = V4L2_CID_AUTOGAIN,
-         .type = V4L2_CTRL_TYPE_BOOLEAN,
-         .name = "Auto Gain",
-         .minimum = 0,
-         .maximum = 1,
-         .step = 1,
-         .default_value = 1,
-         },
-        .set = sd_setautogain,
-        .get = sd_getautogain,
-        },
-};
-
-static struct v4l2_pix_format sif_mode[] = {
+static struct v4l2_pix_format sif_012a_mode[] = {
        {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
                .bytesperline = 160,
                .sizeimage = 160 * 120,
@@ -117,6 +96,29 @@ static struct v4l2_pix_format sif_mode[] = {
                .priv = 0},
 };
 
+static struct v4l2_pix_format sif_072a_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
 /*
  * Initialization data
  * I'm not very sure how to split initialization from open data
@@ -143,12 +145,8 @@ static struct v4l2_pix_format sif_mode[] = {
 #define SPCA561_INDEX_I2C_BASE 0x8800
 #define SPCA561_SNAPBIT 0x20
 #define SPCA561_SNAPCTRL 0x40
-enum {
-       Rev072A = 0,
-       Rev012A,
-};
 
-static void reg_w_val(struct usb_device *dev, __u16 index, __u16 value)
+static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
 {
        int ret;
 
@@ -198,12 +196,6 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
                        index, gspca_dev->usb_buf, len, 500);
 }
 
-static void i2c_init(struct gspca_dev *gspca_dev, __u8 mode)
-{
-       reg_w_val(gspca_dev->dev, 0x92, 0x8804);
-       reg_w_val(gspca_dev->dev, mode, 0x8802);
-}
-
 static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
 {
        int retry = 60;
@@ -212,9 +204,9 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
 
        DataLow = valeur;
        DataHight = valeur >> 8;
-       reg_w_val(gspca_dev->dev, reg, 0x8801);
-       reg_w_val(gspca_dev->dev, DataLow, 0x8805);
-       reg_w_val(gspca_dev->dev, DataHight, 0x8800);
+       reg_w_val(gspca_dev->dev, 0x8801, reg);
+       reg_w_val(gspca_dev->dev, 0x8805, DataLow);
+       reg_w_val(gspca_dev->dev, 0x8800, DataHight);
        while (retry--) {
                reg_r(gspca_dev, 0x8803, 1);
                if (!gspca_dev->usb_buf[0])
@@ -228,14 +220,14 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
        __u8 value;
        __u8 vallsb;
 
-       reg_w_val(gspca_dev->dev, 0x92, 0x8804);
-       reg_w_val(gspca_dev->dev, reg, 0x8801);
-       reg_w_val(gspca_dev->dev, (mode | 0x01), 0x8802);
-       while (retry--) {
+       reg_w_val(gspca_dev->dev, 0x8804, 0x92);
+       reg_w_val(gspca_dev->dev, 0x8801, reg);
+       reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));
+       do {
                reg_r(gspca_dev, 0x8803, 1);
                if (!gspca_dev->usb_buf)
                        break;
-       }
+       } while (--retry);
        if (retry == 0)
                return -1;
        reg_r(gspca_dev, 0x8800, 1);
@@ -438,21 +430,10 @@ static const __u16 spca561_init_data[][2] = {
        {0x0035, 0x8801},       /* 0x14 - set gain general */
        {0x001f, 0x8805},       /* 0x14 */
        {0x0000, 0x8800},
-       {0x0030, 0x8112},
+       {0x000e, 0x8112},       /* white balance - was 30 */
        {}
 };
 
-static void sensor_reset(struct gspca_dev *gspca_dev)
-{
-       reg_w_val(gspca_dev->dev, 0x8631, 0xc8);
-       reg_w_val(gspca_dev->dev, 0x8634, 0xc8);
-       reg_w_val(gspca_dev->dev, 0x8112, 0x00);
-       reg_w_val(gspca_dev->dev, 0x8114, 0x00);
-       reg_w_val(gspca_dev->dev, 0x8118, 0x21);
-       i2c_init(gspca_dev, 0x14);
-       i2c_write(gspca_dev, 1, 0x0d);
-       i2c_write(gspca_dev, 0, 0x0d);
-}
 
 /******************** QC Express etch2 stuff ********************/
 static const __u16 Pb100_1map8300[][2] = {
@@ -462,9 +443,9 @@ static const __u16 Pb100_1map8300[][2] = {
        {0x8303, 0x0125},       /* image area */
        {0x8304, 0x0169},
        {0x8328, 0x000b},
-       {0x833c, 0x0001},
+       {0x833c, 0x0001},               /*fixme: win:07*/
 
-       {0x832f, 0x0419},
+       {0x832f, 0x1904},               /*fixme: was 0419*/
        {0x8307, 0x00aa},
        {0x8301, 0x0003},
        {0x8302, 0x000e},
@@ -478,9 +459,10 @@ static const __u16 Pb100_2map8300[][2] = {
 };
 
 static const __u16 spca561_161rev12A_data1[][2] = {
-       {0x21, 0x8118},
-       {0x01, 0x8114},
-       {0x00, 0x8112},
+       {0x29, 0x8118},         /* white balance - was 21 */
+       {0x08, 0x8114},         /* white balance - was 01 */
+       {0x0e, 0x8112},         /* white balance - was 00 */
+       {0x00, 0x8102},         /* white balance - new */
        {0x92, 0x8804},
        {0x04, 0x8802},         /* windows uses 08 */
        {}
@@ -505,14 +487,16 @@ static const __u16 spca561_161rev12A_data2[][2] = {
        {0xb0, 0x8603},
 
        /* sensor gains */
+       {0x07, 0x8601},         /* white balance - new */
+       {0x07, 0x8602},         /* white balance - new */
        {0x00, 0x8610},         /* *red */
        {0x00, 0x8611},         /* 3f   *green */
        {0x00, 0x8612},         /* green *blue */
        {0x00, 0x8613},         /* blue *green */
-       {0x35, 0x8614},         /* green *red */
-       {0x35, 0x8615},         /* 40   *green */
-       {0x35, 0x8616},         /* 7a   *blue */
-       {0x35, 0x8617},         /* 40   *green */
+       {0x43, 0x8614},         /* green *red - white balance - was 0x35 */
+       {0x40, 0x8615},         /* 40   *green - white balance - was 0x35 */
+       {0x71, 0x8616},         /* 7a   *blue - white balance - was 0x35 */
+       {0x40, 0x8617},         /* 40   *green - white balance - was 0x35 */
 
        {0x0c, 0x8620},         /* 0c */
        {0xc8, 0x8631},         /* c8 */
@@ -527,6 +511,7 @@ static const __u16 spca561_161rev12A_data2[][2] = {
        {0xdf, 0x863c},         /* df */
        {0xf0, 0x8505},
        {0x32, 0x850a},
+/*     {0x99, 0x8700},          * - white balance - new (removed) */
        {}
 };
 
@@ -545,9 +530,10 @@ static void sensor_mapwrite(struct gspca_dev *gspca_dev,
 }
 static void init_161rev12A(struct gspca_dev *gspca_dev)
 {
-       sensor_reset(gspca_dev);
+/*     sensor_reset(gspca_dev);        (not in win) */
        write_vector(gspca_dev, spca561_161rev12A_data1);
        sensor_mapwrite(gspca_dev, Pb100_1map8300);
+/*fixme: should be in sd_start*/
        write_vector(gspca_dev, spca561_161rev12A_data2);
        sensor_mapwrite(gspca_dev, Pb100_2map8300);
 }
@@ -581,35 +567,38 @@ static int sd_config(struct gspca_dev *gspca_dev,
        }
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        gspca_dev->nbalt = 7 + 1;       /* choose alternate 7 first */
-       cam->cam_mode = sif_mode;
-       cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
 
        sd->chip_revision = id->driver_info;
-       sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
-       sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
-       sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
+       if (sd->chip_revision == Rev012A) {
+               cam->cam_mode = sif_012a_mode;
+               cam->nmodes = ARRAY_SIZE(sif_012a_mode);
+       } else {
+               cam->cam_mode = sif_072a_mode;
+               cam->nmodes = ARRAY_SIZE(sif_072a_mode);
+       }
+       sd->brightness = BRIGHTNESS_DEF;
+       sd->contrast = CONTRAST_DEF;
+       sd->white = WHITE_DEF;
+       sd->exposure = EXPOSURE_DEF;
+       sd->autogain = AUTOGAIN_DEF;
+       sd->gain = GAIN_DEF;
+       sd->expo12a = EXPO12A_DEF;
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init_12a(struct gspca_dev *gspca_dev)
 {
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->chip_revision) {
-       case Rev072A:
-               PDEBUG(D_STREAM, "Chip revision id: 072a");
-               write_vector(gspca_dev, spca561_init_data);
-               break;
-       default:
-/*     case Rev012A: */
-               PDEBUG(D_STREAM, "Chip revision id: 012a");
-               init_161rev12A(gspca_dev);
-               break;
-       }
+       PDEBUG(D_STREAM, "Chip revision: 012a");
+       init_161rev12A(gspca_dev);
+       return 0;
+}
+static int sd_init_72a(struct gspca_dev *gspca_dev)
+{
+       PDEBUG(D_STREAM, "Chip revision: 072a");
+       write_vector(gspca_dev, spca561_init_data);
        return 0;
 }
 
@@ -618,25 +607,20 @@ static void setcontrast(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
        struct usb_device *dev = gspca_dev->dev;
        __u8 lowb;
-       int expotimes;
 
        switch (sd->chip_revision) {
        case Rev072A:
                lowb = sd->contrast >> 8;
-               reg_w_val(dev, lowb, 0x8651);
-               reg_w_val(dev, lowb, 0x8652);
-               reg_w_val(dev, lowb, 0x8653);
-               reg_w_val(dev, lowb, 0x8654);
+               reg_w_val(dev, 0x8651, lowb);
+               reg_w_val(dev, 0x8652, lowb);
+               reg_w_val(dev, 0x8653, lowb);
+               reg_w_val(dev, 0x8654, lowb);
                break;
-       case Rev012A: {
-               __u8 Reg8391[] =
-                       { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 };
-
-               /* Write camera sensor settings */
-               expotimes = (sd->contrast >> 5) & 0x07ff;
-               Reg8391[0] = expotimes & 0xff;  /* exposure */
-               Reg8391[1] = 0x18 | (expotimes >> 8);
-               Reg8391[2] = sd->brightness;    /* gain */
+       default: {
+/*     case Rev012A: { */
+               static const __u8 Reg8391[] =
+                       { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 };
+
                reg_w_buf(gspca_dev, 0x8391, Reg8391, 8);
                reg_w_buf(gspca_dev, 0x8390, Reg8391, 8);
                break;
@@ -644,93 +628,151 @@ static void setcontrast(struct gspca_dev *gspca_dev)
        }
 }
 
-static void setautogain(struct gspca_dev *gspca_dev)
+/* rev12a only */
+static void setwhite(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
+       __u16 white;
+       __u8 reg8614, reg8616;
+
+       white = sd->white;
+       /* try to emulate MS-win as possible */
+       reg8616 = 0x90 - white * 5 / 8;
+       reg_w_val(gspca_dev->dev, 0x8616, reg8616);
+       reg8614 = 0x20 + white * 3 / 8;
+       reg_w_val(gspca_dev->dev, 0x8614, reg8614);
+}
 
-       if (sd->chip_revision == Rev072A) {
-               if (sd->autogain)
-                       sd->ag_cnt = AG_CNT_START;
-               else
-                       sd->ag_cnt = -1;
+/* rev 12a only */
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int expo;
+       int clock_divider;
+       __u8 data[2];
+
+       /* Register 0x8309 controls exposure for the spca561,
+          the basic exposure setting goes from 1-2047, where 1 is completely
+          dark and 2047 is very bright. It not only influences exposure but
+          also the framerate (to allow for longer exposure) from 1 - 300 it
+          only raises the exposure time then from 300 - 600 it halves the
+          framerate to be able to further raise the exposure time and for every
+          300 more it halves the framerate again. This allows for a maximum
+          exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
+          Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
+          configure a divider for the base framerate which us used at the
+          exposure setting of 1-300. These bits configure the base framerate
+          according to the following formula: fps = 60 / (value + 2) */
+       if (sd->exposure < 2048) {
+               expo = sd->exposure;
+               clock_divider = 0;
+       } else {
+               /* Add 900 to make the 0 setting of the second part of the
+                  exposure equal to the 2047 setting of the first part. */
+               expo = (sd->exposure - 2048) + 900;
+               clock_divider = 3;
        }
+       expo |= clock_divider << 11;
+       data[0] = expo;
+       data[1] = expo >> 8;
+       reg_w_buf(gspca_dev, 0x8309, data, 2);
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+/* rev 12a only */
+static void setgain(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
+       __u8 data[2];
+
+       data[0] = sd->gain;
+       data[1] = 0;
+       reg_w_buf(gspca_dev, 0x8335, data, 2);
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->autogain)
+               sd->ag_cnt = AG_CNT_START;
+       else
+               sd->ag_cnt = -1;
+}
+
+static void sd_start_12a(struct gspca_dev *gspca_dev)
+{
        struct usb_device *dev = gspca_dev->dev;
-       int Clck;
+       int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */
        __u8 Reg8307[] = { 0xaa, 0x00 };
        int mode;
 
        mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-       switch (sd->chip_revision) {
-       case Rev072A:
-               switch (mode) {
-               default:
-/*             case 0:
-               case 1: */
-                       Clck = 0x25;
-                       break;
-               case 2:
-                       Clck = 0x22;
-                       break;
-               case 3:
-                       Clck = 0x21;
-                       break;
-               }
-               reg_w_val(dev, 0x8500, mode);   /* mode */
-               reg_w_val(dev, 0x8700, Clck);   /* 0x27 clock */
-               reg_w_val(dev, 0x8112, 0x10 | 0x20);
-               setautogain(gspca_dev);
-               break;
+       if (mode <= 1) {
+               /* Use compression on 320x240 and above */
+               reg_w_val(dev, 0x8500, 0x10 | mode);
+       } else {
+               /* I couldn't get the compression to work below 320x240
+                * Fortunately at these resolutions the bandwidth
+                * is sufficient to push raw frames at ~20fps */
+               reg_w_val(dev, 0x8500, mode);
+       }               /* -- qq@kuku.eu.org */
+       reg_w_buf(gspca_dev, 0x8307, Reg8307, 2);
+       reg_w_val(gspca_dev->dev, 0x8700, Clck);
+                                       /* 0x8f 0x85 0x27 clock */
+       reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
+       reg_w_val(gspca_dev->dev, 0x850b, 0x03);
+       setcontrast(gspca_dev);
+       setwhite(gspca_dev);
+       setautogain(gspca_dev);
+       setexposure(gspca_dev);
+}
+static void sd_start_72a(struct gspca_dev *gspca_dev)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int Clck;
+       int mode;
+
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       switch (mode) {
        default:
-/*     case Rev012A: */
-               switch (mode) {
-               case 0:
-               case 1:
-                       Clck = 0x8a;
-                       break;
-               case 2:
-                       Clck = 0x85;
-                       break;
-               default:
-                       Clck = 0x83;
-                       break;
-               }
-               if (mode <= 1) {
-                       /* Use compression on 320x240 and above */
-                       reg_w_val(dev, 0x8500, 0x10 | mode);
-               } else {
-                       /* I couldn't get the compression to work below 320x240
-                        * Fortunately at these resolutions the bandwidth
-                        * is sufficient to push raw frames at ~20fps */
-                       reg_w_val(dev, 0x8500, mode);
-               }               /* -- qq@kuku.eu.org */
-               reg_w_buf(gspca_dev, 0x8307, Reg8307, 2);
-               reg_w_val(gspca_dev->dev, 0x8700, Clck);
-                                               /* 0x8f 0x85 0x27 clock */
-               reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
-               reg_w_val(gspca_dev->dev, 0x850b, 0x03);
-               setcontrast(gspca_dev);
+/*     case 0:
+       case 1: */
+               Clck = 0x25;
+               break;
+       case 2:
+               Clck = 0x22;
+               break;
+       case 3:
+               Clck = 0x21;
                break;
        }
+       reg_w_val(dev, 0x8500, mode);   /* mode */
+       reg_w_val(dev, 0x8700, Clck);   /* 0x27 clock */
+       reg_w_val(dev, 0x8112, 0x10 | 0x20);
+       setautogain(gspca_dev);
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
-       reg_w_val(gspca_dev->dev, 0x8112, 0x20);
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->chip_revision == Rev012A) {
+               reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
+       } else {
+               reg_w_val(gspca_dev->dev, 0x8112, 0x20);
+/*             reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
+       }
 }
 
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
-}
+       struct sd *sd = (struct sd *) gspca_dev;
 
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-       reg_w_val(gspca_dev->dev, 0x8114, 0);
+       if (sd->chip_revision == Rev012A) {
+               reg_w_val(gspca_dev->dev, 0x8118, 0x29);
+               reg_w_val(gspca_dev->dev, 0x8114, 0x08);
+       }
+/*     reg_w_val(gspca_dev->dev, 0x8114, 0); */
 }
 
 static void do_autogain(struct gspca_dev *gspca_dev)
@@ -744,6 +786,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
        __u8 luma_mean = 110;
        __u8 luma_delta = 20;
        __u8 spring = 4;
+       __u8 reg8339[2];
 
        if (sd->ag_cnt < 0)
                return;
@@ -798,13 +841,16 @@ static void do_autogain(struct gspca_dev *gspca_dev)
                }
                break;
        case Rev012A:
-               /* sensor registers is access and memory mapped to 0x8300 */
-               /* readind all 0x83xx block the sensor */
-               /*
-                * The data from the header seem wrong where is the luma
-                * and chroma mean value
-                * at the moment set exposure in contrast set
-                */
+               reg_r(gspca_dev, 0x8330, 2);
+               if (gspca_dev->usb_buf[1] > 0x08) {
+                       reg8339[0] = ++sd->expo12a;
+                       reg8339[1] = 0;
+                       reg_w_buf(gspca_dev, 0x8339, reg8339, 2);
+               } else if (gspca_dev->usb_buf[1] < 0x02) {
+                       reg8339[0] = --sd->expo12a;
+                       reg8339[1] = 0;
+                       reg_w_buf(gspca_dev, 0x8339, reg8339, 2);
+               }
                break;
        }
 }
@@ -814,6 +860,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        __u8 *data,             /* isoc packet */
                        int len)                /* iso packet length */
 {
+       struct sd *sd = (struct sd *) gspca_dev;
+
        switch (data[0]) {
        case 0:         /* start of frame */
                frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
@@ -826,8 +874,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                                        frame, data, len);
                } else {
                        /* raw bayer (with a header, which we skip) */
-                       data += 20;
-                       len -= 20;
+                       if (sd->chip_revision == Rev012A) {
+                               data += 20;
+                               len -= 20;
+                       } else {
+                               data += 16;
+                               len -= 16;
+                       }
                        gspca_frame_add(gspca_dev, FIRST_PACKET,
                                                frame, data, len);
                }
@@ -841,24 +894,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
        gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
+/* rev 72a only */
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        __u8 value;
 
-       switch (sd->chip_revision) {
-       case Rev072A:
-               value = sd->brightness;
-               reg_w_val(gspca_dev->dev, value, 0x8611);
-               reg_w_val(gspca_dev->dev, value, 0x8612);
-               reg_w_val(gspca_dev->dev, value, 0x8613);
-               reg_w_val(gspca_dev->dev, value, 0x8614);
-               break;
-       default:
-/*     case Rev012A: */
-               setcontrast(gspca_dev);
-               break;
-       }
+       value = sd->brightness;
+       reg_w_val(gspca_dev->dev, 0x8611, value);
+       reg_w_val(gspca_dev->dev, 0x8612, value);
+       reg_w_val(gspca_dev->dev, 0x8613, value);
+       reg_w_val(gspca_dev->dev, 0x8614, value);
 }
 
 static void getbrightness(struct gspca_dev *gspca_dev)
@@ -866,52 +912,38 @@ static void getbrightness(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
        __u16 tot;
 
-       switch (sd->chip_revision) {
-       case Rev072A:
-               tot = 0;
-               reg_r(gspca_dev, 0x8611, 1);
-               tot += gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8612, 1);
-               tot += gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8613, 1);
-               tot += gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8614, 1);
-               tot += gspca_dev->usb_buf[0];
-               sd->brightness = tot >> 2;
-               break;
-       default:
-/*     case Rev012A: */
-               /* no way to read sensor settings */
-               break;
-       }
+       tot = 0;
+       reg_r(gspca_dev, 0x8611, 1);
+       tot += gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0x8612, 1);
+       tot += gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0x8613, 1);
+       tot += gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0x8614, 1);
+       tot += gspca_dev->usb_buf[0];
+       sd->brightness = tot >> 2;
 }
 
+/* rev72a only */
 static void getcontrast(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        __u16 tot;
 
-       switch (sd->chip_revision) {
-       case Rev072A:
-               tot = 0;
-               reg_r(gspca_dev, 0x8651, 1);
-               tot += gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8652, 1);
-               tot += gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8653, 1);
-               tot += gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8654, 1);
-               tot += gspca_dev->usb_buf[0];
-               sd->contrast = tot << 6;
-               break;
-       default:
-/*     case Rev012A: */
-               /* no way to read sensor settings */
-               break;
-       }
+       tot = 0;
+       reg_r(gspca_dev, 0x8651, 1);
+       tot += gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0x8652, 1);
+       tot += gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0x8653, 1);
+       tot += gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0x8654, 1);
+       tot += gspca_dev->usb_buf[0];
+       sd->contrast = tot << 6;
        PDEBUG(D_CONF, "get contrast %d", sd->contrast);
 }
 
+/* rev 72a only */
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -931,6 +963,7 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
+/* rev 72a only */
 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -968,20 +1001,190 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
+/* rev12a only */
+static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->white = val;
+       if (gspca_dev->streaming)
+               setwhite(gspca_dev);
+       return 0;
+}
+
+static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->white;
+       return 0;
+}
+
+/* rev12a only */
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->exposure = val;
+       if (gspca_dev->streaming)
+               setexposure(gspca_dev);
+       return 0;
+}
+
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->exposure;
+       return 0;
+}
+
+/* rev12a only */
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->gain = val;
+       if (gspca_dev->streaming)
+               setgain(gspca_dev);
+       return 0;
+}
+
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->gain;
+       return 0;
+}
+
+/* control tables */
+static struct ctrl sd_ctrls_12a[] = {
+       {
+           {
+               .id = V4L2_CID_DO_WHITE_BALANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "While Balance",
+               .minimum = WHITE_MIN,
+               .maximum = WHITE_MAX,
+               .step = 1,
+               .default_value = WHITE_DEF,
+           },
+           .set = sd_setwhite,
+           .get = sd_getwhite,
+       },
+       {
+           {
+               .id = V4L2_CID_EXPOSURE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Exposure",
+               .minimum = EXPOSURE_MIN,
+               .maximum = EXPOSURE_MAX,
+               .step = 1,
+               .default_value = EXPOSURE_DEF,
+           },
+           .set = sd_setexposure,
+           .get = sd_getexposure,
+       },
+       {
+           {
+               .id = V4L2_CID_AUTOGAIN,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Auto Gain",
+               .minimum = AUTOGAIN_MIN,
+               .maximum = AUTOGAIN_MAX,
+               .step = 1,
+               .default_value = AUTOGAIN_DEF,
+           },
+           .set = sd_setautogain,
+           .get = sd_getautogain,
+       },
+       {
+           {
+               .id = V4L2_CID_GAIN,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Gain",
+               .minimum = GAIN_MIN,
+               .maximum = GAIN_MAX,
+               .step = 1,
+               .default_value = GAIN_DEF,
+           },
+           .set = sd_setgain,
+           .get = sd_getgain,
+       },
+};
+
+static struct ctrl sd_ctrls_72a[] = {
+       {
+          {
+               .id = V4L2_CID_BRIGHTNESS,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Brightness",
+               .minimum = BRIGHTNESS_MIN,
+               .maximum = BRIGHTNESS_MAX,
+               .step = 1,
+               .default_value = BRIGHTNESS_DEF,
+           },
+           .set = sd_setbrightness,
+           .get = sd_getbrightness,
+       },
+       {
+           {
+               .id = V4L2_CID_CONTRAST,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Contrast",
+               .minimum = CONTRAST_MIN,
+               .maximum = CONTRAST_MAX,
+               .step = 1,
+               .default_value = CONTRAST_DEF,
+           },
+           .set = sd_setcontrast,
+           .get = sd_getcontrast,
+       },
+       {
+           {
+               .id = V4L2_CID_AUTOGAIN,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Auto Gain",
+               .minimum = AUTOGAIN_MIN,
+               .maximum = AUTOGAIN_MAX,
+               .step = 1,
+               .default_value = AUTOGAIN_DEF,
+           },
+           .set = sd_setautogain,
+           .get = sd_getautogain,
+       },
+};
+
 /* sub-driver description */
-static const struct sd_desc sd_desc = {
+static const struct sd_desc sd_desc_12a = {
+       .name = MODULE_NAME,
+       .ctrls = sd_ctrls_12a,
+       .nctrls = ARRAY_SIZE(sd_ctrls_12a),
+       .config = sd_config,
+       .init = sd_init_12a,
+       .start = sd_start_12a,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+/*     .dq_callback = do_autogain,      * fixme */
+};
+static const struct sd_desc sd_desc_72a = {
        .name = MODULE_NAME,
-       .ctrls = sd_ctrls,
-       .nctrls = ARRAY_SIZE(sd_ctrls),
+       .ctrls = sd_ctrls_72a,
+       .nctrls = ARRAY_SIZE(sd_ctrls_72a),
        .config = sd_config,
-       .open = sd_open,
-       .start = sd_start,
+       .init = sd_init_72a,
+       .start = sd_start_72a,
        .stopN = sd_stopN,
        .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .dq_callback = do_autogain,
 };
+static const struct sd_desc *sd_desc[2] = {
+       &sd_desc_12a,
+       &sd_desc_72a
+};
 
 /* -- module initialisation -- */
 static const __devinitdata struct usb_device_id device_table[] = {
@@ -1009,7 +1212,9 @@ MODULE_DEVICE_TABLE(usb, device_table);
 static int sd_probe(struct usb_interface *intf,
                    const struct usb_device_id *id)
 {
-       return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+       return gspca_dev_probe(intf, id,
+                               sd_desc[id->driver_info],
+                               sizeof(struct sd),
                               THIS_MODULE);
 }
 
@@ -1018,6 +1223,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 16219cf6a6d5105b555126b5c381f7d1024bc0b7..2f2de429e273470669c42aa7d25749add1a33800 100644 (file)
@@ -306,8 +306,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        int ret;
 
@@ -398,14 +398,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        PDEBUG(D_STREAM, "camera stopped");
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -535,11 +527,9 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .querymenu = sd_querymenu,
 };
@@ -564,6 +554,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 54efa48bee014cd55d3cde1912debbe6c348cd9b..1cfcc6c4955874ab0bb05da32ef387136967c701 100644 (file)
@@ -449,31 +449,47 @@ static const __u8 qtable_spca504_default[2][64] = {
         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
 };
 
-static void reg_r(struct usb_device *dev,
-                          __u16 req,
-                          __u16 index,
-                          __u8 *buffer, __u16 length)
+/* read <len> bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 __u16 req,
+                 __u16 index,
+                 __u16 len)
 {
-       usb_control_msg(dev,
-                       usb_rcvctrlpipe(dev, 0),
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               err("reg_r: buffer overflow");
+               return;
+       }
+#endif
+       usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
                        req,
                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                        0,              /* value */
-                       index, buffer, length,
+                       index,
+                       len ? gspca_dev->usb_buf : NULL, len,
                        500);
 }
 
-static void reg_w(struct usb_device *dev,
-                           __u16 req,
-                           __u16 value,
-                           __u16 index,
-                           __u8 *buffer, __u16 length)
+/* write <len> bytes from gspca_dev->usb_buf */
+static void reg_w(struct gspca_dev *gspca_dev,
+                  __u16 req,
+                  __u16 value,
+                  __u16 index,
+                  __u16 len)
 {
-       usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               err("reg_w: buffer overflow");
+               return;
+       }
+#endif
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
                        req,
                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, buffer, length,
+                       value, index,
+                       len ? gspca_dev->usb_buf : NULL, len,
                        500);
 }
 
@@ -634,7 +650,7 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
        int count = 10;
 
        while (--count > 0) {
-               reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
+               reg_r(gspca_dev, 0x21, 0, 1);
                if ((gspca_dev->usb_buf[0] & 0x01) == 0)
                        break;
                msleep(10);
@@ -644,15 +660,14 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
 
 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
 {
-       struct usb_device *dev = gspca_dev->dev;
        int count = 50;
 
        while (--count > 0) {
-               reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
+               reg_r(gspca_dev, 0x21, 1, 1);
                if (gspca_dev->usb_buf[0] != 0) {
                        gspca_dev->usb_buf[0] = 0;
-                       reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
-                       reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
+                       reg_w(gspca_dev, 0x21, 0, 1, 1);
+                       reg_r(gspca_dev, 0x21, 1, 1);
                        spca504B_PollingDataReady(gspca_dev);
                        break;
                }
@@ -662,16 +677,14 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
 
 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
 {
-       struct usb_device *dev = gspca_dev->dev;
        __u8 *data;
 
-       data = kmalloc(64, GFP_KERNEL);
-       reg_r(dev, 0x20, 0, data, 5);
+       data = gspca_dev->usb_buf;
+       reg_r(gspca_dev, 0x20, 0, 5);
        PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
                data[0], data[1], data[2], data[3], data[4]);
-       reg_r(dev, 0x23, 0, data, 64);
-       reg_r(dev, 0x23, 1, data, 64);
-       kfree(data);
+       reg_r(gspca_dev, 0x23, 0, 64);
+       reg_r(gspca_dev, 0x23, 1, 64);
 }
 
 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
@@ -686,21 +699,21 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
        Type = 0;
        switch (sd->bridge) {
        case BRIDGE_SPCA533:
-               reg_w(dev, 0x31, 0, 0, NULL, 0);
+               reg_w(gspca_dev, 0x31, 0, 0, 0);
                spca504B_WaitCmdStatus(gspca_dev);
                rc = spca504B_PollingDataReady(gspca_dev);
                spca50x_GetFirmware(gspca_dev);
                gspca_dev->usb_buf[0] = 2;                      /* type */
-               reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
-               reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
+               reg_w(gspca_dev, 0x24, 0, 8, 1);
+               reg_r(gspca_dev, 0x24, 8, 1);
 
                gspca_dev->usb_buf[0] = Size;
-               reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
-               reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1);     /* size */
+               reg_w(gspca_dev, 0x25, 0, 4, 1);
+               reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
                rc = spca504B_PollingDataReady(gspca_dev);
 
                /* Init the cam width height with some values get on init ? */
-               reg_w(dev, 0x31, 0, 4, NULL, 0);
+               reg_w(gspca_dev, 0x31, 0, 4, 0);
                spca504B_WaitCmdStatus(gspca_dev);
                rc = spca504B_PollingDataReady(gspca_dev);
                break;
@@ -708,12 +721,12 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
 /* case BRIDGE_SPCA504B: */
 /* case BRIDGE_SPCA536: */
                gspca_dev->usb_buf[0] = Size;
-               reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
-               reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1);     /* size */
+               reg_w(gspca_dev, 0x25, 0, 4, 1);
+               reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
                Type = 6;
                gspca_dev->usb_buf[0] = Type;
-               reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
-               reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1);     /* type */
+               reg_w(gspca_dev, 0x27, 0, 0, 1);
+               reg_r(gspca_dev, 0x27, 0, 1);                   /* type */
                rc = spca504B_PollingDataReady(gspca_dev);
                break;
        case BRIDGE_SPCA504:
@@ -752,18 +765,15 @@ static void spca504_wait_status(struct gspca_dev *gspca_dev)
 
 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
 {
-       struct usb_device *dev = gspca_dev->dev;
-
        gspca_dev->usb_buf[0] = 3;
-       reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
-       reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
+       reg_w(gspca_dev, 0x26, 0, 0, 1);
+       reg_r(gspca_dev, 0x26, 0, 1);
        spca504B_PollingDataReady(gspca_dev);
 }
 
 static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *dev = gspca_dev->dev;
        int pollreg = 1;
 
        switch (sd->bridge) {
@@ -774,20 +784,20 @@ static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
        default:
 /*     case BRIDGE_SPCA533: */
 /*     case BRIDGE_SPCA504B: */
-               reg_w(dev, 0, 0, 0x21a7, NULL, 0);      /* brightness */
-               reg_w(dev, 0, 0x20, 0x21a8, NULL, 0);   /* contrast */
-               reg_w(dev, 0, 0, 0x21ad, NULL, 0);      /* hue */
-               reg_w(dev, 0, 1, 0x21ac, NULL, 0);      /* sat/hue */
-               reg_w(dev, 0, 0x20, 0x21ae, NULL, 0);   /* saturation */
-               reg_w(dev, 0, 0, 0x21a3, NULL, 0);      /* gamma */
+               reg_w(gspca_dev, 0, 0, 0x21a7, 0);      /* brightness */
+               reg_w(gspca_dev, 0, 0x20, 0x21a8, 0);   /* contrast */
+               reg_w(gspca_dev, 0, 0, 0x21ad, 0);      /* hue */
+               reg_w(gspca_dev, 0, 1, 0x21ac, 0);      /* sat/hue */
+               reg_w(gspca_dev, 0, 0x20, 0x21ae, 0);   /* saturation */
+               reg_w(gspca_dev, 0, 0, 0x21a3, 0);      /* gamma */
                break;
        case BRIDGE_SPCA536:
-               reg_w(dev, 0, 0, 0x20f0, NULL, 0);
-               reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
-               reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
-               reg_w(dev, 0, 1, 0x20f4, NULL, 0);
-               reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
-               reg_w(dev, 0, 0, 0x2089, NULL, 0);
+               reg_w(gspca_dev, 0, 0, 0x20f0, 0);
+               reg_w(gspca_dev, 0, 0x21, 0x20f1, 0);
+               reg_w(gspca_dev, 0, 0x40, 0x20f5, 0);
+               reg_w(gspca_dev, 0, 1, 0x20f4, 0);
+               reg_w(gspca_dev, 0, 0x40, 0x20f6, 0);
+               reg_w(gspca_dev, 0, 0, 0x2089, 0);
                break;
        }
        if (pollreg)
@@ -799,7 +809,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
                        const struct usb_device_id *id)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *dev = gspca_dev->dev;
        struct cam *cam;
 
        cam = &gspca_dev->cam;
@@ -811,7 +820,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        if (sd->subtype == AiptekMiniPenCam13) {
 /* try to get the firmware as some cam answer 2.0.1.2.2
  * and should be a spca504b then overwrite that setting */
-               reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
+               reg_r(gspca_dev, 0x20, 0, 1);
                switch (gspca_dev->usb_buf[0]) {
                case 1:
                        break;          /* (right bridge/subtype) */
@@ -848,8 +857,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct usb_device *dev = gspca_dev->dev;
@@ -860,12 +869,12 @@ static int sd_open(struct gspca_dev *gspca_dev)
 
        switch (sd->bridge) {
        case BRIDGE_SPCA504B:
-               reg_w(dev, 0x1d, 0, 0, NULL, 0);
-               reg_w(dev, 0, 1, 0x2306, NULL, 0);
-               reg_w(dev, 0, 0, 0x0d04, NULL, 0);
-               reg_w(dev, 0, 0, 0x2000, NULL, 0);
-               reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
-               reg_w(dev, 0, 0, 0x2306, NULL, 0);
+               reg_w(gspca_dev, 0x1d, 0, 0, 0);
+               reg_w(gspca_dev, 0, 1, 0x2306, 0);
+               reg_w(gspca_dev, 0, 0, 0x0d04, 0);
+               reg_w(gspca_dev, 0, 0, 0x2000, 0);
+               reg_w(gspca_dev, 0, 0x13, 0x2301, 0);
+               reg_w(gspca_dev, 0, 0, 0x2306, 0);
                /* fall thru */
        case BRIDGE_SPCA533:
                rc = spca504B_PollingDataReady(gspca_dev);
@@ -873,12 +882,12 @@ static int sd_open(struct gspca_dev *gspca_dev)
                break;
        case BRIDGE_SPCA536:
                spca50x_GetFirmware(gspca_dev);
-               reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
+               reg_r(gspca_dev, 0x00, 0x5002, 1);
                gspca_dev->usb_buf[0] = 0;
-               reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
-               reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
+               reg_w(gspca_dev, 0x24, 0, 0, 1);
+               reg_r(gspca_dev, 0x24, 0, 1);
                rc = spca504B_PollingDataReady(gspca_dev);
-               reg_w(dev, 0x34, 0, 0, NULL, 0);
+               reg_w(gspca_dev, 0x34, 0, 0, 0);
                spca504B_WaitCmdStatus(gspca_dev);
                break;
        case BRIDGE_SPCA504C:   /* pccam600 */
@@ -971,12 +980,12 @@ static void sd_start(struct gspca_dev *gspca_dev)
 /*     case BRIDGE_SPCA536: */
                if (sd->subtype == MegapixV4 ||
                    sd->subtype == LogitechClickSmart820) {
-                       reg_w(dev, 0xf0, 0, 0, NULL, 0);
+                       reg_w(gspca_dev, 0xf0, 0, 0, 0);
                        spca504B_WaitCmdStatus(gspca_dev);
-                       reg_r(dev, 0xf0, 4, NULL, 0);
+                       reg_r(gspca_dev, 0xf0, 4, 0);
                        spca504B_WaitCmdStatus(gspca_dev);
                } else {
-                       reg_w(dev, 0x31, 0, 4, NULL, 0);
+                       reg_w(gspca_dev, 0x31, 0, 4, 0);
                        spca504B_WaitCmdStatus(gspca_dev);
                        rc = spca504B_PollingDataReady(gspca_dev);
                }
@@ -1045,7 +1054,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
 /*     case BRIDGE_SPCA533: */
 /*     case BRIDGE_SPCA536: */
 /*     case BRIDGE_SPCA504B: */
-               reg_w(dev, 0x31, 0, 0, NULL, 0);
+               reg_w(gspca_dev, 0x31, 0, 0, 0);
                spca504B_WaitCmdStatus(gspca_dev);
                spca504B_PollingDataReady(gspca_dev);
                break;
@@ -1069,14 +1078,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        }
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -1369,11 +1370,9 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -1456,6 +1455,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 91b555c34c68ff7509b50796cfd03dd4d9ac200a..f034c748fc7ef5c3a608ff88e6ca1ab18e94261e 100644 (file)
@@ -30,7 +30,7 @@
 
 #define MAX_GAMMA 0x10         /* 0 to 15 */
 
-#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
 
 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
@@ -233,7 +233,7 @@ static char *effects_control[] = {
 static struct v4l2_pix_format vga_mode_t16[] = {
        {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
                .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 8 + 590,
+               .sizeimage = 160 * 120 * 4 / 8 + 590,
                .colorspace = V4L2_COLORSPACE_JPEG,
                .priv = 4},
        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -391,7 +391,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
                                NULL, 0, 500);
                return;
        }
-       if (len <= sizeof gspca_dev->usb_buf) {
+       if (len <= USB_BUF_SZ) {
                memcpy(gspca_dev->usb_buf, buffer, len);
                usb_control_msg(gspca_dev->dev,
                                usb_sndctrlpipe(gspca_dev->dev, 0),
@@ -552,6 +552,13 @@ static int init_default_parameters(struct gspca_dev *gspca_dev)
        return 0;
 }
 
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       init_default_parameters(gspca_dev);
+       return 0;
+}
+
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -893,18 +900,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
        setcolors(gspca_dev);
 }
 
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -972,24 +967,14 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
        return -EINVAL;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
-{
-       init_default_parameters(gspca_dev);
-       return 0;
-}
-
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
        .name = MODULE_NAME,
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .querymenu = sd_querymenu,
 };
@@ -1014,6 +999,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index 1ff8ba2f7fe54ca83cb10a6428483bcf8b7bd694..084af05302a0399f7e84e993437557d7433e3a3e 100644 (file)
@@ -331,8 +331,8 @@ static void tv_8532_PollReg(struct gspca_dev *gspca_dev)
        }
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
        reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
@@ -450,14 +450,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void tv8532_preprocess(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -611,11 +603,9 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
 };
 
@@ -644,6 +634,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index f4a52956e0d91eaf8e5b8b37eaee0651f3f040d6..bd4c226c9a077843d2b787210cf227574c8dedea 100644 (file)
@@ -69,6 +69,7 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setautogain,
            .get = sd_getautogain,
        },
+#define LIGHTFREQ_IDX 1
        {
            {
                .id      = V4L2_CID_POWER_LINE_FREQUENCY,
@@ -87,12 +88,12 @@ static struct ctrl sd_ctrls[] = {
 };
 
 static struct v4l2_pix_format vc0321_mode[] = {
-       {320, 240, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
+       {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
                .bytesperline = 320,
                .sizeimage = 320 * 240 * 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
                .priv = 1},
-       {640, 480, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
+       {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
                .bytesperline = 640,
                .sizeimage = 640 * 480 * 2,
                .colorspace = V4L2_COLORSPACE_SRGB,
@@ -1463,6 +1464,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->qindex = 7;
        sd->autogain = AUTOGAIN_DEF;
        sd->lightfreq = FREQ_DEF;
+       if (sd->sensor != SENSOR_OV7670)
+               gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX);
 
        if (sd->bridge == BRIDGE_VC0321) {
                reg_r(gspca_dev, 0x8a, 0, 3);
@@ -1474,8 +1477,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        return 0;
 }
@@ -1637,19 +1640,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
        reg_w(dev, 0x89, 0xffff, 0xffff);
 }
 
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-/*     struct usb_device *dev = gspca_dev->dev;
-       __u8 buffread;
-
-       reg_w(dev, 0x89, 0xffff, 0xffff);
-       reg_w(dev, 0xa0, 0x01, 0xb301);
-       reg_w(dev, 0xa0, 0x09, 0xb303);
-       reg_w(dev, 0x89, 0xffff, 0xffff);
-*/
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __u8 *data,                     /* isoc packet */
@@ -1738,11 +1728,10 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
        .stopN = sd_stopN,
        .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .querymenu = sd_querymenu,
 };
@@ -1774,6 +1763,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
index bc7d0eedcd8105ad056e14136c70bfab0bba6ec4..8d7c27e6ac77dd697cab8f9ff4e0b0b617499eaa 100644 (file)
@@ -85,6 +85,7 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
+#define BRIGHTNESS_IDX 0
 #define SD_BRIGHTNESS 0
        {
            {
@@ -141,6 +142,7 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setautogain,
            .get = sd_getautogain,
        },
+#define LIGHTFREQ_IDX 4
 #define SD_FREQ 4
        {
            {
@@ -6964,8 +6966,13 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
        case SENSOR_MC501CB:
                return -1;              /* don't probe */
        case SENSOR_TAS5130C_VF0250:
-                               /* may probe but with write in reg 0x0010 */
+                       /* may probe but with no write in reg 0x0010 */
                return -1;              /* don't probe */
+       case SENSOR_PAS106:
+               sensor =  sif_probe(gspca_dev);
+               if (sensor >= 0)
+                       return sensor;
+               break;
        }
        sensor = vga_2wr_probe(gspca_dev);
        if (sensor >= 0) {
@@ -6974,12 +6981,10 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
                /* next probe is needed for OmniVision ? */
        }
        sensor2 = vga_3wr_probe(gspca_dev);
-       if (sensor2 >= 0) {
-               if (sensor >= 0)
-                       return sensor;
-               return sensor2;
-       }
-       return sif_probe(gspca_dev);
+       if (sensor2 >= 0
+           && sensor >= 0)
+               return sensor;
+       return sensor2;
 }
 
 /* this function is called at probe time */
@@ -7147,13 +7152,27 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
        sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
 
+       switch (sd->sensor) {
+       case SENSOR_GC0305:
+       case SENSOR_OV7620:
+       case SENSOR_PO2030:
+               gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX);
+               break;
+       case SENSOR_HDCS2020:
+       case SENSOR_HV7131B:
+       case SENSOR_HV7131C:
+       case SENSOR_OV7630C:
+               gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX);
+               break;
+       }
+
        /* switch the led off */
        reg_w(gspca_dev->dev, 0x01, 0x0000);
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        reg_w(gspca_dev->dev, 0x01, 0x0000);
        return 0;
@@ -7314,10 +7333,6 @@ static void sd_start(struct gspca_dev *gspca_dev)
        }
 }
 
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -7325,11 +7340,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
        send_unknown(gspca_dev->dev, sd->sensor);
 }
 
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,
                        __u8 *data,
@@ -7489,37 +7499,30 @@ static const struct sd_desc sd_desc = {
        .ctrls = sd_ctrls,
        .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0],
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
-       .stopN = sd_stopN,
        .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
        .querymenu = sd_querymenu,
 };
 
 static const __devinitdata struct usb_device_id device_table[] = {
        {USB_DEVICE(0x041e, 0x041e)},
-#ifndef CONFIG_USB_ZC0301
        {USB_DEVICE(0x041e, 0x4017)},
-       {USB_DEVICE(0x041e, 0x401c)},
+       {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
        {USB_DEVICE(0x041e, 0x401e)},
        {USB_DEVICE(0x041e, 0x401f)},
-#endif
+       {USB_DEVICE(0x041e, 0x4022)},
        {USB_DEVICE(0x041e, 0x4029)},
-#ifndef CONFIG_USB_ZC0301
-       {USB_DEVICE(0x041e, 0x4034)},
-       {USB_DEVICE(0x041e, 0x4035)},
+       {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106},
        {USB_DEVICE(0x041e, 0x4036)},
        {USB_DEVICE(0x041e, 0x403a)},
-#endif
        {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250},
        {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250},
-#ifndef CONFIG_USB_ZC0301
        {USB_DEVICE(0x0458, 0x7007)},
        {USB_DEVICE(0x0458, 0x700c)},
        {USB_DEVICE(0x0458, 0x700f)},
-#endif
        {USB_DEVICE(0x0461, 0x0a00)},
        {USB_DEVICE(0x046d, 0x08a0)},
        {USB_DEVICE(0x046d, 0x08a1)},
@@ -7531,7 +7534,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
        {USB_DEVICE(0x046d, 0x08aa)},
        {USB_DEVICE(0x046d, 0x08ac)},
        {USB_DEVICE(0x046d, 0x08ad)},
-#ifndef CONFIG_USB_ZC0301
+#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE
        {USB_DEVICE(0x046d, 0x08ae)},
 #endif
        {USB_DEVICE(0x046d, 0x08af)},
@@ -7541,27 +7544,25 @@ static const __devinitdata struct usb_device_id device_table[] = {
        {USB_DEVICE(0x046d, 0x08d8)},
        {USB_DEVICE(0x046d, 0x08da)},
        {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
-       {USB_DEVICE(0x0471, 0x0325)},
-       {USB_DEVICE(0x0471, 0x0326)},
-       {USB_DEVICE(0x0471, 0x032d)},
-       {USB_DEVICE(0x0471, 0x032e)},
+       {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106},
        {USB_DEVICE(0x055f, 0xc005)},
-#ifndef CONFIG_USB_ZC0301
        {USB_DEVICE(0x055f, 0xd003)},
        {USB_DEVICE(0x055f, 0xd004)},
-#endif
        {USB_DEVICE(0x0698, 0x2003)},
+       {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106},
        {USB_DEVICE(0x0ac8, 0x0302)},
-#ifndef CONFIG_USB_ZC0301
        {USB_DEVICE(0x0ac8, 0x301b)},
+#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE
        {USB_DEVICE(0x0ac8, 0x303b)},
 #endif
        {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250},
-#ifndef CONFIG_USB_ZC0301
        {USB_DEVICE(0x0ac8, 0x307b)},
        {USB_DEVICE(0x10fd, 0x0128)},
+       {USB_DEVICE(0x10fd, 0x804d)},
        {USB_DEVICE(0x10fd, 0x8050)},
-#endif
        {}                      /* end of entry */
 };
 #undef DVNAME
@@ -7581,6 +7582,10 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 static int __init sd_mod_init(void)
index aea1664948ce16beaa7cfff28cb7c0cf05e5d02d..4afc7ea07e86ec16866862c4c4e118367dd8116a 100644 (file)
@@ -688,7 +688,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
        spin_lock_init(&itv->lock);
        spin_lock_init(&itv->dma_reg_lock);
 
-       itv->irq_work_queues = create_workqueue(itv->name);
+       itv->irq_work_queues = create_singlethread_workqueue(itv->name);
        if (itv->irq_work_queues == NULL) {
                IVTV_ERR("Could not create ivtv workqueue\n");
                return -1;
index ab287b48fc2b91a7940bd1f158ddbf438f78b1bd..2ceb5227637c86e3a268323741b72f5fd021effb 100644 (file)
@@ -251,6 +251,7 @@ struct ivtv_mailbox_data {
 #define IVTV_F_I_DEC_PAUSED       20   /* the decoder is paused */
 #define IVTV_F_I_INITED                   21   /* set after first open */
 #define IVTV_F_I_FAILED                   22   /* set if first open failed */
+#define IVTV_F_I_WORK_INITED       23  /* worker thread was initialized */
 
 /* Event notifications */
 #define IVTV_F_I_EV_DEC_STOPPED           28   /* decoder stopped event */
index fba150a6cd2306caa7b877cd8ec053230aa3270a..34f3ab82785853634bc3c47deb7587d7590508d3 100644 (file)
@@ -76,6 +76,13 @@ void ivtv_irq_work_handler(struct work_struct *work)
 
        DEFINE_WAIT(wait);
 
+       if (test_and_clear_bit(IVTV_F_I_WORK_INITED, &itv->i_flags)) {
+               struct sched_param param = { .sched_priority = 99 };
+
+               /* This thread must use the FIFO scheduler as it
+                  is realtime sensitive. */
+               sched_setscheduler(current, SCHED_FIFO, &param);
+       }
        if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
                ivtv_pio_work_handler(itv);
 
@@ -678,34 +685,14 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv)
 
 static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
 {
-       struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
        u32 data[CX2341X_MBOX_MAX_DATA];
        struct ivtv_stream *s;
 
        IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n");
        s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
 
-       /* If more than two VBI buffers are pending, then
-          clear the old ones and start with this new one.
-          This can happen during transition stages when MPEG capturing is
-          started, but the first interrupts haven't arrived yet. During
-          that period VBI requests can accumulate without being able to
-          DMA the data. Since at most four VBI DMA buffers are available,
-          we just drop the old requests when there are already three
-          requests queued. */
-       if (s->sg_pending_size > 2) {
-               struct ivtv_buffer *buf;
-               list_for_each_entry(buf, &s->q_predma.list, list)
-                       ivtv_buf_sync_for_cpu(s, buf);
-               ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0);
-               s->sg_pending_size = 0;
-       }
-       /* if we can append the data, and the MPEG stream isn't capturing,
-          then start a DMA request for just the VBI data. */
-       if (!stream_enc_dma_append(s, data) &&
-                       !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) {
+       if (!stream_enc_dma_append(s, data))
                set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
-       }
 }
 
 static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
index 7cfc0c9ab050ca781386068ea3c1f0fd1d671e25..476556afd39aa2bc99c8f3b4cee03d91d07a0fd8 100644 (file)
@@ -23,7 +23,7 @@
 #define IVTV_QUEUE_H
 
 #define IVTV_DMA_UNMAPPED      ((u32) -1)
-#define SLICED_VBI_PIO 1
+#define SLICED_VBI_PIO 0
 
 /* ivtv_buffer utility functions */
 
index 54d2023b26c4b341ff742a43149eb7063b0a9f84..730e85d86fc82d0c27e7351ea4b4689dbcb5bd89 100644 (file)
@@ -363,7 +363,7 @@ static void ivtv_vbi_setup(struct ivtv *itv)
        /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */
        data[1] = 1;
        /* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */
-       data[2] = raw ? 4 : 8;
+       data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size);
        /* The start/stop codes determine which VBI lines end up in the raw VBI data area.
           The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line
           is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video)
index 71798f0da27f9172f4dc3d34027b37a786b7966e..1ce9deb1104fc1bdc970811d65ea52a346087570 100644 (file)
@@ -293,6 +293,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8
        u32 line_size = itv->vbi.sliced_decoder_line_size;
        struct v4l2_decode_vbi_line vbi;
        int i;
+       unsigned lines = 0;
 
        /* find the first valid line */
        for (i = 0; i < size; i++, buf++) {
@@ -313,7 +314,8 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8
                }
                vbi.p = p + 4;
                itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
-               if (vbi.type) {
+               if (vbi.type && !(lines & (1 << vbi.line))) {
+                       lines |= 1 << vbi.line;
                        itv->vbi.sliced_data[line].id = vbi.type;
                        itv->vbi.sliced_data[line].field = vbi.is_second_field;
                        itv->vbi.sliced_data[line].line = vbi.line;
index 442f43f11b7387dfbf8fbc05e497feef1d0ed2a3..8cd753d30bf76160bf4f3f2a951b34c5a31b760e 100644 (file)
@@ -22,7 +22,7 @@
 
 #define IVTV_DRIVER_NAME "ivtv"
 #define IVTV_DRIVER_VERSION_MAJOR 1
-#define IVTV_DRIVER_VERSION_MINOR 3
+#define IVTV_DRIVER_VERSION_MINOR 4
 #define IVTV_DRIVER_VERSION_PATCHLEVEL 0
 
 #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
index 4895540be195ad0e8854b563c6eb53a50d5ccb14..2fd4b4a44aa92c44d5262302eda6e3e3e96d646c 100644 (file)
@@ -679,26 +679,27 @@ static int ks0127_command(struct i2c_client *client,
 
        case DECODER_ENABLE_OUTPUT:
        {
+               int enable;
 
-               int *iarg = arg;
-               int enable = (*iarg != 0);
-                       if (enable) {
-                               dprintk("ks0127: command "
+               iarg = arg;
+               enable = (*iarg != 0);
+               if (enable) {
+                       dprintk("ks0127: command "
                                        "DECODER_ENABLE_OUTPUT on "
                                        "(%d)\n", enable);
-                               /* All output pins on */
-                               ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
-                               /* Obey the OEN pin */
-                               ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
-                       } else {
-                               dprintk("ks0127: command "
+                       /* All output pins on */
+                       ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
+                       /* Obey the OEN pin */
+                       ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
+               } else {
+                       dprintk("ks0127: command "
                                        "DECODER_ENABLE_OUTPUT off "
                                        "(%d)\n", enable);
-                               /* Video output pins off */
-                               ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
-                               /* Ignore the OEN pin */
-                               ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
-                       }
+                       /* Video output pins off */
+                       ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
+                       /* Ignore the OEN pin */
+                       ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
+               }
        }
                break;
 
index 7c8ef6ac6c39cf646a9cfc3d4223d8bea51e48de..a9ef7802eb5fcdaf793d8f695d4ecc35e0ddb903 100644 (file)
@@ -1806,6 +1806,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        memcpy(meye.video_dev, &meye_template, sizeof(meye_template));
        meye.video_dev->parent = &meye.mchip_dev->dev;
 
+       ret = -EIO;
        if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
                printk(KERN_ERR "meye: unable to power on the camera\n");
                printk(KERN_ERR "meye: did you enable the camera in "
@@ -1813,7 +1814,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
                goto outsonypienable;
        }
 
-       ret = -EIO;
        if ((ret = pci_enable_device(meye.mchip_dev))) {
                printk(KERN_ERR "meye: pci_enable_device failed\n");
                goto outenabledev;
index f68e91fbe7fbcbe7d6e28705a00100eb4c57c06f..8ef578caba3b982c8d63f1047b4c300ac11b45ee 100644 (file)
@@ -931,27 +931,29 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
+static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
 {
-       struct mxb* mxb = (struct mxb*)dev->ext_priv;
+       struct mxb *mxb = (struct mxb *)dev->ext_priv;
        int zero = 0;
        int one = 1;
 
-       if(V4L2_STD_PAL_I == std->id ) {
+       if (V4L2_STD_PAL_I == standard->id) {
                v4l2_std_id std = V4L2_STD_PAL_I;
+
                DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
                /* set the 7146 gpio register -- I don't know what this does exactly */
                saa7146_write(dev, GPIO_CTRL, 0x00404050);
                /* unset the 7111 gpio register -- I don't know what this does exactly */
-               mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero);
+               mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &zero);
                mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
        } else {
                v4l2_std_id std = V4L2_STD_PAL_BG;
+
                DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
                /* set the 7146 gpio register -- I don't know what this does exactly */
                saa7146_write(dev, GPIO_CTRL, 0x00404050);
                /* set the 7111 gpio register -- I don't know what this does exactly */
-               mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one);
+               mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &one);
                mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
        }
        return 0;
index 9edaca4371d7cedb5903d324e531eb4f16469a38..3d3c48db45d958c4813e8dc2c0ea850a356b796a 100644 (file)
@@ -626,9 +626,9 @@ ov511_i2c_write_internal(struct usb_ov511 *ov,
                        break;
 
                /* Retry until idle */
-               do
+               do {
                        rc = reg_r(ov, R511_I2C_CTL);
-               while (rc > 0 && ((rc&1) == 0));
+               while (rc > 0 && ((rc&1) == 0));
                if (rc < 0)
                        break;
 
@@ -703,9 +703,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
                        return rc;
 
                /* Retry until idle */
-               do
-                        rc = reg_r(ov, R511_I2C_CTL);
-               while (rc > 0 && ((rc&1) == 0));
+               do {
+                       rc = reg_r(ov, R511_I2C_CTL);
+               } while (rc > 0 && ((rc & 1) == 0));
                if (rc < 0)
                        return rc;
 
@@ -729,9 +729,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
                        return rc;
 
                /* Retry until idle */
-               do
+               do {
                        rc = reg_r(ov, R511_I2C_CTL);
-               while (rc > 0 && ((rc&1) == 0));
+               while (rc > 0 && ((rc&1) == 0));
                if (rc < 0)
                        return rc;
 
index 00425d7436569e8081e525892fbf8b7f464b1683..7c84f795db54bcb188d39b541cb0f1f673246c8c 100644 (file)
@@ -1019,10 +1019,23 @@ static int init_mediavision(void)
  *     Initialization and module stuff
  */
 
+#ifndef MODULE
+static int enable;
+module_param(enable, int, 0);
+#endif
+
 static int __init init_pms_cards(void)
 {
        printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
 
+#ifndef MODULE
+       if (!enable) {
+               printk(KERN_INFO "PMS: not enabled, use pms.enable=1 to "
+                                "probe\n");
+               return -ENODEV;
+       }
+#endif
+
        data_port = io_port +1;
 
        if(init_mediavision())
index 1cccd5c77048955502d00fe4732e3999c559914f..dbc560742553ec98b3c5aa2e487f0e2e05d232a5 100644 (file)
@@ -1635,15 +1635,15 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 
        case VIDIOCPWCGVIDCMD:
        {
-               ARG_DEF(struct pwc_video_command, cmd);
-
-               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)
+               ARG_DEF(struct pwc_video_command, vcmd);
+
+               ARGR(vcmd).type = pdev->type;
+               ARGR(vcmd).release = pdev->release;
+               ARGR(vcmd).command_len = pdev->cmd_len;
+               memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
+               ARGR(vcmd).bandlength = pdev->vbandlength;
+               ARGR(vcmd).frame_size = pdev->frame_size;
+               ARG_OUT(vcmd)
                break;
        }
        /*
index bcd1c8f6cf6b8bb5f3572a7a0caa4682680a1c25..ad733caec720f1b782921f5b4718ea56fdf246f7 100644 (file)
@@ -1489,10 +1489,9 @@ static int saa7115_probe(struct i2c_client *client,
                 client->addr << 1, client->adapter->name);
 
        state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
-       i2c_set_clientdata(client, state);
-       if (state == NULL) {
+       if (state == NULL)
                return -ENOMEM;
-       }
+       i2c_set_clientdata(client, state);
        state->input = -1;
        state->output = SAA7115_IPORT_ON;
        state->enable = 1;
index f481277892da9be5eedf81d4ffe93043a5a012b1..acceed5d04aee9f9a0aa1b0abb4cb1fef52d90f3 100644 (file)
@@ -1397,7 +1397,7 @@ static int se401_probe(struct usb_interface *intf,
        mutex_init(&se401->lock);
        wmb();
 
-       if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+       if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                kfree(se401);
                err("video_register_device failed");
                return -EIO;
index 23408764d0ef6db55e9f8df3eaa57fa57e8007ce..2da6938718f2c1a7969065f24b575d4615afdea5 100644 (file)
@@ -3312,6 +3312,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        cam->v4ldev->fops = &sn9c102_fops;
        cam->v4ldev->minor = video_nr[dev_nr];
        cam->v4ldev->release = video_device_release;
+       cam->v4ldev->parent = &udev->dev;
 
        init_completion(&cam->probe);
 
index 6ff489baacf3bad48ab8e0fd2ec4b4f0f861b47b..90a401dc38849b20cba1fe16cffba82e2f3fe16f 100644 (file)
@@ -40,11 +40,14 @@ struct sn9c102_device;
 
 static const struct usb_device_id sn9c102_id_table[] = {
        /* SN9C101 and SN9C102 */
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
        { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
+#endif
        { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
        { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
@@ -53,29 +56,33 @@ static const struct usb_device_id sn9c102_id_table[] = {
        { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
        { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
        /* SN9C103 */
        { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */
        { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
        { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
+#endif
        { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5130 */
        { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
        { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
+#endif
        { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), },
        { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), },
@@ -105,7 +112,7 @@ static const struct usb_device_id sn9c102_id_table[] = {
        { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
        { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
        { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
        { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
        { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
index 56dc3d6b5b29e6e64d1589f2232577b76be0dba5..dce947439459ca46e2d020b49440a318a6c9e20c 100644 (file)
@@ -1462,7 +1462,7 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
        mutex_init (&stv680->lock);
        wmb ();
 
-       if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+       if (video_register_device(stv680->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                PDEBUG (0, "STV(e): video_register_device failed");
                retval = -EIO;
                goto error_vdev;
index 59166b760104884b4d0573e61572fd9b40b2ebcd..cc27efe121ddb225fd598d426da3ba44e7379ae0 100644 (file)
@@ -736,12 +736,12 @@ static enum ParseState ibmcam_model2_320x240_parse_lines(
                 * make black color and quit the horizontal scanning loop.
                 */
                if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
-                       const int j = i * V4L_BYTES_PER_PIXEL;
+                       const int offset = i * V4L_BYTES_PER_PIXEL;
 #if USES_IBMCAM_PUTPIXEL
                        /* Refresh 'f' because we don't use it much with PUTPIXEL */
-                       f = frame->data + (v4l_linesize * frame->curline) + j;
+                       f = frame->data + (v4l_linesize * frame->curline) + offset;
 #endif
-                       memset(f, 0, v4l_linesize - j);
+                       memset(f, 0, v4l_linesize - offset);
                        break;
                }
 
index b7792451a2993f4d2f0329958e5ab0adefc52a5d..2eb45829791ccf509a04a15599df1381f1c732cd 100644 (file)
@@ -866,7 +866,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
        cam->udev = dev;
        cam->bulkEndpoint = bulkEndpoint;
 
-       if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
+       if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) {
                kfree(cam);
                printk(KERN_WARNING "video_register_device failed\n");
                return -EIO;
index 6f36006aecda17108885dfbe62b4603c803b1866..155fdec9ac7d7c4fc0aa773581021fbe59ab3355 100644 (file)
@@ -257,6 +257,9 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
        int ret;
        char *name_base;
 
+       if (vfd == NULL)
+               return -EINVAL;
+
        switch (type) {
        case VFL_TYPE_GRABBER:
                base = MINOR_VFL_TYPE_GRABBER_MIN;
@@ -281,7 +284,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
        default:
                printk(KERN_ERR "%s called with unknown type: %d\n",
                       __func__, type);
-               return -1;
+               return -EINVAL;
        }
 
        /* pick a minor number */
index fdfe7739c96ed929dd56941ce617c8d352d38600..140ef92c19c1e5c1333f1e30881a8150c0edbfed 100644 (file)
@@ -499,7 +499,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
                        p->timestamp.tv_sec / 3600,
                        (int)(p->timestamp.tv_sec / 60) % 60,
                        (int)(p->timestamp.tv_sec % 60),
-                       p->timestamp.tv_usec,
+                       (long)p->timestamp.tv_usec,
                        p->index,
                        prt_names(p->type, v4l2_type_names),
                        p->bytesused, p->flags,
@@ -674,7 +674,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
         __video_do_ioctl will be called again, with one or more
         V4L2 ioctls.
         ********************************************************/
-       if (_IOC_TYPE(cmd) == 'v')
+       if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE)
                return v4l_compat_translate_ioctl(inode, file, cmd, arg,
                                                __video_do_ioctl);
 #endif
index 3518af071a2e2633cc7ec7a62cde3a6ab5cb6c95..8ba8daafd7ea2a3a2dff574b535a2908128b8d8b 100644 (file)
@@ -1021,13 +1021,13 @@ static int vivi_release(void)
                dev = list_entry(list, struct vivi_dev, vivi_devlist);
 
                if (-1 != dev->vfd->minor) {
-                       video_unregister_device(dev->vfd);
-                       printk(KERN_INFO "%s: /dev/video%d unregistered.\n",
+                       printk(KERN_INFO "%s: unregistering /dev/video%d\n",
                                VIVI_MODULE_NAME, dev->vfd->minor);
+                       video_unregister_device(dev->vfd);
                } else {
-                       video_device_release(dev->vfd);
-                       printk(KERN_INFO "%s: /dev/video%d released.\n",
+                       printk(KERN_INFO "%s: releasing /dev/video%d\n",
                                VIVI_MODULE_NAME, dev->vfd->minor);
+                       video_device_release(dev->vfd);
                }
 
                kfree(dev);
@@ -1104,19 +1104,29 @@ static struct video_device vivi_template = {
        Initialization and module stuff
    ------------------------------------------------------------------*/
 
+/* This routine allocates from 1 to n_devs virtual drivers.
+
+   The real maximum number of virtual drivers will depend on how many drivers
+   will succeed. This is limited to the maximum number of devices that
+   videodev supports. Since there are 64 minors for video grabbers, this is
+   currently the theoretical maximum limit. However, a further limit does
+   exist at videodev that forbids any driver to register more than 32 video
+   grabbers.
+ */
 static int __init vivi_init(void)
 {
        int ret = -ENOMEM, i;
        struct vivi_dev *dev;
        struct video_device *vfd;
 
+       if (n_devs <= 0)
+               n_devs = 1;
+
        for (i = 0; i < n_devs; i++) {
                dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-               if (NULL == dev)
+               if (!dev)
                        break;
 
-               list_add_tail(&dev->vivi_devlist, &vivi_devlist);
-
                /* init video dma queues */
                INIT_LIST_HEAD(&dev->vidq.active);
                init_waitqueue_head(&dev->vidq.wq);
@@ -1126,14 +1136,27 @@ static int __init vivi_init(void)
                mutex_init(&dev->mutex);
 
                vfd = video_device_alloc();
-               if (NULL == vfd)
+               if (!vfd) {
+                       kfree(dev);
                        break;
+               }
 
                *vfd = vivi_template;
 
                ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
-               if (ret < 0)
+               if (ret < 0) {
+                       video_device_release(vfd);
+                       kfree(dev);
+
+                       /* If some registers succeeded, keep driver */
+                       if (i)
+                               ret = 0;
+
                        break;
+               }
+
+               /* Now that everything is fine, let's add it to device list */
+               list_add_tail(&dev->vivi_devlist, &vivi_devlist);
 
                snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
                         vivi_template.name, vfd->minor);
@@ -1149,11 +1172,16 @@ static int __init vivi_init(void)
        if (ret < 0) {
                vivi_release();
                printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
-       } else
+       } else {
                printk(KERN_INFO "Video Technology Magazine Virtual Video "
                        "Capture Board ver %u.%u.%u successfully loaded.\n",
                        (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
                        VIVI_VERSION & 0xFF);
+
+               /* n_devs will reflect the actual number of allocated devices */
+               n_devs = i;
+       }
+
        return ret;
 }
 
@@ -1169,10 +1197,10 @@ MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
 MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
 MODULE_LICENSE("Dual BSD/GPL");
 
-module_param(video_nr, int, 0);
+module_param(video_nr, uint, 0444);
 MODULE_PARM_DESC(video_nr, "video iminor start number");
 
-module_param(n_devs, int, 0);
+module_param(n_devs, uint, 0444);
 MODULE_PARM_DESC(n_devs, "number of video devices to create");
 
 module_param_named(debug, vivi_template.debug, int, 0444);
index 9402f40095b469f1caced200f9f63e04b74b7c00..2ff00bc5ad64cf2aa79a2c915296ea03220a4572 100644 (file)
@@ -334,7 +334,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
        memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device));
        cam->vdev.priv = cam;
 
-       if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1)
+       if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
                return -1;
 
        w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
index 550ce7bd5c87d8720402abc0e98f15d7b654b5f9..0c3287734c93f0b77900cb2c9ca6156ee2de592d 100644 (file)
@@ -1988,6 +1988,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        cam->v4ldev->fops = &zc0301_fops;
        cam->v4ldev->minor = video_nr[dev_nr];
        cam->v4ldev->release = video_device_release;
+       cam->v4ldev->parent = &udev->dev;
        video_set_drvdata(cam->v4ldev, cam);
 
        init_completion(&cam->probe);
index 70fe6fc6cdd531eac31b8fc98c321b70d1bba18f..b0cd49c438a3259b18490b50023864abd44b5756 100644 (file)
@@ -60,27 +60,8 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor);
 
 #define ZC0301_ID_TABLE                                                       \
 static const struct usb_device_id zc0301_id_table[] =  {                      \
-       { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, /* ICM105 */            \
-       { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */            \
-       { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131 */            \
-       { ZC0301_USB_DEVICE(0x041e, 0x401f, 0xff), }, /* TAS5130 */           \
-       { ZC0301_USB_DEVICE(0x041e, 0x4022, 0xff), },                         \
-       { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */            \
-       { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */            \
-       { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */            \
-       { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */            \
-       { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */           \
-       { ZC0301_USB_DEVICE(0x0458, 0x700c, 0xff), }, /* TAS5130 */           \
-       { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */           \
        { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
-       { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */           \
-       { ZC0301_USB_DEVICE(0x055f, 0xd004, 0xff), }, /* TAS5130 */           \
-       { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), },                         \
-       { ZC0301_USB_DEVICE(0x0ac8, 0x301b, 0xff), }, /* PB-0330/HV7131 */    \
        { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */           \
-       { ZC0301_USB_DEVICE(0x10fd, 0x0128, 0xff), }, /* TAS5130 */           \
-       { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130 */           \
-       { ZC0301_USB_DEVICE(0x10fd, 0x804e, 0xff), }, /* TAS5130 */           \
        { }                                                                   \
 };
 
index c6c77a505ec1e621307ded371c224094b0222b13..d8b0d326e4522232fbcc1455dce67fb3e207c059 100644 (file)
@@ -1189,7 +1189,7 @@ static int create_debugfs(void)
        return 0;
 
 error_debugfs:
-               remove_debugfs();
+       remove_debugfs();
        return -ENOMEM;
 }
 
@@ -1272,6 +1272,7 @@ error_platform_register:
 static void __exit acer_wmi_exit(void)
 {
        remove_sysfs(acer_platform_device);
+       remove_debugfs();
        platform_device_del(acer_platform_device);
        platform_driver_unregister(&acer_platform_driver);
 
index 7a1ef6c262defaf338bbfcbb7dff8c56f3c03c99..3e56203e494720fc4af8bb8f44ed047f81cf1b8a 100644 (file)
@@ -463,6 +463,13 @@ static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
                     DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
                     },
         .callback = dmi_check_cb_s6410},
+       {
+        .ident = "FUJITSU LifeBook P8010",
+        .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
+                   },
+        .callback = dmi_check_cb_s6410},
        {}
 };
 
index 1dbcbcb323a28e9e9679c3026982b74d7338fd9a..6d407c2a4f91d80e54d5885e741ce436fb21aa31 100644 (file)
@@ -49,6 +49,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
 #define HPWMI_ALS_QUERY 0x3
 #define HPWMI_DOCK_QUERY 0x4
 #define HPWMI_WIRELESS_QUERY 0x5
+#define HPWMI_HOTKEY_QUERY 0xc
 
 static int __init hp_wmi_bios_setup(struct platform_device *device);
 static int __exit hp_wmi_bios_remove(struct platform_device *device);
@@ -69,7 +70,7 @@ struct bios_return {
 
 struct key_entry {
        char type;              /* See KE_* below */
-       u8 code;
+       u16 code;
        u16 keycode;
 };
 
@@ -79,7 +80,9 @@ static struct key_entry hp_wmi_keymap[] = {
        {KE_SW, 0x01, SW_DOCK},
        {KE_KEY, 0x02, KEY_BRIGHTNESSUP},
        {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
-       {KE_KEY, 0x04, KEY_HELP},
+       {KE_KEY, 0x20e6, KEY_PROG1},
+       {KE_KEY, 0x2142, KEY_MEDIA},
+       {KE_KEY, 0x231b, KEY_HELP},
        {KE_END, 0}
 };
 
@@ -177,9 +180,9 @@ static int hp_wmi_wifi_state(void)
        int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
 
        if (wireless & 0x100)
-               return 1;
+               return RFKILL_STATE_UNBLOCKED;
        else
-               return 0;
+               return RFKILL_STATE_SOFT_BLOCKED;
 }
 
 static int hp_wmi_bluetooth_state(void)
@@ -187,9 +190,9 @@ static int hp_wmi_bluetooth_state(void)
        int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
 
        if (wireless & 0x10000)
-               return 1;
+               return RFKILL_STATE_UNBLOCKED;
        else
-               return 0;
+               return RFKILL_STATE_SOFT_BLOCKED;
 }
 
 static int hp_wmi_wwan_state(void)
@@ -197,9 +200,9 @@ static int hp_wmi_wwan_state(void)
        int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
 
        if (wireless & 0x1000000)
-               return 1;
+               return RFKILL_STATE_UNBLOCKED;
        else
-               return 0;
+               return RFKILL_STATE_SOFT_BLOCKED;
 }
 
 static ssize_t show_display(struct device *dev, struct device_attribute *attr,
@@ -318,6 +321,9 @@ void hp_wmi_notify(u32 value, void *context)
 
        if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) {
                int eventcode = *((u8 *) obj->buffer.pointer);
+               if (eventcode == 0x4)
+                       eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
+                                                        0);
                key = hp_wmi_get_entry_by_scancode(eventcode);
                if (key) {
                        switch (key->type) {
@@ -338,12 +344,14 @@ void hp_wmi_notify(u32 value, void *context)
                        }
                } else if (eventcode == 0x5) {
                        if (wifi_rfkill)
-                               wifi_rfkill->state = hp_wmi_wifi_state();
+                               rfkill_force_state(wifi_rfkill,
+                                                  hp_wmi_wifi_state());
                        if (bluetooth_rfkill)
-                               bluetooth_rfkill->state =
-                                   hp_wmi_bluetooth_state();
+                               rfkill_force_state(bluetooth_rfkill,
+                                                  hp_wmi_bluetooth_state());
                        if (wwan_rfkill)
-                               wwan_rfkill->state = hp_wmi_wwan_state();
+                               rfkill_force_state(wwan_rfkill,
+                                                  hp_wmi_wwan_state());
                } else
                        printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
                               eventcode);
@@ -398,6 +406,7 @@ static void cleanup_sysfs(struct platform_device *device)
 static int __init hp_wmi_bios_setup(struct platform_device *device)
 {
        int err;
+       int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
 
        err = device_create_file(&device->dev, &dev_attr_display);
        if (err)
@@ -412,28 +421,33 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
        if (err)
                goto add_sysfs_error;
 
-       wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
-       wifi_rfkill->name = "hp-wifi";
-       wifi_rfkill->state = hp_wmi_wifi_state();
-       wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
-       wifi_rfkill->user_claim_unsupported = 1;
-
-       bluetooth_rfkill = rfkill_allocate(&device->dev,
-                                          RFKILL_TYPE_BLUETOOTH);
-       bluetooth_rfkill->name = "hp-bluetooth";
-       bluetooth_rfkill->state = hp_wmi_bluetooth_state();
-       bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
-       bluetooth_rfkill->user_claim_unsupported = 1;
-
-       wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX);
-       wwan_rfkill->name = "hp-wwan";
-       wwan_rfkill->state = hp_wmi_wwan_state();
-       wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
-       wwan_rfkill->user_claim_unsupported = 1;
-
-       rfkill_register(wifi_rfkill);
-       rfkill_register(bluetooth_rfkill);
-       rfkill_register(wwan_rfkill);
+       if (wireless & 0x1) {
+               wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
+               wifi_rfkill->name = "hp-wifi";
+               wifi_rfkill->state = hp_wmi_wifi_state();
+               wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
+               wifi_rfkill->user_claim_unsupported = 1;
+               rfkill_register(wifi_rfkill);
+       }
+
+       if (wireless & 0x2) {
+               bluetooth_rfkill = rfkill_allocate(&device->dev,
+                                                  RFKILL_TYPE_BLUETOOTH);
+               bluetooth_rfkill->name = "hp-bluetooth";
+               bluetooth_rfkill->state = hp_wmi_bluetooth_state();
+               bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
+               bluetooth_rfkill->user_claim_unsupported = 1;
+               rfkill_register(bluetooth_rfkill);
+       }
+
+       if (wireless & 0x4) {
+               wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN);
+               wwan_rfkill->name = "hp-wwan";
+               wwan_rfkill->state = hp_wmi_wwan_state();
+               wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
+               wwan_rfkill->user_claim_unsupported = 1;
+               rfkill_register(wwan_rfkill);
+       }
 
        return 0;
 add_sysfs_error:
@@ -445,9 +459,12 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device)
 {
        cleanup_sysfs(device);
 
-       rfkill_unregister(wifi_rfkill);
-       rfkill_unregister(bluetooth_rfkill);
-       rfkill_unregister(wwan_rfkill);
+       if (wifi_rfkill)
+               rfkill_unregister(wifi_rfkill);
+       if (bluetooth_rfkill)
+               rfkill_unregister(bluetooth_rfkill);
+       if (wwan_rfkill)
+               rfkill_unregister(wwan_rfkill);
 
        return 0;
 }
index d3eb7903c346aa9db41abf5897d8be04445f6213..6b9300779a431c1828acad495ddfbbec41332836 100644 (file)
@@ -3086,7 +3086,6 @@ static struct ibm_struct wan_driver_data = {
        .read = wan_read,
        .write = wan_write,
        .exit = wan_exit,
-       .flags.experimental = 1,
 };
 
 /*************************************************************************
index 86dbb366415a14a76b3961180cd3f14176f911cc..6986f392624426e0bfa6cb0f6085766f56cae90e 100644 (file)
@@ -103,8 +103,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
                        check_disk_change(inode->i_bdev);
                ret = 0;
 
-               if ((filp->f_mode & FMODE_WRITE) && md->read_only)
+               if ((filp->f_mode & FMODE_WRITE) && md->read_only) {
+                       mmc_blk_put(md);
                        ret = -EROFS;
+               }
        }
 
        return ret;
index 6915f40ac8ab4c293775563ed932a95d326bbbdb..1f8b5b36222c26645576c3a338673839178ad267 100644 (file)
@@ -621,12 +621,21 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
                                if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
                                        if (host->total_length < 12)
                                                host->total_length = 12;
-                               host->buffer = dma_alloc_coherent(NULL,
-                                               host->total_length,
-                                               &host->physical_address, GFP_KERNEL);
+
+                               host->buffer = kmalloc(host->total_length, GFP_KERNEL);
+                               if (!host->buffer) {
+                                       pr_debug("Can't alloc tx buffer\n");
+                                       cmd->error = -ENOMEM;
+                                       mmc_request_done(host->mmc, host->request);
+                                       return;
+                               }
 
                                at91_mci_sg_to_dma(host, data);
 
+                               host->physical_address = dma_map_single(NULL,
+                                               host->buffer, host->total_length,
+                                               DMA_TO_DEVICE);
+
                                pr_debug("Transmitting %d bytes\n", host->total_length);
 
                                at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
@@ -694,7 +703,10 @@ static void at91_mci_completed_command(struct at91mci_host *host, unsigned int s
        cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
 
        if (host->buffer) {
-               dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
+               dma_unmap_single(NULL,
+                               host->physical_address, host->total_length,
+                               DMA_TO_DEVICE);
+               kfree(host->buffer);
                host->buffer = NULL;
        }
 
index d2f331876e4c86a9b8ee74a36541a1baf01b4b9a..e00d424e6575da02ed20246b44c6545c1cbe8b34 100644 (file)
@@ -410,16 +410,20 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
 
        case MEMGETREGIONINFO:
        {
-               struct region_info_user ur;
+               uint32_t ur_idx;
+               struct mtd_erase_region_info *kr;
+               struct region_info_user *ur = (struct region_info_user *) argp;
 
-               if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
+               if (get_user(ur_idx, &(ur->regionindex)))
                        return -EFAULT;
 
-               if (ur.regionindex >= mtd->numeraseregions)
-                       return -EINVAL;
-               if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
-                               sizeof(struct mtd_erase_region_info)))
+               kr = &(mtd->eraseregions[ur_idx]);
+
+               if (put_user(kr->offset, &(ur->offset))
+                   || put_user(kr->erasesize, &(ur->erasesize))
+                   || put_user(kr->numblocks, &(ur->numblocks)))
                        return -EFAULT;
+
                break;
        }
 
index cbab654b03c8464a48b4b501f753e727b579c27a..edb1e322113d20905e9d02f7fac26489748d6480 100644 (file)
@@ -109,7 +109,7 @@ struct tmio_nand {
 
        void __iomem *ccr;
        void __iomem *fcr;
-       unsigned long fcr_phys;
+       unsigned long fcr_base;
 
        unsigned int irq;
 
@@ -316,8 +316,8 @@ static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio)
        tmio_iowrite8(0x81, tmio->ccr + CCR_ICC);
 
        /* (10h)BaseAddress    0x1000 spba.spba2 */
-       tmio_iowrite16(tmio->fcr_phys, tmio->ccr + CCR_BASE);
-       tmio_iowrite16(tmio->fcr_phys >> 16, tmio->ccr + CCR_BASE + 16);
+       tmio_iowrite16(tmio->fcr_base, tmio->ccr + CCR_BASE);
+       tmio_iowrite16(tmio->fcr_base >> 16, tmio->ccr + CCR_BASE + 2);
 
        /* (04h)Command Register I/O spcmd */
        tmio_iowrite8(0x02, tmio->ccr + CCR_COMMAND);
@@ -395,7 +395,7 @@ static int tmio_probe(struct platform_device *dev)
                goto err_iomap_ccr;
        }
 
-       tmio->fcr_phys = (unsigned long)fcr->start;
+       tmio->fcr_base = fcr->start & 0xfffff;
        tmio->fcr = ioremap(fcr->start, fcr->end - fcr->start + 1);
        if (!tmio->fcr) {
                retval = -EIO;
index a14dba1afcc56210508ce0b03805f37aea0035f7..fd705d1295a7b0ea78c27d79a905b5d21ba165cf 100644 (file)
@@ -151,6 +151,8 @@ struct sw_rx_page {
 #define PAGES_PER_SGE_SHIFT            0
 #define PAGES_PER_SGE                  (1 << PAGES_PER_SGE_SHIFT)
 
+#define BCM_RX_ETH_PAYLOAD_ALIGN       64
+
 /* SGE ring related macros */
 #define NUM_RX_SGE_PAGES               2
 #define RX_SGE_CNT             (BCM_PAGE_SIZE / sizeof(struct eth_rx_sge))
@@ -750,8 +752,7 @@ struct bnx2x {
 
        u32                     rx_csum;
        u32                     rx_offset;
-       u32                     rx_buf_use_size;        /* useable size */
-       u32                     rx_buf_size;            /* with alignment */
+       u32                     rx_buf_size;
 #define ETH_OVREHEAD                   (ETH_HLEN + 8)  /* 8 for CRC + VLAN */
 #define ETH_MIN_PACKET_SIZE            60
 #define ETH_MAX_PACKET_SIZE            1500
index 82deea0a63f568dc390d47435aec60c9af98d94f..a8eb3c4a47c84c2021c7ad782be3d92fa62ca0c8 100644 (file)
@@ -59,8 +59,8 @@
 #include "bnx2x.h"
 #include "bnx2x_init.h"
 
-#define DRV_MODULE_VERSION     "1.45.20"
-#define DRV_MODULE_RELDATE     "2008/08/25"
+#define DRV_MODULE_VERSION     "1.45.21"
+#define DRV_MODULE_RELDATE     "2008/09/03"
 #define BNX2X_BC_VER           0x040200
 
 /* Time in jiffies before concluding the transmitter is hung */
@@ -1027,7 +1027,7 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
        if (unlikely(skb == NULL))
                return -ENOMEM;
 
-       mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
+       mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_size,
                                 PCI_DMA_FROMDEVICE);
        if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
                dev_kfree_skb(skb);
@@ -1169,7 +1169,7 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
        /* move empty skb from pool to prod and map it */
        prod_rx_buf->skb = fp->tpa_pool[queue].skb;
        mapping = pci_map_single(bp->pdev, fp->tpa_pool[queue].skb->data,
-                                bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+                                bp->rx_buf_size, PCI_DMA_FROMDEVICE);
        pci_unmap_addr_set(prod_rx_buf, mapping, mapping);
 
        /* move partial skb from cons to pool (don't unmap yet) */
@@ -1276,7 +1276,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
           pool entry status to BNX2X_TPA_STOP even if new skb allocation
           fails. */
        pci_unmap_single(bp->pdev, pci_unmap_addr(rx_buf, mapping),
-                        bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+                        bp->rx_buf_size, PCI_DMA_FROMDEVICE);
 
        if (likely(new_skb)) {
                /* fix ip xsum and give it to the stack */
@@ -1520,7 +1520,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                        } else if (bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0) {
                                pci_unmap_single(bp->pdev,
                                        pci_unmap_addr(rx_buf, mapping),
-                                                bp->rx_buf_use_size,
+                                                bp->rx_buf_size,
                                                 PCI_DMA_FROMDEVICE);
                                skb_reserve(skb, pad);
                                skb_put(skb, len);
@@ -4229,7 +4229,7 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
                if (fp->tpa_state[i] == BNX2X_TPA_START)
                        pci_unmap_single(bp->pdev,
                                         pci_unmap_addr(rx_buf, mapping),
-                                        bp->rx_buf_use_size,
+                                        bp->rx_buf_size,
                                         PCI_DMA_FROMDEVICE);
 
                dev_kfree_skb(skb);
@@ -4245,15 +4245,14 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
        u16 ring_prod, cqe_ring_prod;
        int i, j;
 
-       bp->rx_buf_use_size = bp->dev->mtu;
-       bp->rx_buf_use_size += bp->rx_offset + ETH_OVREHEAD;
-       bp->rx_buf_size = bp->rx_buf_use_size + 64;
+       bp->rx_buf_size = bp->dev->mtu;
+       bp->rx_buf_size += bp->rx_offset + ETH_OVREHEAD +
+               BCM_RX_ETH_PAYLOAD_ALIGN;
 
        if (bp->flags & TPA_ENABLE_FLAG) {
                DP(NETIF_MSG_IFUP,
-                  "rx_buf_use_size %d  rx_buf_size %d  effective_mtu %d\n",
-                  bp->rx_buf_use_size, bp->rx_buf_size,
-                  bp->dev->mtu + ETH_OVREHEAD);
+                  "rx_buf_size %d  effective_mtu %d\n",
+                  bp->rx_buf_size, bp->dev->mtu + ETH_OVREHEAD);
 
                for_each_queue(bp, j) {
                        struct bnx2x_fastpath *fp = &bp->fp[j];
@@ -4462,9 +4461,10 @@ static void bnx2x_init_context(struct bnx2x *bp)
                context->ustorm_st_context.common.status_block_id = sb_id;
                context->ustorm_st_context.common.flags =
                        USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT;
-               context->ustorm_st_context.common.mc_alignment_size = 64;
+               context->ustorm_st_context.common.mc_alignment_size =
+                       BCM_RX_ETH_PAYLOAD_ALIGN;
                context->ustorm_st_context.common.bd_buff_size =
-                                               bp->rx_buf_use_size;
+                                               bp->rx_buf_size;
                context->ustorm_st_context.common.bd_page_base_hi =
                                                U64_HI(fp->rx_desc_mapping);
                context->ustorm_st_context.common.bd_page_base_lo =
@@ -4717,7 +4717,7 @@ static void bnx2x_init_internal_func(struct bnx2x *bp)
        }
 
        /* Init CQ ring mapping and aggregation size */
-       max_agg_size = min((u32)(bp->rx_buf_use_size +
+       max_agg_size = min((u32)(bp->rx_buf_size +
                                 8*BCM_PAGE_SIZE*PAGES_PER_SGE),
                           (u32)0xffff);
        for_each_queue(bp, i) {
@@ -5940,7 +5940,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
 
                        pci_unmap_single(bp->pdev,
                                         pci_unmap_addr(rx_buf, mapping),
-                                        bp->rx_buf_use_size,
+                                        bp->rx_buf_size,
                                         PCI_DMA_FROMDEVICE);
 
                        rx_buf->skb = NULL;
index 331b86b01fa98735b498f4aef16e478204b24419..0b6ecef9a849d6ea2238fcf807e6601d73ab8aca 100644 (file)
@@ -5975,10 +5975,12 @@ static void nv_shutdown(struct pci_dev *pdev)
        if (netif_running(dev))
                nv_close(dev);
 
-       pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
-       pci_enable_wake(pdev, PCI_D3cold, np->wolenabled);
        pci_disable_device(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
+       if (system_state == SYSTEM_POWER_OFF) {
+               if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled))
+                       pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
+               pci_set_power_state(pdev, PCI_D3hot);
+       }
 }
 #else
 #define nv_suspend NULL
index 53f41b649f03638dccbb40a3180b8d8e35e773ca..a417be7f8be5d0584a4371e240c4116ead185591 100644 (file)
@@ -2303,6 +2303,12 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
        int err = 0;
        int vector, v_budget;
 
+       /*
+        * Set the default interrupt throttle rate.
+        */
+       adapter->rx_eitr = (1000000 / IXGBE_DEFAULT_ITR_RX_USECS);
+       adapter->tx_eitr = (1000000 / IXGBE_DEFAULT_ITR_TX_USECS);
+
        /*
         * It's easy to be greedy for MSI-X vectors, but it really
         * doesn't do us much good if we have a lot more vectors
index 32bb47adbe39b3db3b2c44b083c73ece4fbd3b9a..008fd6618a5f527b39abfa4742c9be8b63c67ed3 100644 (file)
@@ -359,16 +359,6 @@ static void netxen_pcie_strap_init(struct netxen_adapter *adapter)
        int i, pos;
        struct pci_dev *pdev;
 
-       pdev = pci_get_device(0x1166, 0x0140, NULL);
-       if (pdev) {
-               pci_dev_put(pdev);
-               adapter->hw_read_wx(adapter,
-                       NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
-               chicken |= 0x4000;
-               adapter->hw_write_wx(adapter,
-                       NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
-       }
-
        pdev = adapter->pdev;
 
        adapter->hw_read_wx(adapter,
index 3f682d49a4e6f7796450d891a7052dceb82e0a74..52bf11b73c6e950e0829bed0dcee087f98c52b38 100644 (file)
@@ -784,6 +784,7 @@ static struct pcmcia_device_id axnet_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5),
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e),
        PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90),
+       PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2),
        PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
        PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
index 2d4c4ad89b8dbda9fdcd773b7c9825d4de1889b8..ebc1ae6bcbe5fc27f7152add5064a8dde48b9f70 100644 (file)
@@ -1626,6 +1626,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
        PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83),
        PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
        PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
        PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
@@ -1737,7 +1738,6 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
        PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
        PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
-       PCMCIA_DEVICE_PROD_ID1("IC-CARD", 0x60cb09a6),
        PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
        PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
        /* too generic! */
index a84ba487c713d705d7052963d3e230ebf26dc746..8c19307e50403b139ff2ad674bb94b222a263453 100644 (file)
@@ -117,7 +117,7 @@ static void ctrl_callback(struct urb *urb)
        case -ENOENT:
                break;
        default:
-               if (netif_msg_drv(pegasus))
+               if (netif_msg_drv(pegasus) && printk_ratelimit())
                        dev_dbg(&pegasus->intf->dev, "%s, status %d\n",
                                __FUNCTION__, urb->status);
        }
@@ -166,7 +166,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
                set_current_state(TASK_RUNNING);
                if (ret == -ENODEV)
                        netif_device_detach(pegasus->net);
-               if (netif_msg_drv(pegasus))
+               if (netif_msg_drv(pegasus) && printk_ratelimit())
                        dev_err(&pegasus->intf->dev, "%s, status %d\n",
                                        __FUNCTION__, ret);
                goto out;
@@ -275,7 +275,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
        if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
                if (ret == -ENODEV)
                        netif_device_detach(pegasus->net);
-               if (netif_msg_drv(pegasus))
+               if (netif_msg_drv(pegasus) && printk_ratelimit())
                        dev_err(&pegasus->intf->dev, "%s, status %d\n",
                                        __FUNCTION__, ret);
                goto out;
@@ -1209,8 +1209,7 @@ static void pegasus_set_multicast(struct net_device *net)
                pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
                if (netif_msg_link(pegasus))
                        pr_info("%s: Promiscuous mode enabled.\n", net->name);
-       } else if (net->mc_count ||
-                  (net->flags & IFF_ALLMULTI)) {
+       } else if (net->mc_count || (net->flags & IFF_ALLMULTI)) {
                pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
                pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
                if (netif_msg_link(pegasus))
@@ -1220,6 +1219,8 @@ static void pegasus_set_multicast(struct net_device *net)
                pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
        }
 
+       pegasus->ctrl_urb->status = 0;
+
        pegasus->flags |= ETH_REGS_CHANGE;
        ctrl_callback(pegasus->ctrl_urb);
 }
index a17eb130f57431e104a9141596037cfe9ef7e31e..6dbfed0b4149ecf2e2c10070f5333bb66edc48e0 100644 (file)
@@ -7285,15 +7285,15 @@ ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
                }
                break;
        case ATH9K_CIPHER_WEP:
-               if (k->kv_len < 40 / NBBY) {
+               if (k->kv_len < LEN_WEP40) {
                        DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
                                 "%s: WEP key length %u too small\n",
                                 __func__, k->kv_len);
                        return false;
                }
-               if (k->kv_len <= 40 / NBBY)
+               if (k->kv_len <= LEN_WEP40)
                        keyType = AR_KEYTABLE_TYPE_40;
-               else if (k->kv_len <= 104 / NBBY)
+               else if (k->kv_len <= LEN_WEP104)
                        keyType = AR_KEYTABLE_TYPE_104;
                else
                        keyType = AR_KEYTABLE_TYPE_128;
@@ -7313,7 +7313,7 @@ ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
        key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask;
        key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff;
        key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask;
-       if (k->kv_len <= 104 / NBBY)
+       if (k->kv_len <= LEN_WEP104)
                key4 &= 0xff;
 
        if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
index 2888778040e43f28803bab54be3b82a8e8d02232..c5107f269f24f2e250563814e800cdccad725538 100644 (file)
@@ -206,7 +206,8 @@ static int ath_key_config(struct ath_softc *sc,
        if (!ret)
                return -EIO;
 
-       sc->sc_keytype = hk.kv_type;
+       if (mac)
+               sc->sc_keytype = hk.kv_type;
        return 0;
 }
 
@@ -756,7 +757,8 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
                        key->hw_key_idx = key->keyidx;
                        /* push IV and Michael MIC generation to stack */
                        key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-                       key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+                       if (key->alg == ALG_TKIP)
+                               key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
                }
                break;
        case DISABLE_KEY:
@@ -1065,8 +1067,16 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
                tx_status->flags &= ~ATH_TX_BAR;
        }
-       if (tx_status->flags)
-               tx_info->status.excessive_retries = 1;
+
+       if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
+               if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+                       /* Frame was not ACKed, but an ACK was expected */
+                       tx_info->status.excessive_retries = 1;
+               }
+       } else {
+               /* Frame was ACKed */
+               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+       }
 
        tx_info->status.retry_count = tx_status->retries;
 
index 2fe806175c01c3a2ca4afda05fac81cd7f2ccf3d..20ddb7acdb9493c881ced6e2c0e1fb659fc7f003 100644 (file)
@@ -360,8 +360,9 @@ static void ath_rx_flush_tid(struct ath_softc *sc,
        struct ath_arx_tid *rxtid, int drop)
 {
        struct ath_rxbuf *rxbuf;
+       unsigned long flag;
 
-       spin_lock_bh(&rxtid->tidlock);
+       spin_lock_irqsave(&rxtid->tidlock, flag);
        while (rxtid->baw_head != rxtid->baw_tail) {
                rxbuf = rxtid->rxbuf + rxtid->baw_head;
                if (!rxbuf->rx_wbuf) {
@@ -382,7 +383,7 @@ static void ath_rx_flush_tid(struct ath_softc *sc,
                INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
                INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
        }
-       spin_unlock_bh(&rxtid->tidlock);
+       spin_unlock_irqrestore(&rxtid->tidlock, flag);
 }
 
 static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc,
index 157f830ee6b851983b9422c6b3fae421ff00eb86..550129f717e2c58ebd3f62f5edc6df0735e3c073 100644 (file)
@@ -357,9 +357,9 @@ static int ath_tx_prepare(struct ath_softc *sc,
        txctl->flags = ATH9K_TXDESC_CLRDMASK;    /* needed for crypto errors */
 
        if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
-               tx_info->flags |= ATH9K_TXDESC_NOACK;
+               txctl->flags |= ATH9K_TXDESC_NOACK;
        if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
-               tx_info->flags |= ATH9K_TXDESC_RTSENA;
+               txctl->flags |= ATH9K_TXDESC_RTSENA;
 
        /*
         * Setup for rate calculations.
index e2581229d8b2b6e6ac68a58f5ae20d001475b50e..23fed32989624a586216405303d118f85df7bc83 100644 (file)
@@ -474,8 +474,8 @@ static void iwl4965_apm_stop(struct iwl_priv *priv)
        iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
 
        udelay(10);
-
-       iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+       /* clear "init complete"  move adapter D0A* --> D0U state */
+       iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
index cbc01a00eaf4416e42ea3b2261df33506fe52d14..b08036a9d8945555efca52e64df7a87e69270d97 100644 (file)
@@ -145,7 +145,8 @@ static void iwl5000_apm_stop(struct iwl_priv *priv)
 
        udelay(10);
 
-       iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+       /* clear "init complete"  move adapter D0A* --> D0U state */
+       iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
 
        spin_unlock_irqrestore(&priv->lock, flags);
 }
@@ -577,14 +578,11 @@ static int iwl5000_load_section(struct iwl_priv *priv,
                FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
                phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
 
-       /* FIME: write the MSB of the phy_addr in CTRL1
-        * iwl_write_direct32(priv,
-               IWL_FH_TFDIB_CTRL1_REG(IWL_FH_SRVC_CHNL),
-               ((phy_addr & MSB_MSK)
-                       << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_count);
-        */
        iwl_write_direct32(priv,
-               FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), byte_cnt);
+               FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
+               (iwl_get_dma_hi_address(phy_addr)
+                       << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
+
        iwl_write_direct32(priv,
                FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
                1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
index 754fef5b592f656f20cca1e13b74b9361e2d01b9..90a2b6dee7c0e609063e945fefc9f6c13be936c9 100644 (file)
@@ -1153,7 +1153,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
            !sta->ht_info.ht_supported)
                return -1;
 
-       if (priv->current_ht_config.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC)
+       if (((sta->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS) >> 2)
+                                               == IWL_MIMO_PS_STATIC)
                return -1;
 
        /* Need both Tx chains/antennas to support MIMO */
index 061ffba9c884c017c00970bc2a148fd3d6dc0602..e01f048a02dda7bd3fd663c1f70c1080e0811a23 100644 (file)
@@ -181,14 +181,14 @@ static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
 }
 
 /**
- * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
+ * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
  * @priv: staging_rxon is compared to active_rxon
  *
  * If the RXON structure is changing enough to require a new tune,
  * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
  * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
  */
-static int iwl4965_full_rxon_required(struct iwl_priv *priv)
+static int iwl_full_rxon_required(struct iwl_priv *priv)
 {
 
        /* These items are only settable from the full RXON command */
@@ -207,7 +207,6 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv)
             priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
            (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
             priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
-           (priv->staging_rxon.rx_chain != priv->active_rxon.rx_chain) ||
            (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
                return 1;
 
@@ -263,7 +262,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
        /* If we don't need to send a full RXON, we can use
         * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
         * and other flags for the current radio configuration. */
-       if (!iwl4965_full_rxon_required(priv)) {
+       if (!iwl_full_rxon_required(priv)) {
                ret = iwl_send_rxon_assoc(priv);
                if (ret) {
                        IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret);
@@ -587,8 +586,6 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
                iwl_conf->supported_chan_width = 0;
        }
 
-       iwl_conf->tx_mimo_ps_mode =
-               (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
        memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
 
        iwl_conf->control_channel = ht_bss_conf->primary_channel;
@@ -2190,7 +2187,10 @@ static void __iwl4965_down(struct iwl_priv *priv)
        udelay(5);
 
        /* FIXME: apm_ops.suspend(priv) */
-       priv->cfg->ops->lib->apm_ops.reset(priv);
+       if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+               priv->cfg->ops->lib->apm_ops.stop(priv);
+       else
+               priv->cfg->ops->lib->apm_ops.reset(priv);
        priv->cfg->ops->lib->free_shared_mem(priv);
 
  exit:
@@ -2602,6 +2602,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
 {
        struct iwl_priv *priv = hw->priv;
        int ret;
+       u16 pci_cmd;
 
        IWL_DEBUG_MAC80211("enter\n");
 
@@ -2612,6 +2613,13 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
        pci_restore_state(priv->pci_dev);
        pci_enable_msi(priv->pci_dev);
 
+       /* enable interrupts if needed: hw bug w/a */
+       pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
+       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+               pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
+       }
+
        ret = request_irq(priv->pci_dev->irq, iwl4965_isr, IRQF_SHARED,
                          DRV_NAME, priv);
        if (ret) {
@@ -3580,7 +3588,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
 
        priv->assoc_id = 0;
        timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-       priv->timestamp = le64_to_cpu(timestamp) +  (priv->beacon_int * 1000);
+       priv->timestamp = le64_to_cpu(timestamp);
 
        IWL_DEBUG_MAC80211("leave\n");
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -4364,15 +4372,18 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
        iwl_dbgfs_unregister(priv);
        sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
 
+       /* ieee80211_unregister_hw call wil cause iwl4965_mac_stop to
+        * to be called and iwl4965_down since we are removing the device
+        * we need to set STATUS_EXIT_PENDING bit.
+        */
+       set_bit(STATUS_EXIT_PENDING, &priv->status);
        if (priv->mac80211_registered) {
                ieee80211_unregister_hw(priv->hw);
                priv->mac80211_registered = 0;
+       } else {
+               iwl4965_down(priv);
        }
 
-       set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-       iwl4965_down(priv);
-
        /* make sure we flush any pending irq or
         * tasklet for the driver
         */
index c72f72579beaeb2f70e2760a695f7b9268a533ab..80f2f84defa8b639e076ddbf7d4eefebd53dda90 100644 (file)
@@ -592,12 +592,11 @@ static void iwlcore_free_geos(struct iwl_priv *priv)
        clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
 }
 
-static u8 is_single_rx_stream(struct iwl_priv *priv)
+static bool is_single_rx_stream(struct iwl_priv *priv)
 {
        return !priv->current_ht_config.is_ht ||
               ((priv->current_ht_config.supp_mcs_set[1] == 0) &&
-               (priv->current_ht_config.supp_mcs_set[2] == 0)) ||
-              priv->ps_mode == IWL_MIMO_PS_STATIC;
+               (priv->current_ht_config.supp_mcs_set[2] == 0));
 }
 
 static u8 iwl_is_channel_extension(struct iwl_priv *priv,
@@ -704,33 +703,39 @@ EXPORT_SYMBOL(iwl_set_rxon_ht);
  * MIMO (dual stream) requires at least 2, but works better with 3.
  * This does not determine *which* chains to use, just how many.
  */
-static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv,
-                                       u8 *idle_state, u8 *rx_state)
+static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
 {
-       u8 is_single = is_single_rx_stream(priv);
-       u8 is_cam = test_bit(STATUS_POWER_PMI, &priv->status) ? 0 : 1;
+       bool is_single = is_single_rx_stream(priv);
+       bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
 
        /* # of Rx chains to use when expecting MIMO. */
        if (is_single || (!is_cam && (priv->ps_mode == IWL_MIMO_PS_STATIC)))
-               *rx_state = 2;
+               return 2;
        else
-               *rx_state = 3;
+               return 3;
+}
 
+static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
+{
+       int idle_cnt;
+       bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
        /* # Rx chains when idling and maybe trying to save power */
        switch (priv->ps_mode) {
        case IWL_MIMO_PS_STATIC:
        case IWL_MIMO_PS_DYNAMIC:
-               *idle_state = (is_cam) ? 2 : 1;
+               idle_cnt = (is_cam) ? 2 : 1;
                break;
        case IWL_MIMO_PS_NONE:
-               *idle_state = (is_cam) ? *rx_state : 1;
+               idle_cnt = (is_cam) ? active_cnt : 1;
                break;
+       case IWL_MIMO_PS_INVALID:
        default:
-               *idle_state = 1;
+               IWL_ERROR("invalide mimo ps mode %d\n", priv->ps_mode);
+               WARN_ON(1);
+               idle_cnt = -1;
                break;
        }
-
-       return 0;
+       return idle_cnt;
 }
 
 /**
@@ -741,34 +746,44 @@ static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv,
  */
 void iwl_set_rxon_chain(struct iwl_priv *priv)
 {
-       u8 is_single = is_single_rx_stream(priv);
-       u8 idle_state, rx_state;
-
-       priv->staging_rxon.rx_chain = 0;
-       rx_state = idle_state = 3;
+       bool is_single = is_single_rx_stream(priv);
+       bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
+       u8 idle_rx_cnt, active_rx_cnt;
+       u16 rx_chain;
 
        /* Tell uCode which antennas are actually connected.
         * Before first association, we assume all antennas are connected.
         * Just after first association, iwl_chain_noise_calibration()
         *    checks which antennas actually *are* connected. */
-       priv->staging_rxon.rx_chain |=
-                   cpu_to_le16(priv->hw_params.valid_rx_ant <<
-                                                RXON_RX_CHAIN_VALID_POS);
+       rx_chain = priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
 
        /* How many receivers should we use? */
-       iwlcore_get_rx_chain_counter(priv, &idle_state, &rx_state);
-       priv->staging_rxon.rx_chain |=
-               cpu_to_le16(rx_state << RXON_RX_CHAIN_MIMO_CNT_POS);
-       priv->staging_rxon.rx_chain |=
-               cpu_to_le16(idle_state << RXON_RX_CHAIN_CNT_POS);
-
-       if (!is_single && (rx_state >= 2) &&
-           !test_bit(STATUS_POWER_PMI, &priv->status))
+       active_rx_cnt = iwl_get_active_rx_chain_count(priv);
+       idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
+
+       /* correct rx chain count accoridng hw settings */
+       if (priv->hw_params.rx_chains_num < active_rx_cnt)
+               active_rx_cnt = priv->hw_params.rx_chains_num;
+
+       if (priv->hw_params.rx_chains_num < idle_rx_cnt)
+               idle_rx_cnt = priv->hw_params.rx_chains_num;
+
+       rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
+       rx_chain |= idle_rx_cnt  << RXON_RX_CHAIN_CNT_POS;
+
+       priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
+
+       if (!is_single && (active_rx_cnt >= 2) && is_cam)
                priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
        else
                priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
 
-       IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain);
+       IWL_DEBUG_ASSOC("rx_chain=0x%Xi active=%d idle=%d\n",
+                       priv->staging_rxon.rx_chain,
+                       active_rx_cnt, idle_rx_cnt);
+
+       WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
+               active_rx_cnt < idle_rx_cnt);
 }
 EXPORT_SYMBOL(iwl_set_rxon_chain);
 
index c19db438306cf9fc914b8b05bb278bf1fb417737..cdfb343c7ec6b3afc597de1204ae48421cf90fd3 100644 (file)
@@ -412,7 +412,6 @@ struct iwl_ht_info {
        /* self configuration data */
        u8 is_ht;
        u8 supported_chan_width;
-       u16 tx_mimo_ps_mode;
        u8 is_green_field;
        u8 sgf;                 /* HT_SHORT_GI_* short guard interval */
        u8 max_amsdu_size;
index 944642450d3d051b319fb93a302c0fbb4a647ea8..cd11c0ca29918bf75ff2d606885f3cfcd1195de7 100644 (file)
 
 #define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE      (0x01000000)
 
+#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT        28
 
 /**
  * Transmit DMA Channel Control/Status Registers (TCSR)
index f3f6ea49fdd2d0f287e2d0ca891483dd8faf97bd..e81bfc42a7cb7ced067f255641ade21107e03963 100644 (file)
@@ -1173,7 +1173,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 
        rx_status.antenna = 0;
        rx_status.flag = 0;
-       rx_status.flag |= RX_FLAG_TSFT;
+
+       /* TSF isn't reliable. In order to allow smooth user experience,
+        * this W/A doesn't propagate it to the mac80211 */
+       /*rx_status.flag |= RX_FLAG_TSFT;*/
 
        if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
                IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n",
index 9bb6adb28b73dd5a1aaf4041d61d03f9f2e0200b..6c8ac3a87d547f5ca2c4ad1543ec530e180dd467 100644 (file)
@@ -421,7 +421,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
                else
                        scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
 
-               if ((scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) && n_probes)
+               if (n_probes)
                        scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
 
                scan_ch->active_dwell = cpu_to_le16(active_dwell);
index d82823b5c8abce08948fad392cd9e8c3368aabf5..78b1a7a4ca409b88e8663d37643b1bf07fcdad69 100644 (file)
@@ -402,12 +402,11 @@ static int iwl_hw_tx_queue_init(struct iwl_priv *priv,
 /**
  * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue
  */
-static int iwl_tx_queue_init(struct iwl_priv *priv,
-                            struct iwl_tx_queue *txq,
+static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
                             int slots_num, u32 txq_id)
 {
        int i, len;
-       int rc = 0;
+       int ret;
 
        /*
         * Alloc buffer array for commands (Tx or other types of commands).
@@ -426,19 +425,16 @@ static int iwl_tx_queue_init(struct iwl_priv *priv,
                                continue;
                }
 
-               txq->cmd[i] = kmalloc(len, GFP_KERNEL | GFP_DMA);
+               txq->cmd[i] = kmalloc(len, GFP_KERNEL);
                if (!txq->cmd[i])
-                       return -ENOMEM;
+                       goto err;
        }
 
        /* Alloc driver data array and TFD circular buffer */
-       rc = iwl_tx_queue_alloc(priv, txq, txq_id);
-       if (rc) {
-               for (i = 0; i < slots_num; i++)
-                       kfree(txq->cmd[i]);
+       ret = iwl_tx_queue_alloc(priv, txq, txq_id);
+       if (ret)
+               goto err;
 
-               return -ENOMEM;
-       }
        txq->need_update = 0;
 
        /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
@@ -452,6 +448,17 @@ static int iwl_tx_queue_init(struct iwl_priv *priv,
        iwl_hw_tx_queue_init(priv, txq);
 
        return 0;
+err:
+       for (i = 0; i < slots_num; i++) {
+               kfree(txq->cmd[i]);
+               txq->cmd[i] = NULL;
+       }
+
+       if (txq_id == IWL_CMD_QUEUE_NUM) {
+               kfree(txq->cmd[slots_num]);
+               txq->cmd[slots_num] = NULL;
+       }
+       return -ENOMEM;
 }
 /**
  * iwl_hw_txq_ctx_free - Free TXQ Context
index 04d7a251e3f0c75a9c0084ca6cd401f7bbd980d0..8941919001bbf8a0c120eb8734f9a88f76b6c723 100644 (file)
@@ -595,7 +595,7 @@ static int if_cs_prog_helper(struct if_cs_card *card)
                if (ret < 0) {
                        lbs_pr_err("can't download helper at 0x%x, ret %d\n",
                                sent, ret);
-                       goto done;
+                       goto err_release;
                }
 
                if (count == 0)
@@ -604,9 +604,8 @@ static int if_cs_prog_helper(struct if_cs_card *card)
                sent += count;
        }
 
+err_release:
        release_firmware(fw);
-       ret = 0;
-
 done:
        lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
        return ret;
@@ -676,14 +675,8 @@ static int if_cs_prog_real(struct if_cs_card *card)
        }
 
        ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
-       if (ret < 0) {
+       if (ret < 0)
                lbs_pr_err("firmware download failed\n");
-               goto err_release;
-       }
-
-       ret = 0;
-       goto done;
-
 
 err_release:
        release_firmware(fw);
index 1ebcafe7ca5fd7aa90421385ee864c0459a8d17f..36c004e1560218904db4ed2667e18a2eb55fb426 100644 (file)
@@ -1970,6 +1970,9 @@ __orinoco_set_multicast_list(struct net_device *dev)
                        priv->promiscuous = promisc;
        }
 
+       /* If we're not in promiscuous mode, then we need to set the
+        * group address if either we want to multicast, or if we were
+        * multicasting and want to stop */
        if (! promisc && (mc_count || priv->mc_count) ) {
                struct dev_mc_list *p = dev->mc_list;
                struct hermes_multicast mclist;
@@ -1989,9 +1992,10 @@ __orinoco_set_multicast_list(struct net_device *dev)
                        printk(KERN_WARNING "%s: Multicast list is "
                               "longer than mc_count\n", dev->name);
 
-               err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
-                                      HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
-                                      &mclist);
+               err = hermes_write_ltv(hw, USER_BAP,
+                                  HERMES_RID_CNFGROUPADDRESSES,
+                                  HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
+                                  &mclist);
                if (err)
                        printk(KERN_ERR "%s: Error %d setting multicast list.\n",
                               dev->name, err);
index 7e88ce5651b95041f35fde0a8ec682b09ca091eb..2ea7866abd5d775c66ebe9050e729c5efe64ef3a 100644 (file)
@@ -136,7 +136,7 @@ struct rt2x00_field32 {
  */
 #define is_power_of_two(x)     ( !((x) & ((x)-1)) )
 #define low_bit_mask(x)                ( ((x)-1) & ~(x) )
-#define is_valid_mask(x)       is_power_of_two(1 + (x) + low_bit_mask(x))
+#define is_valid_mask(x)       is_power_of_two(1LU + (x) + low_bit_mask(x))
 
 /*
  * Macro's to find first set bit in a variable.
@@ -173,8 +173,7 @@ struct rt2x00_field32 {
  * does not exceed the given typelimit.
  */
 #define FIELD_CHECK(__mask, __type)                    \
-       BUILD_BUG_ON(!__builtin_constant_p(__mask) ||   \
-                    !(__mask) ||                       \
+       BUILD_BUG_ON(!(__mask) ||                       \
                     !is_valid_mask(__mask) ||          \
                     (__mask) != (__type)(__mask))      \
 
index 82634a2f1b1d82da305e73ef1287330ea0cf01ed..1aad599816f7988ac080084dc14083b0b8a50736 100644 (file)
@@ -352,11 +352,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
                                continue;
                        r_size = r->end - r->start + 1;
                        /* For bridges size != alignment */
-                       align = (i < PCI_BRIDGE_RESOURCES) ? r_size : r->start;
+                       align = resource_alignment(r);
                        order = __ffs(align) - 20;
                        if (order > 11) {
-                               dev_warn(&dev->dev, "BAR %d too large: "
+                               dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
                                       "%#016llx-%#016llx\n", i,
+                                      (unsigned long long)align,
                                       (unsigned long long)r->start,
                                       (unsigned long long)r->end);
                                r->flags = 0;
index c48f3f69bdaf419f7e7394a37e081976244a99af..da3972153226a019c424ae98972ae8796e274f89 100644 (file)
@@ -748,7 +748,9 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
 
                add_timer(&skt->poll_timer);
 
-               device_create_file(&skt->socket.dev, &dev_attr_status);
+               ret = device_create_file(&skt->socket.dev, &dev_attr_status);
+               if (ret)
+                       goto out_err_8;
        }
 
        dev_set_drvdata(dev, sinfo);
@@ -758,6 +760,8 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
        do {
                skt = &sinfo->skt[i];
 
+               device_remove_file(&skt->socket.dev, &dev_attr_status);
+ out_err_8:
                del_timer_sync(&skt->poll_timer);
                pcmcia_unregister_socket(&skt->socket);
 
index d7e9f2152df0913305495ee7c7c25f36cdbb9f18..95015cbfd33f47bbfbb729b48aada46bd6d8d27e 100644 (file)
@@ -405,8 +405,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 
        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
                extended_irq = &res->data.extended_irq;
-               if (extended_irq->producer_consumer == ACPI_PRODUCER)
-                       return AE_OK;
 
                if (extended_irq->interrupt_count == 0)
                        pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
index 6ea349aba3ba1fa81f159bcbb18235073cf80164..b184367637d06d65f09b2b8af2517e077ad37de2 100644 (file)
@@ -800,7 +800,6 @@ static void __exit cmos_do_remove(struct device *dev)
 static int cmos_suspend(struct device *dev, pm_message_t mesg)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
-       int             do_wake = device_may_wakeup(dev);
        unsigned char   tmp;
 
        /* only the alarm might be a wakeup event source */
@@ -809,7 +808,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
        if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
                unsigned char   mask;
 
-               if (do_wake)
+               if (device_may_wakeup(dev))
                        mask = RTC_IRQMASK & ~RTC_AIE;
                else
                        mask = RTC_IRQMASK;
@@ -837,6 +836,17 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
        return 0;
 }
 
+/* We want RTC alarms to wake us from e.g. ACPI G2/S5 "soft off", even
+ * after a detour through G3 "mechanical off", although the ACPI spec
+ * says wakeup should only work from G1/S4 "hibernate".  To most users,
+ * distinctions between S4 and S5 are pointless.  So when the hardware
+ * allows, don't draw that distinction.
+ */
+static inline int cmos_poweroff(struct device *dev)
+{
+       return cmos_suspend(dev, PMSG_HIBERNATE);
+}
+
 static int cmos_resume(struct device *dev)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
@@ -884,6 +894,12 @@ static int cmos_resume(struct device *dev)
 #else
 #define        cmos_suspend    NULL
 #define        cmos_resume     NULL
+
+static inline int cmos_poweroff(struct device *dev)
+{
+       return -ENOSYS;
+}
+
 #endif
 
 /*----------------------------------------------------------------*/
@@ -903,10 +919,6 @@ static int cmos_resume(struct device *dev)
 static int __devinit
 cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
-       /* REVISIT paranoia argues for a shutdown notifier, since PNP
-        * drivers can't provide shutdown() methods to disable IRQs.
-        * Or better yet, fix PNP to allow those methods...
-        */
        if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0))
                /* Some machines contain a PNP entry for the RTC, but
                 * don't define the IRQ. It should always be safe to
@@ -942,6 +954,13 @@ static int cmos_pnp_resume(struct pnp_dev *pnp)
 #define        cmos_pnp_resume         NULL
 #endif
 
+static void cmos_pnp_shutdown(struct device *pdev)
+{
+       if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev))
+               return;
+
+       cmos_do_shutdown();
+}
 
 static const struct pnp_device_id rtc_ids[] = {
        { .id = "PNP0b00", },
@@ -961,6 +980,10 @@ static struct pnp_driver cmos_pnp_driver = {
        .flags          = PNP_DRIVER_RES_DO_NOT_CHANGE,
        .suspend        = cmos_pnp_suspend,
        .resume         = cmos_pnp_resume,
+       .driver         = {
+               .name     = (char *)driver_name,
+               .shutdown = cmos_pnp_shutdown,
+       }
 };
 
 #endif /* CONFIG_PNP */
@@ -986,6 +1009,9 @@ static int __exit cmos_platform_remove(struct platform_device *pdev)
 
 static void cmos_platform_shutdown(struct platform_device *pdev)
 {
+       if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pdev->dev))
+               return;
+
        cmos_do_shutdown();
 }
 
index 9f996ec881ce90dbf2a97cef5ecb73e090d634c7..dd70bf73ce9d5e3dd5fa1686c12f1c46421b5624 100644 (file)
@@ -51,10 +51,11 @@ EXPORT_SYMBOL(rtc_year_days);
  */
 void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
 {
-       unsigned int days, month, year;
+       unsigned int month, year;
+       int days;
 
        days = time / 86400;
-       time -= days * 86400;
+       time -= (unsigned int) days * 86400;
 
        /* day of the week, 1970-01-01 was a Thursday */
        tm->tm_wday = (days + 4) % 7;
index db00b05917331b5901091f7697fa1fa2f2de8d96..f1216cf6fa8fdd098cc3bc9c145d352fb907059d 100644 (file)
@@ -423,7 +423,7 @@ int chp_new(struct chp_id chpid)
        ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
        if (ret) {
                device_unregister(&chp->dev);
-               goto out_free;
+               goto out;
        }
        mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
        if (channel_subsystems[chpid.cssid]->cm_enabled) {
@@ -432,14 +432,15 @@ int chp_new(struct chp_id chpid)
                        sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
                        device_unregister(&chp->dev);
                        mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
-                       goto out_free;
+                       goto out;
                }
        }
        channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
        mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
-       return ret;
+       goto out;
 out_free:
        kfree(chp);
+out:
        return ret;
 }
 
index 33bff8fec7d10b0a5b02cb0ed0824cdd210b2256..5954b905e3cab9723116646069356ad7928c31d8 100644 (file)
@@ -208,8 +208,10 @@ cio_start_key (struct subchannel *sch,     /* subchannel structure */
        case 1:         /* status pending */
        case 2:         /* busy */
                return -EBUSY;
-       default:                /* device/path not operational */
+       case 3:         /* device/path not operational */
                return cio_start_handle_notoper(sch, lpm);
+       default:
+               return ccode;
        }
 }
 
index 51489eff6b0b4484ad234e6b7b7a0819a6d1ddd6..1261e1a9e8cd518f78aa44754a00318182de2ad8 100644 (file)
@@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev)
 
        css = to_css(dev);
        mutex_destroy(&css->mutex);
+       if (css->pseudo_subchannel) {
+               /* Implies that it has been generated but never registered. */
+               css_subchannel_release(&css->pseudo_subchannel->dev);
+               css->pseudo_subchannel = NULL;
+       }
        kfree(css);
 }
 
@@ -785,11 +790,15 @@ init_channel_subsystem (void)
                }
                channel_subsystems[i] = css;
                ret = setup_css(i);
-               if (ret)
-                       goto out_free;
+               if (ret) {
+                       kfree(channel_subsystems[i]);
+                       goto out_unregister;
+               }
                ret = device_register(&css->device);
-               if (ret)
-                       goto out_free_all;
+               if (ret) {
+                       put_device(&css->device);
+                       goto out_unregister;
+               }
                if (css_chsc_characteristics.secm) {
                        ret = device_create_file(&css->device,
                                                 &dev_attr_cm_enable);
@@ -802,7 +811,7 @@ init_channel_subsystem (void)
        }
        ret = register_reboot_notifier(&css_reboot_notifier);
        if (ret)
-               goto out_pseudo;
+               goto out_unregister;
        css_init_done = 1;
 
        /* Enable default isc for I/O subchannels. */
@@ -810,18 +819,12 @@ init_channel_subsystem (void)
 
        for_each_subchannel(__init_channel_subsystem, NULL);
        return 0;
-out_pseudo:
-       device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev);
 out_file:
-       device_remove_file(&channel_subsystems[i]->device,
-                          &dev_attr_cm_enable);
+       if (css_chsc_characteristics.secm)
+               device_remove_file(&channel_subsystems[i]->device,
+                                  &dev_attr_cm_enable);
 out_device:
        device_unregister(&channel_subsystems[i]->device);
-out_free_all:
-       kfree(channel_subsystems[i]->pseudo_subchannel->lock);
-       kfree(channel_subsystems[i]->pseudo_subchannel);
-out_free:
-       kfree(channel_subsystems[i]);
 out_unregister:
        while (i > 0) {
                struct channel_subsystem *css;
@@ -829,6 +832,7 @@ out_unregister:
                i--;
                css = channel_subsystems[i];
                device_unregister(&css->pseudo_subchannel->dev);
+               css->pseudo_subchannel = NULL;
                if (css_chsc_characteristics.secm)
                        device_remove_file(&css->device,
                                           &dev_attr_cm_enable);
index 550508df952b89693f5b13e4de5e5bec2a976ac3..84cc9ea346dbc264639d892a19e591ef7535ef8f 100644 (file)
@@ -658,6 +658,13 @@ ccw_device_offline(struct ccw_device *cdev)
 {
        struct subchannel *sch;
 
+       /* Allow ccw_device_offline while disconnected. */
+       if (cdev->private->state == DEV_STATE_DISCONNECTED ||
+           cdev->private->state == DEV_STATE_NOT_OPER) {
+               cdev->private->flags.donotify = 0;
+               ccw_device_done(cdev, DEV_STATE_NOT_OPER);
+               return 0;
+       }
        if (ccw_device_is_orphan(cdev)) {
                ccw_device_done(cdev, DEV_STATE_OFFLINE);
                return 0;
index e5e7d78564545543925fc6136c6e7c7fc994c028..2a2bc89aba83204f331f3023424150cc1a050f99 100644 (file)
@@ -1875,6 +1875,7 @@ static int sd_probe(struct device *dev)
 
        dev_set_drvdata(dev, sdkp);
        add_disk(gd);
+       blk_register_filter(gd);
        sd_dif_config_host(sdkp);
 
        sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
@@ -1908,6 +1909,7 @@ static int sd_remove(struct device *dev)
        struct scsi_disk *sdkp = dev_get_drvdata(dev);
 
        device_del(&sdkp->dev);
+       blk_unregister_filter(sdkp->disk);
        del_gendisk(sdkp->disk);
        sd_shutdown(dev);
 
index 27f5bfd1def343e205c2710a587571650026410f..3292965bfd84272ad83450b46d7a454c588c01bb 100644 (file)
@@ -656,6 +656,7 @@ static int sr_probe(struct device *dev)
        dev_set_drvdata(dev, cd);
        disk->flags |= GENHD_FL_REMOVABLE;
        add_disk(disk);
+       blk_register_filter(disk);
 
        sdev_printk(KERN_DEBUG, sdev,
                    "Attached scsi CD-ROM %s\n", cd->cdi.name);
@@ -894,6 +895,7 @@ static int sr_remove(struct device *dev)
 {
        struct scsi_cd *cd = dev_get_drvdata(dev);
 
+       blk_unregister_filter(cd->disk);
        del_gendisk(cd->disk);
 
        mutex_lock(&sr_ref_mutex);
index 342e12fb1c2525f74bb15d0e21ca4e473962ecd1..9ccc563d87303604c8cd63f355040177c30faf81 100644 (file)
@@ -1908,14 +1908,22 @@ static int serial8250_startup(struct uart_port *port)
                 * kick the UART on a regular basis.
                 */
                if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
+                       up->bugs |= UART_BUG_THRE;
                        pr_debug("ttyS%d - using backup timer\n", port->line);
-                       up->timer.function = serial8250_backup_timeout;
-                       up->timer.data = (unsigned long)up;
-                       mod_timer(&up->timer, jiffies +
-                               poll_timeout(up->port.timeout) + HZ / 5);
                }
        }
 
+       /*
+        * The above check will only give an accurate result the first time
+        * the port is opened so this value needs to be preserved.
+        */
+       if (up->bugs & UART_BUG_THRE) {
+               up->timer.function = serial8250_backup_timeout;
+               up->timer.data = (unsigned long)up;
+               mod_timer(&up->timer, jiffies +
+                         poll_timeout(up->port.timeout) + HZ / 5);
+       }
+
        /*
         * If the "interrupt" for this port doesn't correspond with any
         * hardware interrupt, we use a timer-based system.  The original
index 78c00162b04e7630bd5a08f3df952dd441e8e503..520260326f3dfeb64b67643e1a27938e733d71fc 100644 (file)
@@ -47,6 +47,7 @@ struct serial8250_config {
 #define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
 #define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
 #define UART_BUG_NOMSR (1 << 2)        /* UART has buggy MSR status bits (Au1x00) */
+#define UART_BUG_THRE  (1 << 3)        /* UART has buggy THRE reassertion */
 
 #define PROBE_RSA      (1 << 0)
 #define PROBE_ANY      (~0)
index 1eb64d08b60a9591bd994f757c0372602b7c7ef4..95b3ec89c126cdd0609306c034ae348a1324a184 100644 (file)
@@ -208,7 +208,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
        if (cpu_is_omap16xx())
                ocpi_enable();
 
-#ifdef CONFIG_ARCH_OMAP_OTG
+#ifdef CONFIG_USB_OTG
        if (need_transceiver) {
                ohci->transceiver = otg_get_transceiver();
                if (ohci->transceiver) {
index 7b74238ad1c7a2ab1aed27bc219b94f23b997c9e..e980766bb84bed3fc05abb203dc3c3bc02b7daff 100644 (file)
@@ -161,7 +161,7 @@ static int usb_console_setup(struct console *co, char *options)
                if (serial->type->set_termios) {
                        termios->c_cflag = cflag;
                        tty_termios_encode_baud_rate(termios, baud, baud);
-                       serial->type->set_termios(NULL, port, &dummy);
+                       serial->type->set_termios(tty, port, &dummy);
 
                        port->port.tty = NULL;
                        kfree(termios);
index 9c5925927ece04d4f39961ddaa0e596288c5a780..5a24c6411d3486baee17ed6d79d1bfdb4764a2aa 100644 (file)
@@ -939,7 +939,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
        ret = register_framebuffer(info);
        if (ret < 0) {
                dev_err(dev, "failed to register framebuffer device: %d\n", ret);
-               goto free_cmap;
+               goto reset_drvdata;
        }
 
        /* add selected videomode to modelist */
@@ -955,7 +955,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 
        return 0;
 
-
+reset_drvdata:
+       dev_set_drvdata(dev, NULL);
 free_cmap:
        fb_dealloc_cmap(&info->cmap);
 unregister_irqs:
@@ -992,10 +993,11 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct fb_info *info = dev_get_drvdata(dev);
-       struct atmel_lcdfb_info *sinfo = info->par;
+       struct atmel_lcdfb_info *sinfo;
 
-       if (!sinfo)
+       if (!info || !info->par)
                return 0;
+       sinfo = info->par;
 
        cancel_work_sync(&sinfo->task);
        exit_backlight(sinfo);
index c14b2435d23ede7e09fbe7ac54d83339bf29a7f0..e729fb279645dd34f634be1fb0ddaea60396a7bb 100644 (file)
@@ -628,27 +628,18 @@ static long cirrusfb_get_mclk(long freq, int bpp, long *div)
 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
                              struct fb_info *info)
 {
-       int nom, den;           /* translyting from pixels->bytes */
-       int yres, i;
-       static struct { int xres, yres; } modes[] =
-       { { 1600, 1280 },
-         { 1280, 1024 },
-         { 1024, 768 },
-         { 800, 600 },
-         { 640, 480 },
-         { -1, -1 } };
+       int yres;
+       /* memory size in pixels */
+       unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
 
        switch (var->bits_per_pixel) {
        case 1:
-               nom = 4;
-               den = 8;
+               pixels /= 4;
                break;          /* 8 pixel per byte, only 1/4th of mem usable */
        case 8:
        case 16:
        case 24:
        case 32:
-               nom = var->bits_per_pixel / 8;
-               den = 1;
                break;          /* 1 pixel == 1 byte */
        default:
                printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
@@ -658,43 +649,29 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
 
-       if (var->xres * nom / den * var->yres > info->screen_size) {
-               printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
-                       "resolution too high to fit into video memory!\n",
-                       var->xres, var->yres, var->bits_per_pixel);
-               DPRINTK("EXIT - EINVAL error\n");
-               return -EINVAL;
-       }
-
+       if (var->xres_virtual < var->xres)
+               var->xres_virtual = var->xres;
        /* use highest possible virtual resolution */
-       if (var->xres_virtual == -1 &&
-           var->yres_virtual == -1) {
-               printk(KERN_INFO
-                    "cirrusfb: using maximum available virtual resolution\n");
-               for (i = 0; modes[i].xres != -1; i++) {
-                       int size = modes[i].xres * nom / den * modes[i].yres;
-                       if (size < info->screen_size / 2)
-                               break;
-               }
-               if (modes[i].xres == -1) {
-                       printk(KERN_ERR "cirrusfb: could not find a virtual "
-                               "resolution that fits into video memory!!\n");
-                       DPRINTK("EXIT - EINVAL error\n");
-                       return -EINVAL;
-               }
-               var->xres_virtual = modes[i].xres;
-               var->yres_virtual = modes[i].yres;
+       if (var->yres_virtual == -1) {
+               var->yres_virtual = pixels / var->xres_virtual;
 
                printk(KERN_INFO "cirrusfb: virtual resolution set to "
                        "maximum of %dx%d\n", var->xres_virtual,
                        var->yres_virtual);
        }
-
-       if (var->xres_virtual < var->xres)
-               var->xres_virtual = var->xres;
        if (var->yres_virtual < var->yres)
                var->yres_virtual = var->yres;
 
+       if (var->xres_virtual * var->yres_virtual > pixels) {
+               printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... "
+                     "virtual resolution too high to fit into video memory!\n",
+                       var->xres_virtual, var->yres_virtual,
+                       var->bits_per_pixel);
+               DPRINTK("EXIT - EINVAL error\n");
+               return -EINVAL;
+       }
+
+
        if (var->xoffset < 0)
                var->xoffset = 0;
        if (var->yoffset < 0)
index 77aafcfae0373ce0b50a0f8210ad0e9f85c67dec..4599a4385bc9794337d87ad697b313e9421d8246 100644 (file)
@@ -95,7 +95,6 @@ static inline int mtrr_del(int reg, unsigned long base,
 #define VOODOO5_MAX_PIXCLOCK 350000
 
 static struct fb_fix_screeninfo tdfx_fix __devinitdata = {
-       .id =           "3Dfx",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
        .ypanstep =     1,
@@ -426,7 +425,7 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
        if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) {
                /* Banshee/Voodoo3 */
                chip_size = 2;
-               if (has_sgram && (draminit0 & DRAMINIT0_SGRAM_TYPE))
+               if (has_sgram && !(draminit0 & DRAMINIT0_SGRAM_TYPE))
                        chip_size = 1;
        } else {
                /* Voodoo4/5 */
@@ -1200,15 +1199,15 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
        /* Configure the default fb_fix_screeninfo first */
        switch (pdev->device) {
        case PCI_DEVICE_ID_3DFX_BANSHEE:
-               strcat(tdfx_fix.id, " Banshee");
+               strcpy(tdfx_fix.id, "3Dfx Banshee");
                default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
                break;
        case PCI_DEVICE_ID_3DFX_VOODOO3:
-               strcat(tdfx_fix.id, " Voodoo3");
+               strcpy(tdfx_fix.id, "3Dfx Voodoo3");
                default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
                break;
        case PCI_DEVICE_ID_3DFX_VOODOO5:
-               strcat(tdfx_fix.id, " Voodoo5");
+               strcpy(tdfx_fix.id, "3Dfx Voodoo5");
                default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
                break;
        }
index d4427cb869791cd0f1b910f5371f78aefe42c626..2e15da5459cf6bd5b0e144a0fef70cccfa6549c3 100644 (file)
@@ -60,7 +60,7 @@
 
 #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
 
-#define BALLOON_CLASS_NAME "memory"
+#define BALLOON_CLASS_NAME "xen_memory"
 
 struct balloon_stats {
        /* We aim for 'current allocation' == 'target allocation'. */
index 9fe86041f86e547fe71753609be8c56c0ae27dcc..da75a6fbc6baa1dec30fa37b6846c9b9d2e5fc88 100644 (file)
@@ -146,15 +146,27 @@ $(patsubst %,$(obj)/%.gen.o, $(fw-external-y)): $(obj)/%.gen.o: $(fwdir)/%
 $(obj)/%: $(obj)/%.ihex | $(objtree)/$(obj)/$$(dir %)
        $(call cmd,ihex)
 
+# Don't depend on ihex2fw if we're installing and it already exists.
+# Putting it after | in the dependencies doesn't seem sufficient when
+# we're installing after a cross-compile, because ihex2fw has dependencies
+# on stuff like /usr/lib/gcc/ppc64-redhat-linux/4.3.0/include/stddef.h and 
+# thus wants to be rebuilt. Which it can't be, if the prebuilt kernel tree
+# is exported read-only for someone to run 'make install'.
+ifeq ($(INSTALL):$(wildcard $(obj)/ihex2fw),install:$(obj)/ihex2fw)
+ihex2fw_dep :=
+else
+ihex2fw_dep := $(obj)/ihex2fw
+endif
+
 # .HEX is also Intel HEX, but where the offset and length in each record
 # is actually meaningful, because the firmware has to be loaded in a certain
 # order rather than as a single binary blob. Thus, we convert them into our
 # more compact binary representation of ihex records (<linux/ihex.h>)
-$(obj)/%.fw: $(obj)/%.HEX $(obj)/ihex2fw | $(objtree)/$(obj)/$$(dir %)
+$(obj)/%.fw: $(obj)/%.HEX $(ihex2fw_dep) | $(objtree)/$(obj)/$$(dir %)
        $(call cmd,ihex2fw)
 
 # .H16 is our own modified form of Intel HEX, with 16-bit length for records.
-$(obj)/%.fw: $(obj)/%.H16 $(obj)/ihex2fw | $(objtree)/$(obj)/$$(dir %)
+$(obj)/%.fw: $(obj)/%.H16 $(ihex2fw_dep) | $(objtree)/$(obj)/$$(dir %)
        $(call cmd,h16tofw)
 
 $(firmware-dirs):
index f9e4ad97a79e708fc27a9896ead78aee49ed396a..06e521a945c33494130c7f1ab637d5ecfbef234c 100644 (file)
@@ -9,7 +9,10 @@ files (e.g. "cp -a") to Windows servers.  For mkdir and create honor setgid bit
 on parent directory when server supports Unix Extensions but not POSIX
 create. Update cifs.upcall version to handle new Kerberos sec flags
 (this requires update of cifs.upcall program from Samba).  Fix memory leak
-on dns_upcall (resolving DFS referralls).
+on dns_upcall (resolving DFS referralls).  Fix plain text password
+authentication (requires setting SecurityFlags to 0x30030 to enable
+lanman and plain text though).  Fix writes to be at correct offset when
+file is open with O_APPEND and file is on a directio (forcediretio) mount.
 
 Version 1.53
 ------------
index 68b5c1169d9d7e3eff5a3aff67cfb60980fa2050..bd2343d4c6a638218d50c80a9091ef3dd8205a14 100644 (file)
@@ -542,10 +542,20 @@ SecurityFlags             Flags which control security negotiation and
                        hashing mechanisms (as "must use") on the other hand 
                        does not make much sense. Default flags are 
                                0x07007 
-                       (NTLM, NTLMv2 and packet signing allowed).  Maximum 
+                       (NTLM, NTLMv2 and packet signing allowed).  The maximum 
                        allowable flags if you want to allow mounts to servers
                        using weaker password hashes is 0x37037 (lanman,
-                       plaintext, ntlm, ntlmv2, signing allowed):
+                       plaintext, ntlm, ntlmv2, signing allowed).  Some
+                       SecurityFlags require the corresponding menuconfig
+                       options to be enabled (lanman and plaintext require
+                       CONFIG_CIFS_WEAK_PW_HASH for example).  Enabling
+                       plaintext authentication currently requires also
+                       enabling lanman authentication in the security flags
+                       because the cifs module only supports sending
+                       laintext passwords using the older lanman dialect
+                       form of the session setup SMB.  (e.g. for authentication
+                       using plain text passwords, set the SecurityFlags
+                       to 0x30030):
  
                        may use packet signing                          0x00001
                        must use packet signing                         0x01001
index 83fd40dc1ef0ffc3d6f1136f6966b90155481e98..bd5f13d38450ba5872658b2bee53a3ca017eb812 100644 (file)
@@ -294,6 +294,7 @@ void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
 
        if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
                if (extended_security & CIFSSEC_MAY_PLNTXT) {
+                       memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE);
                        memcpy(lnm_session_key, password_with_pad,
                                CIFS_ENCPWD_SIZE);
                        return;
index ff14d14903a0c182667d757eadc390f3a509cc93..cbefe1f1f9fe2c4c92e97e8b4999039ba5c15b99 100644 (file)
@@ -833,6 +833,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
                return -EBADF;
        open_file = (struct cifsFileInfo *) file->private_data;
 
+       rc = generic_write_checks(file, poffset, &write_size, 0);
+       if (rc)
+               return rc;
+
        xid = GetXid();
 
        if (*poffset > file->f_path.dentry->d_inode->i_size)
index b537fad3bf50684c2b3405df74a69ea9dd9e29a3..252fdc0567f1aa186f36f8c68d83f259d6db4ee0 100644 (file)
@@ -409,6 +409,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
                char lnm_session_key[CIFS_SESS_KEY_SIZE];
 
+               pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
+
                /* no capabilities flags in old lanman negotiation */
 
                pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
index 9abcd2b329f7357b0af65065613e996b643e1747..e9b20173fef33835e9d87be1a9b67e718b8dfe0a 100644 (file)
@@ -1279,6 +1279,12 @@ static int nfs_parse_mount_options(char *raw,
                }
        }
 
+       if (errors > 0) {
+               dfprintk(MOUNT, "NFS: parsing encountered %d error%s\n",
+                               errors, (errors == 1 ? "" : "s"));
+               if (!sloppy)
+                       return 0;
+       }
        return 1;
 
 out_nomem:
index b6ed38380ab805179f8354ab9454fc533e50da53..54b8b4140c8f6e32203363bd9b53e8aa2ed09f7e 100644 (file)
@@ -443,7 +443,7 @@ init_state(struct posix_acl_state *state, int cnt)
         * enough space for either:
         */
        alloc = sizeof(struct posix_ace_state_array)
-               + cnt*sizeof(struct posix_ace_state);
+               + cnt*sizeof(struct posix_user_ace_state);
        state->users = kzalloc(alloc, GFP_KERNEL);
        if (!state->users)
                return -ENOMEM;
index 2e51adac65de7c03e722134bf21947ee15de611a..e5b51ffafc6c2c2300fb61f3fb0c0036e0762115 100644 (file)
@@ -867,11 +867,6 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
        int             slack_bytes;
        __be32          status;
 
-       status = nfserr_resource;
-       cstate = cstate_alloc();
-       if (cstate == NULL)
-               goto out;
-
        resp->xbuf = &rqstp->rq_res;
        resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
        resp->tagp = resp->p;
@@ -890,6 +885,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
        if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION)
                goto out;
 
+       status = nfserr_resource;
+       cstate = cstate_alloc();
+       if (cstate == NULL)
+               goto out;
+
        status = nfs_ok;
        while (!status && resp->opcnt < args->opcnt) {
                op = &args->ops[resp->opcnt++];
@@ -957,9 +957,9 @@ encode_op:
                nfsd4_increment_op_stats(op->opnum);
        }
 
+       cstate_free(cstate);
 out:
        nfsd4_release_compoundargs(args);
-       cstate_free(cstate);
        dprintk("nfsv4 compound returned %d\n", ntohl(status));
        return status;
 }
index 3a8af75351e8662235eff32b67f9810f1c717248..4087fbdac327e19a586576aa6bc5bf95d307f96d 100644 (file)
@@ -113,7 +113,7 @@ typedef struct {
  * Reason flags (32-bit).  Cumulative flags describing the change(s) to the
  * file since it was last opened.  I think the names speak for themselves but
  * if you disagree check out the descriptions in the Linux NTFS project NTFS
- * documentation: http://linux-ntfs.sourceforge.net/ntfs/files/usnjrnl.html
+ * documentation: http://www.linux-ntfs.org/
  */
 enum {
        USN_REASON_DATA_OVERWRITE       = const_cpu_to_le32(0x00000001),
@@ -145,7 +145,7 @@ typedef le32 USN_REASON_FLAGS;
  * Source info flags (32-bit).  Information about the source of the change(s)
  * to the file.  For detailed descriptions of what these mean, see the Linux
  * NTFS project NTFS documentation:
- *     http://linux-ntfs.sourceforge.net/ntfs/files/usnjrnl.html
+ *     http://www.linux-ntfs.org/
  */
 enum {
        USN_SOURCE_DATA_MANAGEMENT        = const_cpu_to_le32(0x00000001),
index 0d6eb33597c6627f24586407f7e0a820454b3612..71c9be59c9c2574045d69c33aa024d618b681b4c 100644 (file)
@@ -337,65 +337,6 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
        return 0;
 }
 
-/*
- * Use precise platform statistics if available:
- */
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-static cputime_t task_utime(struct task_struct *p)
-{
-       return p->utime;
-}
-
-static cputime_t task_stime(struct task_struct *p)
-{
-       return p->stime;
-}
-#else
-static cputime_t task_utime(struct task_struct *p)
-{
-       clock_t utime = cputime_to_clock_t(p->utime),
-               total = utime + cputime_to_clock_t(p->stime);
-       u64 temp;
-
-       /*
-        * Use CFS's precise accounting:
-        */
-       temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
-
-       if (total) {
-               temp *= utime;
-               do_div(temp, total);
-       }
-       utime = (clock_t)temp;
-
-       p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime));
-       return p->prev_utime;
-}
-
-static cputime_t task_stime(struct task_struct *p)
-{
-       clock_t stime;
-
-       /*
-        * Use CFS's precise accounting. (we subtract utime from
-        * the total, to make sure the total observed by userspace
-        * grows monotonically - apps rely on that):
-        */
-       stime = nsec_to_clock_t(p->se.sum_exec_runtime) -
-                       cputime_to_clock_t(task_utime(p));
-
-       if (stime >= 0)
-               p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime));
-
-       return p->prev_stime;
-}
-#endif
-
-static cputime_t task_gtime(struct task_struct *p)
-{
-       return p->gtime;
-}
-
 static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
                        struct pid *pid, struct task_struct *task, int whole)
 {
index ded96986296099a036af1400a1ecdd7f3f71c058..00f10a2dcf1239d0b72b48a62d8265a0a59b3d78 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/tty.h>
 #include <linux/string.h>
 #include <linux/mman.h>
+#include <linux/quicklist.h>
 #include <linux/proc_fs.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
@@ -189,7 +190,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
                "Committed_AS: %8lu kB\n"
                "VmallocTotal: %8lu kB\n"
                "VmallocUsed:  %8lu kB\n"
-               "VmallocChunk: %8lu kB\n",
+               "VmallocChunk: %8lu kB\n"
+               "Quicklists:   %8lu kB\n",
                K(i.totalram),
                K(i.freeram),
                K(i.bufferram),
@@ -221,7 +223,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
                K(committed),
                (unsigned long)VMALLOC_TOTAL >> 10,
                vmi.used >> 10,
-               vmi.largest_chunk >> 10
+               vmi.largest_chunk >> 10,
+               K(quicklist_total_size())
                );
 
                len += hugetlb_report_meminfo(page + len);
index 1540981574738e45b4585c27d9cf5a8f43df21c9..73db464cd08b7a213365c0331824ce478a69e4d1 100644 (file)
@@ -302,18 +302,6 @@ long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs)
        int subtract_lebs;
        long long available;
 
-       /*
-        * Force the amount available to the total size reported if the used
-        * space is zero.
-        */
-       if (c->lst.total_used <= UBIFS_INO_NODE_SZ &&
-           c->budg_data_growth + c->budg_dd_growth == 0) {
-               /* Do the same calculation as for c->block_cnt */
-               available = c->main_lebs - 2;
-               available *= c->leb_size - c->dark_wm;
-               return available;
-       }
-
        available = c->main_bytes - c->lst.total_used;
 
        /*
@@ -714,34 +702,106 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
 }
 
 /**
- * ubifs_budg_get_free_space - return amount of free space.
+ * ubifs_reported_space - calculate reported free space.
+ * @c: the UBIFS file-system description object
+ * @free: amount of free space
+ *
+ * This function calculates amount of free space which will be reported to
+ * user-space. User-space application tend to expect that if the file-system
+ * (e.g., via the 'statfs()' call) reports that it has N bytes available, they
+ * are able to write a file of size N. UBIFS attaches node headers to each data
+ * node and it has to write indexind nodes as well. This introduces additional
+ * overhead, and UBIFS it has to report sligtly less free space to meet the
+ * above expectetion.
+ *
+ * This function assumes free space is made up of uncompressed data nodes and
+ * full index nodes (one per data node, tripled because we always allow enough
+ * space to write the index thrice).
+ *
+ * Note, the calculation is pessimistic, which means that most of the time
+ * UBIFS reports less space than it actually has.
+ */
+long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free)
+{
+       int divisor, factor, f;
+
+       /*
+        * Reported space size is @free * X, where X is UBIFS block size
+        * divided by UBIFS block size + all overhead one data block
+        * introduces. The overhead is the node header + indexing overhead.
+        *
+        * Indexing overhead calculations are based on the following formula:
+        * I = N/(f - 1) + 1, where I - number of indexing nodes, N - number
+        * of data nodes, f - fanout. Because effective UBIFS fanout is twice
+        * as less than maximum fanout, we assume that each data node
+        * introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes.
+        * Note, the multiplier 3 is because UBIFS reseves thrice as more space
+        * for the index.
+        */
+       f = c->fanout > 3 ? c->fanout >> 1 : 2;
+       factor = UBIFS_BLOCK_SIZE;
+       divisor = UBIFS_MAX_DATA_NODE_SZ;
+       divisor += (c->max_idx_node_sz * 3) / (f - 1);
+       free *= factor;
+       do_div(free, divisor);
+       return free;
+}
+
+/**
+ * ubifs_get_free_space - return amount of free space.
  * @c: UBIFS file-system description object
  *
- * This function returns amount of free space on the file-system.
+ * This function calculates amount of free space to report to user-space.
+ *
+ * Because UBIFS may introduce substantial overhead (the index, node headers,
+ * alighment, wastage at the end of eraseblocks, etc), it cannot report real
+ * amount of free flash space it has (well, because not all dirty space is
+ * reclamable, UBIFS does not actually know the real amount). If UBIFS did so,
+ * it would bread user expectetion about what free space is. Users seem to
+ * accustomed to assume that if the file-system reports N bytes of free space,
+ * they would be able to fit a file of N bytes to the FS. This almost works for
+ * traditional file-systems, because they have way less overhead than UBIFS.
+ * So, to keep users happy, UBIFS tries to take the overhead into account.
  */
-long long ubifs_budg_get_free_space(struct ubifs_info *c)
+long long ubifs_get_free_space(struct ubifs_info *c)
 {
-       int min_idx_lebs, rsvd_idx_lebs;
+       int min_idx_lebs, rsvd_idx_lebs, lebs;
        long long available, outstanding, free;
 
-       /* Do exactly the same calculations as in 'do_budget_space()' */
        spin_lock(&c->space_lock);
        min_idx_lebs = ubifs_calc_min_idx_lebs(c);
+       outstanding = c->budg_data_growth + c->budg_dd_growth;
 
-       if (min_idx_lebs > c->lst.idx_lebs)
-               rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
-       else
-               rsvd_idx_lebs = 0;
-
-       if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt
-                               - c->lst.taken_empty_lebs) {
+       /*
+        * Force the amount available to the total size reported if the used
+        * space is zero.
+        */
+       if (c->lst.total_used <= UBIFS_INO_NODE_SZ && !outstanding) {
                spin_unlock(&c->space_lock);
-               return 0;
+               return (long long)c->block_cnt << UBIFS_BLOCK_SHIFT;
        }
 
        available = ubifs_calc_available(c, min_idx_lebs);
-       outstanding = c->budg_data_growth + c->budg_dd_growth;
-       c->min_idx_lebs = min_idx_lebs;
+
+       /*
+        * When reporting free space to user-space, UBIFS guarantees that it is
+        * possible to write a file of free space size. This means that for
+        * empty LEBs we may use more precise calculations than
+        * 'ubifs_calc_available()' is using. Namely, we know that in empty
+        * LEBs we would waste only @c->leb_overhead bytes, not @c->dark_wm.
+        * Thus, amend the available space.
+        *
+        * Note, the calculations below are similar to what we have in
+        * 'do_budget_space()', so refer there for comments.
+        */
+       if (min_idx_lebs > c->lst.idx_lebs)
+               rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
+       else
+               rsvd_idx_lebs = 0;
+       lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
+              c->lst.taken_empty_lebs;
+       lebs -= rsvd_idx_lebs;
+       available += lebs * (c->dark_wm - c->leb_overhead);
        spin_unlock(&c->space_lock);
 
        if (available > outstanding)
index 5c96f1fb70166dbd75217692722d9e727be1d031..2b267c9a18065030ff8caff09fc6b2d5cc08b558 100644 (file)
@@ -587,7 +587,6 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
        if (err) {
                if (err != -ENOSPC)
                        return err;
-               err = 0;
                budgeted = 0;
        }
 
index 4071d1cae29f7cb0b65221ecd541b3832b37be31..3d698e2022b1ee7b2c8250fc75c89fff79785097 100644 (file)
@@ -793,7 +793,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
        int err;
        struct ubifs_budget_req req;
        loff_t old_size = inode->i_size, new_size = attr->ia_size;
-       int offset = new_size & (UBIFS_BLOCK_SIZE - 1);
+       int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1;
        struct ubifs_inode *ui = ubifs_inode(inode);
 
        dbg_gen("ino %lu, size %lld -> %lld", inode->i_ino, old_size, new_size);
@@ -811,8 +811,15 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
        /* A funny way to budget for truncation node */
        req.dirtied_ino_d = UBIFS_TRUN_NODE_SZ;
        err = ubifs_budget_space(c, &req);
-       if (err)
-               return err;
+       if (err) {
+               /*
+                * Treat truncations to zero as deletion and always allow them,
+                * just like we do for '->unlink()'.
+                */
+               if (new_size || err != -ENOSPC)
+                       return err;
+               budgeted = 0;
+       }
 
        err = vmtruncate(inode, new_size);
        if (err)
@@ -869,7 +876,12 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
        err = ubifs_jnl_truncate(c, inode, old_size, new_size);
        mutex_unlock(&ui->ui_mutex);
 out_budg:
-       ubifs_release_budget(c, &req);
+       if (budgeted)
+               ubifs_release_budget(c, &req);
+       else {
+               c->nospace = c->nospace_rp = 0;
+               smp_wmb();
+       }
        return err;
 }
 
index adee7b5ddeabb6cb63769f1cfcd4b68ba959e40c..e045c8b55423e9adc7c312efbd8164f7e3584bc5 100644 (file)
@@ -211,14 +211,8 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
  * dirty index heap, and it falls-back to LPT scanning if the heaps are empty
  * or do not have an LEB which satisfies the @min_space criteria.
  *
- * Note:
- *   o LEBs which have less than dead watermark of dirty space are never picked
- *   by this function;
- *
- * Returns zero and the LEB properties of
- * found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a
- * negative error code in case of other failures. The returned LEB is marked as
- * "taken".
+ * Note, LEBs which have less than dead watermark of free + dirty space are
+ * never picked by this function.
  *
  * The additional @pick_free argument controls if this function has to return a
  * free or freeable LEB if one is present. For example, GC must to set it to %1,
@@ -231,6 +225,10 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
  *
  * In addition @pick_free is set to %2 by the recovery process in order to
  * recover gc_lnum in which case an index LEB must not be returned.
+ *
+ * This function returns zero and the LEB properties of found dirty LEB in case
+ * of success, %-ENOSPC if no dirty LEB was found and a negative error code in
+ * case of other failures. The returned LEB is marked as "taken".
  */
 int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
                         int min_space, int pick_free)
@@ -245,7 +243,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
                int lebs, rsvd_idx_lebs = 0;
 
                spin_lock(&c->space_lock);
-               lebs = c->lst.empty_lebs;
+               lebs = c->lst.empty_lebs + c->idx_gc_cnt;
                lebs += c->freeable_cnt - c->lst.taken_empty_lebs;
 
                /*
@@ -317,7 +315,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
                lp = idx_lp;
 
        if (lp) {
-               ubifs_assert(lp->dirty >= c->dead_wm);
+               ubifs_assert(lp->free + lp->dirty >= c->dead_wm);
                goto found;
        }
 
index d0f3dac2908133f1ea7398d8bac29ffbd5eaa8a8..13f1019c859f254bed9ee9512007b50ee79274da 100644 (file)
@@ -344,6 +344,12 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
                if (err)
                        goto out;
 
+               /* Allow for races with TNC */
+               c->gced_lnum = lnum;
+               smp_wmb();
+               c->gc_seq += 1;
+               smp_wmb();
+
                if (c->gc_lnum == -1) {
                        c->gc_lnum = lnum;
                        err = LEB_RETAINED;
index 87dabf9fe742ea05674ec8cb2bf78f5fe98f510d..4c12a9215d7f24571d13603a382179bb223a1b40 100644 (file)
@@ -283,38 +283,6 @@ static inline void *ubifs_idx_key(const struct ubifs_info *c,
        return (void *)((struct ubifs_branch *)idx->branches)->key;
 }
 
-/**
- * ubifs_reported_space - calculate reported free space.
- * @c: the UBIFS file-system description object
- * @free: amount of free space
- *
- * This function calculates amount of free space which will be reported to
- * user-space. User-space application tend to expect that if the file-system
- * (e.g., via the 'statfs()' call) reports that it has N bytes available, they
- * are able to write a file of size N. UBIFS attaches node headers to each data
- * node and it has to write indexind nodes as well. This introduces additional
- * overhead, and UBIFS it has to report sligtly less free space to meet the
- * above expectetion.
- *
- * This function assumes free space is made up of uncompressed data nodes and
- * full index nodes (one per data node, doubled because we always allow enough
- * space to write the index twice).
- *
- * Note, the calculation is pessimistic, which means that most of the time
- * UBIFS reports less space than it actually has.
- */
-static inline long long ubifs_reported_space(const struct ubifs_info *c,
-                                            uint64_t free)
-{
-       int divisor, factor;
-
-       divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz * 3);
-       factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ;
-       do_div(free, divisor);
-
-       return free * factor;
-}
-
 /**
  * ubifs_current_time - round current time to time granularity.
  * @inode: inode
@@ -325,4 +293,21 @@ static inline struct timespec ubifs_current_time(struct inode *inode)
                current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
 }
 
+/**
+ * ubifs_tnc_lookup - look up a file-system node.
+ * @c: UBIFS file-system description object
+ * @key: node key to lookup
+ * @node: the node is returned here
+ *
+ * This function look up and reads node with key @key. The caller has to make
+ * sure the @node buffer is large enough to fit the node. Returns zero in case
+ * of success, %-ENOENT if the node was not found, and a negative error code in
+ * case of failure.
+ */
+static inline int ubifs_tnc_lookup(struct ubifs_info *c,
+                                  const union ubifs_key *key, void *node)
+{
+       return ubifs_tnc_locate(c, key, node, NULL, NULL);
+}
+
 #endif /* __UBIFS_MISC_H__ */
index f71e6b8822c4fac6dbaab1913098e7a61c81dcfa..7562464ac83fba3c19101afea8cf9495bf6cd692 100644 (file)
@@ -370,8 +370,9 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct ubifs_info *c = dentry->d_sb->s_fs_info;
        unsigned long long free;
+       __le32 *uuid = (__le32 *)c->uuid;
 
-       free = ubifs_budg_get_free_space(c);
+       free = ubifs_get_free_space(c);
        dbg_gen("free space %lld bytes (%lld blocks)",
                free, free >> UBIFS_BLOCK_SHIFT);
 
@@ -386,7 +387,8 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_files = 0;
        buf->f_ffree = 0;
        buf->f_namelen = UBIFS_MAX_NLEN;
-
+       buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]);
+       buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]);
        return 0;
 }
 
@@ -530,6 +532,12 @@ static int init_constants_early(struct ubifs_info *c)
        c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size);
        c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
 
+       /*
+        * Calculate how many bytes would be wasted at the end of LEB if it was
+        * fully filled with data nodes of maximum size. This is used in
+        * calculations when reporting free space.
+        */
+       c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ;
        return 0;
 }
 
@@ -647,13 +655,11 @@ static int init_constants_late(struct ubifs_info *c)
         * internally because it does not make much sense for UBIFS, but it is
         * necessary to report something for the 'statfs()' call.
         *
-        * Subtract the LEB reserved for GC and the LEB which is reserved for
-        * deletions.
-        *
-        * Review 'ubifs_calc_available()' if changing this calculation.
+        * Subtract the LEB reserved for GC, the LEB which is reserved for
+        * deletions, and assume only one journal head is available.
         */
-       tmp64 = c->main_lebs - 2;
-       tmp64 *= (uint64_t)c->leb_size - c->dark_wm;
+       tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1;
+       tmp64 *= (uint64_t)c->leb_size - c->leb_overhead;
        tmp64 = ubifs_reported_space(c, tmp64);
        c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
 
index e909f4a96443a65de717771b3004344f02263332..7da209ab93788f8cafb30d6532b946897d9ae384 100644 (file)
@@ -506,7 +506,7 @@ static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,
                if (keys_cmp(c, key, &node_key) != 0)
                        ret = 0;
        }
-       if (ret == 0)
+       if (ret == 0 && c->replaying)
                dbg_mnt("dangling branch LEB %d:%d len %d, key %s",
                        zbr->lnum, zbr->offs, zbr->len, DBGKEY(key));
        return ret;
@@ -1382,50 +1382,39 @@ static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key,
 }
 
 /**
- * ubifs_tnc_lookup - look up a file-system node.
+ * maybe_leb_gced - determine if a LEB may have been garbage collected.
  * @c: UBIFS file-system description object
- * @key: node key to lookup
- * @node: the node is returned here
+ * @lnum: LEB number
+ * @gc_seq1: garbage collection sequence number
  *
- * This function look up and reads node with key @key. The caller has to make
- * sure the @node buffer is large enough to fit the node. Returns zero in case
- * of success, %-ENOENT if the node was not found, and a negative error code in
- * case of failure.
+ * This function determines if @lnum may have been garbage collected since
+ * sequence number @gc_seq1. If it may have been then %1 is returned, otherwise
+ * %0 is returned.
  */
-int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key,
-                    void *node)
+static int maybe_leb_gced(struct ubifs_info *c, int lnum, int gc_seq1)
 {
-       int found, n, err;
-       struct ubifs_znode *znode;
-       struct ubifs_zbranch zbr, *zt;
+       int gc_seq2, gced_lnum;
 
-       mutex_lock(&c->tnc_mutex);
-       found = ubifs_lookup_level0(c, key, &znode, &n);
-       if (!found) {
-               err = -ENOENT;
-               goto out;
-       } else if (found < 0) {
-               err = found;
-               goto out;
-       }
-       zt = &znode->zbranch[n];
-       if (is_hash_key(c, key)) {
-               /*
-                * In this case the leaf node cache gets used, so we pass the
-                * address of the zbranch and keep the mutex locked
-                */
-               err = tnc_read_node_nm(c, zt, node);
-               goto out;
-       }
-       zbr = znode->zbranch[n];
-       mutex_unlock(&c->tnc_mutex);
-
-       err = ubifs_tnc_read_node(c, &zbr, node);
-       return err;
-
-out:
-       mutex_unlock(&c->tnc_mutex);
-       return err;
+       gced_lnum = c->gced_lnum;
+       smp_rmb();
+       gc_seq2 = c->gc_seq;
+       /* Same seq means no GC */
+       if (gc_seq1 == gc_seq2)
+               return 0;
+       /* Different by more than 1 means we don't know */
+       if (gc_seq1 + 1 != gc_seq2)
+               return 1;
+       /*
+        * We have seen the sequence number has increased by 1. Now we need to
+        * be sure we read the right LEB number, so read it again.
+        */
+       smp_rmb();
+       if (gced_lnum != c->gced_lnum)
+               return 1;
+       /* Finally we can check lnum */
+       if (gced_lnum == lnum)
+               return 1;
+       return 0;
 }
 
 /**
@@ -1436,16 +1425,19 @@ out:
  * @lnum: LEB number is returned here
  * @offs: offset is returned here
  *
- * This function is the same as 'ubifs_tnc_lookup()' but it returns the node
- * location also. See 'ubifs_tnc_lookup()'.
+ * This function look up and reads node with key @key. The caller has to make
+ * sure the @node buffer is large enough to fit the node. Returns zero in case
+ * of success, %-ENOENT if the node was not found, and a negative error code in
+ * case of failure. The node location can be returned in @lnum and @offs.
  */
 int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
                     void *node, int *lnum, int *offs)
 {
-       int found, n, err;
+       int found, n, err, safely = 0, gc_seq1;
        struct ubifs_znode *znode;
        struct ubifs_zbranch zbr, *zt;
 
+again:
        mutex_lock(&c->tnc_mutex);
        found = ubifs_lookup_level0(c, key, &znode, &n);
        if (!found) {
@@ -1456,24 +1448,43 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
                goto out;
        }
        zt = &znode->zbranch[n];
+       if (lnum) {
+               *lnum = zt->lnum;
+               *offs = zt->offs;
+       }
        if (is_hash_key(c, key)) {
                /*
                 * In this case the leaf node cache gets used, so we pass the
                 * address of the zbranch and keep the mutex locked
                 */
-               *lnum = zt->lnum;
-               *offs = zt->offs;
                err = tnc_read_node_nm(c, zt, node);
                goto out;
        }
+       if (safely) {
+               err = ubifs_tnc_read_node(c, zt, node);
+               goto out;
+       }
+       /* Drop the TNC mutex prematurely and race with garbage collection */
        zbr = znode->zbranch[n];
+       gc_seq1 = c->gc_seq;
        mutex_unlock(&c->tnc_mutex);
 
-       *lnum = zbr.lnum;
-       *offs = zbr.offs;
+       if (ubifs_get_wbuf(c, zbr.lnum)) {
+               /* We do not GC journal heads */
+               err = ubifs_tnc_read_node(c, &zbr, node);
+               return err;
+       }
 
-       err = ubifs_tnc_read_node(c, &zbr, node);
-       return err;
+       err = fallible_read_node(c, key, &zbr, node);
+       if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) {
+               /*
+                * The node may have been GC'ed out from under us so try again
+                * while keeping the TNC mutex locked.
+                */
+               safely = 1;
+               goto again;
+       }
+       return 0;
 
 out:
        mutex_unlock(&c->tnc_mutex);
@@ -1498,7 +1509,6 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
 {
        int found, n, err;
        struct ubifs_znode *znode;
-       struct ubifs_zbranch zbr;
 
        dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key));
        mutex_lock(&c->tnc_mutex);
@@ -1522,11 +1532,7 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
                goto out_unlock;
        }
 
-       zbr = znode->zbranch[n];
-       mutex_unlock(&c->tnc_mutex);
-
-       err = tnc_read_node_nm(c, &zbr, node);
-       return err;
+       err = tnc_read_node_nm(c, &znode->zbranch[n], node);
 
 out_unlock:
        mutex_unlock(&c->tnc_mutex);
index bd2121f3426eb5cacee42602dca1dcacb0150acd..a9ecbd9af20dbeb9a0ddefccd21f8b7393ba1d0a 100644 (file)
@@ -87,7 +87,7 @@
 #define UBIFS_SK_LEN 8
 
 /* Minimum index tree fanout */
-#define UBIFS_MIN_FANOUT 2
+#define UBIFS_MIN_FANOUT 3
 
 /* Maximum number of levels in UBIFS indexing B-tree */
 #define UBIFS_MAX_LEVELS 512
index d7f706f7a3024ab18200c382e790202273adc1e4..17c620b93eec324ced7165b4b2de16482e1b8fda 100644 (file)
@@ -995,6 +995,9 @@ struct ubifs_mount_opts {
  * @max_idx_node_sz: maximum indexing node aligned on 8-bytes boundary
  * @max_inode_sz: maximum possible inode size in bytes
  * @max_znode_sz: size of znode in bytes
+ *
+ * @leb_overhead: how many bytes are wasted in an LEB when it is filled with
+ *                data nodes of maximum size - used in free space reporting
  * @dead_wm: LEB dead space watermark
  * @dark_wm: LEB dark space watermark
  * @block_cnt: count of 4KiB blocks on the FS
@@ -1028,6 +1031,8 @@ struct ubifs_mount_opts {
  * @sbuf: a buffer of LEB size used by GC and replay for scanning
  * @idx_gc: list of index LEBs that have been garbage collected
  * @idx_gc_cnt: number of elements on the idx_gc list
+ * @gc_seq: incremented for every non-index LEB garbage collected
+ * @gced_lnum: last non-index LEB that was garbage collected
  *
  * @infos_list: links all 'ubifs_info' objects
  * @umount_mutex: serializes shrinker and un-mount
@@ -1224,6 +1229,8 @@ struct ubifs_info {
        int max_idx_node_sz;
        long long max_inode_sz;
        int max_znode_sz;
+
+       int leb_overhead;
        int dead_wm;
        int dark_wm;
        int block_cnt;
@@ -1257,6 +1264,8 @@ struct ubifs_info {
        void *sbuf;
        struct list_head idx_gc;
        int idx_gc_cnt;
+       volatile int gc_seq;
+       volatile int gced_lnum;
 
        struct list_head infos_list;
        struct mutex umount_mutex;
@@ -1434,9 +1443,10 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode,
                                struct ubifs_budget_req *req);
 void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
                         struct ubifs_budget_req *req);
-long long ubifs_budg_get_free_space(struct ubifs_info *c);
+long long ubifs_get_free_space(struct ubifs_info *c);
 int ubifs_calc_min_idx_lebs(struct ubifs_info *c);
 void ubifs_convert_page_budget(struct ubifs_info *c);
+long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free);
 long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs);
 
 /* find.c */
@@ -1451,8 +1461,6 @@ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c);
 /* tnc.c */
 int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
                        struct ubifs_znode **zn, int *n);
-int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key,
-                    void *node);
 int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
                        void *node, const struct qstr *nm);
 int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
index 1170dc60e638b35a9ee42cf39ba84b3982178a21..1870d5e05f1cc03b649a5969dad5f5fd026ec869 100644 (file)
@@ -1,8 +1,10 @@
-ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
+ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \
+                 $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
 header-y  += kvm.h
 endif
 
-ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
+ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \
+                 $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
 unifdef-y += a.out.h
 endif
 unifdef-y += auxvec.h
index 8feeae1f2369b64cdf1be263880200503c5c3a41..79a7ff925bf8ea24f0d2fa83a02115113d772a34 100644 (file)
@@ -14,4 +14,10 @@ extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __initdata_begin[], __initdata_end[];
 extern char __start_rodata[], __end_rodata[];
 
+/* function descriptor handling (if any).  Override
+ * in asm/sections.h */
+#ifndef dereference_function_descriptor
+#define dereference_function_descriptor(p) (p)
+#endif
+
 #endif /* _ASM_GENERIC_SECTIONS_H_ */
index abcf34c2fdc7928c7a60153bc7840a82e61f5e90..ea8087b55ffc18ecedfc5d7e754b2457b7189f92 100644 (file)
@@ -126,7 +126,7 @@ void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
  * @args:      array of argument values to store
  *
  * Changes @n arguments to the system call starting with the @i'th argument.
- * @n'th argument to @val.  Argument @i gets value @args[0], and so on.
+ * Argument @i gets value @args[0], and so on.
  * An arch inline version is probably optimal when @i and @n are constants.
  *
  * It's only valid to call this when @task is stopped for tracing on
index d5c0f2fda51bb0fc8cace8174d2865a3e0a27c98..03b1d69b142fcf4650b1dc16cb0fb1683fe94b88 100644 (file)
@@ -63,6 +63,7 @@ static inline void flush_icache_page(struct vm_area_struct *vma,
 }
 
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
+extern void (*local_flush_icache_range)(unsigned long start, unsigned long end);
 
 extern void (*__flush_cache_vmap)(void);
 
index fdd43ec42ec56fb5e4ca7552458f81dc35066e53..9d13c3507ad612f95fcc77085cc26e3a2d31192f 100644 (file)
@@ -4,4 +4,9 @@
 /* nothing to see, move along */
 #include <asm-generic/sections.h>
 
+#ifdef CONFIG_64BIT
+#undef dereference_function_descriptor
+void *dereference_function_descriptor(void *);
+#endif
+
 #endif
index 762f6a6bc707cedfcabc15db59a2977a54decab2..9489283a4bcfbc6bbb4f9e8fd5c25dbb8ed547f8 100644 (file)
 #define X86_FEATURE_UP         (3*32+ 9) /* smp kernel running on up */
 #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
 #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS       (3*32+12)  /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS                (3*32+13)  /* Branch Trace Store */
-#define X86_FEATURE_SYSCALL32  (3*32+14)  /* syscall in ia32 userspace */
-#define X86_FEATURE_SYSENTER32 (3*32+15)  /* sysenter in ia32 userspace */
+#define X86_FEATURE_PEBS       (3*32+12) /* Precise-Event Based Sampling */
+#define X86_FEATURE_BTS                (3*32+13) /* Branch Trace Store */
+#define X86_FEATURE_SYSCALL32  (3*32+14) /* syscall in ia32 userspace */
+#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */
 #define X86_FEATURE_REP_GOOD   (3*32+16) /* rep microcode works well on this CPU */
 #define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */
 #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */
-#define X86_FEATURE_11AP       (3*32+19)  /* Bad local APIC aka 11AP */
+#define X86_FEATURE_11AP       (3*32+19) /* Bad local APIC aka 11AP */
+#define X86_FEATURE_NOPL       (3*32+20) /* The NOPL (0F 1F) instructions */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
index adec887dd7cd5f07c1148f8c233e033e05160e40..5c2ff4bc2980b0c21d4973f52c123ab1cca45e7f 100644 (file)
 # define NEED_3DNOW    0
 #endif
 
+#if defined(CONFIG_X86_P6_NOP) || defined(CONFIG_X86_64)
+# define NEED_NOPL     (1<<(X86_FEATURE_NOPL & 31))
+#else
+# define NEED_NOPL     0
+#endif
+
 #ifdef CONFIG_X86_64
 #define NEED_PSE       0
 #define NEED_MSR       (1<<(X86_FEATURE_MSR & 31))
@@ -67,7 +73,7 @@
 #define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW)
 
 #define REQUIRED_MASK2 0
-#define REQUIRED_MASK3 0
+#define REQUIRED_MASK3 (NEED_NOPL)
 #define REQUIRED_MASK4 0
 #define REQUIRED_MASK5 0
 #define REQUIRED_MASK6 0
index 7d970678f9402bbb7c0b73a084831d14dd3d622c..b68ec09399be562110b92b0903a26ca058875e0e 100644 (file)
@@ -167,7 +167,8 @@ unifdef-y += acct.h
 unifdef-y += adb.h
 unifdef-y += adfs_fs.h
 unifdef-y += agpgart.h
-ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
+ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \
+                 $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
 unifdef-y += a.out.h
 endif
 unifdef-y += apm_bios.h
@@ -258,7 +259,8 @@ unifdef-y += kd.h
 unifdef-y += kernelcapi.h
 unifdef-y += kernel.h
 unifdef-y += keyboard.h
-ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
+ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \
+                 $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
 unifdef-y += kvm.h
 endif
 unifdef-y += llc.h
@@ -297,7 +299,6 @@ unifdef-y += parport.h
 unifdef-y += patchkey.h
 unifdef-y += pci.h
 unifdef-y += personality.h
-unifdef-y += pim.h
 unifdef-y += pktcdvd.h
 unifdef-y += pmu.h
 unifdef-y += poll.h
index c33b0dc28e4db5de75df8a2419c128d22c8e29d9..ed3a5d473e52b2282c0d09c2c25d406400dc7522 100644 (file)
@@ -127,6 +127,8 @@ extern int clockevents_register_notifier(struct notifier_block *nb);
 extern int clockevents_program_event(struct clock_event_device *dev,
                                     ktime_t expires, ktime_t now);
 
+extern void clockevents_handle_noop(struct clock_event_device *dev);
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void clockevents_notify(unsigned long reason, void *arg);
 #else
index e8f450c499b0ac42302fe6c0cf91ecb4115973f2..2691926fb50641305219b74db1a96f94a143c4f7 100644 (file)
@@ -160,7 +160,7 @@ static inline int current_cpuset_is_being_rebound(void)
 
 static inline void rebuild_sched_domains(void)
 {
-       partition_sched_domains(0, NULL, NULL);
+       partition_sched_domains(1, NULL, NULL);
 }
 
 #endif /* !CONFIG_CPUSETS */
index 87c12ed969548a233a8f9d8e8440ed0bc972a566..1524829f73f2cd8c5aa4fc9cbc6bd47c7a1fa48f 100644 (file)
@@ -1111,7 +1111,6 @@ void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 int ide_pci_set_master(struct pci_dev *, const char *);
 unsigned long ide_pci_dma_base(ide_hwif_t *, const struct ide_port_info *);
-extern const struct ide_dma_ops sff_dma_ops;
 int ide_pci_check_simplex(ide_hwif_t *, const struct ide_port_info *);
 int ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
 #else
@@ -1275,6 +1274,7 @@ extern int __ide_dma_end(ide_drive_t *);
 int ide_dma_test_irq(ide_drive_t *);
 extern void ide_dma_lost_irq(ide_drive_t *);
 extern void ide_dma_timeout(ide_drive_t *);
+extern const struct ide_dma_ops sff_dma_ops;
 #endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
 
 #else
@@ -1448,8 +1448,7 @@ static inline void ide_dump_identify(u8 *id)
 
 static inline int hwif_to_node(ide_hwif_t *hwif)
 {
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       return hwif->dev ? pcibus_to_node(dev->bus) : -1;
+       return hwif->dev ? dev_to_node(hwif->dev) : -1;
 }
 
 static inline ide_drive_t *ide_get_paired_drive(ide_drive_t *drive)
index db35ef02e74522881a1d5b1e00ce993280e2178b..969f6e92d0895a93b593829159bdef20220b0dcb 100644 (file)
@@ -619,6 +619,19 @@ static inline void hlist_add_after(struct hlist_node *n,
                next->next->pprev  = &next->next;
 }
 
+/*
+ * Move a list from one list head to another. Fixup the pprev
+ * reference of the first entry if it exists.
+ */
+static inline void hlist_move_list(struct hlist_head *old,
+                                  struct hlist_head *new)
+{
+       new->first = old->first;
+       if (new->first)
+               new->first->pprev = &new->first;
+       old->first = NULL;
+}
+
 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
 
 #define hlist_for_each(pos, head) \
index 07112ee9293a5aa25b8186db6e19c990c7863f11..8a455694d6826c84b3f606c7ea9c81a888094354 100644 (file)
@@ -6,7 +6,6 @@
 #ifdef __KERNEL__
 #include <linux/in.h>
 #endif
-#include <linux/pim.h>
 
 /*
  *     Based on the MROUTING 3.5 defines primarily to keep
@@ -130,6 +129,7 @@ struct igmpmsg
  */
 
 #ifdef __KERNEL__
+#include <linux/pim.h>
 #include <net/sock.h>
 
 #ifdef CONFIG_IP_MROUTE
index 5cf50473a10f0f6877263bb822a59c865b66163f..6f4c180179e2ef34fd06e2829bc2c99ba4bd39d3 100644 (file)
@@ -115,6 +115,7 @@ struct sioc_mif_req6
 
 #ifdef __KERNEL__
 
+#include <linux/pim.h>
 #include <linux/skbuff.h>      /* for struct sk_buff_head */
 
 #ifdef CONFIG_IPV6_MROUTE
index 236ffd317394c1fc01df81f32cb096775e0aec4b..1ba0661561a44d3dc7aaa6d951d28d8566fdcaa3 100644 (file)
@@ -3,22 +3,6 @@
 
 #include <asm/byteorder.h>
 
-#ifndef __KERNEL__
-struct pim {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-       __u8    pim_type:4,             /* PIM message type */
-               pim_ver:4;              /* PIM version */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-       __u8    pim_ver:4;              /* PIM version */
-               pim_type:4;             /* PIM message type */
-#endif
-       __u8    pim_rsv;                /* Reserved */
-       __be16  pim_cksum;              /* Checksum */
-};
-
-#define PIM_MINLEN             8
-#endif
-
 /* Message types - V1 */
 #define PIM_V1_VERSION         __constant_htonl(0x10000000)
 #define PIM_V1_REGISTER                1
@@ -27,7 +11,6 @@ struct pim {
 #define PIM_VERSION            2
 #define PIM_REGISTER           1
 
-#if defined(__KERNEL__)
 #define PIM_NULL_REGISTER      __constant_htonl(0x40000000)
 
 /* PIMv2 register message header layout (ietf-draft-idmr-pimvsm-v2-00.ps */
@@ -42,4 +25,3 @@ struct pimreghdr
 struct sk_buff;
 extern int pim_rcv_v1(struct sk_buff *);
 #endif
-#endif
index 39b66713a0bba015c9a1d94df6c54d9e781d3991..bd466439c58837fc422aab012388d082c5bd077b 100644 (file)
@@ -80,6 +80,13 @@ void quicklist_trim(int nr, void (*dtor)(void *),
 
 unsigned long quicklist_total_size(void);
 
+#else
+
+static inline unsigned long quicklist_total_size(void)
+{
+       return 0;
+}
+
 #endif
 
 #endif /* LINUX_QUICKLIST_H */
index fdeadd9740dc5f99deaa4a8662494914f438e8c4..271c1c2c9f6f741016f0917c360469ae5ee872a5 100644 (file)
@@ -166,7 +166,7 @@ static inline int res_counter_set_limit(struct res_counter *cnt,
        int ret = -EBUSY;
 
        spin_lock_irqsave(&cnt->lock, flags);
-       if (cnt->usage < limit) {
+       if (cnt->usage <= limit) {
                cnt->limit = limit;
                ret = 0;
        }
index cfb0d87b99fcafb8ff0eb753e0ea489dc20478dd..3d9120c5ad1589a0da722e514c370c0a3f1c4fe4 100644 (file)
@@ -1475,6 +1475,10 @@ static inline void put_task_struct(struct task_struct *t)
                __put_task_struct(t);
 }
 
+extern cputime_t task_utime(struct task_struct *p);
+extern cputime_t task_stime(struct task_struct *p);
+extern cputime_t task_gtime(struct task_struct *p);
+
 /*
  * Per process flags
  */
index ef2e3a20bf3bdf514d55d9bd0a89a3fe40e78898..dc05b54bd3a3c4f7d7b0e167e219844c0f163f73 100644 (file)
@@ -143,7 +143,6 @@ struct svcxprt_rdma {
        unsigned long        sc_flags;
        struct list_head     sc_dto_q;          /* DTO tasklet I/O pending Q */
        struct list_head     sc_read_complete_q;
-       spinlock_t           sc_read_complete_lock;
        struct work_struct   sc_work;
 };
 /* sc_flags */
index b48d8196957436284c429e1d196c434459d8f0be..6186a789d6c7a2f6d5c3ce7a3651a1db184b67ed 100644 (file)
@@ -272,7 +272,7 @@ static inline void tracehook_finish_clone(struct task_struct *child,
  * tracehook_report_clone_complete().  This must prevent the child from
  * self-reaping if tracehook_report_clone_complete() uses the @child
  * pointer; otherwise it might have died and been released by the time
- * tracehook_report_report_clone_complete() is called.
+ * tracehook_report_clone_complete() is called.
  *
  * Called with no locks held, but the child cannot run until this returns.
  */
index e65a6bed4e3ee0baf1c5185f676ff7e08b8a4351..303d93ffd6b23c2ccdf42bb676799f8ee295ef23 100644 (file)
@@ -334,6 +334,8 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SPCA508  v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */
 #define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
 #define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_PJPG     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
+#define V4L2_PIX_FMT_YVYU    v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16  YVU 4:2:2     */
 
 /*
  *     F O R M A T   E N U M E R A T I O N
index cbf751094688cfb024d7931c4ca755a70a33ab42..46a43b721dd6a104ed3252f211d9dfaa2b3d36e9 100644 (file)
@@ -325,7 +325,8 @@ int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
 
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
+int hci_conn_check_link_mode(struct hci_conn *conn);
 int hci_conn_auth(struct hci_conn *conn);
 int hci_conn_encrypt(struct hci_conn *conn);
 int hci_conn_change_link_key(struct hci_conn *conn);
index 95c660c9719ba957c3a57f9957e75528d98083ae..91324908fccd367953bcce47aeb537afbd242f2e 100644 (file)
@@ -208,6 +208,9 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
 extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
                                 struct inet_timewait_death_row *twdr);
 
+extern void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
+                           struct inet_timewait_death_row *twdr, int family);
+
 static inline
 struct net *twsk_net(const struct inet_timewait_sock *twsk)
 {
index 972f8e61d36ac4ca7742038b2a3f3004f1857eb9..59cedfb040e7864cdfa3199ae2557f236cdd1122 100644 (file)
@@ -243,10 +243,11 @@ static inline int open_arg(int flags, int mask)
 
 static int audit_match_perm(struct audit_context *ctx, int mask)
 {
+       unsigned n;
        if (unlikely(!ctx))
                return 0;
 
-       unsigned n = ctx->major;
+       n = ctx->major;
        switch (audit_classify_syscall(ctx->arch, n)) {
        case 0: /* native */
                if ((mask & AUDIT_PERM_WRITE) &&
index d5ab79cf516d7edf77f8e45afe15c04cdae2cda4..f227bc1726906a52a803907299230f62b39edd84 100644 (file)
@@ -14,6 +14,8 @@
  *  2003-10-22 Updates by Stephen Hemminger.
  *  2004 May-July Rework by Paul Jackson.
  *  2006 Rework by Paul Menage to use generic cgroups
+ *  2008 Rework of the scheduler domains and CPU hotplug handling
+ *       by Max Krasnyansky
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License.  See the file COPYING in the main directory of the Linux
@@ -236,9 +238,11 @@ static struct cpuset top_cpuset = {
 
 static DEFINE_MUTEX(callback_mutex);
 
-/* This is ugly, but preserves the userspace API for existing cpuset
+/*
+ * This is ugly, but preserves the userspace API for existing cpuset
  * users. If someone tries to mount the "cpuset" filesystem, we
- * silently switch it to mount "cgroup" instead */
+ * silently switch it to mount "cgroup" instead
+ */
 static int cpuset_get_sb(struct file_system_type *fs_type,
                         int flags, const char *unused_dev_name,
                         void *data, struct vfsmount *mnt)
@@ -473,10 +477,9 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
 }
 
 /*
- * Helper routine for rebuild_sched_domains().
+ * Helper routine for generate_sched_domains().
  * Do cpusets a, b have overlapping cpus_allowed masks?
  */
-
 static int cpusets_overlap(struct cpuset *a, struct cpuset *b)
 {
        return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
@@ -518,26 +521,15 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
 }
 
 /*
- * rebuild_sched_domains()
- *
- * This routine will be called to rebuild the scheduler's dynamic
- * sched domains:
- * - if the flag 'sched_load_balance' of any cpuset with non-empty
- *   'cpus' changes,
- * - or if the 'cpus' allowed changes in any cpuset which has that
- *   flag enabled,
- * - or if the 'sched_relax_domain_level' of any cpuset which has
- *   that flag enabled and with non-empty 'cpus' changes,
- * - or if any cpuset with non-empty 'cpus' is removed,
- * - or if a cpu gets offlined.
- *
- * This routine builds a partial partition of the systems CPUs
- * (the set of non-overlappping cpumask_t's in the array 'part'
- * below), and passes that partial partition to the kernel/sched.c
- * partition_sched_domains() routine, which will rebuild the
- * schedulers load balancing domains (sched domains) as specified
- * by that partial partition.  A 'partial partition' is a set of
- * non-overlapping subsets whose union is a subset of that set.
+ * generate_sched_domains()
+ *
+ * This function builds a partial partition of the systems CPUs
+ * A 'partial partition' is a set of non-overlapping subsets whose
+ * union is a subset of that set.
+ * The output of this function needs to be passed to kernel/sched.c
+ * partition_sched_domains() routine, which will rebuild the scheduler's
+ * load balancing domains (sched domains) as specified by that partial
+ * partition.
  *
  * See "What is sched_load_balance" in Documentation/cpusets.txt
  * for a background explanation of this.
@@ -547,13 +539,7 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
  * domains when operating in the severe memory shortage situations
  * that could cause allocation failures below.
  *
- * Call with cgroup_mutex held.  May take callback_mutex during
- * call due to the kfifo_alloc() and kmalloc() calls.  May nest
- * a call to the get_online_cpus()/put_online_cpus() pair.
- * Must not be called holding callback_mutex, because we must not
- * call get_online_cpus() while holding callback_mutex.  Elsewhere
- * the kernel nests callback_mutex inside get_online_cpus() calls.
- * So the reverse nesting would risk an ABBA deadlock.
+ * Must be called with cgroup_lock held.
  *
  * The three key local variables below are:
  *    q  - a linked-list queue of cpuset pointers, used to implement a
@@ -588,10 +574,10 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
  *     element of the partition (one sched domain) to be passed to
  *     partition_sched_domains().
  */
-
-void rebuild_sched_domains(void)
+static int generate_sched_domains(cpumask_t **domains,
+                       struct sched_domain_attr **attributes)
 {
-       LIST_HEAD(q);           /* queue of cpusets to be scanned*/
+       LIST_HEAD(q);           /* queue of cpusets to be scanned */
        struct cpuset *cp;      /* scans q */
        struct cpuset **csa;    /* array of all cpuset ptrs */
        int csn;                /* how many cpuset ptrs in csa so far */
@@ -601,23 +587,26 @@ void rebuild_sched_domains(void)
        int ndoms;              /* number of sched domains in result */
        int nslot;              /* next empty doms[] cpumask_t slot */
 
-       csa = NULL;
+       ndoms = 0;
        doms = NULL;
        dattr = NULL;
+       csa = NULL;
 
        /* Special case for the 99% of systems with one, full, sched domain */
        if (is_sched_load_balance(&top_cpuset)) {
-               ndoms = 1;
                doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
                if (!doms)
-                       goto rebuild;
+                       goto done;
+
                dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL);
                if (dattr) {
                        *dattr = SD_ATTR_INIT;
                        update_domain_attr_tree(dattr, &top_cpuset);
                }
                *doms = top_cpuset.cpus_allowed;
-               goto rebuild;
+
+               ndoms = 1;
+               goto done;
        }
 
        csa = kmalloc(number_of_cpusets * sizeof(cp), GFP_KERNEL);
@@ -680,61 +669,141 @@ restart:
                }
        }
 
-       /* Convert <csn, csa> to <ndoms, doms> */
+       /*
+        * Now we know how many domains to create.
+        * Convert <csn, csa> to <ndoms, doms> and populate cpu masks.
+        */
        doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
-       if (!doms)
-               goto rebuild;
+       if (!doms) {
+               ndoms = 0;
+               goto done;
+       }
+
+       /*
+        * The rest of the code, including the scheduler, can deal with
+        * dattr==NULL case. No need to abort if alloc fails.
+        */
        dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL);
 
        for (nslot = 0, i = 0; i < csn; i++) {
                struct cpuset *a = csa[i];
+               cpumask_t *dp;
                int apn = a->pn;
 
-               if (apn >= 0) {
-                       cpumask_t *dp = doms + nslot;
-
-                       if (nslot == ndoms) {
-                               static int warnings = 10;
-                               if (warnings) {
-                                       printk(KERN_WARNING
-                                        "rebuild_sched_domains confused:"
-                                         " nslot %d, ndoms %d, csn %d, i %d,"
-                                         " apn %d\n",
-                                         nslot, ndoms, csn, i, apn);
-                                       warnings--;
-                               }
-                               continue;
+               if (apn < 0) {
+                       /* Skip completed partitions */
+                       continue;
+               }
+
+               dp = doms + nslot;
+
+               if (nslot == ndoms) {
+                       static int warnings = 10;
+                       if (warnings) {
+                               printk(KERN_WARNING
+                                "rebuild_sched_domains confused:"
+                                 " nslot %d, ndoms %d, csn %d, i %d,"
+                                 " apn %d\n",
+                                 nslot, ndoms, csn, i, apn);
+                               warnings--;
                        }
+                       continue;
+               }
 
-                       cpus_clear(*dp);
-                       if (dattr)
-                               *(dattr + nslot) = SD_ATTR_INIT;
-                       for (j = i; j < csn; j++) {
-                               struct cpuset *b = csa[j];
-
-                               if (apn == b->pn) {
-                                       cpus_or(*dp, *dp, b->cpus_allowed);
-                                       b->pn = -1;
-                                       if (dattr)
-                                               update_domain_attr_tree(dattr
-                                                                  + nslot, b);
-                               }
+               cpus_clear(*dp);
+               if (dattr)
+                       *(dattr + nslot) = SD_ATTR_INIT;
+               for (j = i; j < csn; j++) {
+                       struct cpuset *b = csa[j];
+
+                       if (apn == b->pn) {
+                               cpus_or(*dp, *dp, b->cpus_allowed);
+                               if (dattr)
+                                       update_domain_attr_tree(dattr + nslot, b);
+
+                               /* Done with this partition */
+                               b->pn = -1;
                        }
-                       nslot++;
                }
+               nslot++;
        }
        BUG_ON(nslot != ndoms);
 
-rebuild:
-       /* Have scheduler rebuild sched domains */
+done:
+       kfree(csa);
+
+       *domains    = doms;
+       *attributes = dattr;
+       return ndoms;
+}
+
+/*
+ * Rebuild scheduler domains.
+ *
+ * Call with neither cgroup_mutex held nor within get_online_cpus().
+ * Takes both cgroup_mutex and get_online_cpus().
+ *
+ * Cannot be directly called from cpuset code handling changes
+ * to the cpuset pseudo-filesystem, because it cannot be called
+ * from code that already holds cgroup_mutex.
+ */
+static void do_rebuild_sched_domains(struct work_struct *unused)
+{
+       struct sched_domain_attr *attr;
+       cpumask_t *doms;
+       int ndoms;
+
        get_online_cpus();
-       partition_sched_domains(ndoms, doms, dattr);
+
+       /* Generate domain masks and attrs */
+       cgroup_lock();
+       ndoms = generate_sched_domains(&doms, &attr);
+       cgroup_unlock();
+
+       /* Have scheduler rebuild the domains */
+       partition_sched_domains(ndoms, doms, attr);
+
        put_online_cpus();
+}
 
-done:
-       kfree(csa);
-       /* Don't kfree(doms) -- partition_sched_domains() does that. */
-       /* Don't kfree(dattr) -- partition_sched_domains() does that. */
+static DECLARE_WORK(rebuild_sched_domains_work, do_rebuild_sched_domains);
+
+/*
+ * Rebuild scheduler domains, asynchronously via workqueue.
+ *
+ * If the flag 'sched_load_balance' of any cpuset with non-empty
+ * 'cpus' changes, or if the 'cpus' allowed changes in any cpuset
+ * which has that flag enabled, or if any cpuset with a non-empty
+ * 'cpus' is removed, then call this routine to rebuild the
+ * scheduler's dynamic sched domains.
+ *
+ * The rebuild_sched_domains() and partition_sched_domains()
+ * routines must nest cgroup_lock() inside get_online_cpus(),
+ * but such cpuset changes as these must nest that locking the
+ * other way, holding cgroup_lock() for much of the code.
+ *
+ * So in order to avoid an ABBA deadlock, the cpuset code handling
+ * these user changes delegates the actual sched domain rebuilding
+ * to a separate workqueue thread, which ends up processing the
+ * above do_rebuild_sched_domains() function.
+ */
+static void async_rebuild_sched_domains(void)
+{
+       schedule_work(&rebuild_sched_domains_work);
+}
+
+/*
+ * Accomplishes the same scheduler domain rebuild as the above
+ * async_rebuild_sched_domains(), however it directly calls the
+ * rebuild routine synchronously rather than calling it via an
+ * asynchronous work thread.
+ *
+ * This can only be called from code that is not holding
+ * cgroup_mutex (not nested in a cgroup_lock() call.)
+ */
+void rebuild_sched_domains(void)
+{
+       do_rebuild_sched_domains(NULL);
 }
 
 /**
@@ -863,7 +932,7 @@ static int update_cpumask(struct cpuset *cs, const char *buf)
                return retval;
 
        if (is_load_balanced)
-               rebuild_sched_domains();
+               async_rebuild_sched_domains();
        return 0;
 }
 
@@ -1090,7 +1159,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
        if (val != cs->relax_domain_level) {
                cs->relax_domain_level = val;
                if (!cpus_empty(cs->cpus_allowed) && is_sched_load_balance(cs))
-                       rebuild_sched_domains();
+                       async_rebuild_sched_domains();
        }
 
        return 0;
@@ -1131,7 +1200,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
        mutex_unlock(&callback_mutex);
 
        if (cpus_nonempty && balance_flag_changed)
-               rebuild_sched_domains();
+               async_rebuild_sched_domains();
 
        return 0;
 }
@@ -1492,6 +1561,9 @@ static u64 cpuset_read_u64(struct cgroup *cont, struct cftype *cft)
        default:
                BUG();
        }
+
+       /* Unreachable but makes gcc happy */
+       return 0;
 }
 
 static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft)
@@ -1504,6 +1576,9 @@ static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft)
        default:
                BUG();
        }
+
+       /* Unrechable but makes gcc happy */
+       return 0;
 }
 
 
@@ -1692,15 +1767,9 @@ static struct cgroup_subsys_state *cpuset_create(
 }
 
 /*
- * Locking note on the strange update_flag() call below:
- *
  * If the cpuset being removed has its flag 'sched_load_balance'
  * enabled, then simulate turning sched_load_balance off, which
- * will call rebuild_sched_domains().  The get_online_cpus()
- * call in rebuild_sched_domains() must not be made while holding
- * callback_mutex.  Elsewhere the kernel nests callback_mutex inside
- * get_online_cpus() calls.  So the reverse nesting would risk an
- * ABBA deadlock.
+ * will call async_rebuild_sched_domains().
  */
 
 static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
@@ -1719,7 +1788,7 @@ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
 struct cgroup_subsys cpuset_subsys = {
        .name = "cpuset",
        .create = cpuset_create,
-       .destroy  = cpuset_destroy,
+       .destroy = cpuset_destroy,
        .can_attach = cpuset_can_attach,
        .attach = cpuset_attach,
        .populate = cpuset_populate,
@@ -1811,7 +1880,7 @@ static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to)
 }
 
 /*
- * If common_cpu_mem_hotplug_unplug(), below, unplugs any CPUs
+ * If CPU and/or memory hotplug handlers, below, unplug any CPUs
  * or memory nodes, we need to walk over the cpuset hierarchy,
  * removing that CPU or node from all cpusets.  If this removes the
  * last CPU or node from a cpuset, then move the tasks in the empty
@@ -1902,35 +1971,6 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
        }
 }
 
-/*
- * The cpus_allowed and mems_allowed nodemasks in the top_cpuset track
- * cpu_online_map and node_states[N_HIGH_MEMORY].  Force the top cpuset to
- * track what's online after any CPU or memory node hotplug or unplug event.
- *
- * Since there are two callers of this routine, one for CPU hotplug
- * events and one for memory node hotplug events, we could have coded
- * two separate routines here.  We code it as a single common routine
- * in order to minimize text size.
- */
-
-static void common_cpu_mem_hotplug_unplug(int rebuild_sd)
-{
-       cgroup_lock();
-
-       top_cpuset.cpus_allowed = cpu_online_map;
-       top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
-       scan_for_empty_cpusets(&top_cpuset);
-
-       /*
-        * Scheduler destroys domains on hotplug events.
-        * Rebuild them based on the current settings.
-        */
-       if (rebuild_sd)
-               rebuild_sched_domains();
-
-       cgroup_unlock();
-}
-
 /*
  * The top_cpuset tracks what CPUs and Memory Nodes are online,
  * period.  This is necessary in order to make cpusets transparent
@@ -1939,40 +1979,52 @@ static void common_cpu_mem_hotplug_unplug(int rebuild_sd)
  *
  * This routine ensures that top_cpuset.cpus_allowed tracks
  * cpu_online_map on each CPU hotplug (cpuhp) event.
+ *
+ * Called within get_online_cpus().  Needs to call cgroup_lock()
+ * before calling generate_sched_domains().
  */
-
-static int cpuset_handle_cpuhp(struct notifier_block *unused_nb,
+static int cpuset_track_online_cpus(struct notifier_block *unused_nb,
                                unsigned long phase, void *unused_cpu)
 {
+       struct sched_domain_attr *attr;
+       cpumask_t *doms;
+       int ndoms;
+
        switch (phase) {
-       case CPU_UP_CANCELED:
-       case CPU_UP_CANCELED_FROZEN:
-       case CPU_DOWN_FAILED:
-       case CPU_DOWN_FAILED_FROZEN:
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-               common_cpu_mem_hotplug_unplug(1);
                break;
+
        default:
                return NOTIFY_DONE;
        }
 
+       cgroup_lock();
+       top_cpuset.cpus_allowed = cpu_online_map;
+       scan_for_empty_cpusets(&top_cpuset);
+       ndoms = generate_sched_domains(&doms, &attr);
+       cgroup_unlock();
+
+       /* Have scheduler rebuild the domains */
+       partition_sched_domains(ndoms, doms, attr);
+
        return NOTIFY_OK;
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
- * Call this routine anytime after you change
- * node_states[N_HIGH_MEMORY].
- * See also the previous routine cpuset_handle_cpuhp().
+ * Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
+ * See also the previous routine cpuset_track_online_cpus().
  */
-
 void cpuset_track_online_nodes(void)
 {
-       common_cpu_mem_hotplug_unplug(0);
+       cgroup_lock();
+       top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+       scan_for_empty_cpusets(&top_cpuset);
+       cgroup_unlock();
 }
 #endif
 
@@ -1987,7 +2039,7 @@ void __init cpuset_init_smp(void)
        top_cpuset.cpus_allowed = cpu_online_map;
        top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
 
-       hotcpu_notifier(cpuset_handle_cpuhp, 0);
+       hotcpu_notifier(cpuset_track_online_cpus, 0);
 }
 
 /**
index 75c6473876394f7a1956908fe0bb423f5e5536f7..16395644a98ff8c060b2f5fd776fe7abadd61c6a 100644 (file)
@@ -112,9 +112,9 @@ static void __exit_signal(struct task_struct *tsk)
                 * We won't ever get here for the group leader, since it
                 * will have been the last reference on the signal_struct.
                 */
-               sig->utime = cputime_add(sig->utime, tsk->utime);
-               sig->stime = cputime_add(sig->stime, tsk->stime);
-               sig->gtime = cputime_add(sig->gtime, tsk->gtime);
+               sig->utime = cputime_add(sig->utime, task_utime(tsk));
+               sig->stime = cputime_add(sig->stime, task_stime(tsk));
+               sig->gtime = cputime_add(sig->gtime, task_gtime(tsk));
                sig->min_flt += tsk->min_flt;
                sig->maj_flt += tsk->maj_flt;
                sig->nvcsw += tsk->nvcsw;
@@ -831,26 +831,50 @@ static void reparent_thread(struct task_struct *p, struct task_struct *father)
  * the child reaper process (ie "init") in our pid
  * space.
  */
+static struct task_struct *find_new_reaper(struct task_struct *father)
+{
+       struct pid_namespace *pid_ns = task_active_pid_ns(father);
+       struct task_struct *thread;
+
+       thread = father;
+       while_each_thread(father, thread) {
+               if (thread->flags & PF_EXITING)
+                       continue;
+               if (unlikely(pid_ns->child_reaper == father))
+                       pid_ns->child_reaper = thread;
+               return thread;
+       }
+
+       if (unlikely(pid_ns->child_reaper == father)) {
+               write_unlock_irq(&tasklist_lock);
+               if (unlikely(pid_ns == &init_pid_ns))
+                       panic("Attempted to kill init!");
+
+               zap_pid_ns_processes(pid_ns);
+               write_lock_irq(&tasklist_lock);
+               /*
+                * We can not clear ->child_reaper or leave it alone.
+                * There may by stealth EXIT_DEAD tasks on ->children,
+                * forget_original_parent() must move them somewhere.
+                */
+               pid_ns->child_reaper = init_pid_ns.child_reaper;
+       }
+
+       return pid_ns->child_reaper;
+}
+
 static void forget_original_parent(struct task_struct *father)
 {
-       struct task_struct *p, *n, *reaper = father;
+       struct task_struct *p, *n, *reaper;
        LIST_HEAD(ptrace_dead);
 
        write_lock_irq(&tasklist_lock);
-
+       reaper = find_new_reaper(father);
        /*
         * First clean up ptrace if we were using it.
         */
        ptrace_exit(father, &ptrace_dead);
 
-       do {
-               reaper = next_thread(reaper);
-               if (reaper == father) {
-                       reaper = task_child_reaper(father);
-                       break;
-               }
-       } while (reaper->flags & PF_EXITING);
-
        list_for_each_entry_safe(p, n, &father->children, sibling) {
                p->real_parent = reaper;
                if (p->parent == father) {
@@ -959,39 +983,6 @@ static void check_stack_usage(void)
 static inline void check_stack_usage(void) {}
 #endif
 
-static inline void exit_child_reaper(struct task_struct *tsk)
-{
-       if (likely(tsk->group_leader != task_child_reaper(tsk)))
-               return;
-
-       if (tsk->nsproxy->pid_ns == &init_pid_ns)
-               panic("Attempted to kill init!");
-
-       /*
-        * @tsk is the last thread in the 'cgroup-init' and is exiting.
-        * Terminate all remaining processes in the namespace and reap them
-        * before exiting @tsk.
-        *
-        * Note that @tsk (last thread of cgroup-init) may not necessarily
-        * be the child-reaper (i.e main thread of cgroup-init) of the
-        * namespace i.e the child_reaper may have already exited.
-        *
-        * Even after a child_reaper exits, we let it inherit orphaned children,
-        * because, pid_ns->child_reaper remains valid as long as there is
-        * at least one living sub-thread in the cgroup init.
-
-        * This living sub-thread of the cgroup-init will be notified when
-        * a child inherited by the 'child-reaper' exits (do_notify_parent()
-        * uses __group_send_sig_info()). Further, when reaping child processes,
-        * do_wait() iterates over children of all living sub threads.
-
-        * i.e even though 'child_reaper' thread is listed as the parent of the
-        * orphaned children, any living sub-thread in the cgroup-init can
-        * perform the role of the child_reaper.
-        */
-       zap_pid_ns_processes(tsk->nsproxy->pid_ns);
-}
-
 NORET_TYPE void do_exit(long code)
 {
        struct task_struct *tsk = current;
@@ -1051,7 +1042,6 @@ NORET_TYPE void do_exit(long code)
        }
        group_dead = atomic_dec_and_test(&tsk->signal->live);
        if (group_dead) {
-               exit_child_reaper(tsk);
                hrtimer_cancel(&tsk->signal->real_timer);
                exit_itimers(tsk->signal);
        }
index ea567b78d1aa6111bf207ac0556ff1e35b088794..fab8ea86fac3f44156b0e3c50c00404080073da6 100644 (file)
@@ -179,9 +179,6 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
                rc = sys_wait4(-1, NULL, __WALL, NULL);
        } while (rc != -ECHILD);
 
-
-       /* Child reaper for the pid namespace is going away */
-       pid_ns->child_reaper = NULL;
        acct_exit_ns(pid_ns);
        return;
 }
index da9c2dda6a4e8ea8330841aee41851c022ab95ef..dfdec524d1b7dc9de49380d6d4552dd71add9a7a 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/uaccess.h>
 
 /*
- * locking rule: all changes to target_value or requirements or notifiers lists
+ * locking rule: all changes to requirements or notifiers lists
  * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
  * held, taken with _irqsave.  One lock to rule them all
  */
@@ -66,7 +66,7 @@ struct pm_qos_object {
        struct miscdevice pm_qos_power_miscdev;
        char *name;
        s32 default_value;
-       s32 target_value;
+       atomic_t target_value;
        s32 (*comparitor)(s32, s32);
 };
 
@@ -77,7 +77,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
        .notifiers = &cpu_dma_lat_notifier,
        .name = "cpu_dma_latency",
        .default_value = 2000 * USEC_PER_SEC,
-       .target_value = 2000 * USEC_PER_SEC,
+       .target_value = ATOMIC_INIT(2000 * USEC_PER_SEC),
        .comparitor = min_compare
 };
 
@@ -87,7 +87,7 @@ static struct pm_qos_object network_lat_pm_qos = {
        .notifiers = &network_lat_notifier,
        .name = "network_latency",
        .default_value = 2000 * USEC_PER_SEC,
-       .target_value = 2000 * USEC_PER_SEC,
+       .target_value = ATOMIC_INIT(2000 * USEC_PER_SEC),
        .comparitor = min_compare
 };
 
@@ -99,7 +99,7 @@ static struct pm_qos_object network_throughput_pm_qos = {
        .notifiers = &network_throughput_notifier,
        .name = "network_throughput",
        .default_value = 0,
-       .target_value = 0,
+       .target_value = ATOMIC_INIT(0),
        .comparitor = max_compare
 };
 
@@ -150,11 +150,11 @@ static void update_target(int target)
                extreme_value = pm_qos_array[target]->comparitor(
                                extreme_value, node->value);
        }
-       if (pm_qos_array[target]->target_value != extreme_value) {
+       if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
                call_notifier = 1;
-               pm_qos_array[target]->target_value = extreme_value;
+               atomic_set(&pm_qos_array[target]->target_value, extreme_value);
                pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
-                       pm_qos_array[target]->target_value);
+                       atomic_read(&pm_qos_array[target]->target_value));
        }
        spin_unlock_irqrestore(&pm_qos_lock, flags);
 
@@ -193,14 +193,7 @@ static int find_pm_qos_object_by_minor(int minor)
  */
 int pm_qos_requirement(int pm_qos_class)
 {
-       int ret_val;
-       unsigned long flags;
-
-       spin_lock_irqsave(&pm_qos_lock, flags);
-       ret_val = pm_qos_array[pm_qos_class]->target_value;
-       spin_unlock_irqrestore(&pm_qos_lock, flags);
-
-       return ret_val;
+       return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
 }
 EXPORT_SYMBOL_GPL(pm_qos_requirement);
 
index cf0a178c751345f0c8358b066fa937d379adc777..03d796c1b2e980c1ea55c5f1dc3bbfed64b0233e 100644 (file)
@@ -438,7 +438,7 @@ int insert_resource(struct resource *parent, struct resource *new)
 
 /**
  * insert_resource_expand_to_fit - Insert a resource into the resource tree
- * @parent: parent of the new resource
+ * @root: root resource descriptor
  * @new: new resource to insert
  *
  * Insert a resource into the resource tree, possibly expanding it in order
index 9a1ddb84e26d56e7d6b283daab1edbad20ae2042..cc1f81b50b82dddb19658dc4d10dd419087a59fc 100644 (file)
@@ -4178,6 +4178,65 @@ void account_steal_time(struct task_struct *p, cputime_t steal)
                cpustat->steal = cputime64_add(cpustat->steal, tmp);
 }
 
+/*
+ * Use precise platform statistics if available:
+ */
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+cputime_t task_utime(struct task_struct *p)
+{
+       return p->utime;
+}
+
+cputime_t task_stime(struct task_struct *p)
+{
+       return p->stime;
+}
+#else
+cputime_t task_utime(struct task_struct *p)
+{
+       clock_t utime = cputime_to_clock_t(p->utime),
+               total = utime + cputime_to_clock_t(p->stime);
+       u64 temp;
+
+       /*
+        * Use CFS's precise accounting:
+        */
+       temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
+
+       if (total) {
+               temp *= utime;
+               do_div(temp, total);
+       }
+       utime = (clock_t)temp;
+
+       p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime));
+       return p->prev_utime;
+}
+
+cputime_t task_stime(struct task_struct *p)
+{
+       clock_t stime;
+
+       /*
+        * Use CFS's precise accounting. (we subtract utime from
+        * the total, to make sure the total observed by userspace
+        * grows monotonically - apps rely on that):
+        */
+       stime = nsec_to_clock_t(p->se.sum_exec_runtime) -
+                       cputime_to_clock_t(task_utime(p));
+
+       if (stime >= 0)
+               p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime));
+
+       return p->prev_stime;
+}
+#endif
+
+inline cputime_t task_gtime(struct task_struct *p)
+{
+       return p->gtime;
+}
+
 /*
  * This function gets called by the timer code, with HZ frequency.
  * We call it with interrupts disabled.
@@ -7637,24 +7696,27 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
  * and partition_sched_domains() will fallback to the single partition
  * 'fallback_doms', it also forces the domains to be rebuilt.
  *
+ * If doms_new==NULL it will be replaced with cpu_online_map.
+ * ndoms_new==0 is a special case for destroying existing domains.
+ * It will not create the default domain.
+ *
  * Call with hotplug lock held
  */
 void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
                             struct sched_domain_attr *dattr_new)
 {
-       int i, j;
+       int i, j, n;
 
        mutex_lock(&sched_domains_mutex);
 
        /* always unregister in case we don't destroy any domains */
        unregister_sched_domain_sysctl();
 
-       if (doms_new == NULL)
-               ndoms_new = 0;
+       n = doms_new ? ndoms_new : 0;
 
        /* Destroy deleted domains */
        for (i = 0; i < ndoms_cur; i++) {
-               for (j = 0; j < ndoms_new; j++) {
+               for (j = 0; j < n; j++) {
                        if (cpus_equal(doms_cur[i], doms_new[j])
                            && dattrs_equal(dattr_cur, i, dattr_new, j))
                                goto match1;
@@ -7667,7 +7729,6 @@ match1:
 
        if (doms_new == NULL) {
                ndoms_cur = 0;
-               ndoms_new = 1;
                doms_new = &fallback_doms;
                cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
                dattr_new = NULL;
@@ -7704,8 +7765,13 @@ match2:
 int arch_reinit_sched_domains(void)
 {
        get_online_cpus();
+
+       /* Destroy domains first to force the rebuild */
+       partition_sched_domains(0, NULL, NULL);
+
        rebuild_sched_domains();
        put_online_cpus();
+
        return 0;
 }
 
@@ -7789,7 +7855,7 @@ static int update_sched_domains(struct notifier_block *nfb,
        case CPU_ONLINE_FROZEN:
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-               partition_sched_domains(0, NULL, NULL);
+               partition_sched_domains(1, NULL, NULL);
                return NOTIFY_OK;
 
        default:
index 1a07f8ca4b923e99c76824a1d585da26a0c53d7d..cb838ee93a82000bc5b313271487836e9fb5804e 100644 (file)
@@ -180,10 +180,6 @@ static void check_hung_task(struct task_struct *t, unsigned long now)
        if (t->flags & PF_FROZEN)
                return;
 
-       /* Don't check for tasks waiting on network file systems like NFS */
-       if (t->state & TASK_KILLABLE)
-               return;
-
        if (switch_count != t->last_switch_count || !t->last_switch_timestamp) {
                t->last_switch_count = switch_count;
                t->last_switch_timestamp = now;
@@ -237,7 +233,8 @@ static void check_hung_uninterruptible_tasks(int this_cpu)
        do_each_thread(g, t) {
                if (!--max_count)
                        goto unlock;
-               if (t->state & TASK_UNINTERRUPTIBLE)
+               /* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */
+               if (t->state == TASK_UNINTERRUPTIBLE)
                        check_hung_task(t, now);
        } while_each_thread(g, t);
  unlock:
index fe47133472758853b039c47ac9390e5eadd34bed..50ec0886fa3d355d696e9992a9057ce11a721525 100644 (file)
@@ -159,6 +159,7 @@ static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *
 static struct ctl_table root_table[];
 static struct ctl_table_root sysctl_table_root;
 static struct ctl_table_header root_table_header = {
+       .count = 1,
        .ctl_table = root_table,
        .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),
        .root = &sysctl_table_root,
index 3d1e3e1a19716e94cdad4116b1ca73242ac45f1e..1876b526c7783db17d4dd5050a899e640670ef59 100644 (file)
@@ -177,7 +177,7 @@ void clockevents_register_device(struct clock_event_device *dev)
 /*
  * Noop handler when we shut down an event device
  */
-static void clockevents_handle_noop(struct clock_event_device *dev)
+void clockevents_handle_noop(struct clock_event_device *dev)
 {
 }
 
@@ -199,7 +199,6 @@ void clockevents_exchange_device(struct clock_event_device *old,
         * released list and do a notify add later.
         */
        if (old) {
-               old->event_handler = clockevents_handle_noop;
                clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
                list_del(&old->list);
                list_add(&old->list, &clockevents_released);
index 5125ddd8196ba3cffb2fd683c2fd3abdac0a695b..1ad46f3df6e76cd8994403b1c1ca72c14ec3553b 100644 (file)
@@ -245,7 +245,7 @@ static void sync_cmos_clock(unsigned long dummy)
        if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
                fail = update_persistent_clock(now);
 
-       next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;
+       next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);
        if (next.tv_nsec <= 0)
                next.tv_nsec += NSEC_PER_SEC;
 
index 31463d370b944ff37919d184a125e7efc1bf563a..2f5a38294bf9ffc8639a5e623760c5242e96629b 100644 (file)
@@ -175,6 +175,8 @@ static void tick_do_periodic_broadcast(void)
  */
 static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
 {
+       ktime_t next;
+
        tick_do_periodic_broadcast();
 
        /*
@@ -185,10 +187,13 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
 
        /*
         * Setup the next period for devices, which do not have
-        * periodic mode:
+        * periodic mode. We read dev->next_event first and add to it
+        * when the event alrady expired. clockevents_program_event()
+        * sets dev->next_event only when the event is really
+        * programmed to the device.
         */
-       for (;;) {
-               ktime_t next = ktime_add(dev->next_event, tick_period);
+       for (next = dev->next_event; ;) {
+               next = ktime_add(next, tick_period);
 
                if (!clockevents_program_event(dev, next, ktime_get()))
                        return;
@@ -205,7 +210,7 @@ static void tick_do_broadcast_on_off(void *why)
        struct clock_event_device *bc, *dev;
        struct tick_device *td;
        unsigned long flags, *reason = why;
-       int cpu;
+       int cpu, bc_stopped;
 
        spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -223,6 +228,8 @@ static void tick_do_broadcast_on_off(void *why)
        if (!tick_device_is_functional(dev))
                goto out;
 
+       bc_stopped = cpus_empty(tick_broadcast_mask);
+
        switch (*reason) {
        case CLOCK_EVT_NOTIFY_BROADCAST_ON:
        case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
@@ -245,9 +252,10 @@ static void tick_do_broadcast_on_off(void *why)
                break;
        }
 
-       if (cpus_empty(tick_broadcast_mask))
-               clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
-       else {
+       if (cpus_empty(tick_broadcast_mask)) {
+               if (!bc_stopped)
+                       clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+       } else if (bc_stopped) {
                if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
                        tick_broadcast_start_periodic(bc);
                else
@@ -364,16 +372,8 @@ cpumask_t *tick_get_broadcast_oneshot_mask(void)
 static int tick_broadcast_set_event(ktime_t expires, int force)
 {
        struct clock_event_device *bc = tick_broadcast_device.evtdev;
-       ktime_t now = ktime_get();
-       int res;
-
-       for(;;) {
-               res = clockevents_program_event(bc, expires, now);
-               if (!res || !force)
-                       return res;
-               now = ktime_get();
-               expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
-       }
+
+       return tick_dev_program_event(bc, expires, force);
 }
 
 int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
@@ -491,14 +491,52 @@ static void tick_broadcast_clear_oneshot(int cpu)
        cpu_clear(cpu, tick_broadcast_oneshot_mask);
 }
 
+static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
+{
+       struct tick_device *td;
+       int cpu;
+
+       for_each_cpu_mask_nr(cpu, *mask) {
+               td = &per_cpu(tick_cpu_device, cpu);
+               if (td->evtdev)
+                       td->evtdev->next_event = expires;
+       }
+}
+
 /**
  * tick_broadcast_setup_oneshot - setup the broadcast device
  */
 void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
-       bc->event_handler = tick_handle_oneshot_broadcast;
-       clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-       bc->next_event.tv64 = KTIME_MAX;
+       /* Set it up only once ! */
+       if (bc->event_handler != tick_handle_oneshot_broadcast) {
+               int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
+               int cpu = smp_processor_id();
+               cpumask_t mask;
+
+               bc->event_handler = tick_handle_oneshot_broadcast;
+               clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+
+               /* Take the do_timer update */
+               tick_do_timer_cpu = cpu;
+
+               /*
+                * We must be careful here. There might be other CPUs
+                * waiting for periodic broadcast. We need to set the
+                * oneshot_mask bits for those and program the
+                * broadcast device to fire.
+                */
+               mask = tick_broadcast_mask;
+               cpu_clear(cpu, mask);
+               cpus_or(tick_broadcast_oneshot_mask,
+                       tick_broadcast_oneshot_mask, mask);
+
+               if (was_periodic && !cpus_empty(mask)) {
+                       tick_broadcast_init_next_event(&mask, tick_next_period);
+                       tick_broadcast_set_event(tick_next_period, 1);
+               } else
+                       bc->next_event.tv64 = KTIME_MAX;
+       }
 }
 
 /*
index 80c4336f4188409a077d3f4ae4dde727f856de55..c4777193d56734d0276aa210ddbbad2e79c416c8 100644 (file)
@@ -161,6 +161,7 @@ static void tick_setup_device(struct tick_device *td,
        } else {
                handler = td->evtdev->event_handler;
                next_event = td->evtdev->next_event;
+               td->evtdev->event_handler = clockevents_handle_noop;
        }
 
        td->evtdev = newdev;
index f13f2b7f4fd46bda983d7138edce267b1a9e0c91..0ffc2918ea6fb8365523ad0a63266cd68628b65f 100644 (file)
@@ -17,6 +17,8 @@ extern void tick_handle_periodic(struct clock_event_device *dev);
 extern void tick_setup_oneshot(struct clock_event_device *newdev,
                               void (*handler)(struct clock_event_device *),
                               ktime_t nextevt);
+extern int tick_dev_program_event(struct clock_event_device *dev,
+                                 ktime_t expires, int force);
 extern int tick_program_event(ktime_t expires, int force);
 extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
index 450c04935b66b050e35671d821c5f190b394414f..2e8de678e767a76d444c822307b7bd34baff67c5 100644 (file)
 #include "tick-internal.h"
 
 /**
- * tick_program_event
+ * tick_program_event internal worker function
  */
-int tick_program_event(ktime_t expires, int force)
+int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires,
+                          int force)
 {
-       struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
        ktime_t now = ktime_get();
+       int i;
 
-       while (1) {
+       for (i = 0;;) {
                int ret = clockevents_program_event(dev, expires, now);
 
                if (!ret || !force)
                        return ret;
+
+               /*
+                * We tried 2 times to program the device with the given
+                * min_delta_ns. If that's not working then we double it
+                * and emit a warning.
+                */
+               if (++i > 2) {
+                       /* Increase the min. delta and try again */
+                       if (!dev->min_delta_ns)
+                               dev->min_delta_ns = 5000;
+                       else
+                               dev->min_delta_ns += dev->min_delta_ns >> 1;
+
+                       printk(KERN_WARNING
+                              "CE: %s increasing min_delta_ns to %lu nsec\n",
+                              dev->name ? dev->name : "?",
+                              dev->min_delta_ns << 1);
+
+                       i = 0;
+               }
+
                now = ktime_get();
-               expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
+               expires = ktime_add_ns(now, dev->min_delta_ns);
        }
 }
 
+/**
+ * tick_program_event
+ */
+int tick_program_event(ktime_t expires, int force)
+{
+       struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+
+       return tick_dev_program_event(dev, expires, force);
+}
+
 /**
  * tick_resume_onshot - resume oneshot mode
  */
@@ -61,7 +93,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev,
 {
        newdev->event_handler = handler;
        clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
-       clockevents_program_event(newdev, next_event, ktime_get());
+       tick_dev_program_event(newdev, next_event, 1);
 }
 
 /**
index 7a46bde78c66f77e15ba75f8e570e4c46de274de..a87b0468568b026d90683bde0b2e9da0295c7caa 100644 (file)
@@ -162,6 +162,8 @@ void tick_nohz_stop_idle(int cpu)
                ts->idle_lastupdate = now;
                ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
                ts->idle_active = 0;
+
+               sched_clock_idle_wakeup_event(0);
        }
 }
 
@@ -177,6 +179,7 @@ static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
        }
        ts->idle_entrytime = now;
        ts->idle_active = 1;
+       sched_clock_idle_sleep_event();
        return now;
 }
 
index 8b5a7d304a5f5709cfb97436396916fc074db428..0b504814e378067ff120b266e5b26c9fdd6fb90e 100644 (file)
@@ -394,7 +394,7 @@ config LOCKDEP
        bool
        depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
        select STACKTRACE
-       select FRAME_POINTER if !X86 && !MIPS
+       select FRAME_POINTER if !X86 && !MIPS && !PPC
        select KALLSYMS
        select KALLSYMS_ALL
 
@@ -676,13 +676,13 @@ config FAULT_INJECTION_STACKTRACE_FILTER
        depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
        depends on !X86_64
        select STACKTRACE
-       select FRAME_POINTER
+       select FRAME_POINTER if !PPC
        help
          Provide stacktrace filter for fault-injection capabilities
 
 config LATENCYTOP
        bool "Latency measuring infrastructure"
-       select FRAME_POINTER if !MIPS
+       select FRAME_POINTER if !MIPS && !PPC
        select KALLSYMS
        select KALLSYMS_ALL
        select STACKTRACE
index 45a6bde762d12232fab2c1f422e398625bb35e37..e3ab374e1334ab80fc172c3d256d2eb4fddd665e 100644 (file)
@@ -112,6 +112,7 @@ static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b)
 
 /*
  * Allocate a new object. If the pool is empty, switch off the debugger.
+ * Must be called with interrupts disabled.
  */
 static struct debug_obj *
 alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
@@ -148,17 +149,18 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
 static void free_object(struct debug_obj *obj)
 {
        unsigned long idx = (unsigned long)(obj - obj_static_pool);
+       unsigned long flags;
 
        if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) {
-               spin_lock(&pool_lock);
+               spin_lock_irqsave(&pool_lock, flags);
                hlist_add_head(&obj->node, &obj_pool);
                obj_pool_free++;
                obj_pool_used--;
-               spin_unlock(&pool_lock);
+               spin_unlock_irqrestore(&pool_lock, flags);
        } else {
-               spin_lock(&pool_lock);
+               spin_lock_irqsave(&pool_lock, flags);
                obj_pool_used--;
-               spin_unlock(&pool_lock);
+               spin_unlock_irqrestore(&pool_lock, flags);
                kmem_cache_free(obj_cache, obj);
        }
 }
@@ -171,6 +173,7 @@ static void debug_objects_oom(void)
 {
        struct debug_bucket *db = obj_hash;
        struct hlist_node *node, *tmp;
+       HLIST_HEAD(freelist);
        struct debug_obj *obj;
        unsigned long flags;
        int i;
@@ -179,11 +182,14 @@ static void debug_objects_oom(void)
 
        for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {
                spin_lock_irqsave(&db->lock, flags);
-               hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) {
+               hlist_move_list(&db->list, &freelist);
+               spin_unlock_irqrestore(&db->lock, flags);
+
+               /* Now free them */
+               hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) {
                        hlist_del(&obj->node);
                        free_object(obj);
                }
-               spin_unlock_irqrestore(&db->lock, flags);
        }
 }
 
@@ -498,8 +504,9 @@ void debug_object_free(void *addr, struct debug_obj_descr *descr)
                return;
        default:
                hlist_del(&obj->node);
+               spin_unlock_irqrestore(&db->lock, flags);
                free_object(obj);
-               break;
+               return;
        }
 out_unlock:
        spin_unlock_irqrestore(&db->lock, flags);
@@ -510,6 +517,7 @@ static void __debug_check_no_obj_freed(const void *address, unsigned long size)
 {
        unsigned long flags, oaddr, saddr, eaddr, paddr, chunks;
        struct hlist_node *node, *tmp;
+       HLIST_HEAD(freelist);
        struct debug_obj_descr *descr;
        enum debug_obj_state state;
        struct debug_bucket *db;
@@ -545,11 +553,18 @@ repeat:
                                goto repeat;
                        default:
                                hlist_del(&obj->node);
-                               free_object(obj);
+                               hlist_add_head(&obj->node, &freelist);
                                break;
                        }
                }
                spin_unlock_irqrestore(&db->lock, flags);
+
+               /* Now free them */
+               hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) {
+                       hlist_del(&obj->node);
+                       free_object(obj);
+               }
+
                if (cnt > debug_objects_maxchain)
                        debug_objects_maxchain = cnt;
        }
index d8d1d1142248a511561b401a87b1590a5f94ba33..c399bc1093cbedb276f3e974353534560197e940 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/div64.h>
+#include <asm/sections.h>      /* for dereference_function_descriptor() */
 
 /* Works only for digits and letters, but small and fast */
 #define TOLOWER(x) ((x) | 0x20)
@@ -513,16 +514,6 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio
        return buf;
 }
 
-static inline void *dereference_function_descriptor(void *ptr)
-{
-#if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
-       void *p;
-       if (!probe_kernel_address(ptr, p))
-               ptr = p;
-#endif
-       return ptr;
-}
-
 static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags)
 {
        unsigned long value = (unsigned long) ptr;
index 54e9686508550b198b4779df048bbfe46b2ddb08..876bc595d0f8b3b3e4f626bf1ad7acbb657bdc66 100644 (file)
@@ -2129,13 +2129,20 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
         * After a write we want buffered reads to be sure to go to disk to get
         * the new data.  We invalidate clean cached page from the region we're
         * about to write.  We do this *before* the write so that we can return
-        * -EIO without clobbering -EIOCBQUEUED from ->direct_IO().
+        * without clobbering -EIOCBQUEUED from ->direct_IO().
         */
        if (mapping->nrpages) {
                written = invalidate_inode_pages2_range(mapping,
                                        pos >> PAGE_CACHE_SHIFT, end);
-               if (written)
+               /*
+                * If a page can not be invalidated, return 0 to fall back
+                * to buffered write.
+                */
+               if (written) {
+                       if (written == -EBUSY)
+                               return 0;
                        goto out;
+               }
        }
 
        written = mapping->a_ops->direct_IO(WRITE, iocb, iov, pos, *nr_segs);
index 339cf5c4d5d8c3a82b04cf57fa6b973f5ad75408..e7a5a68a9c2e4ef0b477aba5850a7299bc410aab 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1030,6 +1030,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
        } else {
                switch (flags & MAP_TYPE) {
                case MAP_SHARED:
+                       /*
+                        * Ignore pgoff.
+                        */
+                       pgoff = 0;
                        vm_flags |= VM_SHARED | VM_MAYSHARE;
                        break;
                case MAP_PRIVATE:
index af982f7cdb2a8d409315f8fd95b140277e62c3af..e293c58bea58fc2195da7f34d95417262cedeffa 100644 (file)
@@ -694,6 +694,9 @@ static int move_freepages(struct zone *zone,
 #endif
 
        for (page = start_page; page <= end_page;) {
+               /* Make sure we are not inadvertently changing nodes */
+               VM_BUG_ON(page_to_nid(page) != zone_to_nid(zone));
+
                if (!pfn_valid_within(page_to_pfn(page))) {
                        page++;
                        continue;
@@ -2516,6 +2519,10 @@ static void setup_zone_migrate_reserve(struct zone *zone)
                        continue;
                page = pfn_to_page(pfn);
 
+               /* Watch out for overlapping nodes */
+               if (page_to_nid(page) != zone_to_nid(zone))
+                       continue;
+
                /* Blocks with reserved pages will never free, skip them. */
                if (PageReserved(page))
                        continue;
@@ -4064,7 +4071,7 @@ void __init set_dma_reserve(unsigned long new_dma_reserve)
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-struct pglist_data contig_page_data = { .bdata = &bootmem_node_data[0] };
+struct pglist_data __refdata contig_page_data = { .bdata = &bootmem_node_data[0] };
 EXPORT_SYMBOL(contig_page_data);
 #endif
 
index 3444b58033c87e4263c1d2f1db79f8f416580a29..c69f84fe038d8b725b8639aae0fd88151206b515 100644 (file)
@@ -2,7 +2,6 @@
  * linux/mm/page_isolation.c
  */
 
-#include <stddef.h>
 #include <linux/mm.h>
 #include <linux/page-isolation.h>
 #include <linux/pageblock-flags.h>
index 3f703f7cb398056547af212577909a3d6c46b116..8dbb6805ef35a91af20a8aeb7090090e044d86e9 100644 (file)
@@ -26,7 +26,10 @@ DEFINE_PER_CPU(struct quicklist, quicklist)[CONFIG_NR_QUICK];
 static unsigned long max_pages(unsigned long min_pages)
 {
        unsigned long node_free_pages, max;
-       struct zone *zones = NODE_DATA(numa_node_id())->node_zones;
+       int node = numa_node_id();
+       struct zone *zones = NODE_DATA(node)->node_zones;
+       int num_cpus_on_node;
+       node_to_cpumask_ptr(cpumask_on_node, node);
 
        node_free_pages =
 #ifdef CONFIG_ZONE_DMA
@@ -38,6 +41,10 @@ static unsigned long max_pages(unsigned long min_pages)
                zone_page_state(&zones[ZONE_NORMAL], NR_FREE_PAGES);
 
        max = node_free_pages / FRACTION_OF_NODE_MEM;
+
+       num_cpus_on_node = cpus_weight_nr(*cpumask_on_node);
+       max /= num_cpus_on_node;
+
        return max(max, min_pages);
 }
 
index 250505091d3773e67449c547a0b16f8c67680257..6650c1d878b463a114e0e024688ecdc1d0fa6b74 100644 (file)
@@ -380,7 +380,7 @@ static int do_launder_page(struct address_space *mapping, struct page *page)
  * Any pages which are found to be mapped into pagetables are unmapped prior to
  * invalidation.
  *
- * Returns -EIO if any pages could not be invalidated.
+ * Returns -EBUSY if any pages could not be invalidated.
  */
 int invalidate_inode_pages2_range(struct address_space *mapping,
                                  pgoff_t start, pgoff_t end)
@@ -440,7 +440,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
                        ret2 = do_launder_page(mapping, page);
                        if (ret2 == 0) {
                                if (!invalidate_complete_page2(mapping, page))
-                                       ret2 = -EIO;
+                                       ret2 = -EBUSY;
                        }
                        if (ret2 < 0)
                                ret = ret2;
index 1edfdf4c095ba085ebe134eb6a3ee00d23128f1d..f6348e078aa434077bf26c57ffb8f0eabf4ecbe3 100644 (file)
@@ -49,7 +49,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.12"
+#define VERSION "2.13"
 
 /* Bluetooth sockets */
 #define BT_MAX_PROTO   8
index ca8d05245ca0cb9e27586cfdbdeb90e5afff81e3..b7002429f1525311053f14171a1d94a25bf1ff04 100644 (file)
@@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route);
 
 /* Create SCO or ACL connection.
  * Device _must_ be locked */
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type)
 {
        struct hci_conn *acl;
        struct hci_conn *sco;
@@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
        hci_conn_hold(acl);
 
-       if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
+       if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
+               acl->auth_type = auth_type;
                hci_acl_connect(acl);
+       }
 
        if (type == ACL_LINK)
                return acl;
@@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
 }
 EXPORT_SYMBOL(hci_connect);
 
+/* Check link security requirement */
+int hci_conn_check_link_mode(struct hci_conn *conn)
+{
+       BT_DBG("conn %p", conn);
+
+       if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
+                                       !(conn->link_mode & HCI_LM_ENCRYPT))
+               return 0;
+
+       return 1;
+}
+EXPORT_SYMBOL(hci_conn_check_link_mode);
+
 /* Authenticate remote device */
 int hci_conn_auth(struct hci_conn *conn)
 {
@@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn)
 
        if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
                if (!(conn->auth_type & 0x01)) {
-                       conn->auth_type = HCI_AT_GENERAL_BONDING_MITM;
+                       conn->auth_type |= 0x01;
                        conn->link_mode &= ~HCI_LM_AUTH;
                }
        }
index 0e3db289f4be2b1f97fca8034f26150b56013b26..ad7a553d77131c469bf4c9ebc3bc8bbfe84d1a33 100644 (file)
@@ -1605,14 +1605,11 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
 
                if (conn->state == BT_CONFIG) {
                        if (!ev->status && hdev->ssp_mode > 0 &&
-                                                       conn->ssp_mode > 0) {
-                               if (conn->out) {
-                                       struct hci_cp_auth_requested cp;
-                                       cp.handle = ev->handle;
-                                       hci_send_cmd(hdev,
-                                               HCI_OP_AUTH_REQUESTED,
+                                       conn->ssp_mode > 0 && conn->out) {
+                               struct hci_cp_auth_requested cp;
+                               cp.handle = ev->handle;
+                               hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
                                                        sizeof(cp), &cp);
-                               }
                        } else {
                                conn->state = BT_CONNECTED;
                                hci_proto_connect_cfm(conn, ev->status);
index 3396d5bdef1c3f8e0f24af0a64dd7b1eca7a333f..9610a9c85b9896e69cd6c62712cb5f8376a33040 100644 (file)
@@ -55,7 +55,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.10"
+#define VERSION "2.11"
 
 static u32 l2cap_feat_mask = 0x0000;
 
@@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk)
        struct l2cap_conn *conn;
        struct hci_conn *hcon;
        struct hci_dev *hdev;
+       __u8 auth_type;
        int err = 0;
 
        BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
@@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk)
 
        err = -ENOMEM;
 
-       hcon = hci_connect(hdev, ACL_LINK, dst);
+       if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH ||
+                       l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT ||
+                               l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
+               if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
+                       auth_type = HCI_AT_NO_BONDING_MITM;
+               else
+                       auth_type = HCI_AT_GENERAL_BONDING_MITM;
+       } else {
+               if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
+                       auth_type = HCI_AT_NO_BONDING;
+               else
+                       auth_type = HCI_AT_GENERAL_BONDING;
+       }
+
+       hcon = hci_connect(hdev, ACL_LINK, dst, auth_type);
        if (!hcon)
                goto done;
 
@@ -1553,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
        struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
        struct l2cap_conn_rsp rsp;
        struct sock *sk, *parent;
-       int result, status = 0;
+       int result, status = L2CAP_CS_NO_INFO;
 
        u16 dcid = 0, scid = __le16_to_cpu(req->scid);
-       __le16 psm  = req->psm;
+       __le16 psm = req->psm;
 
        BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
 
@@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
                goto sendresp;
        }
 
+       /* Check if the ACL is secure enough (if not SDP) */
+       if (psm != cpu_to_le16(0x0001) &&
+                               !hci_conn_check_link_mode(conn->hcon)) {
+               result = L2CAP_CR_SEC_BLOCK;
+               goto response;
+       }
+
        result = L2CAP_CR_NO_MEM;
 
        /* Check for backlog size */
@@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
                        rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
                        rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
                        rsp.result = cpu_to_le16(result);
-                       rsp.status = cpu_to_le16(0);
+                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
                        l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_RSP, sizeof(rsp), &rsp);
                }
@@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                        rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
                        rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
                        rsp.result = cpu_to_le16(result);
-                       rsp.status = cpu_to_le16(0);
+                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
                        l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_RSP, sizeof(rsp), &rsp);
                }
index a16011fedc1d73d3adc24e66ff5e7ff24a37373c..0cc91e6da76d7f9d16983985f176ab1d7319eaab 100644 (file)
@@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk)
        else
                type = SCO_LINK;
 
-       hcon = hci_connect(hdev, type, dst);
+       hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING);
        if (!hcon)
                goto done;
 
index eeee218eed80a9357e2abf5d409e74fcf9423ae6..5bbf07362172fb13733df97ae3d76238e0c7b0a5 100644 (file)
@@ -188,15 +188,21 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                return 0;
 
        case BRCTL_SET_BRIDGE_HELLO_TIME:
+       {
+               unsigned long t = clock_t_to_jiffies(args[1]);
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
+               if (t < HZ)
+                       return -EINVAL;
+
                spin_lock_bh(&br->lock);
-               br->bridge_hello_time = clock_t_to_jiffies(args[1]);
+               br->bridge_hello_time = t;
                if (br_is_root_bridge(br))
                        br->hello_time = br->bridge_hello_time;
                spin_unlock_bh(&br->lock);
                return 0;
+       }
 
        case BRCTL_SET_BRIDGE_MAX_AGE:
                if (!capable(CAP_NET_ADMIN))
index 27d6a511c8c124534320be3971c1bdc98d1d4c5d..158dee8b4965307c045d6fec2d5a930070a4cd68 100644 (file)
  */
 static ssize_t store_bridge_parm(struct device *d,
                                 const char *buf, size_t len,
-                                void (*set)(struct net_bridge *, unsigned long))
+                                int (*set)(struct net_bridge *, unsigned long))
 {
        struct net_bridge *br = to_bridge(d);
        char *endp;
        unsigned long val;
+       int err;
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -43,9 +44,9 @@ static ssize_t store_bridge_parm(struct device *d,
                return -EINVAL;
 
        spin_lock_bh(&br->lock);
-       (*set)(br, val);
+       err = (*set)(br, val);
        spin_unlock_bh(&br->lock);
-       return len;
+       return err ? err : len;
 }
 
 
@@ -56,12 +57,13 @@ static ssize_t show_forward_delay(struct device *d,
        return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
 }
 
-static void set_forward_delay(struct net_bridge *br, unsigned long val)
+static int set_forward_delay(struct net_bridge *br, unsigned long val)
 {
        unsigned long delay = clock_t_to_jiffies(val);
        br->forward_delay = delay;
        if (br_is_root_bridge(br))
                br->bridge_forward_delay = delay;
+       return 0;
 }
 
 static ssize_t store_forward_delay(struct device *d,
@@ -80,12 +82,17 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr,
                       jiffies_to_clock_t(to_bridge(d)->hello_time));
 }
 
-static void set_hello_time(struct net_bridge *br, unsigned long val)
+static int set_hello_time(struct net_bridge *br, unsigned long val)
 {
        unsigned long t = clock_t_to_jiffies(val);
+
+       if (t < HZ)
+               return -EINVAL;
+
        br->hello_time = t;
        if (br_is_root_bridge(br))
                br->bridge_hello_time = t;
+       return 0;
 }
 
 static ssize_t store_hello_time(struct device *d,
@@ -104,12 +111,13 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr,
                       jiffies_to_clock_t(to_bridge(d)->max_age));
 }
 
-static void set_max_age(struct net_bridge *br, unsigned long val)
+static int set_max_age(struct net_bridge *br, unsigned long val)
 {
        unsigned long t = clock_t_to_jiffies(val);
        br->max_age = t;
        if (br_is_root_bridge(br))
                br->bridge_max_age = t;
+       return 0;
 }
 
 static ssize_t store_max_age(struct device *d, struct device_attribute *attr,
@@ -126,9 +134,10 @@ static ssize_t show_ageing_time(struct device *d,
        return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
 }
 
-static void set_ageing_time(struct net_bridge *br, unsigned long val)
+static int set_ageing_time(struct net_bridge *br, unsigned long val)
 {
        br->ageing_time = clock_t_to_jiffies(val);
+       return 0;
 }
 
 static ssize_t store_ageing_time(struct device *d,
@@ -180,9 +189,10 @@ static ssize_t show_priority(struct device *d, struct device_attribute *attr,
                       (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
 }
 
-static void set_priority(struct net_bridge *br, unsigned long val)
+static int set_priority(struct net_bridge *br, unsigned long val)
 {
        br_stp_set_bridge_priority(br, (u16) val);
+       return 0;
 }
 
 static ssize_t store_priority(struct device *d, struct device_attribute *attr,
index 60c51f7658870257571ee9455f95bb48888b4398..e719ed29310ff5695c347db907a6311aa79e36c5 100644 (file)
@@ -1991,8 +1991,13 @@ static void net_tx_action(struct softirq_action *h)
                                spin_unlock(root_lock);
                        } else {
                                if (!test_bit(__QDISC_STATE_DEACTIVATED,
-                                             &q->state))
+                                             &q->state)) {
                                        __netif_reschedule(q);
+                               } else {
+                                       smp_mb__before_clear_bit();
+                                       clear_bit(__QDISC_STATE_SCHED,
+                                                 &q->state);
+                               }
                        }
                }
        }
index 91d3d96805d03aef392e0f514b1bd1750a9757d4..b12dae2b0b2dbcc527eee09a5d7309ffd4852ebc 100644 (file)
@@ -1029,6 +1029,11 @@ skip:
        }
 }
 
+static inline bool inetdev_valid_mtu(unsigned mtu)
+{
+       return mtu >= 68;
+}
+
 /* Called only under RTNL semaphore */
 
 static int inetdev_event(struct notifier_block *this, unsigned long event,
@@ -1048,6 +1053,10 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
                                IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
                                IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
                        }
+               } else if (event == NETDEV_CHANGEMTU) {
+                       /* Re-enabling IP */
+                       if (inetdev_valid_mtu(dev->mtu))
+                               in_dev = inetdev_init(dev);
                }
                goto out;
        }
@@ -1058,7 +1067,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
                dev->ip_ptr = NULL;
                break;
        case NETDEV_UP:
-               if (dev->mtu < 68)
+               if (!inetdev_valid_mtu(dev->mtu))
                        break;
                if (dev->flags & IFF_LOOPBACK) {
                        struct in_ifaddr *ifa;
@@ -1080,9 +1089,9 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
                ip_mc_down(in_dev);
                break;
        case NETDEV_CHANGEMTU:
-               if (dev->mtu >= 68)
+               if (inetdev_valid_mtu(dev->mtu))
                        break;
-               /* MTU falled under 68, disable IP */
+               /* disable IP when MTU is not enough */
        case NETDEV_UNREGISTER:
                inetdev_destroy(in_dev);
                break;
index d985bd613d25d3895f3b7d32fee5f571062d52be..743f011b9a84189bd9284721e4a1ac2a704e68b8 100644 (file)
@@ -409,3 +409,38 @@ out:
 }
 
 EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
+
+void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
+                    struct inet_timewait_death_row *twdr, int family)
+{
+       struct inet_timewait_sock *tw;
+       struct sock *sk;
+       struct hlist_node *node;
+       int h;
+
+       local_bh_disable();
+       for (h = 0; h < (hashinfo->ehash_size); h++) {
+               struct inet_ehash_bucket *head =
+                       inet_ehash_bucket(hashinfo, h);
+               rwlock_t *lock = inet_ehash_lockp(hashinfo, h);
+restart:
+               write_lock(lock);
+               sk_for_each(sk, node, &head->twchain) {
+
+                       tw = inet_twsk(sk);
+                       if (!net_eq(twsk_net(tw), net) ||
+                           tw->tw_family != family)
+                               continue;
+
+                       atomic_inc(&tw->tw_refcnt);
+                       write_unlock(lock);
+                       inet_twsk_deschedule(tw, twdr);
+                       inet_twsk_put(tw);
+
+                       goto restart;
+               }
+               write_unlock(lock);
+       }
+       local_bh_enable();
+}
+EXPORT_SYMBOL_GPL(inet_twsk_purge);
index 44c1e934824bfc024169250bbd5a47de532a91c3..1b4fee20fc932a54ad11f113c1f51786fb4b85f4 100644 (file)
@@ -2376,6 +2376,7 @@ static int __net_init tcp_sk_init(struct net *net)
 static void __net_exit tcp_sk_exit(struct net *net)
 {
        inet_ctl_sock_destroy(net->ipv4.tcp_sock);
+       inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET);
 }
 
 static struct pernet_operations __net_initdata tcp_sk_ops = {
index 0e844c2736a77b0dad9aa87095298be92d01bf7c..3df2c442d90bc7adef4ea3b2809639bf5955bce4 100644 (file)
@@ -943,39 +943,39 @@ static int ip6_dst_lookup_tail(struct sock *sk,
        }
 
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
-               /*
-                * Here if the dst entry we've looked up
-                * has a neighbour entry that is in the INCOMPLETE
-                * state and the src address from the flow is
-                * marked as OPTIMISTIC, we release the found
-                * dst entry and replace it instead with the
-                * dst entry of the nexthop router
-                */
-               if (!((*dst)->neighbour->nud_state & NUD_VALID)) {
-                       struct inet6_ifaddr *ifp;
-                       struct flowi fl_gw;
-                       int redirect;
-
-                       ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
-                                             (*dst)->dev, 1);
-
-                       redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
-                       if (ifp)
-                               in6_ifa_put(ifp);
-
-                       if (redirect) {
-                               /*
-                                * We need to get the dst entry for the
-                                * default router instead
-                                */
-                               dst_release(*dst);
-                               memcpy(&fl_gw, fl, sizeof(struct flowi));
-                               memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
-                               *dst = ip6_route_output(net, sk, &fl_gw);
-                               if ((err = (*dst)->error))
-                                       goto out_err_release;
-                       }
+       /*
+        * Here if the dst entry we've looked up
+        * has a neighbour entry that is in the INCOMPLETE
+        * state and the src address from the flow is
+        * marked as OPTIMISTIC, we release the found
+        * dst entry and replace it instead with the
+        * dst entry of the nexthop router
+        */
+       if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
+               struct inet6_ifaddr *ifp;
+               struct flowi fl_gw;
+               int redirect;
+
+               ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
+                                     (*dst)->dev, 1);
+
+               redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
+               if (ifp)
+                       in6_ifa_put(ifp);
+
+               if (redirect) {
+                       /*
+                        * We need to get the dst entry for the
+                        * default router instead
+                        */
+                       dst_release(*dst);
+                       memcpy(&fl_gw, fl, sizeof(struct flowi));
+                       memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
+                       *dst = ip6_route_output(net, sk, &fl_gw);
+                       if ((err = (*dst)->error))
+                               goto out_err_release;
                }
+       }
 #endif
 
        return 0;
index 01d47674f7e5c802214565108e14a820ef7963fc..e53e493606c54b0f6ef36be803d8e73e89ddc1ce 100644 (file)
@@ -377,14 +377,14 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
            skb_checksum_complete(skb)) {
                atomic_inc(&sk->sk_drops);
                kfree_skb(skb);
-               return 0;
+               return NET_RX_DROP;
        }
 
        /* Charge it to the socket. */
        if (sock_queue_rcv_skb(sk,skb)<0) {
                atomic_inc(&sk->sk_drops);
                kfree_skb(skb);
-               return 0;
+               return NET_RX_DROP;
        }
 
        return 0;
@@ -429,7 +429,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
                if (skb_checksum_complete(skb)) {
                        atomic_inc(&sk->sk_drops);
                        kfree_skb(skb);
-                       return 0;
+                       return NET_RX_DROP;
                }
        }
 
index 5b90b369ccb2577d41e7ac4ab1f4993147e6108f..b585c850a89a3737b1b6a19aab62dd7dd1cee5cb 100644 (file)
@@ -2148,6 +2148,7 @@ static int tcpv6_net_init(struct net *net)
 static void tcpv6_net_exit(struct net *net)
 {
        inet_ctl_sock_destroy(net->ipv6.tcp_sk);
+       inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET6);
 }
 
 static struct pernet_operations tcpv6_net_ops = {
index 7439b63df5d0b72db616e3cf012e310a9720147c..cf82acec913a235a3e87dc4c7222f344449436bd 100644 (file)
@@ -265,7 +265,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
        key = sdata->default_key;
        if (key) {
                sprintf(buf, "../keys/%d", key->debugfs.cnt);
-               sdata->debugfs.default_key =
+               sdata->common_debugfs.default_key =
                        debugfs_create_symlink("default_key",
                                               sdata->debugfsdir, buf);
        } else
@@ -277,8 +277,8 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
        if (!sdata)
                return;
 
-       debugfs_remove(sdata->debugfs.default_key);
-       sdata->debugfs.default_key = NULL;
+       debugfs_remove(sdata->common_debugfs.default_key);
+       sdata->common_debugfs.default_key = NULL;
 }
 
 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
index 586a9b49b0fc6f345c0db6e73e0d96a5b8dbdfd9..4498d8713652ac5b93c82eb7973d4f8812c2cda0 100644 (file)
@@ -496,8 +496,10 @@ struct ieee80211_sub_if_data {
                struct {
                        struct dentry *mode;
                } monitor;
-               struct dentry *default_key;
        } debugfs;
+       struct {
+               struct dentry *default_key;
+       } common_debugfs;
 
 #ifdef CONFIG_MAC80211_MESH
        struct dentry *mesh_stats_dir;
index 9bb68c6a8f44bf4cd3552c31cdf0a5ad69909e66..902cac1bd246ab7f861cb2f1aa8b3c06168dc33a 100644 (file)
@@ -478,21 +478,51 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info(
 static void ieee80211_sta_send_associnfo(struct net_device *dev,
                                         struct ieee80211_if_sta *ifsta)
 {
+       char *buf;
+       size_t len;
+       int i;
        union iwreq_data wrqu;
 
+       if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
+               return;
+
+       buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
+                               ifsta->assocresp_ies_len), GFP_KERNEL);
+       if (!buf)
+               return;
+
+       len = sprintf(buf, "ASSOCINFO(");
        if (ifsta->assocreq_ies) {
-               memset(&wrqu, 0, sizeof(wrqu));
-               wrqu.data.length = ifsta->assocreq_ies_len;
-               wireless_send_event(dev, IWEVASSOCREQIE, &wrqu,
-                                   ifsta->assocreq_ies);
+               len += sprintf(buf + len, "ReqIEs=");
+               for (i = 0; i < ifsta->assocreq_ies_len; i++) {
+                       len += sprintf(buf + len, "%02x",
+                                      ifsta->assocreq_ies[i]);
+               }
        }
-
        if (ifsta->assocresp_ies) {
-               memset(&wrqu, 0, sizeof(wrqu));
-               wrqu.data.length = ifsta->assocresp_ies_len;
-               wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu,
-                                   ifsta->assocresp_ies);
+               if (ifsta->assocreq_ies)
+                       len += sprintf(buf + len, " ");
+               len += sprintf(buf + len, "RespIEs=");
+               for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+                       len += sprintf(buf + len, "%02x",
+                                      ifsta->assocresp_ies[i]);
+               }
+       }
+       len += sprintf(buf + len, ")");
+
+       if (len > IW_CUSTOM_MAX) {
+               len = sprintf(buf, "ASSOCRESPIE=");
+               for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+                       len += sprintf(buf + len, "%02x",
+                                      ifsta->assocresp_ies[i]);
+               }
        }
+
+       memset(&wrqu, 0, sizeof(wrqu));
+       wrqu.data.length = len;
+       wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+
+       kfree(buf);
 }
 
 
index 1b1226d6653f7815970483cdba636c5f22a3934e..20633fdf7e6bb48b48e485b9ba0d110ab1f8459b 100644 (file)
@@ -68,11 +68,21 @@ static const char *const dccprotos[] = {
 static int parse_dcc(char *data, const char *data_end, u_int32_t *ip,
                     u_int16_t *port, char **ad_beg_p, char **ad_end_p)
 {
+       char *tmp;
+
        /* at least 12: "AAAAAAAA P\1\n" */
        while (*data++ != ' ')
                if (data > data_end - 12)
                        return -1;
 
+       /* Make sure we have a newline character within the packet boundaries
+        * because simple_strtoul parses until the first invalid character. */
+       for (tmp = data; tmp <= data_end; tmp++)
+               if (*tmp == '\n')
+                       break;
+       if (tmp > data_end || *tmp != '\n')
+               return -1;
+
        *ad_beg_p = data;
        *ip = simple_strtoul(data, &data, 10);
 
index 654a4f7f12c6f7f74c1412ad432c95661336fcdb..9bd03967fea4b4c66654e5ad1c8f32779a8bc9c2 100644 (file)
@@ -45,12 +45,12 @@ static LIST_HEAD(gre_keymap_list);
 
 void nf_ct_gre_keymap_flush(void)
 {
-       struct list_head *pos, *n;
+       struct nf_ct_gre_keymap *km, *tmp;
 
        write_lock_bh(&nf_ct_gre_lock);
-       list_for_each_safe(pos, n, &gre_keymap_list) {
-               list_del(pos);
-               kfree(pos);
+       list_for_each_entry_safe(km, tmp, &gre_keymap_list, list) {
+               list_del(&km->list);
+               kfree(km);
        }
        write_unlock_bh(&nf_ct_gre_lock);
 }
@@ -97,10 +97,14 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
        kmp = &help->help.ct_pptp_info.keymap[dir];
        if (*kmp) {
                /* check whether it's a retransmission */
+               read_lock_bh(&nf_ct_gre_lock);
                list_for_each_entry(km, &gre_keymap_list, list) {
-                       if (gre_key_cmpfn(km, t) && km == *kmp)
+                       if (gre_key_cmpfn(km, t) && km == *kmp) {
+                               read_unlock_bh(&nf_ct_gre_lock);
                                return 0;
+                       }
                }
+               read_unlock_bh(&nf_ct_gre_lock);
                pr_debug("trying to override keymap_%s for ct %p\n",
                         dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
                return -EEXIST;
index 2f9bbc058b487bede799f9cf2e69e7554aa0a63d..1fa306be60fbf47eda01b59ebad301798c364002 100644 (file)
@@ -1193,7 +1193,6 @@ static const struct sip_handler sip_handlers[] = {
 static int process_sip_response(struct sk_buff *skb,
                                const char **dptr, unsigned int *datalen)
 {
-       static const struct sip_handler *handler;
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        unsigned int matchoff, matchlen;
@@ -1214,6 +1213,8 @@ static int process_sip_response(struct sk_buff *skb,
        dataoff = matchoff + matchlen + 1;
 
        for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
+               const struct sip_handler *handler;
+
                handler = &sip_handlers[i];
                if (handler->response == NULL)
                        continue;
@@ -1228,13 +1229,14 @@ static int process_sip_response(struct sk_buff *skb,
 static int process_sip_request(struct sk_buff *skb,
                               const char **dptr, unsigned int *datalen)
 {
-       static const struct sip_handler *handler;
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        unsigned int matchoff, matchlen;
        unsigned int cseq, i;
 
        for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
+               const struct sip_handler *handler;
+
                handler = &sip_handlers[i];
                if (handler->request == NULL)
                        continue;
index 5cafdd4c801848f00e3d55daca0d81875d709c7d..8eb79e92e94cb82348a7cf76e8399f46f86426a7 100644 (file)
@@ -205,7 +205,7 @@ replay:
                }
        }
 
-       root_lock = qdisc_root_lock(q);
+       root_lock = qdisc_root_sleeping_lock(q);
 
        if (tp == NULL) {
                /* Proto-tcf does not exist, create new one */
index 481260a4f10f333f6eb9c52a73fb52da02f092eb..e3d8455eebc29c32d37a5b2c943c07de1573b0e1 100644 (file)
@@ -75,7 +75,7 @@ static __inline__ int route4_fastmap_hash(u32 id, int iif)
 static inline
 void route4_reset_fastmap(struct Qdisc *q, struct route4_head *head, u32 id)
 {
-       spinlock_t *root_lock = qdisc_root_lock(q);
+       spinlock_t *root_lock = qdisc_root_sleeping_lock(q);
 
        spin_lock_bh(root_lock);
        memset(head->fastmap, 0, sizeof(head->fastmap));
index 506b709510b65bc0849d284f52bdd617735cc778..1122c952aa99bd17f78f3de3d6c6d6600c3d81b5 100644 (file)
@@ -1169,8 +1169,8 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
        if (q->stab && qdisc_dump_stab(skb, q->stab) < 0)
                goto nla_put_failure;
 
-       if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
-                                        TCA_XSTATS, qdisc_root_lock(q), &d) < 0)
+       if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS,
+                                        qdisc_root_sleeping_lock(q), &d) < 0)
                goto nla_put_failure;
 
        if (q->ops->dump_stats && q->ops->dump_stats(q, &d) < 0)
@@ -1461,8 +1461,8 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
        if (cl_ops->dump && cl_ops->dump(q, cl, skb, tcm) < 0)
                goto nla_put_failure;
 
-       if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
-                                        TCA_XSTATS, qdisc_root_lock(q), &d) < 0)
+       if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS,
+                                        qdisc_root_sleeping_lock(q), &d) < 0)
                goto nla_put_failure;
 
        if (cl_ops->dump_stats && cl_ops->dump_stats(q, cl, &d) < 0)
index 9b720adedead51611403d0e3dc846b32445e9474..8b06fa9004828c937e359df4c3c0d0c0bfa0ecf3 100644 (file)
@@ -1754,7 +1754,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg)
 
        if (--cl->refcnt == 0) {
 #ifdef CONFIG_NET_CLS_ACT
-               spinlock_t *root_lock = qdisc_root_lock(sch);
+               spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
                struct cbq_sched_data *q = qdisc_priv(sch);
 
                spin_lock_bh(root_lock);
index 97d4761cc31e8633864a40f1cc35e13b8d668614..d14f02056ae6dcc31dbfad8c90ba57424e4a6d45 100644 (file)
@@ -1043,7 +1043,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 
 static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
-       spinlock_t *root_lock = qdisc_root_lock(sch);
+       spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
        struct htb_sched *q = qdisc_priv(sch);
        struct nlattr *nest;
        struct tc_htb_glob gopt;
@@ -1075,7 +1075,7 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
                          struct sk_buff *skb, struct tcmsg *tcm)
 {
        struct htb_class *cl = (struct htb_class *)arg;
-       spinlock_t *root_lock = qdisc_root_lock(sch);
+       spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
        struct nlattr *nest;
        struct tc_htb_opt opt;
 
index fb0294d0b55e6e71ed87c9b7e1206e755ad5561b..3781e55046d076cc49e5eb80e89bca30ec3eca53 100644 (file)
@@ -341,7 +341,7 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
        for (i = 0; i < n; i++)
                d->table[i] = data[i];
 
-       root_lock = qdisc_root_lock(sch);
+       root_lock = qdisc_root_sleeping_lock(sch);
 
        spin_lock_bh(root_lock);
        d = xchg(&q->delay_dist, d);
index 2c35c678563bec7fafaed3125fe36477b1a7c567..d35ef059abb1781e41becb98e6b1a15e3596001b 100644 (file)
@@ -161,7 +161,7 @@ teql_destroy(struct Qdisc* sch)
                                                txq = netdev_get_tx_queue(master->dev, 0);
                                                master->slaves = NULL;
 
-                                               root_lock = qdisc_root_lock(txq->qdisc);
+                                               root_lock = qdisc_root_sleeping_lock(txq->qdisc);
                                                spin_lock_bh(root_lock);
                                                qdisc_reset(txq->qdisc);
                                                spin_unlock_bh(root_lock);
index 0f8c439b848a1eab04f0f21f2ea763863e424b2f..5231f7aaac0e483ebb8b457c3c6e2218464da409 100644 (file)
@@ -60,24 +60,14 @@ static int proc_do_xprt(ctl_table *table, int write, struct file *file,
                        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        char tmpbuf[256];
-       int len;
+       size_t len;
+
        if ((*ppos && !write) || !*lenp) {
                *lenp = 0;
                return 0;
        }
-       if (write)
-               return -EINVAL;
-       else {
-               len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
-               if (!access_ok(VERIFY_WRITE, buffer, len))
-                       return -EFAULT;
-
-               if (__copy_to_user(buffer, tmpbuf, len))
-                       return -EFAULT;
-       }
-       *lenp -= len;
-       *ppos += len;
-       return 0;
+       len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
+       return simple_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len);
 }
 
 static int
index b4b17f44cb290c443fc009036a319a080a240f33..74de31a066168509db7dba7ab559b29d17dae413 100644 (file)
@@ -443,18 +443,18 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
 
        dprintk("svcrdma: rqstp=%p\n", rqstp);
 
-       spin_lock_bh(&rdma_xprt->sc_read_complete_lock);
+       spin_lock_bh(&rdma_xprt->sc_rq_dto_lock);
        if (!list_empty(&rdma_xprt->sc_read_complete_q)) {
                ctxt = list_entry(rdma_xprt->sc_read_complete_q.next,
                                  struct svc_rdma_op_ctxt,
                                  dto_q);
                list_del_init(&ctxt->dto_q);
        }
-       spin_unlock_bh(&rdma_xprt->sc_read_complete_lock);
-       if (ctxt)
+       if (ctxt) {
+               spin_unlock_bh(&rdma_xprt->sc_rq_dto_lock);
                return rdma_read_complete(rqstp, ctxt);
+       }
 
-       spin_lock_bh(&rdma_xprt->sc_rq_dto_lock);
        if (!list_empty(&rdma_xprt->sc_rq_dto_q)) {
                ctxt = list_entry(rdma_xprt->sc_rq_dto_q.next,
                                  struct svc_rdma_op_ctxt,
index 19ddc382b777865c59b8eb7b1f161abe687910ae..900cb69728c691537e14e85e6f4618c0b0f79cfe 100644 (file)
@@ -359,11 +359,11 @@ static void sq_cq_reap(struct svcxprt_rdma *xprt)
                        if (test_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags)) {
                                struct svc_rdma_op_ctxt *read_hdr = ctxt->read_hdr;
                                BUG_ON(!read_hdr);
+                               spin_lock_bh(&xprt->sc_rq_dto_lock);
                                set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags);
-                               spin_lock_bh(&xprt->sc_read_complete_lock);
                                list_add_tail(&read_hdr->dto_q,
                                              &xprt->sc_read_complete_q);
-                               spin_unlock_bh(&xprt->sc_read_complete_lock);
+                               spin_unlock_bh(&xprt->sc_rq_dto_lock);
                                svc_xprt_enqueue(&xprt->sc_xprt);
                        }
                        svc_rdma_put_context(ctxt, 0);
@@ -428,7 +428,6 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
        init_waitqueue_head(&cma_xprt->sc_send_wait);
 
        spin_lock_init(&cma_xprt->sc_lock);
-       spin_lock_init(&cma_xprt->sc_read_complete_lock);
        spin_lock_init(&cma_xprt->sc_rq_dto_lock);
 
        cma_xprt->sc_ord = svcrdma_ord;
index b1ff16aa4bdb1a3acb0c39f0be6fe30cad2064bb..3ddaff42d1bbbe8292d3be98d7b8dd8e0bcbfceb 100644 (file)
@@ -96,8 +96,8 @@ struct bcbearer {
        struct media media;
        struct bcbearer_pair bpairs[MAX_BEARERS];
        struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1];
-       struct node_map remains;
-       struct node_map remains_new;
+       struct tipc_node_map remains;
+       struct tipc_node_map remains_new;
 };
 
 /**
@@ -110,7 +110,7 @@ struct bcbearer {
 
 struct bclink {
        struct link link;
-       struct node node;
+       struct tipc_node node;
 };
 
 
@@ -149,7 +149,7 @@ static void bcbuf_decr_acks(struct sk_buff *buf)
  * Called with 'node' locked, bc_lock unlocked
  */
 
-static void bclink_set_gap(struct node *n_ptr)
+static void bclink_set_gap(struct tipc_node *n_ptr)
 {
        struct sk_buff *buf = n_ptr->bclink.deferred_head;
 
@@ -202,7 +202,7 @@ static void bclink_retransmit_pkt(u32 after, u32 to)
  * Node is locked, bc_lock unlocked.
  */
 
-void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked)
+void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked)
 {
        struct sk_buff *crs;
        struct sk_buff *next;
@@ -250,7 +250,7 @@ void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked)
  * tipc_net_lock and node lock set
  */
 
-static void bclink_send_ack(struct node *n_ptr)
+static void bclink_send_ack(struct tipc_node *n_ptr)
 {
        struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1];
 
@@ -264,7 +264,7 @@ static void bclink_send_ack(struct node *n_ptr)
  * tipc_net_lock and node lock set
  */
 
-static void bclink_send_nack(struct node *n_ptr)
+static void bclink_send_nack(struct tipc_node *n_ptr)
 {
        struct sk_buff *buf;
        struct tipc_msg *msg;
@@ -308,7 +308,7 @@ static void bclink_send_nack(struct node *n_ptr)
  * tipc_net_lock and node lock set
  */
 
-void tipc_bclink_check_gap(struct node *n_ptr, u32 last_sent)
+void tipc_bclink_check_gap(struct tipc_node *n_ptr, u32 last_sent)
 {
        if (!n_ptr->bclink.supported ||
            less_eq(last_sent, mod(n_ptr->bclink.last_in)))
@@ -328,7 +328,7 @@ void tipc_bclink_check_gap(struct node *n_ptr, u32 last_sent)
 
 static void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to)
 {
-       struct node *n_ptr = tipc_node_find(dest);
+       struct tipc_node *n_ptr = tipc_node_find(dest);
        u32 my_after, my_to;
 
        if (unlikely(!n_ptr || !tipc_node_is_up(n_ptr)))
@@ -418,7 +418,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
        static int rx_count = 0;
 #endif
        struct tipc_msg *msg = buf_msg(buf);
-       struct node* node = tipc_node_find(msg_prevnode(msg));
+       struct tipc_node* node = tipc_node_find(msg_prevnode(msg));
        u32 next_in;
        u32 seqno;
        struct sk_buff *deferred;
@@ -538,7 +538,7 @@ u32 tipc_bclink_get_last_sent(void)
        return last_sent;
 }
 
-u32 tipc_bclink_acks_missing(struct node *n_ptr)
+u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
 {
        return (n_ptr->bclink.supported &&
                (tipc_bclink_get_last_sent() != n_ptr->bclink.acked));
index a2416fa6b90688752ea67dddefa9642244281565..5aa024b99c558ba2d6d6aeb5b26216dd67e52a9a 100644 (file)
 #define WSIZE 32
 
 /**
- * struct node_map - set of node identifiers
+ * struct tipc_node_map - set of node identifiers
  * @count: # of nodes in set
  * @map: bitmap of node identifiers that are in the set
  */
 
-struct node_map {
+struct tipc_node_map {
        u32 count;
        u32 map[MAX_NODES / WSIZE];
 };
@@ -68,7 +68,7 @@ struct port_list {
 };
 
 
-struct node;
+struct tipc_node;
 
 extern char tipc_bclink_name[];
 
@@ -77,7 +77,7 @@ extern char tipc_bclink_name[];
  * nmap_add - add a node to a node map
  */
 
-static inline void tipc_nmap_add(struct node_map *nm_ptr, u32 node)
+static inline void tipc_nmap_add(struct tipc_node_map *nm_ptr, u32 node)
 {
        int n = tipc_node(node);
        int w = n / WSIZE;
@@ -93,7 +93,7 @@ static inline void tipc_nmap_add(struct node_map *nm_ptr, u32 node)
  * nmap_remove - remove a node from a node map
  */
 
-static inline void tipc_nmap_remove(struct node_map *nm_ptr, u32 node)
+static inline void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node)
 {
        int n = tipc_node(node);
        int w = n / WSIZE;
@@ -109,7 +109,7 @@ static inline void tipc_nmap_remove(struct node_map *nm_ptr, u32 node)
  * nmap_equal - test for equality of node maps
  */
 
-static inline int tipc_nmap_equal(struct node_map *nm_a, struct node_map *nm_b)
+static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b)
 {
        return !memcmp(nm_a, nm_b, sizeof(*nm_a));
 }
@@ -121,8 +121,8 @@ static inline int tipc_nmap_equal(struct node_map *nm_a, struct node_map *nm_b)
  * @nm_diff: output node map A-B (i.e. nodes of A that are not in B)
  */
 
-static inline void tipc_nmap_diff(struct node_map *nm_a, struct node_map *nm_b,
-                                 struct node_map *nm_diff)
+static inline void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b,
+                                 struct tipc_node_map *nm_diff)
 {
        int stop = sizeof(nm_a->map) / sizeof(u32);
        int w;
@@ -195,12 +195,12 @@ static inline void tipc_port_list_free(struct port_list *pl_ptr)
 
 int  tipc_bclink_init(void);
 void tipc_bclink_stop(void);
-void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked);
+void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked);
 int  tipc_bclink_send_msg(struct sk_buff *buf);
 void tipc_bclink_recv_pkt(struct sk_buff *buf);
 u32  tipc_bclink_get_last_sent(void);
-u32  tipc_bclink_acks_missing(struct node *n_ptr);
-void tipc_bclink_check_gap(struct node *n_ptr, u32 seqno);
+u32  tipc_bclink_acks_missing(struct tipc_node *n_ptr);
+void tipc_bclink_check_gap(struct tipc_node *n_ptr, u32 seqno);
 int  tipc_bclink_stats(char *stats_buf, const u32 buf_size);
 int  tipc_bclink_reset_stats(void);
 int  tipc_bclink_set_queue_limits(u32 limit);
index 6a9aba3edd0813f0389a2590aa50ea2c463c5315..a7a36779b9b3b87cdf717923b462e0cf25a763b2 100644 (file)
@@ -599,7 +599,7 @@ int tipc_block_bearer(const char *name)
        spin_lock_bh(&b_ptr->publ.lock);
        b_ptr->publ.blocked = 1;
        list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
-               struct node *n_ptr = l_ptr->owner;
+               struct tipc_node *n_ptr = l_ptr->owner;
 
                spin_lock_bh(&n_ptr->lock);
                tipc_link_reset(l_ptr);
index 6a36b6600e6c79c7c827eca58061de84e1f7f754..ca5734892713d19f9d6cc37b1fc48b684cc5d539 100644 (file)
@@ -104,7 +104,7 @@ struct bearer {
        u32 continue_count;
        int active;
        char net_plane;
-       struct node_map nodes;
+       struct tipc_node_map nodes;
 };
 
 struct bearer_name {
index 46ee6c58532dcea8baa1a71df457d872bcdefe38..689fdefe9d04c58b7f20e2bc4b90b56ad1d60cce 100644 (file)
@@ -48,8 +48,8 @@ static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
                                u32 lower, u32 upper);
 static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest);
 
-struct node **tipc_local_nodes = NULL;
-struct node_map tipc_cltr_bcast_nodes = {0,{0,}};
+struct tipc_node **tipc_local_nodes = NULL;
+struct tipc_node_map tipc_cltr_bcast_nodes = {0,{0,}};
 u32 tipc_highest_allowed_slave = 0;
 
 struct cluster *tipc_cltr_create(u32 addr)
@@ -115,7 +115,7 @@ void tipc_cltr_delete(struct cluster *c_ptr)
 
 u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr)
 {
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        u32 n_num = tipc_node(addr) + 1;
 
        if (!c_ptr)
@@ -133,7 +133,7 @@ u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr)
        return 0;
 }
 
-void tipc_cltr_attach_node(struct cluster *c_ptr, struct node *n_ptr)
+void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr)
 {
        u32 n_num = tipc_node(n_ptr->addr);
        u32 max_n_num = tipc_max_nodes;
@@ -196,7 +196,7 @@ u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref)
  * Uses deterministic and fair algorithm.
  */
 
-struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector)
+struct tipc_node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector)
 {
        u32 n_num;
        u32 mask = tipc_max_nodes;
@@ -379,7 +379,7 @@ void tipc_cltr_recv_routing_table(struct sk_buff *buf)
 {
        struct tipc_msg *msg = buf_msg(buf);
        struct cluster *c_ptr;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        unchar *node_table;
        u32 table_size;
        u32 router;
@@ -499,7 +499,7 @@ static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
                         u32 lower, u32 upper)
 {
        struct sk_buff *buf_copy;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        u32 n_num;
        u32 tstop;
 
@@ -534,7 +534,7 @@ void tipc_cltr_broadcast(struct sk_buff *buf)
 {
        struct sk_buff *buf_copy;
        struct cluster *c_ptr;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        u32 n_num;
        u32 tstart;
        u32 tstop;
index 62df074afaecf8a5912b5b9a25a0779a391b8da8..333efb0b9c44c28c1c479c293e58213de473b821 100644 (file)
 struct cluster {
        u32 addr;
        struct _zone *owner;
-       struct node **nodes;
+       struct tipc_node **nodes;
        u32 highest_node;
        u32 highest_slave;
 };
 
 
-extern struct node **tipc_local_nodes;
+extern struct tipc_node **tipc_local_nodes;
 extern u32 tipc_highest_allowed_slave;
-extern struct node_map tipc_cltr_bcast_nodes;
+extern struct tipc_node_map tipc_cltr_bcast_nodes;
 
 void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router);
 void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest);
-struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector);
+struct tipc_node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector);
 u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref);
 void tipc_cltr_recv_routing_table(struct sk_buff *buf);
 struct cluster *tipc_cltr_create(u32 addr);
 void tipc_cltr_delete(struct cluster *c_ptr);
-void tipc_cltr_attach_node(struct cluster *c_ptr, struct node *n_ptr);
+void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr);
 void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest);
 void tipc_cltr_broadcast(struct sk_buff *buf);
 int tipc_cltr_init(void);
index 1657f0e795ff4c6b606d4323d9db97631129bd20..74b7d1e28aec0205bbb405185bc5cba4e179d285 100644 (file)
@@ -193,7 +193,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)
                /* Always accept link here */
                struct sk_buff *rbuf;
                struct tipc_media_addr *addr;
-               struct node *n_ptr = tipc_node_find(orig);
+               struct tipc_node *n_ptr = tipc_node_find(orig);
                int link_fully_up;
 
                dbg(" in own cluster\n");
index d60113ba4b1b0cc0cdf0a8a825823bd2da20c98d..dd4c18b9a35b5ec71ad78ba28757ea750c42ac6c 100644 (file)
@@ -1155,7 +1155,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)
 int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
 {
        struct link *l_ptr;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        int res = -ELINKCONG;
 
        read_lock_bh(&tipc_net_lock);
@@ -1226,7 +1226,7 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,
 int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode)
 {
        struct link *l_ptr;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        int res;
        u32 selector = msg_origport(buf_msg(buf)) & 1;
        u32 dummy;
@@ -1270,7 +1270,7 @@ int tipc_link_send_sections_fast(struct port *sender,
        struct tipc_msg *hdr = &sender->publ.phdr;
        struct link *l_ptr;
        struct sk_buff *buf;
-       struct node *node;
+       struct tipc_node *node;
        int res;
        u32 selector = msg_origport(hdr) & 1;
 
@@ -1364,7 +1364,7 @@ static int link_send_sections_long(struct port *sender,
                                   u32 destaddr)
 {
        struct link *l_ptr;
-       struct node *node;
+       struct tipc_node *node;
        struct tipc_msg *hdr = &sender->publ.phdr;
        u32 dsz = msg_data_sz(hdr);
        u32 max_pkt,fragm_sz,rest;
@@ -1636,7 +1636,7 @@ void tipc_link_push_queue(struct link *l_ptr)
 
 static void link_reset_all(unsigned long addr)
 {
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        char addr_string[16];
        u32 i;
 
@@ -1682,7 +1682,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
 
                /* Handle failure on broadcast link */
 
-               struct node *n_ptr;
+               struct tipc_node *n_ptr;
                char addr_string[16];
 
                tipc_printf(TIPC_OUTPUT, "Msg seq number: %u,  ", msg_seqno(msg));
@@ -1843,7 +1843,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
        read_lock_bh(&tipc_net_lock);
        while (head) {
                struct bearer *b_ptr = (struct bearer *)tb_ptr;
-               struct node *n_ptr;
+               struct tipc_node *n_ptr;
                struct link *l_ptr;
                struct sk_buff *crs;
                struct sk_buff *buf = head;
@@ -2935,7 +2935,7 @@ void tipc_link_set_queue_limits(struct link *l_ptr, u32 window)
  * Returns pointer to link (or 0 if invalid link name).
  */
 
-static struct link *link_find_link(const char *name, struct node **node)
+static struct link *link_find_link(const char *name, struct tipc_node **node)
 {
        struct link_name link_name_parts;
        struct bearer *b_ptr;
@@ -2965,7 +2965,7 @@ struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space
        struct tipc_link_config *args;
        u32 new_value;
        struct link *l_ptr;
-       struct node *node;
+       struct tipc_node *node;
        int res;
 
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
@@ -3043,7 +3043,7 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_
 {
        char *link_name;
        struct link *l_ptr;
-       struct node *node;
+       struct tipc_node *node;
 
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -3091,7 +3091,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
 {
        struct print_buf pb;
        struct link *l_ptr;
-       struct node *node;
+       struct tipc_node *node;
        char *status;
        u32 profile_total = 0;
 
@@ -3207,7 +3207,7 @@ int link_control(const char *name, u32 op, u32 val)
        int res = -EINVAL;
        struct link *l_ptr;
        u32 bearer_id;
-       struct node * node;
+       struct tipc_node * node;
        u32 a;
 
        a = link_name2addr(name, &bearer_id);
@@ -3249,7 +3249,7 @@ int link_control(const char *name, u32 op, u32 val)
 
 u32 tipc_link_get_max_pkt(u32 dest, u32 selector)
 {
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        struct link *l_ptr;
        u32 res = MAX_PKT_DEFAULT;
 
index 52f3e7c1871fbee83a5d84a78387fbca00cc60e7..6a51e38ad25c9b027f9852dd5b5d90b9510c1b9b 100644 (file)
@@ -116,7 +116,7 @@ struct link {
        char name[TIPC_MAX_LINK_NAME];
        struct tipc_media_addr media_addr;
        struct timer_list timer;
-       struct node *owner;
+       struct tipc_node *owner;
        struct list_head link_list;
 
        /* Management and link supervision data */
index b9e7cd336d76d54488dc2ded2f0a91914cb7dea1..139882d4ed00708b66d3c1d6640643ca38af7e28 100644 (file)
@@ -76,7 +76,7 @@ struct publication {
        u32 node;
        u32 ref;
        u32 key;
-       struct node_subscr subscr;
+       struct tipc_node_subscr subscr;
        struct list_head local_list;
        struct list_head pport_list;
        struct publication *node_list_next;
index ec7b04fbdc435b7421f5487ff57a2d0df7308801..7906608bf510f4d6eec420e739256e8658647be6 100644 (file)
 DEFINE_RWLOCK(tipc_net_lock);
 struct network tipc_net = { NULL };
 
-struct node *tipc_net_select_remote_node(u32 addr, u32 ref)
+struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref)
 {
        return tipc_zone_select_remote_node(tipc_net.zones[tipc_zone(addr)], addr, ref);
 }
index d154ac2bda9a174ab3114dc3b86e0783511daf8c..de2b9ad8f646098921f54613ea7cfe11d2f6e144 100644 (file)
@@ -55,7 +55,7 @@ extern rwlock_t tipc_net_lock;
 void tipc_net_remove_as_router(u32 router);
 void tipc_net_send_external_routes(u32 dest);
 void tipc_net_route_msg(struct sk_buff *buf);
-struct node *tipc_net_select_remote_node(u32 addr, u32 ref);
+struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref);
 u32 tipc_net_select_router(u32 addr, u32 ref);
 
 int tipc_net_start(u32 addr);
index ee952ad602183b28446055d1bae1e0643b182358..20d98c56e152685a5ab84e584e9a31a33cb1bfec 100644 (file)
 #include "bearer.h"
 #include "name_distr.h"
 
-void node_print(struct print_buf *buf, struct node *n_ptr, char *str);
-static void node_lost_contact(struct node *n_ptr);
-static void node_established_contact(struct node *n_ptr);
+void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str);
+static void node_lost_contact(struct tipc_node *n_ptr);
+static void node_established_contact(struct tipc_node *n_ptr);
 
-struct node *tipc_nodes = NULL;        /* sorted list of nodes within cluster */
+struct tipc_node *tipc_nodes = NULL;   /* sorted list of nodes within cluster */
 
 static DEFINE_SPINLOCK(node_create_lock);
 
@@ -66,11 +66,11 @@ u32 tipc_own_tag = 0;
  * but this is a non-trivial change.)
  */
 
-struct node *tipc_node_create(u32 addr)
+struct tipc_node *tipc_node_create(u32 addr)
 {
        struct cluster *c_ptr;
-       struct node *n_ptr;
-       struct node **curr_node;
+       struct tipc_node *n_ptr;
+       struct tipc_node **curr_node;
 
        spin_lock_bh(&node_create_lock);
 
@@ -120,7 +120,7 @@ struct node *tipc_node_create(u32 addr)
        return n_ptr;
 }
 
-void tipc_node_delete(struct node *n_ptr)
+void tipc_node_delete(struct tipc_node *n_ptr)
 {
        if (!n_ptr)
                return;
@@ -146,7 +146,7 @@ void tipc_node_delete(struct node *n_ptr)
  * Link becomes active (alone or shared) or standby, depending on its priority.
  */
 
-void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
+void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr)
 {
        struct link **active = &n_ptr->active_links[0];
 
@@ -180,7 +180,7 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
  * node_select_active_links - select active link
  */
 
-static void node_select_active_links(struct node *n_ptr)
+static void node_select_active_links(struct tipc_node *n_ptr)
 {
        struct link **active = &n_ptr->active_links[0];
        u32 i;
@@ -208,7 +208,7 @@ static void node_select_active_links(struct node *n_ptr)
  * tipc_node_link_down - handle loss of link
  */
 
-void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
+void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr)
 {
        struct link **active;
 
@@ -235,30 +235,30 @@ void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
                node_lost_contact(n_ptr);
 }
 
-int tipc_node_has_active_links(struct node *n_ptr)
+int tipc_node_has_active_links(struct tipc_node *n_ptr)
 {
        return (n_ptr &&
                ((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
 }
 
-int tipc_node_has_redundant_links(struct node *n_ptr)
+int tipc_node_has_redundant_links(struct tipc_node *n_ptr)
 {
        return (n_ptr->working_links > 1);
 }
 
-static int tipc_node_has_active_routes(struct node *n_ptr)
+static int tipc_node_has_active_routes(struct tipc_node *n_ptr)
 {
        return (n_ptr && (n_ptr->last_router >= 0));
 }
 
-int tipc_node_is_up(struct node *n_ptr)
+int tipc_node_is_up(struct tipc_node *n_ptr)
 {
        return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr));
 }
 
-struct node *tipc_node_attach_link(struct link *l_ptr)
+struct tipc_node *tipc_node_attach_link(struct link *l_ptr)
 {
-       struct node *n_ptr = tipc_node_find(l_ptr->addr);
+       struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr);
 
        if (!n_ptr)
                n_ptr = tipc_node_create(l_ptr->addr);
@@ -285,7 +285,7 @@ struct node *tipc_node_attach_link(struct link *l_ptr)
        return NULL;
 }
 
-void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr)
+void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)
 {
        n_ptr->links[l_ptr->b_ptr->identity] = NULL;
        tipc_net.zones[tipc_zone(l_ptr->addr)]->links--;
@@ -338,7 +338,7 @@ void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr)
  *
  */
 
-static void node_established_contact(struct node *n_ptr)
+static void node_established_contact(struct tipc_node *n_ptr)
 {
        struct cluster *c_ptr;
 
@@ -384,10 +384,10 @@ static void node_established_contact(struct node *n_ptr)
                                  tipc_highest_allowed_slave);
 }
 
-static void node_lost_contact(struct node *n_ptr)
+static void node_lost_contact(struct tipc_node *n_ptr)
 {
        struct cluster *c_ptr;
-       struct node_subscr *ns, *tns;
+       struct tipc_node_subscr *ns, *tns;
        char addr_string[16];
        u32 i;
 
@@ -466,9 +466,9 @@ static void node_lost_contact(struct node *n_ptr)
  * Called by when cluster local lookup has failed.
  */
 
-struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
+struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector)
 {
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        u32 router_addr;
 
        if (!tipc_addr_domain_valid(addr))
@@ -513,7 +513,7 @@ struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
  * Uses a deterministic and fair algorithm for selecting router node.
  */
 
-u32 tipc_node_select_router(struct node *n_ptr, u32 ref)
+u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref)
 {
        u32 ulim;
        u32 mask;
@@ -551,7 +551,7 @@ u32 tipc_node_select_router(struct node *n_ptr, u32 ref)
        return tipc_addr(own_zone(), own_cluster(), r);
 }
 
-void tipc_node_add_router(struct node *n_ptr, u32 router)
+void tipc_node_add_router(struct tipc_node *n_ptr, u32 router)
 {
        u32 r_num = tipc_node(router);
 
@@ -562,7 +562,7 @@ void tipc_node_add_router(struct node *n_ptr, u32 router)
               !n_ptr->routers[n_ptr->last_router]);
 }
 
-void tipc_node_remove_router(struct node *n_ptr, u32 router)
+void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router)
 {
        u32 r_num = tipc_node(router);
 
@@ -580,7 +580,7 @@ void tipc_node_remove_router(struct node *n_ptr, u32 router)
 }
 
 #if 0
-void node_print(struct print_buf *buf, struct node *n_ptr, char *str)
+void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str)
 {
        u32 i;
 
@@ -597,7 +597,7 @@ void node_print(struct print_buf *buf, struct node *n_ptr, char *str)
 
 u32 tipc_available_nodes(const u32 domain)
 {
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        u32 cnt = 0;
 
        read_lock_bh(&tipc_net_lock);
@@ -615,7 +615,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
 {
        u32 domain;
        struct sk_buff *buf;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        struct tipc_node_info node_info;
        u32 payload_size;
 
@@ -667,7 +667,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
 {
        u32 domain;
        struct sk_buff *buf;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        struct tipc_link_info link_info;
        u32 payload_size;
 
index cd1882654bbb27205307e0f61302c72ff8697f16..6f990da5d143cb30b63a87576c21f483186fbbc6 100644 (file)
@@ -43,7 +43,7 @@
 #include "bearer.h"
 
 /**
- * struct node - TIPC node structure
+ * struct tipc_node - TIPC node structure
  * @addr: network address of node
  * @lock: spinlock governing access to structure
  * @owner: pointer to cluster that node belongs to
  *    @defragm: list of partially reassembled b'cast message fragments from node
  */
 
-struct node {
+struct tipc_node {
        u32 addr;
        spinlock_t lock;
        struct cluster *owner;
-       struct node *next;
+       struct tipc_node *next;
        struct list_head nsub;
        struct link *active_links[2];
        struct link *links[MAX_BEARERS];
@@ -94,26 +94,26 @@ struct node {
        } bclink;
 };
 
-extern struct node *tipc_nodes;
+extern struct tipc_node *tipc_nodes;
 extern u32 tipc_own_tag;
 
-struct node *tipc_node_create(u32 addr);
-void tipc_node_delete(struct node *n_ptr);
-struct node *tipc_node_attach_link(struct link *l_ptr);
-void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr);
-void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr);
-void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr);
-int tipc_node_has_active_links(struct node *n_ptr);
-int tipc_node_has_redundant_links(struct node *n_ptr);
-u32 tipc_node_select_router(struct node *n_ptr, u32 ref);
-struct node *tipc_node_select_next_hop(u32 addr, u32 selector);
-int tipc_node_is_up(struct node *n_ptr);
-void tipc_node_add_router(struct node *n_ptr, u32 router);
-void tipc_node_remove_router(struct node *n_ptr, u32 router);
+struct tipc_node *tipc_node_create(u32 addr);
+void tipc_node_delete(struct tipc_node *n_ptr);
+struct tipc_node *tipc_node_attach_link(struct link *l_ptr);
+void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr);
+void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr);
+void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr);
+int tipc_node_has_active_links(struct tipc_node *n_ptr);
+int tipc_node_has_redundant_links(struct tipc_node *n_ptr);
+u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref);
+struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector);
+int tipc_node_is_up(struct tipc_node *n_ptr);
+void tipc_node_add_router(struct tipc_node *n_ptr, u32 router);
+void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router);
 struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
 struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
 
-static inline struct node *tipc_node_find(u32 addr)
+static inline struct tipc_node *tipc_node_find(u32 addr)
 {
        if (likely(in_own_cluster(addr)))
                return tipc_local_nodes[tipc_node(addr)];
@@ -126,19 +126,19 @@ static inline struct node *tipc_node_find(u32 addr)
        return NULL;
 }
 
-static inline struct node *tipc_node_select(u32 addr, u32 selector)
+static inline struct tipc_node *tipc_node_select(u32 addr, u32 selector)
 {
        if (likely(in_own_cluster(addr)))
                return tipc_local_nodes[tipc_node(addr)];
        return tipc_node_select_next_hop(addr, selector);
 }
 
-static inline void tipc_node_lock(struct node *n_ptr)
+static inline void tipc_node_lock(struct tipc_node *n_ptr)
 {
        spin_lock_bh(&n_ptr->lock);
 }
 
-static inline void tipc_node_unlock(struct node *n_ptr)
+static inline void tipc_node_unlock(struct tipc_node *n_ptr)
 {
        spin_unlock_bh(&n_ptr->lock);
 }
index 8ecbd0fb6103442712626899ee59edc6470ee0e2..19194d476a9e6e9ea1a5da38f55d6df4764628c0 100644 (file)
@@ -44,7 +44,7 @@
  * tipc_nodesub_subscribe - create "node down" subscription for specified node
  */
 
-void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
+void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,
                       void *usr_handle, net_ev_handler handle_down)
 {
        if (addr == tipc_own_addr) {
@@ -69,7 +69,7 @@ void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
  * tipc_nodesub_unsubscribe - cancel "node down" subscription (if any)
  */
 
-void tipc_nodesub_unsubscribe(struct node_subscr *node_sub)
+void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub)
 {
        if (!node_sub->node)
                return;
index 5f3f5859b84c3538252a7d21ccf36b0cca8c7af3..006ed739f51515ab17eff973e368b8e8d1733dff 100644 (file)
 typedef void (*net_ev_handler) (void *usr_handle);
 
 /**
- * struct node_subscr - "node down" subscription entry
+ * struct tipc_node_subscr - "node down" subscription entry
  * @node: ptr to node structure of interest (or NULL, if none)
  * @handle_node_down: routine to invoke when node fails
  * @usr_handle: argument to pass to routine when node fails
  * @nodesub_list: adjacent entries in list of subscriptions for the node
  */
 
-struct node_subscr {
-       struct node *node;
+struct tipc_node_subscr {
+       struct tipc_node *node;
        net_ev_handler handle_node_down;
        void *usr_handle;
        struct list_head nodesub_list;
 };
 
-void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
+void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,
                            void *usr_handle, net_ev_handler handle_down);
-void tipc_nodesub_unsubscribe(struct node_subscr *node_sub);
+void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub);
 
 #endif
index e5f8c16429bd36e60a336fd96287cf015bdb7508..ff31ee4a1dc3937d9e878debabbf6f9774bcbc24 100644 (file)
@@ -105,7 +105,7 @@ struct port {
        u32 probing_interval;
        u32 last_in_seqno;
        struct timer_list timer;
-       struct node_subscr subscription;
+       struct tipc_node_subscr subscription;
 };
 
 extern spinlock_t tipc_port_list_lock;
index 3506f856344162669d43a7b63ffebb6b04da0807..2c01ba2d86bf57f1667897b0993fe9ece6053534 100644 (file)
@@ -111,10 +111,10 @@ void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest)
        }
 }
 
-struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref)
+struct tipc_node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref)
 {
        struct cluster *c_ptr;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        u32 c_num;
 
        if (!z_ptr)
index 6e7a08df8af5bc1ca14b7263d7ed9a033edc3a42..7bdc3406ba9b0a1841f34c21411c72824e327fe0 100644 (file)
@@ -54,7 +54,7 @@ struct _zone {
        u32 links;
 };
 
-struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref);
+struct tipc_node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref);
 u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref);
 void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router);
 void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest);
index ab015c62d5612cd42b558179dee05a00ef3b2218..833b024f8f66ef2e1ac7c8a72a600090e41afa61 100644 (file)
@@ -39,4 +39,5 @@ config WIRELESS_EXT_SYSFS
          files in /sys/class/net/*/wireless/. The same information
          is available via the ioctls as well.
 
-         Say Y if you have programs using it (we don't know of any).
+         Say Y if you have programs using it, like old versions of
+         hal.
index 841b32a2e680818aae4b3eb6d8d3d5504acb616c..b7754b1b73a459fee91885c36d74d1d38b3fc9da 100644 (file)
@@ -1077,6 +1077,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
        struct hlist_head *chain = policy_hash_bysel(&pol->selector,
                                                     pol->family, dir);
 
+       list_add_tail(&pol->bytype, &xfrm_policy_bytype[pol->type]);
        hlist_add_head(&pol->bydst, chain);
        hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index));
        xfrm_policy_count[dir]++;
@@ -1731,8 +1732,7 @@ restart:
                         * We can't enlist stable bundles either.
                         */
                        write_unlock_bh(&policy->lock);
-                       if (dst)
-                               dst_free(dst);
+                       dst_free(dst);
 
                        if (pol_dead)
                                XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD);
@@ -1748,8 +1748,7 @@ restart:
                        err = xfrm_dst_update_origin(dst, fl);
                if (unlikely(err)) {
                        write_unlock_bh(&policy->lock);
-                       if (dst)
-                               dst_free(dst);
+                       dst_free(dst);
                        XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
                        goto error;
                }
index 4c6914ef7d92df5830baba92363108e502217c3f..0a8f09c3144c835fccbc1e3de4855b654c45a3b9 100644 (file)
@@ -780,11 +780,13 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
 {
        unsigned int h;
        struct hlist_node *entry;
-       struct xfrm_state *x, *x0;
+       struct xfrm_state *x, *x0, *to_put;
        int acquire_in_progress = 0;
        int error = 0;
        struct xfrm_state *best = NULL;
 
+       to_put = NULL;
+
        spin_lock_bh(&xfrm_state_lock);
        h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family);
        hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
@@ -833,7 +835,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
                if (tmpl->id.spi &&
                    (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi,
                                              tmpl->id.proto, family)) != NULL) {
-                       xfrm_state_put(x0);
+                       to_put = x0;
                        error = -EEXIST;
                        goto out;
                }
@@ -849,13 +851,14 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
                error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
                if (error) {
                        x->km.state = XFRM_STATE_DEAD;
-                       xfrm_state_put(x);
+                       to_put = x;
                        x = NULL;
                        goto out;
                }
 
                if (km_query(x, tmpl, pol) == 0) {
                        x->km.state = XFRM_STATE_ACQ;
+                       list_add_tail(&x->all, &xfrm_state_all);
                        hlist_add_head(&x->bydst, xfrm_state_bydst+h);
                        h = xfrm_src_hash(daddr, saddr, family);
                        hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
@@ -870,7 +873,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
                        xfrm_hash_grow_check(x->bydst.next != NULL);
                } else {
                        x->km.state = XFRM_STATE_DEAD;
-                       xfrm_state_put(x);
+                       to_put = x;
                        x = NULL;
                        error = -ESRCH;
                }
@@ -881,6 +884,8 @@ out:
        else
                *err = acquire_in_progress ? -EAGAIN : error;
        spin_unlock_bh(&xfrm_state_lock);
+       if (to_put)
+               xfrm_state_put(to_put);
        return x;
 }
 
@@ -1051,6 +1056,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
                xfrm_state_hold(x);
                x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
                add_timer(&x->timer);
+               list_add_tail(&x->all, &xfrm_state_all);
                hlist_add_head(&x->bydst, xfrm_state_bydst+h);
                h = xfrm_src_hash(daddr, saddr, family);
                hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
@@ -1067,18 +1073,20 @@ static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
 
 int xfrm_state_add(struct xfrm_state *x)
 {
-       struct xfrm_state *x1;
+       struct xfrm_state *x1, *to_put;
        int family;
        int err;
        int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
 
        family = x->props.family;
 
+       to_put = NULL;
+
        spin_lock_bh(&xfrm_state_lock);
 
        x1 = __xfrm_state_locate(x, use_spi, family);
        if (x1) {
-               xfrm_state_put(x1);
+               to_put = x1;
                x1 = NULL;
                err = -EEXIST;
                goto out;
@@ -1088,7 +1096,7 @@ int xfrm_state_add(struct xfrm_state *x)
                x1 = __xfrm_find_acq_byseq(x->km.seq);
                if (x1 && ((x1->id.proto != x->id.proto) ||
                    xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) {
-                       xfrm_state_put(x1);
+                       to_put = x1;
                        x1 = NULL;
                }
        }
@@ -1110,6 +1118,9 @@ out:
                xfrm_state_put(x1);
        }
 
+       if (to_put)
+               xfrm_state_put(to_put);
+
        return err;
 }
 EXPORT_SYMBOL(xfrm_state_add);
@@ -1269,10 +1280,12 @@ EXPORT_SYMBOL(xfrm_state_migrate);
 
 int xfrm_state_update(struct xfrm_state *x)
 {
-       struct xfrm_state *x1;
+       struct xfrm_state *x1, *to_put;
        int err;
        int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
 
+       to_put = NULL;
+
        spin_lock_bh(&xfrm_state_lock);
        x1 = __xfrm_state_locate(x, use_spi, x->props.family);
 
@@ -1281,7 +1294,7 @@ int xfrm_state_update(struct xfrm_state *x)
                goto out;
 
        if (xfrm_state_kern(x1)) {
-               xfrm_state_put(x1);
+               to_put = x1;
                err = -EEXIST;
                goto out;
        }
@@ -1295,6 +1308,9 @@ int xfrm_state_update(struct xfrm_state *x)
 out:
        spin_unlock_bh(&xfrm_state_lock);
 
+       if (to_put)
+               xfrm_state_put(to_put);
+
        if (err)
                return err;
 
index 7bd296cca041aaa7e62a3f923182ff7ac2adf5ef..46f23971f7e4208d9487cbb9cf477790a8fb378a 100644 (file)
@@ -508,12 +508,11 @@ int devcgroup_inode_permission(struct inode *inode, int mask)
                return 0;
        if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode))
                return 0;
-       dev_cgroup = css_to_devcgroup(task_subsys_state(current,
-                               devices_subsys_id));
-       if (!dev_cgroup)
-               return 0;
 
        rcu_read_lock();
+
+       dev_cgroup = task_devcgroup(current);
+
        list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
                if (wh->type & DEV_ALL)
                        goto acc_check;
@@ -533,6 +532,7 @@ acc_check:
                rcu_read_unlock();
                return 0;
        }
+
        rcu_read_unlock();
 
        return -EPERM;
@@ -543,12 +543,10 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
        struct dev_cgroup *dev_cgroup;
        struct dev_whitelist_item *wh;
 
-       dev_cgroup = css_to_devcgroup(task_subsys_state(current,
-                               devices_subsys_id));
-       if (!dev_cgroup)
-               return 0;
-
        rcu_read_lock();
+
+       dev_cgroup = task_devcgroup(current);
+
        list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
                if (wh->type & DEV_ALL)
                        goto acc_check;
@@ -566,6 +564,8 @@ acc_check:
                rcu_read_unlock();
                return 0;
        }
+
        rcu_read_unlock();
+
        return -EPERM;
 }
index b52f923ce680f95fc5b8ffbbebc70a87697db132..d11a8154500f7f312e4fd83bd56430593c7b1393 100644 (file)
@@ -811,11 +811,12 @@ static int string_to_context_struct(struct policydb *pol,
        /* Check the validity of the new context. */
        if (!policydb_context_isvalid(pol, ctx)) {
                rc = -EINVAL;
-               context_destroy(ctx);
                goto out;
        }
        rc = 0;
 out:
+       if (rc)
+               context_destroy(ctx);
        return rc;
 }
 
@@ -868,8 +869,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
        } else if (rc)
                goto out;
        rc = sidtab_context_to_sid(&sidtab, &context, sid);
-       if (rc)
-               context_destroy(&context);
+       context_destroy(&context);
 out:
        read_unlock(&policy_rwlock);
        kfree(scontext2);
index a37bee094eba4482c612612ae42366002e3b1134..8ebf512ced6caacee8f0f0a8aafa80772e530889 100644 (file)
@@ -91,6 +91,9 @@ endif # SOUND_PRIME
 
 endif # !M68K
 
+endif # SOUND
+
+# AC97_BUS is used from both sound and ucb1400
 config AC97_BUS
        tristate
        help
@@ -99,4 +102,3 @@ config AC97_BUS
          sound although they're sharing the AC97 bus. Concerned drivers
          should "select" this.
 
-endif # SOUND
index d6ec9eef291080502513d9b1fbf0faeac1e1e33a..66025161bd69fc0496973e1b9ee04fddc000c8d3 100644 (file)
@@ -14066,6 +14066,13 @@ static struct hda_verb alc662_auto_init_verbs[] = {
        { }
 };
 
+/* additional verbs for ALC663 */
+static struct hda_verb alc663_auto_init_verbs[] = {
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       { }
+};
+
 static struct hda_verb alc663_m51va_init_verbs[] = {
        {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -14594,6 +14601,14 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
        if (!pin)
                return 0;
 
+       if (pin == 0x17) {
+               /* ALC663 has a mono output pin on 0x17 */
+               sprintf(name, "%s Playback Switch", pfx);
+               err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+                                 HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT));
+               return err;
+       }
+
        if (alc880_is_fixed_pin(pin)) {
                nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
                 /* printk("DAC nid=%x\n",nid); */
@@ -14764,6 +14779,14 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
        spec->input_mux = &spec->private_imux;
        
        spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs;
+       if (codec->vendor_id == 0x10ec0663)
+               spec->init_verbs[spec->num_init_verbs++] =
+                       alc663_auto_init_verbs;
+
+       err = alc_auto_add_mic_boost(codec);
+       if (err < 0)
+               return err;
+
        spec->mixers[spec->num_mixers] = alc662_capture_mixer;
        spec->num_mixers++;
        return 1;
index 7fdafcb0015d8e9030c13c27b9d060c16ff9b39d..ad994fcab72508da6a7e483fd4b51526388643b6 100644 (file)
@@ -560,8 +560,9 @@ static struct hda_verb dell_eq_core_init[] = {
 };
 
 static struct hda_verb dell_m6_core_init[] = {
-       /* set master volume and direct control */
-       { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
+       /* set master volume to max value without distortion
+        * and direct control */
+       { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
        /* setup audio connections */
        { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
        { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
index 8548818eea085f0b89be4721a296431de5f52795..c796b1882776308390fa10e4225ff26820aaa9db 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/platform_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
@@ -81,7 +82,6 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
-       clk_i2s = clk_get(NULL, "I2SCLK");
        if (IS_ERR(clk_i2s))
                return PTR_ERR(clk_i2s);
 
@@ -152,6 +152,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
        pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
        pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
        pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
+       BUG_ON(IS_ERR(clk_i2s));
        clk_enable(clk_i2s);
        pxa_i2s_wait();
 
@@ -317,6 +318,43 @@ struct snd_soc_dai pxa_i2s_dai = {
 
 EXPORT_SYMBOL_GPL(pxa_i2s_dai);
 
+static int pxa2xx_i2s_probe(struct platform_device *dev)
+{
+       clk_i2s = clk_get(&dev->dev, "I2SCLK");
+       return IS_ERR(clk_i2s) ? PTR_ERR(clk_i2s) : 0;
+}
+
+static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
+{
+       clk_put(clk_i2s);
+       clk_i2s = ERR_PTR(-ENOENT);
+       return 0;
+}
+
+static struct platform_driver pxa2xx_i2s_driver = {
+       .probe = pxa2xx_i2s_probe,
+       .remove = __devexit_p(pxa2xx_i2s_remove),
+
+       .driver = {
+               .name = "pxa2xx-i2s",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init pxa2xx_i2s_init(void)
+{
+       clk_i2s = ERR_PTR(-ENOENT);
+       return platform_driver_register(&pxa2xx_i2s_driver);
+}
+
+static void __exit pxa2xx_i2s_exit(void)
+{
+       platform_driver_unregister(&pxa2xx_i2s_driver);
+}
+
+module_init(pxa2xx_i2s_init);
+module_exit(pxa2xx_i2s_exit);
+
 /* Module information */
 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
 MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");