From 6f131f15d38e8f6556282dd5074d4e679cc978cc Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 12 Dec 2006 18:18:26 +0100 Subject: [PATCH] --- yaml --- r: 44526 b: refs/heads/master c: 6b14a546a5a7fde46d20d3c14a4e91a24a3f1be0 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/CodingStyle | 126 +- trunk/Documentation/SubmitChecklist | 6 - trunk/Documentation/accounting/getdelays.c | 64 +- trunk/Documentation/cpu-freq/core.txt | 2 +- trunk/Documentation/dvb/cards.txt | 4 +- .../feature-removal-schedule.txt | 33 +- trunk/Documentation/filesystems/bfs.txt | 2 +- trunk/Documentation/filesystems/ocfs2.txt | 3 - trunk/Documentation/i2c/busses/i2c-amd8111 | 2 +- trunk/Documentation/i2c/busses/i2c-i801 | 5 +- trunk/Documentation/i2c/busses/i2c-nforce2 | 6 +- trunk/Documentation/ioctl/ioctl-decoding.txt | 24 - .../Documentation/kbuild/kconfig-language.txt | 8 +- trunk/Documentation/kernel-parameters.txt | 6 - trunk/Documentation/networking/dccp.txt | 6 +- trunk/Documentation/spi/pxa2xx | 16 +- trunk/Documentation/video4linux/CARDLIST.cx88 | 2 +- .../video4linux/CARDLIST.saa7134 | 7 +- trunk/Documentation/video4linux/cafe_ccic | 54 - trunk/Documentation/video4linux/zr36120.txt | 162 ++ trunk/MAINTAINERS | 17 +- trunk/Makefile | 35 +- trunk/arch/alpha/kernel/osf_sys.c | 6 +- trunk/arch/arm/kernel/apm.c | 2 +- trunk/arch/arm/kernel/ecard.c | 2 +- trunk/arch/arm/mach-omap1/Kconfig | 1 - trunk/arch/arm/mach-omap1/board-osk.c | 1 - trunk/arch/arm/mach-pnx4008/Makefile | 2 +- trunk/arch/arm/mach-pnx4008/i2c.c | 167 -- trunk/arch/arm/mach-pxa/Kconfig | 16 +- trunk/arch/arm/mach-realview/core.c | 13 - trunk/arch/arm/mach-realview/core.h | 1 - trunk/arch/arm/mach-realview/realview_eb.c | 1 - trunk/arch/arm/mach-versatile/core.c | 14 - trunk/arch/arm/plat-omap/Kconfig | 2 +- trunk/arch/arm26/kernel/ecard.c | 2 +- trunk/arch/arm26/kernel/irq.c | 2 +- trunk/arch/avr32/boards/atstk1000/atstk1002.c | 76 +- trunk/arch/avr32/kernel/avr32_ksyms.c | 2 +- trunk/arch/avr32/kernel/process.c | 7 - trunk/arch/avr32/kernel/setup.c | 24 + trunk/arch/avr32/lib/delay.c | 2 +- trunk/arch/avr32/mach-at32ap/at32ap7000.c | 182 +- trunk/arch/avr32/mach-at32ap/extint.c | 22 +- trunk/arch/avr32/mach-at32ap/intc.c | 4 - trunk/arch/avr32/mach-at32ap/pio.c | 85 +- trunk/arch/avr32/mach-at32ap/sm.c | 289 ++ .../arch/cris/arch-v10/drivers/axisflashmap.c | 2 +- trunk/arch/cris/arch-v10/drivers/gpio.c | 2 +- .../arch/cris/arch-v32/drivers/axisflashmap.c | 2 +- trunk/arch/cris/arch-v32/drivers/gpio.c | 2 +- trunk/arch/cris/arch-v32/kernel/signal.c | 2 +- trunk/arch/cris/kernel/profile.c | 2 +- trunk/arch/frv/kernel/pm.c | 6 +- trunk/arch/h8300/kernel/ints.c | 2 +- trunk/arch/h8300/platform/h8s/ints.c | 2 +- trunk/arch/i386/kernel/apm.c | 2 +- trunk/arch/i386/kernel/cpu/cpufreq/Kconfig | 6 +- trunk/arch/i386/kernel/cpu/cpufreq/Makefile | 2 +- .../i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 813 ++---- .../arch/i386/kernel/cpu/cpufreq/gx-suspmod.c | 4 +- trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c | 8 +- .../i386/kernel/cpu/cpufreq/p4-clockmod.c | 38 +- .../arch/i386/kernel/cpu/cpufreq/sc520_freq.c | 7 +- .../kernel/cpu/cpufreq/speedstep-centrino.c | 15 +- .../i386/kernel/cpu/cpufreq/speedstep-lib.c | 32 - .../i386/kernel/cpu/cpufreq/speedstep-lib.h | 1 - .../i386/kernel/cpu/cpufreq/speedstep-smi.c | 3 + trunk/arch/i386/kernel/microcode.c | 6 +- trunk/arch/i386/kernel/smpboot.c | 2 + trunk/arch/ia64/hp/sim/simserial.c | 2 +- trunk/arch/ia64/kernel/Makefile | 1 - trunk/arch/ia64/kernel/crash.c | 22 + trunk/arch/ia64/kernel/crash_dump.c | 48 - trunk/arch/ia64/kernel/jprobes.S | 3 +- trunk/arch/ia64/kernel/kprobes.c | 226 +- trunk/arch/ia64/kernel/machine_kexec.c | 7 +- trunk/arch/ia64/kernel/mca.c | 2 +- trunk/arch/ia64/kernel/setup.c | 33 +- trunk/arch/ia64/kernel/smp.c | 4 +- trunk/arch/ia64/kernel/traps.c | 50 +- trunk/arch/ia64/mm/contig.c | 9 +- trunk/arch/ia64/mm/init.c | 9 +- trunk/arch/ia64/sn/kernel/setup.c | 12 +- trunk/arch/ia64/sn/kernel/sn2/sn_hwperf.c | 2 +- trunk/arch/ia64/sn/kernel/xpc_channel.c | 15 +- trunk/arch/ia64/sn/kernel/xpc_main.c | 64 +- trunk/arch/m68k/mm/kmap.c | 2 +- trunk/arch/mips/configs/malta_defconfig | 80 +- trunk/arch/mips/kernel/apm.c | 2 +- trunk/arch/mips/kernel/kspd.c | 2 +- trunk/arch/mips/kernel/reset.c | 2 - trunk/arch/mips/kernel/vmlinux.lds.S | 2 +- trunk/arch/mips/lasat/sysctl.c | 17 +- trunk/arch/mips/lib/csum_partial_copy.c | 3 - trunk/arch/mips/mips-boards/malta/Makefile | 2 +- .../arch/mips/mips-boards/malta/malta_setup.c | 39 + trunk/arch/mips/mm/cache.c | 1 - trunk/arch/mips/mm/init.c | 17 +- trunk/arch/parisc/hpux/sys_hpux.c | 2 +- trunk/arch/parisc/kernel/unwind.c | 2 +- trunk/arch/powerpc/Kconfig | 8 +- trunk/arch/powerpc/configs/ps3_defconfig | 1 - trunk/arch/powerpc/kernel/Makefile | 1 - trunk/arch/powerpc/kernel/cputable.c | 5 +- trunk/arch/powerpc/kernel/head_32.S | 7 - trunk/arch/powerpc/kernel/module_32.c | 23 +- trunk/arch/powerpc/kernel/module_64.c | 23 +- trunk/arch/powerpc/kernel/nvram_64.c | 4 +- trunk/arch/powerpc/kernel/of_device.c | 4 +- trunk/arch/powerpc/kernel/of_platform.c | 2 +- trunk/arch/powerpc/kernel/pci_32.c | 145 +- trunk/arch/powerpc/kernel/pci_64.c | 42 +- trunk/arch/powerpc/kernel/ppc_ksyms.c | 2 +- trunk/arch/powerpc/kernel/prom.c | 55 - trunk/arch/powerpc/kernel/prom_init.c | 2 +- trunk/arch/powerpc/kernel/rtas.c | 35 +- trunk/arch/powerpc/kernel/sysfs.c | 16 - trunk/arch/powerpc/kernel/traps.c | 56 +- trunk/arch/powerpc/kernel/vmlinux.lds.S | 6 +- trunk/arch/powerpc/mm/imalloc.c | 6 +- trunk/arch/powerpc/mm/numa.c | 65 - trunk/arch/powerpc/platforms/4xx/Kconfig | 2 +- trunk/arch/powerpc/platforms/52xx/lite5200.c | 2 + .../arch/powerpc/platforms/cell/cbe_thermal.c | 2 - trunk/arch/powerpc/platforms/cell/pmu.c | 5 +- .../powerpc/platforms/cell/spufs/coredump.c | 2 +- .../powerpc/platforms/embedded6xx/Kconfig | 2 +- trunk/arch/powerpc/platforms/maple/pci.c | 2 +- trunk/arch/powerpc/platforms/maple/setup.c | 12 - trunk/arch/powerpc/platforms/ps3/Kconfig | 11 - trunk/arch/powerpc/platforms/pseries/Makefile | 2 - trunk/arch/powerpc/platforms/pseries/eeh.c | 1 - .../powerpc/platforms/pseries/eeh_cache.c | 2 +- .../powerpc/platforms/pseries/eeh_driver.c | 13 +- .../powerpc/platforms/pseries/hotplug-cpu.c | 275 -- trunk/arch/powerpc/platforms/pseries/setup.c | 30 +- trunk/arch/powerpc/platforms/pseries/smp.c | 200 ++ trunk/arch/powerpc/sysdev/Makefile | 3 +- trunk/arch/powerpc/sysdev/dcr.S | 39 + trunk/arch/powerpc/sysdev/qe_lib/qe_ic.c | 40 +- trunk/arch/powerpc/sysdev/rom.c | 1 - trunk/arch/powerpc/xmon/xmon.c | 10 +- trunk/arch/ppc/8260_io/fcc_enet.c | 4 +- trunk/arch/ppc/8xx_io/cs4218_tdm.c | 2 +- trunk/arch/ppc/Kconfig | 4 +- trunk/arch/ppc/kernel/pci.c | 41 +- trunk/arch/ppc/platforms/4xx/Kconfig | 2 +- trunk/arch/s390/Kconfig | 2 +- trunk/arch/s390/kernel/debug.c | 8 +- trunk/arch/s390/kernel/s390_ext.c | 2 +- trunk/arch/sh/Kconfig | 14 +- trunk/arch/sh/Kconfig.debug | 3 +- trunk/arch/sh/Makefile | 7 +- trunk/arch/sh/boards/landisk/irq.c | 4 +- trunk/arch/sh/boards/se/7206/irq.c | 16 +- trunk/arch/sh/boards/se/7619/Makefile | 2 +- trunk/arch/sh/boards/se/7619/io.c | 102 + trunk/arch/sh/boards/se/7619/setup.c | 21 + trunk/arch/sh/boot/Makefile | 40 +- trunk/arch/sh/boot/compressed/Makefile | 6 + trunk/arch/sh/boot/compressed/head.S | 3 +- trunk/arch/sh/boot/compressed/misc.c | 3 +- trunk/arch/sh/configs/landisk_defconfig | 85 +- trunk/arch/sh/configs/se7206_defconfig | 142 +- trunk/arch/sh/configs/se7619_defconfig | 744 ----- trunk/arch/sh/drivers/push-switch.c | 13 +- trunk/arch/sh/kernel/cpu/Makefile | 1 - trunk/arch/sh/kernel/cpu/sh2/entry.S | 32 +- trunk/arch/sh/kernel/cpu/sh2/setup-sh7619.c | 41 - trunk/arch/sh/kernel/cpu/sh2a/setup-sh7206.c | 62 +- trunk/arch/sh/kernel/cpu/sh4/Makefile | 9 +- .../kernel/cpu/{sh4a => sh4}/clock-sh73180.c | 0 .../kernel/cpu/{sh4a => sh4}/clock-sh7770.c | 0 .../kernel/cpu/{sh4a => sh4}/clock-sh7780.c | 0 trunk/arch/sh/kernel/cpu/sh4/probe.c | 9 - .../kernel/cpu/{sh4a => sh4}/setup-sh73180.c | 0 .../kernel/cpu/{sh4a => sh4}/setup-sh7343.c | 0 trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c | 31 - .../kernel/cpu/{sh4a => sh4}/setup-sh7770.c | 0 .../kernel/cpu/{sh4a => sh4}/setup-sh7780.c | 0 trunk/arch/sh/kernel/cpu/sh4/sq.c | 7 +- trunk/arch/sh/kernel/cpu/sh4a/Makefile | 19 - trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c | 99 - trunk/arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 80 - trunk/arch/sh/kernel/early_printk.c | 20 +- trunk/arch/sh/kernel/entry-common.S | 15 +- trunk/arch/sh/kernel/head.S | 3 +- trunk/arch/sh/kernel/process.c | 15 +- trunk/arch/sh/kernel/setup.c | 41 +- trunk/arch/sh/kernel/sh_ksyms.c | 15 +- trunk/arch/sh/kernel/signal.c | 2 +- trunk/arch/sh/kernel/sys_sh.c | 8 +- trunk/arch/sh/kernel/traps.c | 35 - trunk/arch/sh/kernel/vmlinux.lds.S | 2 +- trunk/arch/sh/mm/Kconfig | 12 +- trunk/arch/sh/mm/cache-sh4.c | 2 +- trunk/arch/sh/mm/init.c | 2 - trunk/arch/sparc/kernel/ioport.c | 6 +- trunk/arch/sparc/kernel/irq.c | 4 +- trunk/arch/sparc/kernel/of_device.c | 3 +- trunk/arch/sparc/kernel/ptrace.c | 5 +- trunk/arch/sparc/kernel/sun4d_irq.c | 9 +- trunk/arch/sparc/mm/io-unit.c | 8 +- trunk/arch/sparc64/Kconfig | 8 - trunk/arch/sparc64/Kconfig.debug | 4 - trunk/arch/sparc64/defconfig | 54 +- trunk/arch/sparc64/kernel/Makefile | 1 - trunk/arch/sparc64/kernel/chmc.c | 3 +- trunk/arch/sparc64/kernel/entry.S | 27 +- trunk/arch/sparc64/kernel/head.S | 8 - trunk/arch/sparc64/kernel/isa.c | 12 +- trunk/arch/sparc64/kernel/kprobes.c | 91 +- trunk/arch/sparc64/kernel/of_device.c | 3 +- trunk/arch/sparc64/kernel/pci_sun4v.c | 16 +- trunk/arch/sparc64/kernel/ptrace.c | 5 +- trunk/arch/sparc64/kernel/rtrap.S | 23 +- trunk/arch/sparc64/kernel/stacktrace.c | 41 - trunk/arch/sparc64/kernel/sun4v_ivec.S | 20 +- trunk/arch/sparc64/kernel/sys_sunos32.c | 4 +- trunk/arch/sparc64/kernel/traps.c | 30 +- trunk/arch/sparc64/kernel/unaligned.c | 44 +- trunk/arch/sparc64/kernel/visemul.c | 6 + trunk/arch/sparc64/mm/ultra.S | 8 - trunk/arch/um/drivers/net_kern.c | 18 +- trunk/arch/um/include/net_kern.h | 2 - trunk/arch/um/sys-i386/ldt.c | 4 +- trunk/arch/v850/Kconfig | 28 +- trunk/arch/x86_64/Kconfig | 2 +- trunk/arch/x86_64/kernel/cpufreq/Kconfig | 6 +- trunk/arch/x86_64/kernel/cpufreq/Makefile | 2 +- trunk/arch/x86_64/kernel/vsyscall.c | 3 +- trunk/arch/xtensa/Kconfig | 21 +- trunk/arch/xtensa/Makefile | 25 +- trunk/arch/xtensa/boot/boot-elf/bootstrap.S | 3 + .../arch/xtensa/boot/boot-redboot/bootstrap.S | 37 +- trunk/arch/xtensa/configs/iss_defconfig | 6 +- trunk/arch/xtensa/kernel/Makefile | 2 +- trunk/arch/xtensa/kernel/align.S | 42 +- trunk/arch/xtensa/kernel/asm-offsets.c | 5 - trunk/arch/xtensa/kernel/coprocessor.S | 2 +- trunk/arch/xtensa/kernel/entry.S | 256 +- trunk/arch/xtensa/kernel/head.S | 53 +- trunk/arch/xtensa/kernel/irq.c | 107 +- trunk/arch/xtensa/kernel/pci-dma.c | 44 +- trunk/arch/xtensa/kernel/process.c | 108 +- trunk/arch/xtensa/kernel/ptrace.c | 28 +- trunk/arch/xtensa/kernel/setup.c | 41 +- trunk/arch/xtensa/kernel/signal.c | 28 +- trunk/arch/xtensa/kernel/syscall.c | 95 - trunk/arch/xtensa/kernel/syscalls.c | 288 ++ trunk/arch/xtensa/kernel/syscalls.h | 247 ++ trunk/arch/xtensa/kernel/time.c | 8 +- trunk/arch/xtensa/kernel/traps.c | 56 +- trunk/arch/xtensa/kernel/vectors.S | 12 +- trunk/arch/xtensa/kernel/vmlinux.lds.S | 26 +- trunk/arch/xtensa/lib/checksum.S | 3 +- trunk/arch/xtensa/lib/memcopy.S | 2 +- trunk/arch/xtensa/lib/memset.S | 2 +- trunk/arch/xtensa/lib/strncpy_user.S | 2 +- trunk/arch/xtensa/lib/strnlen_user.S | 2 +- trunk/arch/xtensa/lib/usercopy.S | 2 +- trunk/arch/xtensa/mm/fault.c | 10 +- trunk/arch/xtensa/mm/init.c | 6 +- trunk/arch/xtensa/mm/misc.S | 265 +- trunk/arch/xtensa/mm/tlb.c | 445 ++- trunk/arch/xtensa/platform-iss/console.c | 8 +- trunk/arch/xtensa/platform-iss/network.c | 2 +- trunk/block/ll_rw_blk.c | 19 +- trunk/block/scsi_ioctl.c | 10 +- trunk/crypto/blkcipher.c | 1 + trunk/crypto/sha512.c | 2 +- trunk/drivers/Kconfig | 2 - trunk/drivers/Makefile | 1 - trunk/drivers/acorn/block/fd1772.c | 4 +- trunk/drivers/acorn/char/i2c.c | 2 +- trunk/drivers/ata/pdc_adma.c | 4 +- trunk/drivers/atm/.gitignore | 2 +- trunk/drivers/atm/eni.c | 4 +- trunk/drivers/atm/he.c | 2 +- trunk/drivers/atm/lanai.c | 2 +- trunk/drivers/atm/nicstar.c | 4 +- trunk/drivers/atm/zatm.c | 4 +- trunk/drivers/base/dmapool.c | 2 +- trunk/drivers/block/Kconfig | 7 + trunk/drivers/block/Makefile | 1 + trunk/drivers/block/cciss.c | 23 +- trunk/drivers/block/cpqarray.c | 10 +- trunk/drivers/block/swim_iop.c | 578 ++++ trunk/drivers/cdrom/cdrom.c | 8 +- trunk/drivers/cdrom/cm206.c | 2 +- trunk/drivers/char/Kconfig | 10 +- trunk/drivers/char/agp/Kconfig | 4 +- trunk/drivers/char/agp/generic.c | 25 - trunk/drivers/char/consolemap.c | 2 +- trunk/drivers/char/ipmi/ipmi_bt_sm.c | 4 +- trunk/drivers/char/ipmi/ipmi_devintf.c | 2 +- trunk/drivers/char/ipmi/ipmi_msghandler.c | 12 +- trunk/drivers/char/ipmi/ipmi_poweroff.c | 6 +- trunk/drivers/char/ipmi/ipmi_si_intf.c | 132 +- trunk/drivers/char/ipmi/ipmi_watchdog.c | 18 +- trunk/drivers/char/lcd.c | 2 +- trunk/drivers/char/lp.c | 2 +- trunk/drivers/char/mem.c | 12 +- trunk/drivers/char/mxser_new.c | 8 - trunk/drivers/char/n_r3964.c | 37 +- trunk/drivers/char/n_tty.c | 1 + trunk/drivers/char/pcmcia/synclink_cs.c | 2 +- trunk/drivers/char/random.c | 2 +- trunk/drivers/char/rio/riocmd.c | 2 +- trunk/drivers/char/rtc.c | 38 +- trunk/drivers/char/sx.c | 8 - trunk/drivers/char/synclink.c | 2 +- trunk/drivers/char/synclinkmp.c | 4 +- trunk/drivers/char/sysrq.c | 37 +- trunk/drivers/char/tty_io.c | 8 +- trunk/drivers/char/viocons.c | 10 +- trunk/drivers/char/vt.c | 2 +- trunk/drivers/char/vt_ioctl.c | 10 +- trunk/drivers/char/watchdog/at91rm9200_wdt.c | 6 +- trunk/drivers/char/watchdog/mpcore_wdt.c | 2 +- trunk/drivers/char/watchdog/omap_wdt.c | 2 +- trunk/drivers/char/watchdog/pcwd_usb.c | 5 +- trunk/drivers/char/watchdog/rm9k_wdt.c | 44 +- trunk/drivers/clocksource/acpi_pm.c | 6 +- trunk/drivers/cpufreq/cpufreq.c | 153 +- trunk/drivers/cpufreq/cpufreq_conservative.c | 33 +- trunk/drivers/cpufreq/cpufreq_ondemand.c | 33 +- trunk/drivers/cpufreq/cpufreq_performance.c | 9 +- trunk/drivers/cpufreq/cpufreq_powersave.c | 9 +- trunk/drivers/cpufreq/cpufreq_stats.c | 11 +- trunk/drivers/cpufreq/cpufreq_userspace.c | 11 +- trunk/drivers/cpufreq/freq_table.c | 28 +- trunk/drivers/crypto/Kconfig | 2 +- trunk/drivers/fc4/fc.c | 10 +- trunk/drivers/hwmon/f71805f.c | 26 +- trunk/drivers/i2c/algos/Kconfig | 11 + trunk/drivers/i2c/algos/Makefile | 1 + trunk/drivers/i2c/algos/i2c-algo-bit.c | 8 + trunk/drivers/i2c/algos/i2c-algo-ite.c | 806 ++++++ trunk/drivers/i2c/algos/i2c-algo-ite.h | 117 + trunk/drivers/i2c/algos/i2c-algo-pca.c | 7 + trunk/drivers/i2c/algos/i2c-algo-pcf.c | 8 + trunk/drivers/i2c/algos/i2c-algo-sgi.c | 8 + trunk/drivers/i2c/busses/Kconfig | 49 +- trunk/drivers/i2c/busses/Makefile | 4 +- trunk/drivers/i2c/busses/i2c-at91.c | 325 --- trunk/drivers/i2c/busses/i2c-elektor.c | 2 +- trunk/drivers/i2c/busses/i2c-hydra.c | 2 +- trunk/drivers/i2c/busses/i2c-i801.c | 16 +- trunk/drivers/i2c/busses/i2c-i810.c | 6 +- trunk/drivers/i2c/busses/i2c-ibm_iic.c | 9 - trunk/drivers/i2c/busses/i2c-ite.c | 278 ++ trunk/drivers/i2c/busses/i2c-ixp2000.c | 2 +- trunk/drivers/i2c/busses/i2c-ixp4xx.c | 2 +- trunk/drivers/i2c/busses/i2c-nforce2.c | 89 +- trunk/drivers/i2c/busses/i2c-omap.c | 4 +- trunk/drivers/i2c/busses/i2c-parport-light.c | 2 +- trunk/drivers/i2c/busses/i2c-parport.c | 2 +- trunk/drivers/i2c/busses/i2c-pca-isa.c | 2 +- trunk/drivers/i2c/busses/i2c-pnx.c | 708 ----- trunk/drivers/i2c/busses/i2c-prosavage.c | 2 +- trunk/drivers/i2c/busses/i2c-savage4.c | 2 +- trunk/drivers/i2c/busses/i2c-versatile.c | 153 - trunk/drivers/i2c/busses/i2c-via.c | 2 +- trunk/drivers/i2c/busses/i2c-voodoo3.c | 6 +- trunk/drivers/i2c/busses/scx200_i2c.c | 2 +- trunk/drivers/i2c/chips/ds1337.c | 8 +- trunk/drivers/i2c/chips/tps65010.c | 21 +- trunk/drivers/i2c/i2c-core.c | 67 +- trunk/drivers/i2c/i2c-dev.c | 44 +- trunk/drivers/ide/Kconfig | 2 +- trunk/drivers/ide/ide-cd.c | 7 - trunk/drivers/ide/ide-floppy.c | 2 +- trunk/drivers/ide/ide-probe.c | 4 + trunk/drivers/ide/ide-tape.c | 8 +- trunk/drivers/ide/pci/hpt366.c | 886 +++--- trunk/drivers/ide/pci/pdc202xx_new.c | 483 +--- trunk/drivers/ide/pci/piix.c | 4 - trunk/drivers/ide/setup-pci.c | 4 +- trunk/drivers/ieee1394/pcilynx.c | 2 +- trunk/drivers/infiniband/core/Makefile | 6 +- trunk/drivers/infiniband/core/cm.c | 4 - trunk/drivers/infiniband/core/cma.c | 416 +-- trunk/drivers/infiniband/core/fmr_pool.c | 12 +- trunk/drivers/infiniband/core/mad.c | 90 +- trunk/drivers/infiniband/core/mad_priv.h | 6 +- trunk/drivers/infiniband/core/ucma.c | 874 ------ .../drivers/infiniband/core/uverbs_marshall.c | 5 +- trunk/drivers/infiniband/core/uverbs_mem.c | 12 +- trunk/drivers/infiniband/hw/amso1100/c2_qp.c | 13 +- trunk/drivers/infiniband/hw/ipath/Makefile | 1 - trunk/drivers/infiniband/hw/ipath/ipath_dma.c | 189 -- .../infiniband/hw/ipath/ipath_driver.c | 4 +- .../infiniband/hw/ipath/ipath_file_ops.c | 5 +- .../infiniband/hw/ipath/ipath_iba6110.c | 3 +- .../infiniband/hw/ipath/ipath_iba6120.c | 8 +- .../infiniband/hw/ipath/ipath_init_chip.c | 3 +- .../drivers/infiniband/hw/ipath/ipath_intr.c | 3 +- .../drivers/infiniband/hw/ipath/ipath_keys.c | 8 +- trunk/drivers/infiniband/hw/ipath/ipath_mr.c | 7 +- .../drivers/infiniband/hw/ipath/ipath_sysfs.c | 3 + .../drivers/infiniband/hw/ipath/ipath_verbs.c | 1 - .../drivers/infiniband/hw/ipath/ipath_verbs.h | 2 - trunk/drivers/infiniband/ulp/ipoib/ipoib.h | 4 +- trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c | 75 +- .../drivers/infiniband/ulp/ipoib/ipoib_main.c | 3 +- .../drivers/infiniband/ulp/iser/iscsi_iser.h | 2 +- .../infiniband/ulp/iser/iser_initiator.c | 4 + .../drivers/infiniband/ulp/iser/iser_memory.c | 125 +- trunk/drivers/infiniband/ulp/srp/ib_srp.c | 81 +- trunk/drivers/infiniband/ulp/srp/ib_srp.h | 2 +- trunk/drivers/input/keyboard/hilkbd.c | 5 - trunk/drivers/input/touchscreen/Kconfig | 2 +- trunk/drivers/isdn/act2000/act2000_isa.c | 2 +- trunk/drivers/isdn/capi/capidrv.c | 2 +- trunk/drivers/isdn/divert/divert_procfs.c | 2 +- trunk/drivers/isdn/divert/isdn_divert.c | 6 +- trunk/drivers/isdn/gigaset/bas-gigaset.c | 118 +- trunk/drivers/isdn/hisax/Kconfig | 10 +- trunk/drivers/isdn/hysdn/hysdn_procconf.c | 2 +- trunk/drivers/isdn/hysdn/hysdn_proclog.c | 2 +- trunk/drivers/isdn/i4l/isdn_audio.c | 6 +- trunk/drivers/isdn/i4l/isdn_net.c | 2 +- trunk/drivers/isdn/i4l/isdn_ppp.c | 2 +- trunk/drivers/isdn/pcbit/layer2.c | 2 +- trunk/drivers/kvm/Kconfig | 37 - trunk/drivers/kvm/Makefile | 10 - trunk/drivers/kvm/kvm.h | 551 ---- trunk/drivers/kvm/kvm_main.c | 1917 ------------- trunk/drivers/kvm/kvm_svm.h | 44 - trunk/drivers/kvm/kvm_vmx.h | 14 - trunk/drivers/kvm/mmu.c | 686 ----- trunk/drivers/kvm/paging_tmpl.h | 391 --- trunk/drivers/kvm/segment_descriptor.h | 17 - trunk/drivers/kvm/svm.c | 1641 ----------- trunk/drivers/kvm/svm.h | 315 -- trunk/drivers/kvm/vmx.c | 2014 ------------- trunk/drivers/kvm/vmx.h | 296 -- trunk/drivers/kvm/x86_emulate.c | 1409 --------- trunk/drivers/kvm/x86_emulate.h | 185 -- trunk/drivers/leds/Kconfig | 22 +- trunk/drivers/macintosh/adb.c | 2 +- trunk/drivers/macintosh/apm_emu.c | 2 +- trunk/drivers/macintosh/smu.c | 2 +- trunk/drivers/macintosh/via-pmu68k.c | 2 +- trunk/drivers/md/Kconfig | 1 - trunk/drivers/md/faulty.c | 2 +- trunk/drivers/md/md.c | 17 +- trunk/drivers/md/raid1.c | 3 +- trunk/drivers/md/raid10.c | 6 +- trunk/drivers/md/raid5.c | 367 +-- trunk/drivers/media/Kconfig | 2 - trunk/drivers/media/common/ir-keymaps.c | 55 - trunk/drivers/media/common/saa7146_i2c.c | 16 +- trunk/drivers/media/dvb/b2c2/Kconfig | 1 - .../drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 10 +- trunk/drivers/media/dvb/bt8xx/Kconfig | 2 +- trunk/drivers/media/dvb/bt8xx/dst_ca.c | 2 +- trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.c | 11 +- trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.h | 2 +- trunk/drivers/media/dvb/cinergyT2/cinergyT2.c | 13 +- trunk/drivers/media/dvb/dvb-usb/Kconfig | 14 - trunk/drivers/media/dvb/dvb-usb/Makefile | 3 - trunk/drivers/media/dvb/dvb-usb/a800.c | 36 +- trunk/drivers/media/dvb/dvb-usb/cxusb.c | 271 +- trunk/drivers/media/dvb/dvb-usb/dib0700.h | 5 - .../drivers/media/dvb/dvb-usb/dib0700_core.c | 40 +- .../media/dvb/dvb-usb/dib0700_devices.c | 200 +- trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c | 113 +- trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c | 26 +- trunk/drivers/media/dvb/dvb-usb/digitv.c | 22 +- trunk/drivers/media/dvb/dvb-usb/dtt200u.c | 24 +- trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 14 +- .../media/dvb/dvb-usb/dvb-usb-remote.c | 37 +- trunk/drivers/media/dvb/dvb-usb/gp8psk.c | 22 +- trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c | 34 +- trunk/drivers/media/dvb/dvb-usb/ttusb2.c | 270 -- trunk/drivers/media/dvb/dvb-usb/ttusb2.h | 70 - trunk/drivers/media/dvb/dvb-usb/umt-010.c | 24 +- trunk/drivers/media/dvb/dvb-usb/vp702x.c | 20 +- trunk/drivers/media/dvb/dvb-usb/vp7045.c | 40 +- trunk/drivers/media/dvb/frontends/Kconfig | 24 - trunk/drivers/media/dvb/frontends/Makefile | 3 - trunk/drivers/media/dvb/frontends/dib3000mc.c | 7 +- trunk/drivers/media/dvb/frontends/dib7000m.c | 1191 -------- trunk/drivers/media/dvb/frontends/dib7000m.h | 51 - trunk/drivers/media/dvb/frontends/dib7000p.c | 1019 ------- trunk/drivers/media/dvb/frontends/dib7000p.h | 46 - .../media/dvb/frontends/dibx000_common.h | 13 +- trunk/drivers/media/dvb/frontends/dvb-pll.c | 67 +- trunk/drivers/media/dvb/frontends/dvb-pll.h | 7 +- trunk/drivers/media/dvb/frontends/lg_h06xf.h | 64 + trunk/drivers/media/dvb/frontends/lgdt330x.c | 257 +- .../media/dvb/frontends/lgdt330x_priv.h | 15 +- trunk/drivers/media/dvb/frontends/lgh06xf.c | 134 - trunk/drivers/media/dvb/frontends/lgh06xf.h | 35 - trunk/drivers/media/dvb/frontends/or51132.c | 176 +- trunk/drivers/media/dvb/frontends/or51211.c | 124 +- trunk/drivers/media/dvb/frontends/tda1004x.c | 10 +- trunk/drivers/media/dvb/frontends/tda1004x.h | 5 +- trunk/drivers/media/dvb/frontends/tda8083.c | 30 - trunk/drivers/media/dvb/frontends/tda826x.c | 12 +- trunk/drivers/media/dvb/frontends/tua6100.c | 3 +- trunk/drivers/media/dvb/pluto2/pluto2.c | 8 +- trunk/drivers/media/dvb/ttpci/Kconfig | 1 - trunk/drivers/media/dvb/ttpci/av7110.c | 2 +- trunk/drivers/media/dvb/ttpci/av7110_ir.c | 25 +- trunk/drivers/media/dvb/ttpci/budget-av.c | 26 +- trunk/drivers/media/dvb/ttpci/budget-ci.c | 334 +-- trunk/drivers/media/dvb/ttpci/budget.c | 2 +- trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c | 11 +- .../drivers/media/dvb/ttusb-dec/ttusbdecfe.c | 4 +- trunk/drivers/media/video/Kconfig | 31 +- trunk/drivers/media/video/Makefile | 6 +- trunk/drivers/media/video/bt8xx/bttv-driver.c | 2 +- trunk/drivers/media/video/bt8xx/bttv-i2c.c | 6 +- trunk/drivers/media/video/bt8xx/bttv-input.c | 101 +- trunk/drivers/media/video/cafe_ccic-regs.h | 160 -- trunk/drivers/media/video/cafe_ccic.c | 2228 -------------- trunk/drivers/media/video/cx88/Kconfig | 1 - .../drivers/media/video/cx88/cx88-blackbird.c | 179 +- trunk/drivers/media/video/cx88/cx88-cards.c | 86 +- trunk/drivers/media/video/cx88/cx88-core.c | 2 +- trunk/drivers/media/video/cx88/cx88-dvb.c | 333 ++- trunk/drivers/media/video/cx88/cx88-input.c | 77 +- trunk/drivers/media/video/cx88/cx88-mpeg.c | 348 +-- trunk/drivers/media/video/cx88/cx88-tvaudio.c | 13 + trunk/drivers/media/video/cx88/cx88-video.c | 32 - .../media/video/cx88/cx88-vp3054-i2c.c | 2 +- trunk/drivers/media/video/cx88/cx88.h | 47 - trunk/drivers/media/video/dabusb.c | 4 +- trunk/drivers/media/video/ir-kbd-i2c.c | 46 +- trunk/drivers/media/video/mxb.c | 8 +- trunk/drivers/media/video/ov7670.c | 1333 --------- trunk/drivers/media/video/planb.c | 2 +- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 16 - .../drivers/media/video/pvrusb2/pvrusb2-hdw.c | 26 + .../media/video/pvrusb2/pvrusb2-i2c-core.c | 81 +- trunk/drivers/media/video/saa7115.c | 18 +- .../media/video/saa7134/saa7134-alsa.c | 63 +- .../media/video/saa7134/saa7134-cards.c | 222 -- .../media/video/saa7134/saa7134-core.c | 11 +- .../drivers/media/video/saa7134/saa7134-dvb.c | 222 +- .../drivers/media/video/saa7134/saa7134-i2c.c | 1 - .../media/video/saa7134/saa7134-input.c | 76 +- trunk/drivers/media/video/saa7134/saa7134.h | 8 - trunk/drivers/media/video/stv680.c | 21 +- trunk/drivers/media/video/tda9887.c | 6 - trunk/drivers/media/video/tuner-core.c | 4 - trunk/drivers/media/video/tuner-simple.c | 4 - trunk/drivers/media/video/tuner-types.c | 15 +- trunk/drivers/media/video/tveeprom.c | 9 +- .../media/video/usbvideo/quickcam_messenger.c | 9 +- trunk/drivers/media/video/usbvideo/usbvideo.c | 2 +- trunk/drivers/media/video/usbvision/Kconfig | 12 - trunk/drivers/media/video/usbvision/Makefile | 5 - .../media/video/usbvision/usbvision-cards.c | 157 - .../media/video/usbvision/usbvision-core.c | 2554 ----------------- .../media/video/usbvision/usbvision-i2c.c | 571 ---- .../media/video/usbvision/usbvision-video.c | 2051 ------------- .../drivers/media/video/usbvision/usbvision.h | 558 ---- trunk/drivers/media/video/v4l1-compat.c | 18 +- trunk/drivers/media/video/v4l2-common.c | 85 +- trunk/drivers/media/video/videocodec.c | 2 +- trunk/drivers/media/video/videodev.c | 173 +- trunk/drivers/media/video/vino.c | 2 +- trunk/drivers/media/video/vivi.c | 16 +- trunk/drivers/media/video/zoran_card.c | 2 +- trunk/drivers/media/video/zr36120.c | 2079 ++++++++++++++ trunk/drivers/media/video/zr36120.h | 279 ++ trunk/drivers/media/video/zr36120_i2c.c | 132 + trunk/drivers/media/video/zr36120_mem.c | 78 + trunk/drivers/media/video/zr36120_mem.h | 3 + trunk/drivers/message/i2o/core.h | 4 +- trunk/drivers/message/i2o/driver.c | 2 +- trunk/drivers/message/i2o/exec-osm.c | 2 +- trunk/drivers/message/i2o/i2o_config.c | 4 +- trunk/drivers/mmc/at91_mci.c | 346 ++- trunk/drivers/mmc/mmc_queue.c | 4 +- trunk/drivers/mmc/sdhci.c | 4 +- trunk/drivers/mtd/devices/mtd_dataflash.c | 2 +- trunk/drivers/mtd/rfd_ftl.c | 2 +- trunk/drivers/net/8139too.c | 5 +- trunk/drivers/net/Kconfig | 8 - trunk/drivers/net/appletalk/ipddp.c | 2 +- trunk/drivers/net/bsd_comp.c | 2 +- trunk/drivers/net/chelsio/cxgb2.c | 23 +- trunk/drivers/net/chelsio/sge.c | 115 +- trunk/drivers/net/chelsio/sge.h | 4 +- trunk/drivers/net/e100.c | 3 +- trunk/drivers/net/hamradio/baycom_epp.c | 2 +- trunk/drivers/net/irda/donauboe.c | 2 +- trunk/drivers/net/irda/irda-usb.c | 2 +- trunk/drivers/net/irda/irport.c | 2 +- trunk/drivers/net/lp486e.c | 4 +- trunk/drivers/net/macb.c | 8 +- trunk/drivers/net/macb.h | 6 +- trunk/drivers/net/myri10ge/myri10ge.c | 498 ++-- trunk/drivers/net/phy/phy_device.c | 2 +- trunk/drivers/net/ppp_deflate.c | 4 +- trunk/drivers/net/ppp_mppe.c | 2 +- trunk/drivers/net/skge.c | 2 +- trunk/drivers/net/slip.c | 6 +- trunk/drivers/net/smc91x.h | 90 + trunk/drivers/net/ucc_geth.c | 12 +- trunk/drivers/net/wan/Kconfig | 5 +- trunk/drivers/net/wan/hostess_sv11.c | 2 +- trunk/drivers/net/wan/pc300_drv.c | 2 +- trunk/drivers/net/wan/pc300_tty.c | 2 +- trunk/drivers/net/wan/x25_asy.c | 8 +- trunk/drivers/net/wireless/hostap/hostap_ap.c | 2 +- .../net/wireless/hostap/hostap_download.c | 2 +- trunk/drivers/net/wireless/hostap/hostap_hw.c | 2 +- .../net/wireless/hostap/hostap_ioctl.c | 2 +- .../drivers/net/wireless/hostap/hostap_main.c | 2 +- trunk/drivers/net/wireless/ipw2100.c | 2 +- .../drivers/net/wireless/prism54/isl_ioctl.c | 2 +- trunk/drivers/net/wireless/wavelan_cs.c | 2 +- trunk/drivers/net/wireless/zd1211rw/zd_chip.c | 2 +- trunk/drivers/parisc/iosapic.c | 2 +- trunk/drivers/parport/Kconfig | 6 +- trunk/drivers/pci/hotplug/Kconfig | 3 +- trunk/drivers/pci/hotplug/cpqphp_nvram.c | 8 +- trunk/drivers/pci/hotplug/pciehp_hpc.c | 2 +- trunk/drivers/pci/pcie/aer/aerdrv.c | 2 +- trunk/drivers/pcmcia/at91_cf.c | 2 +- trunk/drivers/pcmcia/omap_cf.c | 2 +- trunk/drivers/pnp/isapnp/core.c | 22 +- trunk/drivers/pnp/pnpacpi/core.c | 6 +- trunk/drivers/pnp/pnpacpi/rsparser.c | 22 +- trunk/drivers/pnp/pnpbios/core.c | 16 +- trunk/drivers/pnp/pnpbios/proc.c | 8 +- trunk/drivers/pnp/pnpbios/rsparser.c | 16 +- trunk/drivers/ps3/Makefile | 1 - trunk/drivers/ps3/vuart.c | 965 ------- trunk/drivers/ps3/vuart.h | 94 - trunk/drivers/rtc/Kconfig | 2 +- trunk/drivers/rtc/Makefile | 2 +- .../rtc/{rtc-at91rm9200.c => rtc-at91.c} | 5 +- trunk/drivers/rtc/rtc-dev.c | 2 +- trunk/drivers/rtc/rtc-ds1672.c | 2 +- trunk/drivers/rtc/rtc-lib.c | 81 - trunk/drivers/rtc/rtc-omap.c | 3 +- trunk/drivers/rtc/rtc-pcf8563.c | 6 +- trunk/drivers/rtc/rtc-proc.c | 4 +- trunk/drivers/rtc/rtc-rs5c372.c | 2 +- trunk/drivers/rtc/rtc-s3c.c | 6 +- trunk/drivers/rtc/rtc-sa1100.c | 4 +- trunk/drivers/rtc/rtc-sh.c | 245 +- trunk/drivers/rtc/rtc-sysfs.c | 2 +- trunk/drivers/rtc/rtc-x1205.c | 10 +- trunk/drivers/s390/char/con3215.c | 2 +- trunk/drivers/s390/char/keyboard.c | 2 +- trunk/drivers/s390/char/sclp_cpi.c | 2 +- trunk/drivers/s390/crypto/zcrypt_cex2a.c | 4 +- trunk/drivers/s390/crypto/zcrypt_pcica.c | 4 +- trunk/drivers/s390/crypto/zcrypt_pcixcc.c | 2 +- trunk/drivers/s390/net/ctcmain.c | 6 +- trunk/drivers/s390/net/iucv.c | 2 +- trunk/drivers/s390/scsi/zfcp_aux.c | 2 +- trunk/drivers/sbus/char/vfc_dev.c | 2 +- trunk/drivers/scsi/aacraid/aachba.c | 2 +- trunk/drivers/scsi/aacraid/comminit.c | 2 +- trunk/drivers/scsi/aha1542.c | 2 +- trunk/drivers/scsi/aic7xxx_old.c | 2 +- trunk/drivers/scsi/dc395x.c | 2 +- trunk/drivers/scsi/dpt_i2o.c | 10 +- trunk/drivers/scsi/initio.c | 2 +- trunk/drivers/scsi/osst.c | 2 +- trunk/drivers/scsi/pluto.c | 2 +- trunk/drivers/scsi/sr_ioctl.c | 2 +- trunk/drivers/scsi/sr_vendor.c | 4 +- trunk/drivers/scsi/sym53c8xx_2/sym_hipd.c | 2 +- trunk/drivers/serial/Kconfig | 57 +- trunk/drivers/serial/icom.c | 2 +- trunk/drivers/serial/sh-sci.c | 22 - trunk/drivers/serial/sh-sci.h | 19 - trunk/drivers/spi/pxa2xx_spi.c | 733 ++--- trunk/drivers/usb/gadget/at91_udc.c | 2 +- trunk/drivers/usb/gadget/serial.c | 2 +- trunk/drivers/usb/host/hc_crisv10.c | 2 +- trunk/drivers/usb/misc/auerswald.c | 4 +- trunk/drivers/usb/misc/uss720.c | 2 +- trunk/drivers/usb/net/rndis_host.c | 2 +- trunk/drivers/usb/serial/cypress_m8.c | 2 +- trunk/drivers/usb/serial/digi_acceleport.c | 4 +- trunk/drivers/usb/serial/io_ti.c | 2 +- trunk/drivers/usb/serial/ipaq.c | 2 +- trunk/drivers/usb/serial/kobil_sct.c | 4 +- trunk/drivers/usb/serial/pl2303.c | 2 +- trunk/drivers/usb/serial/ti_usb_3410_5052.c | 2 +- trunk/drivers/usb/serial/whiteheat.c | 4 +- trunk/drivers/usb/storage/sddr09.c | 2 +- trunk/drivers/video/Kconfig | 10 - trunk/drivers/video/Makefile | 1 - trunk/drivers/video/amba-clcd.c | 2 +- trunk/drivers/video/amifb.c | 8 + trunk/drivers/video/aty/atyfb_base.c | 4 + trunk/drivers/video/aty/radeon_i2c.c | 8 +- trunk/drivers/video/gxt4500.c | 741 ----- trunk/drivers/video/i810/i810-i2c.c | 6 +- trunk/drivers/video/intelfb/intelfb_i2c.c | 4 +- trunk/drivers/video/matrox/i2c-matroxfb.c | 4 +- trunk/drivers/video/matrox/matroxfb_base.c | 2 +- trunk/drivers/video/matrox/matroxfb_crtc2.c | 2 +- trunk/drivers/video/nvidia/nv_i2c.c | 6 +- trunk/drivers/video/riva/rivafb-i2c.c | 6 +- trunk/drivers/video/savage/savagefb-i2c.c | 2 +- trunk/drivers/video/sstfb.c | 335 ++- trunk/drivers/w1/slaves/Kconfig | 4 +- trunk/fs/Kconfig | 14 +- trunk/fs/aio.c | 2 +- trunk/fs/autofs4/inode.c | 2 +- trunk/fs/befs/btree.c | 2 +- trunk/fs/befs/debug.c | 6 +- trunk/fs/bfs/inode.c | 4 +- trunk/fs/binfmt_elf_fdpic.c | 3 +- trunk/fs/binfmt_misc.c | 2 +- trunk/fs/bio.c | 2 +- trunk/fs/block_dev.c | 202 +- trunk/fs/buffer.c | 33 +- trunk/fs/cifs/cifssmb.c | 2 +- trunk/fs/cifs/file.c | 2 - trunk/fs/compat.c | 10 +- trunk/fs/direct-io.c | 323 ++- trunk/fs/exec.c | 2 +- trunk/fs/fcntl.c | 5 +- trunk/fs/file.c | 255 +- trunk/fs/inode.c | 43 +- trunk/fs/jbd/transaction.c | 2 +- trunk/fs/jffs/inode-v23.c | 4 +- trunk/fs/jffs/intrep.c | 14 +- trunk/fs/jfs/jfs_dtree.c | 4 +- trunk/fs/jfs/jfs_filsys.h | 42 +- trunk/fs/jfs/jfs_imap.c | 2 +- trunk/fs/lockd/clntlock.c | 10 +- trunk/fs/lockd/clntproc.c | 39 +- trunk/fs/lockd/svclock.c | 4 +- trunk/fs/lockd/svcshare.c | 2 +- trunk/fs/lockd/xdr.c | 8 +- trunk/fs/lockd/xdr4.c | 8 +- trunk/fs/namespace.c | 5 +- trunk/fs/ncpfs/inode.c | 34 +- trunk/fs/nfs/nfs4proc.c | 2 +- trunk/fs/nfsd/export.c | 33 +- trunk/fs/nfsd/lockd.c | 2 +- trunk/fs/nfsd/nfs4proc.c | 625 ++-- trunk/fs/nfsd/nfs4state.c | 91 +- trunk/fs/nfsd/nfs4xdr.c | 14 +- trunk/fs/nfsd/nfsfh.c | 6 +- trunk/fs/nfsd/vfs.c | 2 +- trunk/fs/ocfs2/alloc.c | 2 +- trunk/fs/ocfs2/cluster/heartbeat.c | 4 +- trunk/fs/ocfs2/cluster/nodemanager.c | 198 +- trunk/fs/ocfs2/cluster/nodemanager.h | 17 - trunk/fs/ocfs2/cluster/tcp.c | 162 +- trunk/fs/ocfs2/cluster/tcp.h | 8 - trunk/fs/ocfs2/cluster/tcp_internal.h | 15 +- trunk/fs/ocfs2/dlm/dlmdomain.c | 4 +- trunk/fs/ocfs2/dlm/dlmlock.c | 4 +- trunk/fs/ocfs2/dlm/dlmmaster.c | 2 +- trunk/fs/ocfs2/dlm/dlmrecovery.c | 6 +- trunk/fs/ocfs2/dlmglue.c | 79 +- trunk/fs/ocfs2/file.c | 8 - trunk/fs/ocfs2/heartbeat.c | 9 - trunk/fs/ocfs2/inode.c | 3 +- trunk/fs/ocfs2/journal.c | 46 +- trunk/fs/ocfs2/journal.h | 5 +- trunk/fs/ocfs2/localalloc.c | 2 +- trunk/fs/ocfs2/mmap.c | 6 +- trunk/fs/ocfs2/namei.c | 8 +- trunk/fs/ocfs2/ocfs2.h | 5 - trunk/fs/ocfs2/ocfs2_fs.h | 14 +- trunk/fs/ocfs2/slot_map.c | 2 +- trunk/fs/ocfs2/suballoc.c | 6 +- trunk/fs/ocfs2/super.c | 96 +- trunk/fs/ocfs2/vote.c | 7 +- trunk/fs/open.c | 3 +- trunk/fs/pipe.c | 12 +- trunk/fs/proc/base.c | 24 - trunk/fs/proc/proc_misc.c | 12 +- trunk/fs/read_write.c | 2 + trunk/fs/reiserfs/xattr_acl.c | 2 +- trunk/fs/select.c | 10 +- trunk/fs/smbfs/inode.c | 5 +- trunk/fs/smbfs/proc.c | 6 +- trunk/fs/smbfs/smbiod.c | 5 +- trunk/fs/splice.c | 8 +- trunk/fs/xfs/linux-2.6/xfs_aops.c | 2 +- trunk/include/asm-arm/arch-pnx4008/i2c.h | 67 - trunk/include/asm-arm/arch-pxa/pxa2xx_spi.h | 5 +- trunk/include/asm-arm/thread_info.h | 2 - .../asm-avr32/arch-at32ap/at32ap7000.h | 33 - trunk/include/asm-avr32/arch-at32ap/board.h | 3 + trunk/include/asm-avr32/arch-at32ap/portmux.h | 20 +- trunk/include/asm-avr32/dma-mapping.h | 12 +- trunk/include/asm-avr32/pgalloc.h | 2 +- trunk/include/asm-frv/thread_info.h | 2 - trunk/include/asm-generic/vmlinux.lds.h | 1 - trunk/include/asm-i386/msr.h | 5 - trunk/include/asm-i386/thread_info.h | 2 - trunk/include/asm-i386/topology.h | 1 - trunk/include/asm-ia64/break.h | 4 +- trunk/include/asm-ia64/kprobes.h | 1 - trunk/include/asm-ia64/sn/xpc.h | 2 +- trunk/include/asm-ia64/thread_info.h | 2 - trunk/include/asm-ia64/topology.h | 1 - trunk/include/asm-m68k/swim_iop.h | 221 ++ trunk/include/asm-mips/compat.h | 1 - trunk/include/asm-mips/mach-ip27/irq.h | 2 + trunk/include/asm-mips/mach-ip27/topology.h | 1 + trunk/include/asm-mips/pci.h | 6 - trunk/include/asm-mips/ptrace.h | 8 - trunk/include/asm-mips/sn/arch.h | 1 + trunk/include/asm-mips/sn/klconfig.h | 2 - trunk/include/asm-mips/system.h | 9 + trunk/include/asm-powerpc/Kbuild | 2 +- trunk/include/asm-powerpc/bitops.h | 2 +- trunk/include/asm-powerpc/bug.h | 80 +- trunk/include/asm-powerpc/cputable.h | 16 +- trunk/include/asm-powerpc/dcr-native.h | 37 +- trunk/include/asm-powerpc/dcr.h | 2 - trunk/include/asm-powerpc/hw_irq.h | 19 + trunk/include/asm-powerpc/module.h | 2 + trunk/include/asm-powerpc/pci-bridge.h | 4 +- trunk/include/asm-powerpc/pci.h | 33 +- trunk/include/asm-powerpc/reg.h | 2 - trunk/include/asm-powerpc/rtas.h | 3 +- trunk/include/asm-powerpc/thread_info.h | 2 - trunk/include/asm-powerpc/topology.h | 1 - trunk/include/asm-ppc/pci-bridge.h | 8 +- trunk/include/asm-ppc/pci.h | 23 - trunk/include/asm-ppc/reg_booke.h | 36 +- trunk/include/asm-sh/atomic-irq.h | 71 - trunk/include/asm-sh/atomic-llsc.h | 107 - trunk/include/asm-sh/atomic.h | 153 +- trunk/include/asm-sh/bug.h | 53 +- trunk/include/asm-sh/bugs.h | 12 +- trunk/include/asm-sh/checksum.h | 69 +- trunk/include/asm-sh/cpu-sh4/cache.h | 2 +- trunk/include/asm-sh/cpu-sh4/freq.h | 2 +- trunk/include/asm-sh/dma-mapping.h | 10 +- trunk/include/asm-sh/irq.h | 5 +- trunk/include/asm-sh/pgtable.h | 47 +- trunk/include/asm-sh/processor.h | 8 +- trunk/include/asm-sh/push-switch.h | 3 - trunk/include/asm-sh/thread_info.h | 2 - trunk/include/asm-sh64/pgalloc.h | 2 +- trunk/include/asm-sparc64/dma.h | 6 +- trunk/include/asm-sparc64/irqflags.h | 89 - trunk/include/asm-sparc64/kprobes.h | 11 +- trunk/include/asm-sparc64/rwsem.h | 32 +- trunk/include/asm-sparc64/system.h | 49 +- trunk/include/asm-sparc64/ttable.h | 45 +- trunk/include/asm-x86_64/msr.h | 4 - trunk/include/asm-x86_64/thread_info.h | 2 - trunk/include/asm-x86_64/topology.h | 1 - trunk/include/asm-xtensa/asmmacro.h | 153 - trunk/include/asm-xtensa/bug.h | 25 +- trunk/include/asm-xtensa/byteorder.h | 5 +- trunk/include/asm-xtensa/cache.h | 20 +- trunk/include/asm-xtensa/cacheasm.h | 177 -- trunk/include/asm-xtensa/cacheflush.h | 2 +- trunk/include/asm-xtensa/checksum.h | 2 +- trunk/include/asm-xtensa/coprocessor.h | 13 +- trunk/include/asm-xtensa/dma.h | 5 +- trunk/include/asm-xtensa/elf.h | 9 +- trunk/include/asm-xtensa/fcntl.h | 98 +- trunk/include/asm-xtensa/fixmap.h | 252 ++ trunk/include/asm-xtensa/io.h | 64 +- trunk/include/asm-xtensa/irq.h | 8 +- trunk/include/asm-xtensa/irq_regs.h | 1 - trunk/include/asm-xtensa/mmu_context.h | 269 +- trunk/include/asm-xtensa/page.h | 10 +- trunk/include/asm-xtensa/param.h | 2 +- trunk/include/asm-xtensa/pgtable.h | 41 +- .../asm-xtensa/platform-iss/hardware.h | 10 +- .../include/asm-xtensa/platform-iss/simcall.h | 62 - trunk/include/asm-xtensa/posix_types.h | 2 +- trunk/include/asm-xtensa/processor.h | 24 +- trunk/include/asm-xtensa/ptrace.h | 2 +- trunk/include/asm-xtensa/regs.h | 138 - trunk/include/asm-xtensa/sembuf.h | 2 +- trunk/include/asm-xtensa/shmbuf.h | 21 - trunk/include/asm-xtensa/stat.h | 112 +- trunk/include/asm-xtensa/syscall.h | 20 - trunk/include/asm-xtensa/system.h | 2 +- trunk/include/asm-xtensa/termbits.h | 11 - trunk/include/asm-xtensa/timex.h | 17 +- trunk/include/asm-xtensa/tlbflush.h | 42 +- trunk/include/asm-xtensa/uaccess.h | 1 + trunk/include/asm-xtensa/unistd.h | 798 ++--- trunk/include/asm-xtensa/variant-fsf/core.h | 359 --- trunk/include/asm-xtensa/variant-fsf/tie.h | 22 - trunk/include/asm-xtensa/xtensa/cacheasm.h | 708 +++++ .../include/asm-xtensa/xtensa/cacheattrasm.h | 432 +++ .../asm-xtensa/xtensa/config-linux_be/core.h | 1270 ++++++++ .../asm-xtensa/xtensa/config-linux_be/defs.h | 270 ++ .../xtensa/config-linux_be/specreg.h | 99 + .../xtensa/config-linux_be/system.h | 198 ++ .../asm-xtensa/xtensa/config-linux_be/tie.h | 275 ++ trunk/include/asm-xtensa/xtensa/coreasm.h | 526 ++++ trunk/include/asm-xtensa/xtensa/corebits.h | 77 + trunk/include/asm-xtensa/xtensa/hal.h | 822 ++++++ trunk/include/asm-xtensa/xtensa/simcall.h | 130 + trunk/include/asm-xtensa/xtensa/xt2000-uart.h | 155 + trunk/include/asm-xtensa/xtensa/xt2000.h | 408 +++ trunk/include/asm-xtensa/xtensa/xtboard.h | 120 + trunk/include/linux/Kbuild | 2 +- trunk/include/linux/aio.h | 1 - trunk/include/linux/bio.h | 1 - trunk/include/linux/blkdev.h | 5 + trunk/include/linux/clocksource.h | 2 +- trunk/include/linux/coda_linux.h | 2 +- trunk/include/linux/compiler.h | 2 +- trunk/include/linux/configfs.h | 25 + trunk/include/linux/cpufreq.h | 3 - trunk/include/linux/cpuset.h | 22 +- trunk/include/linux/dccp.h | 26 +- trunk/include/linux/fb.h | 2 + trunk/include/linux/file.h | 15 +- trunk/include/linux/freezer.h | 13 +- trunk/include/linux/fs.h | 1 - trunk/include/linux/fsl_devices.h | 1 - trunk/include/linux/futex.h | 2 - trunk/include/linux/gameport.h | 2 +- trunk/include/linux/i2c-algo-bit.h | 5 +- trunk/include/linux/i2c-algo-ite.h | 72 + trunk/include/linux/i2c-algo-pca.h | 1 + trunk/include/linux/i2c-algo-pcf.h | 3 +- trunk/include/linux/i2c-algo-sgi.h | 1 + trunk/include/linux/i2c-id.h | 19 +- trunk/include/linux/i2c-pnx.h | 43 - trunk/include/linux/i2c.h | 75 +- trunk/include/linux/ide.h | 3 +- trunk/include/linux/init.h | 1 - trunk/include/linux/init_task.h | 3 + trunk/include/linux/interrupt.h | 3 +- trunk/include/linux/kernel.h | 2 + trunk/include/linux/kvm.h | 227 -- trunk/include/linux/lockd/bind.h | 2 +- trunk/include/linux/lockd/lockd.h | 2 +- trunk/include/linux/lockd/sm_inter.h | 2 +- trunk/include/linux/lockd/xdr.h | 8 +- trunk/include/linux/lockdep.h | 16 +- trunk/include/linux/mount.h | 1 - trunk/include/linux/n_r3964.h | 2 +- trunk/include/linux/ncp_mount.h | 2 +- trunk/include/linux/nfsd/nfsd.h | 4 +- trunk/include/linux/nfsd/state.h | 1 + trunk/include/linux/nfsd/xdr4.h | 40 +- trunk/include/linux/nsproxy.h | 1 + trunk/include/linux/pipe_fs_i.h | 5 +- trunk/include/linux/raid/raid5.h | 3 - trunk/include/linux/reciprocal_div.h | 32 - trunk/include/linux/rtc.h | 1 - trunk/include/linux/sched.h | 4 +- trunk/include/linux/seqlock.h | 7 +- trunk/include/linux/slab.h | 306 +- trunk/include/linux/slab_def.h | 100 - trunk/include/linux/smb_fs_sb.h | 2 +- trunk/include/linux/sysctl.h | 7 +- trunk/include/linux/sysrq.h | 22 +- trunk/include/linux/task_io_accounting.h | 37 - trunk/include/linux/task_io_accounting_ops.h | 47 - trunk/include/linux/taskstats.h | 28 +- trunk/include/linux/tfrc.h | 8 +- trunk/include/linux/timer.h | 6 - trunk/include/linux/topology.h | 5 +- trunk/include/linux/videodev2.h | 1 - trunk/include/media/ir-common.h | 1 - trunk/include/media/saa7146.h | 20 +- trunk/include/media/tuner-types.h | 4 - trunk/include/media/tuner.h | 1 - trunk/include/media/tveeprom.h | 2 +- trunk/include/media/v4l2-common.h | 7 - trunk/include/media/v4l2-dev.h | 14 +- trunk/include/net/ax25.h | 2 - trunk/include/net/bluetooth/hci.h | 4 +- trunk/include/net/ip.h | 3 +- trunk/include/net/sctp/sctp.h | 2 +- trunk/include/rdma/ib_marshall.h | 5 +- trunk/include/rdma/ib_verbs.h | 253 -- trunk/include/rdma/rdma_cm.h | 62 +- trunk/include/rdma/rdma_cm_ib.h | 3 - trunk/include/rdma/rdma_user_cm.h | 206 -- trunk/include/video/sstfb.h | 13 +- trunk/init/Kconfig | 11 +- trunk/init/initramfs.c | 6 +- trunk/init/main.c | 15 +- trunk/init/version.c | 5 + trunk/ipc/msgutil.c | 4 +- trunk/kernel/cpuset.c | 82 +- trunk/kernel/exit.c | 8 +- trunk/kernel/fork.c | 38 +- trunk/kernel/lockdep.c | 203 +- trunk/kernel/nsproxy.c | 4 +- trunk/kernel/power/process.c | 21 +- trunk/kernel/relay.c | 4 +- trunk/kernel/sched.c | 515 ++-- trunk/kernel/signal.c | 4 +- trunk/kernel/sysctl.c | 71 +- trunk/kernel/time/clocksource.c | 8 +- trunk/kernel/timer.c | 162 +- trunk/kernel/tsacct.c | 9 - trunk/lib/Kconfig | 5 - trunk/lib/Kconfig.debug | 51 +- trunk/lib/Makefile | 5 +- trunk/lib/bitrev.c | 4 - trunk/lib/ioremap.c | 1 + trunk/lib/reciprocal_div.c | 9 - trunk/mm/filemap.c | 9 +- trunk/mm/hugetlb.c | 2 +- trunk/mm/memory.c | 32 +- trunk/mm/oom_kill.c | 2 +- trunk/mm/page-writeback.c | 89 +- trunk/mm/page_alloc.c | 2 +- trunk/mm/readahead.c | 2 - trunk/mm/slab.c | 36 +- trunk/mm/slob.c | 16 +- trunk/mm/truncate.c | 4 +- trunk/mm/vmscan.c | 8 +- trunk/net/ax25/ax25_addr.c | 2 +- trunk/net/bluetooth/hci_sock.c | 4 +- trunk/net/core/netpoll.c | 39 +- trunk/net/dccp/ackvec.c | 4 +- trunk/net/dccp/ccid.h | 10 + trunk/net/dccp/ccids/ccid2.c | 12 +- trunk/net/dccp/ccids/ccid3.c | 517 ++-- trunk/net/dccp/ccids/ccid3.h | 46 +- trunk/net/dccp/ccids/lib/packet_history.c | 219 +- trunk/net/dccp/ccids/lib/packet_history.h | 128 +- trunk/net/dccp/ccids/lib/tfrc.h | 23 +- trunk/net/dccp/ccids/lib/tfrc_equation.c | 28 +- trunk/net/dccp/dccp.h | 3 +- trunk/net/dccp/feat.c | 6 +- trunk/net/dccp/input.c | 47 +- trunk/net/dccp/ipv4.c | 26 +- trunk/net/dccp/ipv6.c | 24 +- trunk/net/dccp/minisocks.c | 2 +- trunk/net/dccp/options.c | 5 + trunk/net/dccp/output.c | 39 +- trunk/net/dccp/proto.c | 6 +- trunk/net/dccp/timer.c | 14 +- trunk/net/decnet/dn_dev.c | 6 +- trunk/net/decnet/sysctl_net_decnet.c | 6 +- .../softmac/ieee80211softmac_assoc.c | 2 +- trunk/net/ipv4/devinet.c | 3 +- trunk/net/ipv4/ip_fragment.c | 2 +- trunk/net/ipv4/ipvs/ip_vs_sync.c | 17 +- trunk/net/ipv4/route.c | 3 +- trunk/net/ipv4/sysctl_net_ipv4.c | 16 +- trunk/net/ipv6/addrconf.c | 3 +- trunk/net/ipv6/ndisc.c | 9 +- trunk/net/sunrpc/auth_gss/svcauth_gss.c | 11 +- trunk/net/sunrpc/cache.c | 31 +- trunk/net/sunrpc/svc.c | 2 +- trunk/net/sunrpc/svcauth_unix.c | 5 - trunk/net/tipc/config.c | 2 +- trunk/scripts/Kbuild.include | 19 +- trunk/scripts/kconfig/conf.c | 2 +- trunk/scripts/kconfig/confdata.c | 37 +- trunk/scripts/kconfig/gconf.c | 35 +- trunk/scripts/kconfig/gconf.glade | 4 +- trunk/scripts/kconfig/lkc.h | 2 - trunk/scripts/kconfig/lkc_proto.h | 3 +- trunk/scripts/kconfig/mconf.c | 21 +- trunk/scripts/kconfig/qconf.cc | 15 +- trunk/scripts/kconfig/qconf.h | 3 - trunk/scripts/kconfig/symbol.c | 3 +- trunk/scripts/kconfig/zconf.tab.c_shipped | 2 +- trunk/scripts/kconfig/zconf.y | 2 +- trunk/scripts/mod/modpost.c | 1 - trunk/security/selinux/hooks.c | 2 +- trunk/sound/Kconfig | 8 - trunk/sound/Makefile | 3 - trunk/sound/aoa/fabrics/Kconfig | 2 +- trunk/sound/core/oss/mixer_oss.c | 2 +- trunk/sound/drivers/Kconfig | 6 +- trunk/sound/oss/ad1848.c | 2 +- trunk/sound/oss/cs4232.c | 2 +- trunk/sound/oss/emu10k1/audio.c | 6 +- trunk/sound/oss/emu10k1/cardmi.c | 2 +- trunk/sound/oss/emu10k1/cardmo.c | 2 +- trunk/sound/oss/emu10k1/midi.c | 10 +- trunk/sound/oss/emu10k1/mixer.c | 2 +- trunk/sound/oss/hal2.c | 2 +- trunk/sound/oss/mpu401.c | 2 +- trunk/sound/oss/opl3.c | 2 +- trunk/sound/oss/sb_common.c | 2 +- trunk/sound/oss/sb_midi.c | 4 +- trunk/sound/oss/sb_mixer.c | 2 +- trunk/sound/oss/v_midi.c | 2 +- trunk/sound/oss/waveartist.c | 2 +- trunk/sound/pci/ac97/Makefile | 2 + trunk/sound/{ => pci/ac97}/ac97_bus.c | 0 1098 files changed, 22859 insertions(+), 45745 deletions(-) delete mode 100644 trunk/Documentation/ioctl/ioctl-decoding.txt delete mode 100644 trunk/Documentation/video4linux/cafe_ccic create mode 100644 trunk/Documentation/video4linux/zr36120.txt delete mode 100644 trunk/arch/arm/mach-pnx4008/i2c.c create mode 100644 trunk/arch/avr32/mach-at32ap/sm.c delete mode 100644 trunk/arch/ia64/kernel/crash_dump.c delete mode 100644 trunk/arch/powerpc/platforms/pseries/hotplug-cpu.c create mode 100644 trunk/arch/powerpc/sysdev/dcr.S create mode 100644 trunk/arch/sh/boards/se/7619/io.c delete mode 100644 trunk/arch/sh/configs/se7619_defconfig rename trunk/arch/sh/kernel/cpu/{sh4a => sh4}/clock-sh73180.c (100%) rename trunk/arch/sh/kernel/cpu/{sh4a => sh4}/clock-sh7770.c (100%) rename trunk/arch/sh/kernel/cpu/{sh4a => sh4}/clock-sh7780.c (100%) rename trunk/arch/sh/kernel/cpu/{sh4a => sh4}/setup-sh73180.c (100%) rename trunk/arch/sh/kernel/cpu/{sh4a => sh4}/setup-sh7343.c (100%) rename trunk/arch/sh/kernel/cpu/{sh4a => sh4}/setup-sh7770.c (100%) rename trunk/arch/sh/kernel/cpu/{sh4a => sh4}/setup-sh7780.c (100%) delete mode 100644 trunk/arch/sh/kernel/cpu/sh4a/Makefile delete mode 100644 trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c delete mode 100644 trunk/arch/sh/kernel/cpu/sh4a/setup-sh7722.c delete mode 100644 trunk/arch/sparc64/kernel/stacktrace.c delete mode 100644 trunk/arch/xtensa/kernel/syscall.c create mode 100644 trunk/arch/xtensa/kernel/syscalls.c create mode 100644 trunk/arch/xtensa/kernel/syscalls.h create mode 100644 trunk/drivers/block/swim_iop.c create mode 100644 trunk/drivers/i2c/algos/i2c-algo-ite.c create mode 100644 trunk/drivers/i2c/algos/i2c-algo-ite.h delete mode 100644 trunk/drivers/i2c/busses/i2c-at91.c create mode 100644 trunk/drivers/i2c/busses/i2c-ite.c delete mode 100644 trunk/drivers/i2c/busses/i2c-pnx.c delete mode 100644 trunk/drivers/i2c/busses/i2c-versatile.c delete mode 100644 trunk/drivers/infiniband/core/ucma.c delete mode 100644 trunk/drivers/infiniband/hw/ipath/ipath_dma.c delete mode 100644 trunk/drivers/kvm/Kconfig delete mode 100644 trunk/drivers/kvm/Makefile delete mode 100644 trunk/drivers/kvm/kvm.h delete mode 100644 trunk/drivers/kvm/kvm_main.c delete mode 100644 trunk/drivers/kvm/kvm_svm.h delete mode 100644 trunk/drivers/kvm/kvm_vmx.h delete mode 100644 trunk/drivers/kvm/mmu.c delete mode 100644 trunk/drivers/kvm/paging_tmpl.h delete mode 100644 trunk/drivers/kvm/segment_descriptor.h delete mode 100644 trunk/drivers/kvm/svm.c delete mode 100644 trunk/drivers/kvm/svm.h delete mode 100644 trunk/drivers/kvm/vmx.c delete mode 100644 trunk/drivers/kvm/vmx.h delete mode 100644 trunk/drivers/kvm/x86_emulate.c delete mode 100644 trunk/drivers/kvm/x86_emulate.h delete mode 100644 trunk/drivers/media/dvb/dvb-usb/ttusb2.c delete mode 100644 trunk/drivers/media/dvb/dvb-usb/ttusb2.h delete mode 100644 trunk/drivers/media/dvb/frontends/dib7000m.c delete mode 100644 trunk/drivers/media/dvb/frontends/dib7000m.h delete mode 100644 trunk/drivers/media/dvb/frontends/dib7000p.c delete mode 100644 trunk/drivers/media/dvb/frontends/dib7000p.h create mode 100644 trunk/drivers/media/dvb/frontends/lg_h06xf.h delete mode 100644 trunk/drivers/media/dvb/frontends/lgh06xf.c delete mode 100644 trunk/drivers/media/dvb/frontends/lgh06xf.h delete mode 100644 trunk/drivers/media/video/cafe_ccic-regs.h delete mode 100644 trunk/drivers/media/video/cafe_ccic.c delete mode 100644 trunk/drivers/media/video/ov7670.c delete mode 100644 trunk/drivers/media/video/usbvision/Kconfig delete mode 100644 trunk/drivers/media/video/usbvision/Makefile delete mode 100644 trunk/drivers/media/video/usbvision/usbvision-cards.c delete mode 100644 trunk/drivers/media/video/usbvision/usbvision-core.c delete mode 100644 trunk/drivers/media/video/usbvision/usbvision-i2c.c delete mode 100644 trunk/drivers/media/video/usbvision/usbvision-video.c delete mode 100644 trunk/drivers/media/video/usbvision/usbvision.h create mode 100644 trunk/drivers/media/video/zr36120.c create mode 100644 trunk/drivers/media/video/zr36120.h create mode 100644 trunk/drivers/media/video/zr36120_i2c.c create mode 100644 trunk/drivers/media/video/zr36120_mem.c create mode 100644 trunk/drivers/media/video/zr36120_mem.h delete mode 100644 trunk/drivers/ps3/vuart.c delete mode 100644 trunk/drivers/ps3/vuart.h rename trunk/drivers/rtc/{rtc-at91rm9200.c => rtc-at91.c} (99%) delete mode 100644 trunk/drivers/video/gxt4500.c delete mode 100644 trunk/include/asm-arm/arch-pnx4008/i2c.h delete mode 100644 trunk/include/asm-avr32/arch-at32ap/at32ap7000.h create mode 100644 trunk/include/asm-m68k/swim_iop.h delete mode 100644 trunk/include/asm-sh/atomic-irq.h delete mode 100644 trunk/include/asm-sh/atomic-llsc.h delete mode 100644 trunk/include/asm-sparc64/irqflags.h delete mode 100644 trunk/include/asm-xtensa/asmmacro.h delete mode 100644 trunk/include/asm-xtensa/cacheasm.h create mode 100644 trunk/include/asm-xtensa/fixmap.h delete mode 100644 trunk/include/asm-xtensa/irq_regs.h delete mode 100644 trunk/include/asm-xtensa/platform-iss/simcall.h delete mode 100644 trunk/include/asm-xtensa/regs.h delete mode 100644 trunk/include/asm-xtensa/syscall.h delete mode 100644 trunk/include/asm-xtensa/variant-fsf/core.h delete mode 100644 trunk/include/asm-xtensa/variant-fsf/tie.h create mode 100644 trunk/include/asm-xtensa/xtensa/cacheasm.h create mode 100644 trunk/include/asm-xtensa/xtensa/cacheattrasm.h create mode 100644 trunk/include/asm-xtensa/xtensa/config-linux_be/core.h create mode 100644 trunk/include/asm-xtensa/xtensa/config-linux_be/defs.h create mode 100644 trunk/include/asm-xtensa/xtensa/config-linux_be/specreg.h create mode 100644 trunk/include/asm-xtensa/xtensa/config-linux_be/system.h create mode 100644 trunk/include/asm-xtensa/xtensa/config-linux_be/tie.h create mode 100644 trunk/include/asm-xtensa/xtensa/coreasm.h create mode 100644 trunk/include/asm-xtensa/xtensa/corebits.h create mode 100644 trunk/include/asm-xtensa/xtensa/hal.h create mode 100644 trunk/include/asm-xtensa/xtensa/simcall.h create mode 100644 trunk/include/asm-xtensa/xtensa/xt2000-uart.h create mode 100644 trunk/include/asm-xtensa/xtensa/xt2000.h create mode 100644 trunk/include/asm-xtensa/xtensa/xtboard.h create mode 100644 trunk/include/linux/i2c-algo-ite.h delete mode 100644 trunk/include/linux/i2c-pnx.h delete mode 100644 trunk/include/linux/kvm.h delete mode 100644 trunk/include/linux/reciprocal_div.h delete mode 100644 trunk/include/linux/slab_def.h delete mode 100644 trunk/include/linux/task_io_accounting.h delete mode 100644 trunk/include/linux/task_io_accounting_ops.h delete mode 100644 trunk/include/rdma/rdma_user_cm.h delete mode 100644 trunk/lib/reciprocal_div.c rename trunk/sound/{ => pci/ac97}/ac97_bus.c (100%) diff --git a/[refs] b/[refs] index e4dde9d34e85..70c582e0766e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5cbded585d129d0226cb48ac4202b253c781be26 +refs/heads/master: 6b14a546a5a7fde46d20d3c14a4e91a24a3f1be0 diff --git a/trunk/Documentation/CodingStyle b/trunk/Documentation/CodingStyle index 0ad6dcb5d45f..29c18966b050 100644 --- a/trunk/Documentation/CodingStyle +++ b/trunk/Documentation/CodingStyle @@ -35,37 +35,12 @@ In short, 8-char indents make things easier to read, and have the added benefit of warning you when you're nesting your functions too deep. Heed that warning. -The preferred way to ease multiple indentation levels in a switch statement is -to align the "switch" and its subordinate "case" labels in the same column -instead of "double-indenting" the "case" labels. E.g.: - - switch (suffix) { - case 'G': - case 'g': - mem <<= 30; - break; - case 'M': - case 'm': - mem <<= 20; - break; - case 'K': - case 'k': - mem <<= 10; - /* fall through */ - default: - break; - } - - Don't put multiple statements on a single line unless you have something to hide: if (condition) do_this; do_something_everytime; -Don't put multiple assignments on a single line either. Kernel coding style -is super simple. Avoid tricky expressions. - Outside of comments, documentation and except in Kconfig, spaces are never used for indentation, and the above example is deliberately broken. @@ -94,7 +69,7 @@ void fun(int a, int b, int c) next_statement; } - Chapter 3: Placing Braces and Spaces + Chapter 3: Placing Braces The other issue that always comes up in C styling is the placement of braces. Unlike the indent size, there are few technical reasons to @@ -106,20 +81,6 @@ brace last on the line, and put the closing brace first, thusly: we do y } -This applies to all non-function statement blocks (if, switch, for, -while, do). E.g.: - - switch (action) { - case KOBJ_ADD: - return "add"; - case KOBJ_REMOVE: - return "remove"; - case KOBJ_CHANGE: - return "change"; - default: - return NULL; - } - However, there is one special case, namely functions: they have the opening brace at the beginning of the next line, thus: @@ -160,49 +121,6 @@ supply of new-lines on your screen is not a renewable resource (think 25-line terminal screens here), you have more empty lines to put comments on. - 3.1: Spaces - -Linux kernel style for use of spaces depends (mostly) on -function-versus-keyword usage. Use a space after (most) keywords. The -notable exceptions are sizeof, typeof, alignof, and __attribute__, which look -somewhat like functions (and are usually used with parentheses in Linux, -although they are not required in the language, as in: "sizeof info" after -"struct fileinfo info;" is declared). - -So use a space after these keywords: - if, switch, case, for, do, while -but not with sizeof, typeof, alignof, or __attribute__. E.g., - s = sizeof(struct file); - -Do not add spaces around (inside) parenthesized expressions. This example is -*bad*: - - s = sizeof( struct file ); - -When declaring pointer data or a function that returns a pointer type, the -preferred use of '*' is adjacent to the data name or function name and not -adjacent to the type name. Examples: - - char *linux_banner; - unsigned long long memparse(char *ptr, char **retptr); - char *match_strdup(substring_t *s); - -Use one space around (on each side of) most binary and ternary operators, -such as any of these: - - = + - < > * / % | & ^ <= >= == != ? : - -but no space after unary operators: - & * + - ~ ! sizeof typeof alignof __attribute__ defined - -no space before the postfix increment & decrement unary operators: - ++ -- - -no space after the prefix increment & decrement unary operators: - ++ -- - -and no space around the '.' and "->" structure member operators. - Chapter 4: Naming @@ -234,7 +152,7 @@ variable that is used to hold a temporary value. If you are afraid to mix up your local variable names, you have another problem, which is called the function-growth-hormone-imbalance syndrome. -See chapter 6 (Functions). +See next chapter. Chapter 5: Typedefs @@ -340,20 +258,6 @@ generally easily keep track of about 7 different things, anything more and it gets confused. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now. -In source files, separate functions with one blank line. If the function is -exported, the EXPORT* macro for it should follow immediately after the closing -function brace line. E.g.: - -int system_is_up(void) -{ - return system_state == SYSTEM_RUNNING; -} -EXPORT_SYMBOL(system_is_up); - -In function prototypes, include parameter names with their data types. -Although this is not required by the C language, it is preferred in Linux -because it is a simple way to add valuable information for the reader. - Chapter 7: Centralized exiting of functions @@ -402,36 +306,16 @@ time to explain badly written code. Generally, you want your comments to tell WHAT your code does, not HOW. Also, try to avoid putting comments inside a function body: if the function is so complex that you need to separately comment parts of it, -you should probably go back to chapter 6 for a while. You can make +you should probably go back to chapter 5 for a while. You can make small comments to note or warn about something particularly clever (or ugly), but try to avoid excess. Instead, put the comments at the head of the function, telling people what it does, and possibly WHY it does it. -When commenting the kernel API functions, please use the kernel-doc format. +When commenting the kernel API functions, please use the kerneldoc format. See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc for details. -Linux style for comments is the C89 "/* ... */" style. -Don't use C99-style "// ..." comments. - -The preferred style for long (multi-line) comments is: - - /* - * This is the preferred style for multi-line - * comments in the Linux kernel source code. - * Please use it consistently. - * - * Description: A column of asterisks on the left side, - * with beginning and ending almost-blank lines. - */ - -It's also important to comment data, whether they are basic types or derived -types. To this end, use just one data declaration per line (no commas for -multiple data declarations). This leaves you room for a small comment on each -item, explaining its use. - - Chapter 9: You've made a mess of it That's OK, we all do. You've probably been told by your long-time Unix @@ -707,4 +591,4 @@ Kernel CodingStyle, by greg@kroah.com at OLS 2002: http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ -- -Last updated on 2006-December-06. +Last updated on 30 April 2006. diff --git a/trunk/Documentation/SubmitChecklist b/trunk/Documentation/SubmitChecklist index 2270efa10153..7ac61f60037a 100644 --- a/trunk/Documentation/SubmitChecklist +++ b/trunk/Documentation/SubmitChecklist @@ -66,9 +66,3 @@ kernel patches. See Documentation/ABI/README for more information. 20: Check that it all passes `make headers_check'. - -21: Has been checked with injection of at least slab and page-allocation - fauilures. See Documentation/fault-injection/. - - If the new code is substantial, addition of subsystem-specific fault - injection might be appropriate. diff --git a/trunk/Documentation/accounting/getdelays.c b/trunk/Documentation/accounting/getdelays.c index e9126e794ed7..bf2b0e2f87e1 100644 --- a/trunk/Documentation/accounting/getdelays.c +++ b/trunk/Documentation/accounting/getdelays.c @@ -7,8 +7,6 @@ * Copyright (C) Balbir Singh, IBM Corp. 2006 * Copyright (c) Jay Lan, SGI. 2006 * - * Compile with - * gcc -I/usr/src/linux/include getdelays.c -o getdelays */ #include @@ -37,20 +35,13 @@ #define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN)) #define NLA_PAYLOAD(len) (len - NLA_HDRLEN) -#define err(code, fmt, arg...) \ - do { \ - fprintf(stderr, fmt, ##arg); \ - exit(code); \ - } while (0) - -int done; -int rcvbufsz; -char name[100]; -int dbg; -int print_delays; -int print_io_accounting; -__u64 stime, utime; +#define err(code, fmt, arg...) do { printf(fmt, ##arg); exit(code); } while (0) +int done = 0; +int rcvbufsz=0; + char name[100]; +int dbg=0, print_delays=0; +__u64 stime, utime; #define PRINTF(fmt, arg...) { \ if (dbg) { \ printf(fmt, ##arg); \ @@ -87,9 +78,8 @@ static int create_nl_socket(int protocol) if (rcvbufsz) if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbufsz, sizeof(rcvbufsz)) < 0) { - fprintf(stderr, "Unable to set socket rcv buf size " - "to %d\n", - rcvbufsz); + printf("Unable to set socket rcv buf size to %d\n", + rcvbufsz); return -1; } @@ -196,15 +186,6 @@ void print_delayacct(struct taskstats *t) "count", "delay total", t->swapin_count, t->swapin_delay_total); } -void print_ioacct(struct taskstats *t) -{ - printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n", - t->ac_comm, - (unsigned long long)t->read_bytes, - (unsigned long long)t->write_bytes, - (unsigned long long)t->cancelled_write_bytes); -} - int main(int argc, char *argv[]) { int c, rc, rep_len, aggr_len, len2, cmd_type; @@ -227,7 +208,7 @@ int main(int argc, char *argv[]) struct msgtemplate msg; while (1) { - c = getopt(argc, argv, "diw:r:m:t:p:v:l"); + c = getopt(argc, argv, "dw:r:m:t:p:v:l"); if (c < 0) break; @@ -236,10 +217,6 @@ int main(int argc, char *argv[]) printf("print delayacct stats ON\n"); print_delays = 1; break; - case 'i': - printf("printing IO accounting\n"); - print_io_accounting = 1; - break; case 'w': strncpy(logfile, optarg, MAX_FILENAME); printf("write to file %s\n", logfile); @@ -261,12 +238,14 @@ int main(int argc, char *argv[]) if (!tid) err(1, "Invalid tgid\n"); cmd_type = TASKSTATS_CMD_ATTR_TGID; + print_delays = 1; break; case 'p': tid = atoi(optarg); if (!tid) err(1, "Invalid pid\n"); cmd_type = TASKSTATS_CMD_ATTR_PID; + print_delays = 1; break; case 'v': printf("debug on\n"); @@ -298,7 +277,7 @@ int main(int argc, char *argv[]) mypid = getpid(); id = get_family_id(nl_sd); if (!id) { - fprintf(stderr, "Error getting family id, errno %d\n", errno); + printf("Error getting family id, errno %d", errno); goto err; } PRINTF("family id %d\n", id); @@ -309,7 +288,7 @@ int main(int argc, char *argv[]) &cpumask, strlen(cpumask) + 1); PRINTF("Sent register cpumask, retval %d\n", rc); if (rc < 0) { - fprintf(stderr, "error sending register cpumask\n"); + printf("error sending register cpumask\n"); goto err; } } @@ -319,7 +298,7 @@ int main(int argc, char *argv[]) cmd_type, &tid, sizeof(__u32)); PRINTF("Sent pid/tgid, retval %d\n", rc); if (rc < 0) { - fprintf(stderr, "error sending tid/tgid cmd\n"); + printf("error sending tid/tgid cmd\n"); goto done; } } @@ -331,15 +310,13 @@ int main(int argc, char *argv[]) PRINTF("received %d bytes\n", rep_len); if (rep_len < 0) { - fprintf(stderr, "nonfatal reply error: errno %d\n", - errno); + printf("nonfatal reply error: errno %d\n", errno); continue; } if (msg.n.nlmsg_type == NLMSG_ERROR || !NLMSG_OK((&msg.n), rep_len)) { struct nlmsgerr *err = NLMSG_DATA(&msg); - fprintf(stderr, "fatal reply error, errno %d\n", - err->error); + printf("fatal reply error, errno %d\n", err->error); goto done; } @@ -379,8 +356,6 @@ int main(int argc, char *argv[]) count++; if (print_delays) print_delayacct((struct taskstats *) NLA_DATA(na)); - if (print_io_accounting) - print_ioacct((struct taskstats *) NLA_DATA(na)); if (fd) { if (write(fd, NLA_DATA(na), na->nla_len) < 0) { err(1,"write error\n"); @@ -390,9 +365,7 @@ int main(int argc, char *argv[]) goto done; break; default: - fprintf(stderr, "Unknown nested" - " nla_type %d\n", - na->nla_type); + printf("Unknown nested nla_type %d\n", na->nla_type); break; } len2 += NLA_ALIGN(na->nla_len); @@ -401,8 +374,7 @@ int main(int argc, char *argv[]) break; default: - fprintf(stderr, "Unknown nla_type %d\n", - na->nla_type); + printf("Unknown nla_type %d\n", na->nla_type); break; } na = (struct nlattr *) (GENLMSG_DATA(&msg) + len); diff --git a/trunk/Documentation/cpu-freq/core.txt b/trunk/Documentation/cpu-freq/core.txt index ce0666e51036..29b3f9ffc66c 100644 --- a/trunk/Documentation/cpu-freq/core.txt +++ b/trunk/Documentation/cpu-freq/core.txt @@ -24,7 +24,7 @@ Contents: 1. General Information ======================= -The CPUFreq core code is located in drivers/cpufreq/cpufreq.c. This +The CPUFreq core code is located in linux/kernel/cpufreq.c. This cpufreq code offers a standardized interface for the CPUFreq architecture drivers (those pieces of code that do actual frequency transitions), as well as to "notifiers". These are device diff --git a/trunk/Documentation/dvb/cards.txt b/trunk/Documentation/dvb/cards.txt index cc09187a5db7..ca58e339d85f 100644 --- a/trunk/Documentation/dvb/cards.txt +++ b/trunk/Documentation/dvb/cards.txt @@ -22,10 +22,10 @@ o Frontends drivers: - ves1x93 : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993) - cx24110 : Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL) - grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL - - mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLLi, Technisat Sky2Pc with bios Rev. 2.3 + - mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL - stv0299 : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL), LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL), - Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB, Technisat Sky2Pc with bios Rev. 2.6 + Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB DVB-C: - ves1820 : various (ves1820 demodulator, sp5659c or spXXXX PLL) - at76c651 : Atmel AT76c651(B) with DAT7021 PLL diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 64ce44da5936..46f2a559b27c 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -216,6 +216,17 @@ Who: Thomas Gleixner --------------------------- +What: i2c-ite and i2c-algo-ite drivers +When: September 2006 +Why: These drivers never compiled since they were added to the kernel + tree 5 years ago. This feature removal can be reevaluated if + someone shows interest in the drivers, fixes them and takes over + maintenance. + http://marc.theaimsgroup.com/?l=linux-mips&m=115040510817448 +Who: Jean Delvare + +--------------------------- + What: Bridge netfilter deferred IPv4/IPv6 output hook calling When: January 2007 Why: The deferred output hooks are a layering violation causing unusual @@ -259,25 +270,3 @@ Why: The new layer 3 independant connection tracking replaces the old Who: Patrick McHardy --------------------------- - -What: ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver -When: December 2006 -Why: Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are - functionally very much similar. They talk to ACPI in same way. Only - difference between them is the way they do frequency transitions. - One uses MSRs and the other one uses IO ports. Functionaliy of - speedstep_centrino with ACPI hooks is now merged into acpi-cpufreq. - That means one common driver will support all Intel Enhanced Speedstep - capable CPUs. That means less confusion over name of - speedstep-centrino driver (with that driver supposed to be used on - non-centrino platforms). That means less duplication of code and - less maintenance effort and no possibility of these two drivers - going out of sync. - Current users of speedstep_centrino with ACPI hooks are requested to - switch over to acpi-cpufreq driver. speedstep-centrino will continue - to work using older non-ACPI static table based scheme even after this - date. - -Who: Venkatesh Pallipadi - ---------------------------- diff --git a/trunk/Documentation/filesystems/bfs.txt b/trunk/Documentation/filesystems/bfs.txt index ea825e178e79..d2841e0bcf02 100644 --- a/trunk/Documentation/filesystems/bfs.txt +++ b/trunk/Documentation/filesystems/bfs.txt @@ -54,4 +54,4 @@ The first 4 bytes should be 0x1badface. If you have any patches, questions or suggestions regarding this BFS implementation please contact the author: -Tigran Aivazian +Tigran A. Aivazian diff --git a/trunk/Documentation/filesystems/ocfs2.txt b/trunk/Documentation/filesystems/ocfs2.txt index 8ccf0c1b58ed..af6defd10cb6 100644 --- a/trunk/Documentation/filesystems/ocfs2.txt +++ b/trunk/Documentation/filesystems/ocfs2.txt @@ -54,6 +54,3 @@ errors=panic Panic and halt the machine if an error occurs. intr (*) Allow signals to interrupt cluster operations. nointr Do not allow signals to interrupt cluster operations. -atime_quantum=60(*) OCFS2 will not update atime unless this number - of seconds has passed since the last update. - Set to zero to always update atime. diff --git a/trunk/Documentation/i2c/busses/i2c-amd8111 b/trunk/Documentation/i2c/busses/i2c-amd8111 index 460dd6635fd2..db294ee7455a 100644 --- a/trunk/Documentation/i2c/busses/i2c-amd8111 +++ b/trunk/Documentation/i2c/busses/i2c-amd8111 @@ -5,7 +5,7 @@ Supported adapters: Datasheets: AMD datasheet not yet available, but almost everything can be found - in the publicly available ACPI 2.0 specification, which the adapter + in publically available ACPI 2.0 specification, which the adapter follows. Author: Vojtech Pavlik diff --git a/trunk/Documentation/i2c/busses/i2c-i801 b/trunk/Documentation/i2c/busses/i2c-i801 index 3db69a086c41..e46c23458242 100644 --- a/trunk/Documentation/i2c/busses/i2c-i801 +++ b/trunk/Documentation/i2c/busses/i2c-i801 @@ -9,10 +9,7 @@ Supported adapters: * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported) * Intel 6300ESB * Intel 82801FB/FR/FW/FRW (ICH6) - * Intel 82801G (ICH7) - * Intel 631xESB/632xESB (ESB2) - * Intel 82801H (ICH8) - * Intel ICH9 + * Intel ICH7 Datasheets: Publicly available at the Intel website Authors: diff --git a/trunk/Documentation/i2c/busses/i2c-nforce2 b/trunk/Documentation/i2c/busses/i2c-nforce2 index 7f61fbc03f7f..cd49c428a3ab 100644 --- a/trunk/Documentation/i2c/busses/i2c-nforce2 +++ b/trunk/Documentation/i2c/busses/i2c-nforce2 @@ -10,11 +10,11 @@ Supported adapters: * nForce4 MCP51 10de:0264 * nForce4 MCP55 10de:0368 -Datasheet: not publicly available, but seems to be similar to the +Datasheet: not publically available, but seems to be similar to the AMD-8111 SMBus 2.0 adapter. Authors: - Hans-Frieder Vogt , + Hans-Frieder Vogt , Thomas Leibold , Patrick Dreker @@ -38,7 +38,7 @@ Notes ----- The SMBus adapter in the nForce2 chipset seems to be very similar to the -SMBus 2.0 adapter in the AMD-8111 south bridge. However, I could only get +SMBus 2.0 adapter in the AMD-8111 southbridge. However, I could only get the driver to work with direct I/O access, which is different to the EC interface of the AMD-8111. Tested on Asus A7N8X. The ACPI DSDT table of the Asus A7N8X lists two SMBuses, both of which are supported by this driver. diff --git a/trunk/Documentation/ioctl/ioctl-decoding.txt b/trunk/Documentation/ioctl/ioctl-decoding.txt deleted file mode 100644 index bfdf7f3ee4f0..000000000000 --- a/trunk/Documentation/ioctl/ioctl-decoding.txt +++ /dev/null @@ -1,24 +0,0 @@ -To decode a hex IOCTL code: - -Most architecures use this generic format, but check -include/ARCH/ioctl.h for specifics, e.g. powerpc -uses 3 bits to encode read/write and 13 bits for size. - - bits meaning - 31-30 00 - no parameters: uses _IO macro - 10 - read: _IOR - 01 - write: _IOW - 11 - read/write: _IOWR - - 29-16 size of arguments - - 15-8 ascii character supposedly - unique to each driver - - 7-0 function # - - - So for example 0x82187201 is a read with arg length of 0x218, -character 'r' function 1. Grepping the source reveals this is: - -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) diff --git a/trunk/Documentation/kbuild/kconfig-language.txt b/trunk/Documentation/kbuild/kconfig-language.txt index 536d5bfbdb8d..125093c3ef76 100644 --- a/trunk/Documentation/kbuild/kconfig-language.txt +++ b/trunk/Documentation/kbuild/kconfig-language.txt @@ -29,7 +29,7 @@ them. A single configuration option is defined like this: config MODVERSIONS bool "Set version information on all module symbols" - depends on MODULES + depends MODULES help Usually, modules have to be recompiled whenever you switch to a new kernel. ... @@ -163,7 +163,7 @@ The position of a menu entry in the tree is determined in two ways. First it can be specified explicitly: menu "Network device support" - depends on NET + depends NET config NETDEVICES ... @@ -188,10 +188,10 @@ config MODULES config MODVERSIONS bool "Set version information on all module symbols" - depends on MODULES + depends MODULES comment "module support disabled" - depends on !MODULES + depends !MODULES MODVERSIONS directly depends on MODULES, this means it's only visible if MODULES is different from 'n'. The comment on the other hand is always diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index ef69c75780bf..d8323b8893c3 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -1656,12 +1656,6 @@ and is between 256 and 4096 characters. It is defined in the file sym53c416= [HW,SCSI] See header of drivers/scsi/sym53c416.c. - sysrq_always_enabled - [KNL] - Ignore sysrq setting - this boot parameter will - neutralize any effect of /proc/sys/kernel/sysrq. - Useful for debugging. - t128= [HW,SCSI] See header of drivers/scsi/t128.c. diff --git a/trunk/Documentation/networking/dccp.txt b/trunk/Documentation/networking/dccp.txt index 387482e46c47..dda15886bcb5 100644 --- a/trunk/Documentation/networking/dccp.txt +++ b/trunk/Documentation/networking/dccp.txt @@ -19,8 +19,7 @@ for real time and multimedia traffic. It has a base protocol and pluggable congestion control IDs (CCIDs). -It is at proposed standard RFC status and the homepage for DCCP as a protocol -is at: +It is at experimental RFC status and the homepage for DCCP as a protocol is at: http://www.read.cs.ucla.edu/dccp/ Missing features @@ -35,6 +34,9 @@ The known bugs are at: Socket options ============== +DCCP_SOCKOPT_PACKET_SIZE is used for CCID3 to set default packet size for +calculations. + DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of service codes (RFC 4340, sec. 8.1.2); if this socket option is not set, the socket will fall back to 0 (which means that no meaningful service code diff --git a/trunk/Documentation/spi/pxa2xx b/trunk/Documentation/spi/pxa2xx index f9717fe9bd85..a1e0ee20f595 100644 --- a/trunk/Documentation/spi/pxa2xx +++ b/trunk/Documentation/spi/pxa2xx @@ -102,7 +102,7 @@ struct pxa2xx_spi_chip { u8 tx_threshold; u8 rx_threshold; u8 dma_burst_size; - u32 timeout; + u32 timeout_microsecs; u8 enable_loopback; void (*cs_control)(u32 command); }; @@ -121,7 +121,7 @@ the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers to determine the correct value. An SSP configured for byte-wide transfers would use a value of 8. -The "pxa2xx_spi_chip.timeout" fields is used to efficiently handle +The "pxa2xx_spi_chip.timeout_microsecs" fields is used to efficiently handle trailing bytes in the SSP receiver fifo. The correct value for this field is dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific slave device. Please note that the PXA2xx SSP 1 does not support trailing byte @@ -162,18 +162,18 @@ static void cs8405a_cs_control(u32 command) } static struct pxa2xx_spi_chip cs8415a_chip_info = { - .tx_threshold = 8, /* SSP hardward FIFO threshold */ - .rx_threshold = 8, /* SSP hardward FIFO threshold */ + .tx_threshold = 12, /* SSP hardward FIFO threshold */ + .rx_threshold = 4, /* SSP hardward FIFO threshold */ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */ - .timeout = 235, /* See Intel documentation */ + .timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */ .cs_control = cs8415a_cs_control, /* Use external chip select */ }; static struct pxa2xx_spi_chip cs8405a_chip_info = { - .tx_threshold = 8, /* SSP hardward FIFO threshold */ - .rx_threshold = 8, /* SSP hardward FIFO threshold */ + .tx_threshold = 12, /* SSP hardward FIFO threshold */ + .rx_threshold = 4, /* SSP hardward FIFO threshold */ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */ - .timeout = 235, /* See Intel documentation */ + .timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */ .cs_control = cs8405a_cs_control, /* Use external chip select */ }; diff --git a/trunk/Documentation/video4linux/CARDLIST.cx88 b/trunk/Documentation/video4linux/CARDLIST.cx88 index 62e32b49cec9..8755b3e7b09e 100644 --- a/trunk/Documentation/video4linux/CARDLIST.cx88 +++ b/trunk/Documentation/video4linux/CARDLIST.cx88 @@ -43,7 +43,7 @@ 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025,1822:0019] 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1,12ab:2300] 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] - 45 -> KWorld HardwareMpegTV XPert [17de:0840,1421:0305] + 45 -> KWorld HardwareMpegTV XPert [17de:0840] 46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44] 47 -> pcHDTV HD5500 HDTV [7063:5500] 48 -> Kworld MCE 200 Deluxe [17de:0841] diff --git a/trunk/Documentation/video4linux/CARDLIST.saa7134 b/trunk/Documentation/video4linux/CARDLIST.saa7134 index f6201cc37ec5..53ce6a39083c 100644 --- a/trunk/Documentation/video4linux/CARDLIST.saa7134 +++ b/trunk/Documentation/video4linux/CARDLIST.saa7134 @@ -76,7 +76,7 @@ 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] 76 -> SKNet MonsterTV Mobile [1131:4ee9] 77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e] - 78 -> ASUSTeK P7131 Dual [1043:4862,1043:4876] + 78 -> ASUSTeK P7131 Dual [1043:4862] 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) 80 -> ASUS Digimatrix TV [1043:0210] 81 -> Philips Tiger reference design [1131:2018] @@ -99,8 +99,3 @@ 98 -> Proteus Pro 2309 [0919:2003] 99 -> AVerMedia TV Hybrid A16AR [1461:2c00] 100 -> Asus Europa2 OEM [1043:4860] -101 -> Pinnacle PCTV 310i [11bd:002f] -102 -> Avermedia AVerTV Studio 507 [1461:9715] -103 -> Compro Videomate DVB-T200A -104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6701] -105 -> Terratec Cinergy HT PCMCIA [153b:1172] diff --git a/trunk/Documentation/video4linux/cafe_ccic b/trunk/Documentation/video4linux/cafe_ccic deleted file mode 100644 index 88821022a5de..000000000000 --- a/trunk/Documentation/video4linux/cafe_ccic +++ /dev/null @@ -1,54 +0,0 @@ -"cafe_ccic" is a driver for the Marvell 88ALP01 "cafe" CMOS camera -controller. This is the controller found in first-generation OLPC systems, -and this driver was written with support from the OLPC project. - -Current status: the core driver works. It can generate data in YUV422, -RGB565, and RGB444 formats. (Anybody looking at the code will see RGB32 as -well, but that is a debugging aid which will be removed shortly). VGA and -QVGA modes work; CIF is there but the colors remain funky. Only the OV7670 -sensor is known to work with this controller at this time. - -To try it out: either of these commands will work: - - mplayer tv:// -tv driver=v4l2:width=640:height=480 -nosound - mplayer tv:// -tv driver=v4l2:width=640:height=480:outfmt=bgr16 -nosound - -The "xawtv" utility also works; gqcam does not, for unknown reasons. - -There are a few load-time options, most of which can be changed after -loading via sysfs as well: - - - alloc_bufs_at_load: Normally, the driver will not allocate any DMA - buffers until the time comes to transfer data. If this option is set, - then worst-case-sized buffers will be allocated at module load time. - This option nails down the memory for the life of the module, but - perhaps decreases the chances of an allocation failure later on. - - - dma_buf_size: The size of DMA buffers to allocate. Note that this - option is only consulted for load-time allocation; when buffers are - allocated at run time, they will be sized appropriately for the current - camera settings. - - - n_dma_bufs: The controller can cycle through either two or three DMA - buffers. Normally, the driver tries to use three buffers; on faster - systems, however, it will work well with only two. - - - min_buffers: The minimum number of streaming I/O buffers that the driver - will consent to work with. Default is one, but, on slower systems, - better behavior with mplayer can be achieved by setting to a higher - value (like six). - - - max_buffers: The maximum number of streaming I/O buffers; default is - ten. That number was carefully picked out of a hat and should not be - assumed to actually mean much of anything. - - - flip: If this boolean parameter is set, the sensor will be instructed to - invert the video image. Whether it makes sense is determined by how - your particular camera is mounted. - -Work is ongoing with this driver, stay tuned. - -jon - -Jonathan Corbet -corbet@lwn.net diff --git a/trunk/Documentation/video4linux/zr36120.txt b/trunk/Documentation/video4linux/zr36120.txt new file mode 100644 index 000000000000..1a1c2d03a5c8 --- /dev/null +++ b/trunk/Documentation/video4linux/zr36120.txt @@ -0,0 +1,162 @@ +Driver for Trust Computer Products Framegrabber, version 0.6.1 +------ --- ----- -------- -------- ------------ ------- - - - + +- ZORAN ------------------------------------------------------ + Author: Pauline Middelink + Date: 18 September 1999 +Version: 0.6.1 + +- Description ------------------------------------------------ + +Video4Linux compatible driver for an unknown brand framegrabber +(Sold in the Netherlands by TRUST Computer Products) and various +other zoran zr36120 based framegrabbers. + +The card contains a ZR36120 Multimedia PCI Interface and a Philips +SAA7110 Onechip Frontend videodecoder. There is also an DSP of +which I have forgotten the number, since i will never get that thing +to work without specs from the vendor itself. + +The SAA711x are capable of processing 6 different video inputs, +CVBS1..6 and Y1+C1, Y2+C2, Y3+C3. All in 50/60Hz, NTSC, PAL or +SECAM and delivering a YUV datastream. On my card the input +'CVBS-0' corresponds to channel CVBS2 and 'S-Video' to Y2+C2. + +I have some reports of other cards working with the mentioned +chip sets. For a list of other working cards please have a look +at the cards named in the tvcards struct in the beginning of +zr36120.c + +After some testing, I discovered that the carddesigner messed up +on the I2C interface. The Zoran chip includes 2 lines SDA and SCL +which (s)he connected reversely. So we have to clock on the SDA +and r/w data on the SCL pin. Life is fun... Each cardtype now has +a bit which signifies if you have a card with the same deficiency. + +Oh, for the completeness of this story I must mention that my +card delivers the VSYNC pulse of the SAA chip to GIRQ1, not +GIRQ0 as some other cards have. This is also incorporated in +the driver be clearing/setting the 'useirq1' bit in the tvcard +description. + +Another problems of continuous capturing data with a Zoran chip +is something nasty inside the chip. It effectively halves the +fps we ought to get... Here is the scenario: capturing frames +to memory is done in the so-called snapshot mode. In this mode +the Zoran stops after capturing a frame worth of data and wait +till the application set GRAB bit to indicate readiness for the +next frame. After detecting a set bit, the chip neatly waits +till the start of a frame, captures it and it goes back to off. +Smart ppl will notice the problem here. Its the waiting on the +_next_ frame each time we set the GRAB bit... Oh well, 12,5 fps +is still plenty fast for me. +-- update 28/7/1999 -- +Don't believe a word I just said... Proof is the output +of `streamer -t 300 -r 25 -f avi15 -o /dev/null` + ++--+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25 + +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- + syncer: done + writer: done +(note the /dev/null is prudent here, my system is not able to + grab /and/ write 25 fps to a file... gifts welcome :) ) +The technical reasoning follows: The zoran completed the last +frame, the VSYNC goes low, and GRAB is cleared. The interrupt +routine starts to work since its VSYNC driven, and again +activates the GRAB bit. A few ms later the VSYNC (re-)rises and +the zoran starts to work on a new and freshly broadcasted frame.... + +For pointers I used the specs of both chips. Below are the URLs: + http://www.zoran.com/ftp/download/devices/pci/ZR36120/36120data.pdf + http://www-us.semiconductor.philips.com/acrobat/datasheets/SAA_7110_A_1.pdf +Some alternatives for the Philips SAA 7110 datasheet are: + http://www.datasheetcatalog.com/datasheets_pdf/S/A/A/7/SAA7110.shtml + http://www.datasheetarchive.com/search.php?search=SAA7110&sType=part + +The documentation has very little on absolute numbers or timings +needed for the various modes/resolutions, but there are other +programs you can borrow those from. + +------ Install -------------------------------------------- +Read the file called TODO. Note its long list of limitations. + +Build a kernel with VIDEO4LINUX enabled. Activate the +BT848 driver; we need this because we have need for the +other modules (i2c and videodev) it enables. + +To install this software, extract it into a suitable directory. +Examine the makefile and change anything you don't like. Type "make". + +After making the modules check if you have the much needed +/dev/video devices. If not, execute the following 4 lines: + mknod /dev/video c 81 0 + mknod /dev/video1 c 81 1 + mknod /dev/video2 c 81 2 + mknod /dev/video3 c 81 3 + mknod /dev/video4 c 81 4 + +After making/checking the devices do: + modprobe i2c + modprobe videodev + modprobe saa7110 (optional) + modprobe saa7111 (optional) + modprobe tuner (optional) + insmod zoran cardtype= + + is the cardtype of the card you have. The cardnumber can +be found in the source of zr36120. Look for tvcards. If your +card is not there, please try if any other card gives some +response, and mail me if you got a working tvcard addition. + +PS. files); - max_fds = fdt->max_fds; + max_fdset = fdt->max_fdset; rcu_read_unlock(); - if (n < 0 || n > max_fds) + if (n < 0 || n > max_fdset) goto out_nofds; /* diff --git a/trunk/arch/arm/kernel/apm.c b/trunk/arch/arm/kernel/apm.c index 2c37b70b17ab..a11fb9a40c04 100644 --- a/trunk/arch/arm/kernel/apm.c +++ b/trunk/arch/arm/kernel/apm.c @@ -423,7 +423,7 @@ static int apm_open(struct inode * inode, struct file * filp) { struct apm_user *as; - as = kzalloc(sizeof(*as), GFP_KERNEL); + as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL); if (as) { /* * XXX - this is a tiny bit broken, when we consider BSD diff --git a/trunk/arch/arm/kernel/ecard.c b/trunk/arch/arm/kernel/ecard.c index 71257e3d513f..a786f769035d 100644 --- a/trunk/arch/arm/kernel/ecard.c +++ b/trunk/arch/arm/kernel/ecard.c @@ -353,7 +353,7 @@ int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num) } if (c_id(&excd) == 0x80) { /* loader */ if (!ec->loader) { - ec->loader = kmalloc(c_len(&excd), + ec->loader = (loader_t)kmalloc(c_len(&excd), GFP_KERNEL); if (ec->loader) ecard_readbytes(ec->loader, ec, diff --git a/trunk/arch/arm/mach-omap1/Kconfig b/trunk/arch/arm/mach-omap1/Kconfig index 8781aaeb576b..d135568dc9e7 100644 --- a/trunk/arch/arm/mach-omap1/Kconfig +++ b/trunk/arch/arm/mach-omap1/Kconfig @@ -43,7 +43,6 @@ config MACH_OMAP_H3 config MACH_OMAP_OSK bool "TI OSK Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX - select TPS65010 help TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here if you have such a board. diff --git a/trunk/arch/arm/mach-omap1/board-osk.c b/trunk/arch/arm/mach-omap1/board-osk.c index 7d0cf7af88ce..3a622801d7b0 100644 --- a/trunk/arch/arm/mach-omap1/board-osk.c +++ b/trunk/arch/arm/mach-omap1/board-osk.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/arm/mach-pnx4008/Makefile b/trunk/arch/arm/mach-pnx4008/Makefile index 777564c90a12..b457ca0a431a 100644 --- a/trunk/arch/arm/mach-pnx4008/Makefile +++ b/trunk/arch/arm/mach-pnx4008/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o i2c.o +obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o obj-m := obj-n := obj- := diff --git a/trunk/arch/arm/mach-pnx4008/i2c.c b/trunk/arch/arm/mach-pnx4008/i2c.c deleted file mode 100644 index 6f308827c4fe..000000000000 --- a/trunk/arch/arm/mach-pnx4008/i2c.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * I2C initialization for PNX4008. - * - * Author: Vitaly Wool - * - * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include -#include -#include -#include - -static int set_clock_run(struct platform_device *pdev) -{ - struct clk *clk; - char name[10]; - int retval = 0; - - snprintf(name, 10, "i2c%d_ck", pdev->id); - clk = clk_get(&pdev->dev, name); - if (!IS_ERR(clk)) { - clk_set_rate(clk, 1); - clk_put(clk); - } else - retval = -ENOENT; - - return retval; -} - -static int set_clock_stop(struct platform_device *pdev) -{ - struct clk *clk; - char name[10]; - int retval = 0; - - snprintf(name, 10, "i2c%d_ck", pdev->id); - clk = clk_get(&pdev->dev, name); - if (!IS_ERR(clk)) { - clk_set_rate(clk, 0); - clk_put(clk); - } else - retval = -ENOENT; - - return retval; -} - -static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state) -{ - int retval = 0; -#ifdef CONFIG_PM - retval = set_clock_run(pdev); -#endif - return retval; -} - -static int i2c_pnx_resume(struct platform_device *pdev) -{ - int retval = 0; -#ifdef CONFIG_PM - retval = set_clock_run(pdev); -#endif - return retval; -} - -static u32 calculate_input_freq(struct platform_device *pdev) -{ - return HCLK_MHZ; -} - - -static struct i2c_pnx_algo_data pnx_algo_data0 = { - .base = PNX4008_I2C1_BASE, - .irq = I2C_1_INT, -}; - -static struct i2c_pnx_algo_data pnx_algo_data1 = { - .base = PNX4008_I2C2_BASE, - .irq = I2C_2_INT, -}; - -static struct i2c_pnx_algo_data pnx_algo_data2 = { - .base = (PNX4008_USB_CONFIG_BASE + 0x300), - .irq = USB_I2C_INT, -}; - -static struct i2c_adapter pnx_adapter0 = { - .name = I2C_CHIP_NAME "0", - .algo_data = &pnx_algo_data0, -}; -static struct i2c_adapter pnx_adapter1 = { - .name = I2C_CHIP_NAME "1", - .algo_data = &pnx_algo_data1, -}; - -static struct i2c_adapter pnx_adapter2 = { - .name = "USB-I2C", - .algo_data = &pnx_algo_data2, -}; - -static struct i2c_pnx_data i2c0_data = { - .suspend = i2c_pnx_suspend, - .resume = i2c_pnx_resume, - .calculate_input_freq = calculate_input_freq, - .set_clock_run = set_clock_run, - .set_clock_stop = set_clock_stop, - .adapter = &pnx_adapter0, -}; - -static struct i2c_pnx_data i2c1_data = { - .suspend = i2c_pnx_suspend, - .resume = i2c_pnx_resume, - .calculate_input_freq = calculate_input_freq, - .set_clock_run = set_clock_run, - .set_clock_stop = set_clock_stop, - .adapter = &pnx_adapter1, -}; - -static struct i2c_pnx_data i2c2_data = { - .suspend = i2c_pnx_suspend, - .resume = i2c_pnx_resume, - .calculate_input_freq = calculate_input_freq, - .set_clock_run = set_clock_run, - .set_clock_stop = set_clock_stop, - .adapter = &pnx_adapter2, -}; - -static struct platform_device i2c0_device = { - .name = "pnx-i2c", - .id = 0, - .dev = { - .platform_data = &i2c0_data, - }, -}; - -static struct platform_device i2c1_device = { - .name = "pnx-i2c", - .id = 1, - .dev = { - .platform_data = &i2c1_data, - }, -}; - -static struct platform_device i2c2_device = { - .name = "pnx-i2c", - .id = 2, - .dev = { - .platform_data = &i2c2_data, - }, -}; - -static struct platform_device *devices[] __initdata = { - &i2c0_device, - &i2c1_device, - &i2c2_device, -}; - -void __init pnx4008_register_i2c_devices(void) -{ - platform_add_devices(devices, ARRAY_SIZE(devices)); -} diff --git a/trunk/arch/arm/mach-pxa/Kconfig b/trunk/arch/arm/mach-pxa/Kconfig index 5c0a10041cd1..9e3d0bdcba07 100644 --- a/trunk/arch/arm/mach-pxa/Kconfig +++ b/trunk/arch/arm/mach-pxa/Kconfig @@ -75,28 +75,28 @@ endmenu config MACH_POODLE bool "Enable Sharp SL-5600 (Poodle) Support" - depends on PXA_SHARPSL_25x + depends PXA_SHARPSL_25x select SHARP_LOCOMO select PXA_SSP config MACH_CORGI bool "Enable Sharp SL-C700 (Corgi) Support" - depends on PXA_SHARPSL_25x + depends PXA_SHARPSL_25x select PXA_SHARP_C7xx config MACH_SHEPHERD bool "Enable Sharp SL-C750 (Shepherd) Support" - depends on PXA_SHARPSL_25x + depends PXA_SHARPSL_25x select PXA_SHARP_C7xx config MACH_HUSKY bool "Enable Sharp SL-C760 (Husky) Support" - depends on PXA_SHARPSL_25x + depends PXA_SHARPSL_25x select PXA_SHARP_C7xx config MACH_AKITA bool "Enable Sharp SL-1000 (Akita) Support" - depends on PXA_SHARPSL_27x + depends PXA_SHARPSL_27x select PXA_SHARP_Cxx00 select MACH_SPITZ select I2C @@ -104,17 +104,17 @@ config MACH_AKITA config MACH_SPITZ bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" - depends on PXA_SHARPSL_27x + depends PXA_SHARPSL_27x select PXA_SHARP_Cxx00 config MACH_BORZOI bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support" - depends on PXA_SHARPSL_27x + depends PXA_SHARPSL_27x select PXA_SHARP_Cxx00 config MACH_TOSA bool "Enable Sharp SL-6000x (Tosa) Support" - depends on PXA_SHARPSL_25x + depends PXA_SHARPSL_25x config PXA25x bool diff --git a/trunk/arch/arm/mach-realview/core.c b/trunk/arch/arm/mach-realview/core.c index 84d3fe76e94e..68c67053f479 100644 --- a/trunk/arch/arm/mach-realview/core.c +++ b/trunk/arch/arm/mach-realview/core.c @@ -141,19 +141,6 @@ struct platform_device realview_smc91x_device = { .resource = realview_smc91x_resources, }; -static struct resource realview_i2c_resource = { - .start = REALVIEW_I2C_BASE, - .end = REALVIEW_I2C_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, -}; - -struct platform_device realview_i2c_device = { - .name = "versatile-i2c", - .id = -1, - .num_resources = 1, - .resource = &realview_i2c_resource, -}; - #define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET) static unsigned int realview_mmc_status(struct device *dev) diff --git a/trunk/arch/arm/mach-realview/core.h b/trunk/arch/arm/mach-realview/core.h index 2b53420f9c1b..93e86d9f439c 100644 --- a/trunk/arch/arm/mach-realview/core.h +++ b/trunk/arch/arm/mach-realview/core.h @@ -108,7 +108,6 @@ static struct amba_device name##_device = { \ extern struct platform_device realview_flash_device; extern struct platform_device realview_smc91x_device; -extern struct platform_device realview_i2c_device; extern struct mmc_platform_data realview_mmc0_plat_data; extern struct mmc_platform_data realview_mmc1_plat_data; extern struct clk realview_clcd_clk; diff --git a/trunk/arch/arm/mach-realview/realview_eb.c b/trunk/arch/arm/mach-realview/realview_eb.c index 9741b4d3c9cf..84a959530fb6 100644 --- a/trunk/arch/arm/mach-realview/realview_eb.c +++ b/trunk/arch/arm/mach-realview/realview_eb.c @@ -155,7 +155,6 @@ static void __init realview_eb_init(void) platform_device_register(&realview_flash_device); platform_device_register(&realview_smc91x_device); - platform_device_register(&realview_i2c_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; diff --git a/trunk/arch/arm/mach-versatile/core.c b/trunk/arch/arm/mach-versatile/core.c index bf71507c76fd..57196947559f 100644 --- a/trunk/arch/arm/mach-versatile/core.c +++ b/trunk/arch/arm/mach-versatile/core.c @@ -325,19 +325,6 @@ static struct platform_device smc91x_device = { .resource = smc91x_resources, }; -static struct resource versatile_i2c_resource = { - .start = VERSATILE_I2C_BASE, - .end = VERSATILE_I2C_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device versatile_i2c_device = { - .name = "versatile-i2c", - .id = -1, - .num_resources = 1, - .resource = &versatile_i2c_resource, -}; - #define VERSATILE_SYSMCI (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET) unsigned int mmc_status(struct device *dev) @@ -788,7 +775,6 @@ void __init versatile_init(void) clk_register(&versatile_clcd_clk); platform_device_register(&versatile_flash_device); - platform_device_register(&versatile_i2c_device); platform_device_register(&smc91x_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/trunk/arch/arm/plat-omap/Kconfig b/trunk/arch/arm/plat-omap/Kconfig index f2dc363de66b..ec752e16d618 100644 --- a/trunk/arch/arm/plat-omap/Kconfig +++ b/trunk/arch/arm/plat-omap/Kconfig @@ -113,7 +113,7 @@ endchoice config OMAP_SERIAL_WAKE bool "Enable wake-up events for serial ports" - depends on OMAP_MUX + depends OMAP_MUX default y help Select this option if you want to have your system wake up diff --git a/trunk/arch/arm26/kernel/ecard.c b/trunk/arch/arm26/kernel/ecard.c index 9dbc17247c6f..43dd41be71fb 100644 --- a/trunk/arch/arm26/kernel/ecard.c +++ b/trunk/arch/arm26/kernel/ecard.c @@ -215,7 +215,7 @@ int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num) } if (c_id(&excd) == 0x80) { /* loader */ if (!ec->loader) { - ec->loader = kmalloc(c_len(&excd), + ec->loader = (loader_t)kmalloc(c_len(&excd), GFP_KERNEL); if (ec->loader) ecard_readbytes(ec->loader, ec, diff --git a/trunk/arch/arm26/kernel/irq.c b/trunk/arch/arm26/kernel/irq.c index d53382c83bf9..d87d68b77d66 100644 --- a/trunk/arch/arm26/kernel/irq.c +++ b/trunk/arch/arm26/kernel/irq.c @@ -545,7 +545,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ (irq_flags & IRQF_SHARED && !dev_id)) return -EINVAL; - action = kmalloc(sizeof(struct irqaction), GFP_KERNEL); + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; diff --git a/trunk/arch/avr32/boards/atstk1000/atstk1002.c b/trunk/arch/avr32/boards/atstk1000/atstk1002.c index 32b361f31c2c..cced73c58115 100644 --- a/trunk/arch/avr32/boards/atstk1000/atstk1002.c +++ b/trunk/arch/avr32/boards/atstk1000/atstk1002.c @@ -7,83 +7,20 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include -struct eth_addr { - u8 addr[6]; +struct eth_platform_data __initdata eth0_data = { + .valid = 1, + .mii_phy_addr = 0x10, + .is_rmii = 0, + .hw_addr = { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb }, }; -static struct eth_addr __initdata hw_addr[2]; - -static struct eth_platform_data __initdata eth_data[2]; extern struct lcdc_platform_data atstk1000_fb0_data; -/* - * The next two functions should go away as the boot loader is - * supposed to initialize the macb address registers with a valid - * ethernet address. But we need to keep it around for a while until - * we can be reasonably sure the boot loader does this. - * - * The phy_id is ignored as the driver will probe for it. - */ -static int __init parse_tag_ethernet(struct tag *tag) -{ - int i; - - i = tag->u.ethernet.mac_index; - if (i < ARRAY_SIZE(hw_addr)) - memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, - sizeof(hw_addr[i].addr)); - - return 0; -} -__tagtable(ATAG_ETHERNET, parse_tag_ethernet); - -static void __init set_hw_addr(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - const u8 *addr; - void __iomem *regs; - struct clk *pclk; - - if (!res) - return; - if (pdev->id >= ARRAY_SIZE(hw_addr)) - return; - - addr = hw_addr[pdev->id].addr; - if (!is_valid_ether_addr(addr)) - return; - - /* - * Since this is board-specific code, we'll cheat and use the - * physical address directly as we happen to know that it's - * the same as the virtual address. - */ - regs = (void __iomem __force *)res->start; - pclk = clk_get(&pdev->dev, "pclk"); - if (!pclk) - return; - - clk_enable(pclk); - __raw_writel((addr[3] << 24) | (addr[2] << 16) - | (addr[1] << 8) | addr[0], regs + 0x98); - __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); - clk_disable(pclk); - clk_put(pclk); -} - void __init setup_board(void) { at32_map_usart(1, 0); /* /dev/ttyS0 */ @@ -101,8 +38,7 @@ static int __init atstk1002_init(void) at32_add_device_usart(1); at32_add_device_usart(2); - set_hw_addr(at32_add_device_eth(0, ð_data[0])); - + at32_add_device_eth(0, ð0_data); at32_add_device_spi(0); at32_add_device_lcdc(0, &atstk1000_fb0_data); diff --git a/trunk/arch/avr32/kernel/avr32_ksyms.c b/trunk/arch/avr32/kernel/avr32_ksyms.c index 7c4c76114bba..372e3f8b2417 100644 --- a/trunk/arch/avr32/kernel/avr32_ksyms.c +++ b/trunk/arch/avr32/kernel/avr32_ksyms.c @@ -7,12 +7,12 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include #include #include #include #include +#include /* * GCC functions diff --git a/trunk/arch/avr32/kernel/process.c b/trunk/arch/avr32/kernel/process.c index 0b4325946a41..317dc50945f2 100644 --- a/trunk/arch/avr32/kernel/process.c +++ b/trunk/arch/avr32/kernel/process.c @@ -38,13 +38,6 @@ void cpu_idle(void) void machine_halt(void) { - /* - * Enter Stop mode. The 32 kHz oscillator will keep running so - * the RTC will keep the time properly and the system will - * boot quickly. - */ - asm volatile("sleep 3\n\t" - "sub pc, -2"); } void machine_power_off(void) diff --git a/trunk/arch/avr32/kernel/setup.c b/trunk/arch/avr32/kernel/setup.c index a34211601008..ea2d1ffee478 100644 --- a/trunk/arch/avr32/kernel/setup.c +++ b/trunk/arch/avr32/kernel/setup.c @@ -229,6 +229,30 @@ static int __init parse_tag_rsvd_mem(struct tag *tag) } __tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem); +static int __init parse_tag_ethernet(struct tag *tag) +{ +#if 0 + const struct platform_device *pdev; + + /* + * We really need a bus type that supports "classes"...this + * will do for now (until we must handle other kinds of + * ethernet controllers) + */ + pdev = platform_get_device("macb", tag->u.ethernet.mac_index); + if (pdev && pdev->dev.platform_data) { + struct eth_platform_data *data = pdev->dev.platform_data; + + data->valid = 1; + data->mii_phy_addr = tag->u.ethernet.mii_phy_addr; + memcpy(data->hw_addr, tag->u.ethernet.hw_address, + sizeof(data->hw_addr)); + } +#endif + return 0; +} +__tagtable(ATAG_ETHERNET, parse_tag_ethernet); + /* * Scan the tag table for this tag, and call its parse function. The * tag table is built by the linker from all the __tagtable diff --git a/trunk/arch/avr32/lib/delay.c b/trunk/arch/avr32/lib/delay.c index b3bc0b56e2c6..462c8307b680 100644 --- a/trunk/arch/avr32/lib/delay.c +++ b/trunk/arch/avr32/lib/delay.c @@ -12,9 +12,9 @@ #include #include -#include #include +#include #include #include diff --git a/trunk/arch/avr32/mach-at32ap/at32ap7000.c b/trunk/arch/avr32/mach-at32ap/at32ap7000.c index 48f4ef38c70e..7ff6ad8bab5f 100644 --- a/trunk/arch/avr32/mach-at32ap/at32ap7000.c +++ b/trunk/arch/avr32/mach-at32ap/at32ap7000.c @@ -11,7 +11,6 @@ #include -#include #include #include #include @@ -58,9 +57,6 @@ static struct platform_device _name##_id##_device = { \ .num_resources = ARRAY_SIZE(_name##_id##_resource), \ } -#define select_peripheral(pin, periph, flags) \ - at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags) - #define DEV_CLK(_name, devname, bus, _index) \ static struct clk devname##_##_name = { \ .name = #_name, \ @@ -71,6 +67,18 @@ static struct clk devname##_##_name = { \ .index = _index, \ } +enum { + PIOA, + PIOB, + PIOC, + PIOD, +}; + +enum { + FUNC_A, + FUNC_B, +}; + unsigned long at32ap7000_osc_rates[3] = { [0] = 32768, /* FIXME: these are ATSTK1002-specific */ @@ -561,26 +569,26 @@ DEV_CLK(usart, atmel_usart3, pba, 6); static inline void configure_usart0_pins(void) { - select_peripheral(PA(8), PERIPH_B, 0); /* RXD */ - select_peripheral(PA(9), PERIPH_B, 0); /* TXD */ + portmux_set_func(PIOA, 8, FUNC_B); /* RXD */ + portmux_set_func(PIOA, 9, FUNC_B); /* TXD */ } static inline void configure_usart1_pins(void) { - select_peripheral(PA(17), PERIPH_A, 0); /* RXD */ - select_peripheral(PA(18), PERIPH_A, 0); /* TXD */ + portmux_set_func(PIOA, 17, FUNC_A); /* RXD */ + portmux_set_func(PIOA, 18, FUNC_A); /* TXD */ } static inline void configure_usart2_pins(void) { - select_peripheral(PB(26), PERIPH_B, 0); /* RXD */ - select_peripheral(PB(27), PERIPH_B, 0); /* TXD */ + portmux_set_func(PIOB, 26, FUNC_B); /* RXD */ + portmux_set_func(PIOB, 27, FUNC_B); /* TXD */ } static inline void configure_usart3_pins(void) { - select_peripheral(PB(18), PERIPH_B, 0); /* RXD */ - select_peripheral(PB(17), PERIPH_B, 0); /* TXD */ + portmux_set_func(PIOB, 18, FUNC_B); /* RXD */ + portmux_set_func(PIOB, 17, FUNC_B); /* TXD */ } static struct platform_device *at32_usarts[4]; @@ -646,15 +654,6 @@ DEFINE_DEV_DATA(macb, 0); DEV_CLK(hclk, macb0, hsb, 8); DEV_CLK(pclk, macb0, pbb, 6); -static struct eth_platform_data macb1_data; -static struct resource macb1_resource[] = { - PBMEM(0xfff01c00), - IRQ(26), -}; -DEFINE_DEV_DATA(macb, 1); -DEV_CLK(hclk, macb1, hsb, 9); -DEV_CLK(pclk, macb1, pbb, 7); - struct platform_device *__init at32_add_device_eth(unsigned int id, struct eth_platform_data *data) { @@ -664,54 +663,27 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data) case 0: pdev = &macb0_device; - select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */ - select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */ - select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */ - select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */ - select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */ - select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */ - select_peripheral(PC(13), PERIPH_A, 0); /* RXER */ - select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */ - select_peripheral(PC(16), PERIPH_A, 0); /* MDC */ - select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */ - - if (!data->is_rmii) { - select_peripheral(PC(0), PERIPH_A, 0); /* COL */ - select_peripheral(PC(1), PERIPH_A, 0); /* CRS */ - select_peripheral(PC(2), PERIPH_A, 0); /* TXER */ - select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */ - select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */ - select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */ - select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */ - select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */ - select_peripheral(PC(18), PERIPH_A, 0); /* SPD */ - } - break; - - case 1: - pdev = &macb1_device; - - select_peripheral(PD(13), PERIPH_B, 0); /* TXD0 */ - select_peripheral(PD(14), PERIPH_B, 0); /* TXD1 */ - select_peripheral(PD(11), PERIPH_B, 0); /* TXEN */ - select_peripheral(PD(12), PERIPH_B, 0); /* TXCK */ - select_peripheral(PD(10), PERIPH_B, 0); /* RXD0 */ - select_peripheral(PD(6), PERIPH_B, 0); /* RXD1 */ - select_peripheral(PD(5), PERIPH_B, 0); /* RXER */ - select_peripheral(PD(4), PERIPH_B, 0); /* RXDV */ - select_peripheral(PD(3), PERIPH_B, 0); /* MDC */ - select_peripheral(PD(2), PERIPH_B, 0); /* MDIO */ + portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */ + portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */ + portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */ + portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */ + portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */ + portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */ + portmux_set_func(PIOC, 13, FUNC_A); /* RXER */ + portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */ + portmux_set_func(PIOC, 16, FUNC_A); /* MDC */ + portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */ if (!data->is_rmii) { - select_peripheral(PC(19), PERIPH_B, 0); /* COL */ - select_peripheral(PC(23), PERIPH_B, 0); /* CRS */ - select_peripheral(PC(26), PERIPH_B, 0); /* TXER */ - select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */ - select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */ - select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */ - select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */ - select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */ - select_peripheral(PD(15), PERIPH_B, 0); /* SPD */ + portmux_set_func(PIOC, 0, FUNC_A); /* COL */ + portmux_set_func(PIOC, 1, FUNC_A); /* CRS */ + portmux_set_func(PIOC, 2, FUNC_A); /* TXER */ + portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */ + portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */ + portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */ + portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */ + portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */ + portmux_set_func(PIOC, 18, FUNC_A); /* SPD */ } break; @@ -742,12 +714,12 @@ struct platform_device *__init at32_add_device_spi(unsigned int id) switch (id) { case 0: pdev = &spi0_device; - select_peripheral(PA(0), PERIPH_A, 0); /* MISO */ - select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ - select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ - select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */ - select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */ - select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */ + portmux_set_func(PIOA, 0, FUNC_A); /* MISO */ + portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */ + portmux_set_func(PIOA, 2, FUNC_A); /* SCK */ + portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */ + portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */ + portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */ break; default: @@ -790,37 +762,37 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) switch (id) { case 0: pdev = &lcdc0_device; - select_peripheral(PC(19), PERIPH_A, 0); /* CC */ - select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ - select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ - select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */ - select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */ - select_peripheral(PC(24), PERIPH_A, 0); /* MODE */ - select_peripheral(PC(25), PERIPH_A, 0); /* PWR */ - select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */ - select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */ - select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */ - select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */ - select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */ - select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */ - select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */ - select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */ - select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */ - select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */ - select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */ - select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */ - select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */ - select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */ - select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */ - select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */ - select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */ - select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */ - select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */ - select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */ - select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */ - select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */ - select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ - select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ + portmux_set_func(PIOC, 19, FUNC_A); /* CC */ + portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */ + portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */ + portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */ + portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */ + portmux_set_func(PIOC, 24, FUNC_A); /* MODE */ + portmux_set_func(PIOC, 25, FUNC_A); /* PWR */ + portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */ + portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */ + portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */ + portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */ + portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */ + portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */ + portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */ + portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */ + portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */ + portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */ + portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */ + portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */ + portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */ + portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */ + portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */ + portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */ + portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */ + portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */ + portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */ + portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */ + portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */ + portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */ + portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */ + portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */ clk_set_parent(&lcdc0_pixclk, &pll0); clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); @@ -866,8 +838,6 @@ struct clk *at32_clock_list[] = { &atmel_usart3_usart, &macb0_hclk, &macb0_pclk, - &macb1_hclk, - &macb1_pclk, &spi0_mck, &lcdc0_hclk, &lcdc0_pixclk, diff --git a/trunk/arch/avr32/mach-at32ap/extint.c b/trunk/arch/avr32/mach-at32ap/extint.c index b59272e81b9a..4dff1f988900 100644 --- a/trunk/arch/avr32/mach-at32ap/extint.c +++ b/trunk/arch/avr32/mach-at32ap/extint.c @@ -49,25 +49,12 @@ static void eim_unmask_irq(unsigned int irq) static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) { struct at32_sm *sm = get_irq_chip_data(irq); - struct irq_desc *desc; unsigned int i = irq - sm->eim_first_irq; u32 mode, edge, level; unsigned long flags; int ret = 0; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - desc = &irq_desc[irq]; - desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); - desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; - - if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) { - desc->status |= IRQ_LEVEL; - set_irq_handler(irq, handle_level_irq); - } else { - set_irq_handler(irq, handle_edge_irq); - } + flow_type &= IRQ_TYPE_SENSE_MASK; spin_lock_irqsave(&sm->lock, flags); @@ -161,15 +148,10 @@ static int __init eim_init(void) pattern = sm_readl(sm, EIM_MODE); nr_irqs = fls(pattern); - /* Trigger on falling edge unless overridden by driver */ - sm_writel(sm, EIM_MODE, 0UL); - sm_writel(sm, EIM_EDGE, 0UL); - sm->eim_chip = &eim_chip; for (i = 0; i < nr_irqs; i++) { - set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip, - handle_edge_irq); + set_irq_chip(sm->eim_first_irq + i, &eim_chip); set_irq_chip_data(sm->eim_first_irq + i, sm); } diff --git a/trunk/arch/avr32/mach-at32ap/intc.c b/trunk/arch/avr32/mach-at32ap/intc.c index dd5c009cf224..eb87a18ad7b2 100644 --- a/trunk/arch/avr32/mach-at32ap/intc.c +++ b/trunk/arch/avr32/mach-at32ap/intc.c @@ -136,7 +136,3 @@ void __init init_IRQ(void) panic("Interrupt controller initialization failed!\n"); } -unsigned long intc_get_pending(int group) -{ - return intc_readl(&intc0, INTREQ0 + 4 * group); -} diff --git a/trunk/arch/avr32/mach-at32ap/pio.c b/trunk/arch/avr32/mach-at32ap/pio.c index f1280ed8ed6d..d3aabfca8598 100644 --- a/trunk/arch/avr32/mach-at32ap/pio.c +++ b/trunk/arch/avr32/mach-at32ap/pio.c @@ -25,98 +25,27 @@ struct pio_device { void __iomem *regs; const struct platform_device *pdev; struct clk *clk; - u32 pinmux_mask; + u32 alloc_mask; char name[32]; }; static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; -static struct pio_device *gpio_to_pio(unsigned int gpio) +void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, + unsigned int function_id) { struct pio_device *pio; - unsigned int index; + u32 mask = 1 << pin_id; - index = gpio >> 5; - if (index >= MAX_NR_PIO_DEVICES) - return NULL; - pio = &pio_dev[index]; - if (!pio->regs) - return NULL; + BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES); - return pio; -} - -/* Pin multiplexing API */ - -void __init at32_select_periph(unsigned int pin, unsigned int periph, - unsigned long flags) -{ - struct pio_device *pio; - unsigned int pin_index = pin & 0x1f; - u32 mask = 1 << pin_index; - - pio = gpio_to_pio(pin); - if (unlikely(!pio)) { - printk("pio: invalid pin %u\n", pin); - goto fail; - } + pio = &pio_dev[portmux_id]; - if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { - printk("%s: pin %u is busy\n", pio->name, pin_index); - goto fail; - } - - pio_writel(pio, PUER, mask); - if (periph) + if (function_id) pio_writel(pio, BSR, mask); else pio_writel(pio, ASR, mask); - pio_writel(pio, PDR, mask); - if (!(flags & AT32_GPIOF_PULLUP)) - pio_writel(pio, PUDR, mask); - - return; - -fail: - dump_stack(); -} - -void __init at32_select_gpio(unsigned int pin, unsigned long flags) -{ - struct pio_device *pio; - unsigned int pin_index = pin & 0x1f; - u32 mask = 1 << pin_index; - - pio = gpio_to_pio(pin); - if (unlikely(!pio)) { - printk("pio: invalid pin %u\n", pin); - goto fail; - } - - if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { - printk("%s: pin %u is busy\n", pio->name, pin_index); - goto fail; - } - - pio_writel(pio, PUER, mask); - if (flags & AT32_GPIOF_HIGH) - pio_writel(pio, SODR, mask); - else - pio_writel(pio, CODR, mask); - if (flags & AT32_GPIOF_OUTPUT) - pio_writel(pio, OER, mask); - else - pio_writel(pio, ODR, mask); - - pio_writel(pio, PER, mask); - if (!(flags & AT32_GPIOF_PULLUP)) - pio_writel(pio, PUDR, mask); - - return; - -fail: - dump_stack(); } static int __init pio_probe(struct platform_device *pdev) diff --git a/trunk/arch/avr32/mach-at32ap/sm.c b/trunk/arch/avr32/mach-at32ap/sm.c new file mode 100644 index 000000000000..03306eb0345e --- /dev/null +++ b/trunk/arch/avr32/mach-at32ap/sm.c @@ -0,0 +1,289 @@ +/* + * System Manager driver for AT32AP CPUs + * + * Copyright (C) 2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "sm.h" + +#define SM_EIM_IRQ_RESOURCE 1 +#define SM_PM_IRQ_RESOURCE 2 +#define SM_RTC_IRQ_RESOURCE 3 + +#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc) + +struct at32_sm system_manager; + +int __init at32_sm_init(void) +{ + struct resource *regs; + struct at32_sm *sm = &system_manager; + int ret = -ENXIO; + + regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0); + if (!regs) + goto fail; + + spin_lock_init(&sm->lock); + sm->pdev = &at32_sm_device; + + ret = -ENOMEM; + sm->regs = ioremap(regs->start, regs->end - regs->start + 1); + if (!sm->regs) + goto fail; + + return 0; + +fail: + printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret); + return ret; +} + +/* + * External Interrupt Module (EIM). + * + * EIM gets level- or edge-triggered interrupts of either polarity + * from the outside and converts it to active-high level-triggered + * interrupts that the internal interrupt controller can handle. EIM + * also provides masking/unmasking of interrupts, as well as + * acknowledging of edge-triggered interrupts. + */ + +static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq); + disable_irq(irq); + return IRQ_NONE; +} + +static struct irqaction eim_spurious_action = { + .handler = spurious_eim_interrupt, +}; + +static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct irq_controller * irqc = dev_id; + struct at32_sm *sm = to_eim(irqc); + unsigned long pending; + + /* + * No need to disable interrupts globally. The interrupt + * level relevant to this group must be masked all the time, + * so we know that this particular EIM instance will not be + * re-entered. + */ + spin_lock(&sm->lock); + + pending = intc_get_pending(sm->irqc.irq_group); + if (unlikely(!pending)) { + printk(KERN_ERR "EIM (group %u): No interrupts pending!\n", + sm->irqc.irq_group); + goto unlock; + } + + do { + struct irqaction *action; + unsigned int i; + + i = fls(pending) - 1; + pending &= ~(1 << i); + action = sm->action[i]; + + /* Acknowledge the interrupt */ + sm_writel(sm, EIM_ICR, 1 << i); + + spin_unlock(&sm->lock); + + if (action->flags & SA_INTERRUPT) + local_irq_disable(); + action->handler(sm->irqc.first_irq + i, action->dev_id, regs); + local_irq_enable(); + spin_lock(&sm->lock); + if (action->flags & SA_SAMPLE_RANDOM) + add_interrupt_randomness(sm->irqc.first_irq + i); + } while (pending); + +unlock: + spin_unlock(&sm->lock); + return IRQ_HANDLED; +} + +static void eim_mask(struct irq_controller *irqc, unsigned int irq) +{ + struct at32_sm *sm = to_eim(irqc); + unsigned int i; + + i = irq - sm->irqc.first_irq; + sm_writel(sm, EIM_IDR, 1 << i); +} + +static void eim_unmask(struct irq_controller *irqc, unsigned int irq) +{ + struct at32_sm *sm = to_eim(irqc); + unsigned int i; + + i = irq - sm->irqc.first_irq; + sm_writel(sm, EIM_IER, 1 << i); +} + +static int eim_setup(struct irq_controller *irqc, unsigned int irq, + struct irqaction *action) +{ + struct at32_sm *sm = to_eim(irqc); + sm->action[irq - sm->irqc.first_irq] = action; + /* Acknowledge earlier interrupts */ + sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq))); + eim_unmask(irqc, irq); + return 0; +} + +static void eim_free(struct irq_controller *irqc, unsigned int irq, + void *dev) +{ + struct at32_sm *sm = to_eim(irqc); + eim_mask(irqc, irq); + sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action; +} + +static int eim_set_type(struct irq_controller *irqc, unsigned int irq, + unsigned int type) +{ + struct at32_sm *sm = to_eim(irqc); + unsigned long flags; + u32 value, pattern; + + spin_lock_irqsave(&sm->lock, flags); + + pattern = 1 << (irq - sm->irqc.first_irq); + + value = sm_readl(sm, EIM_MODE); + if (type & IRQ_TYPE_LEVEL) + value |= pattern; + else + value &= ~pattern; + sm_writel(sm, EIM_MODE, value); + value = sm_readl(sm, EIM_EDGE); + if (type & IRQ_EDGE_RISING) + value |= pattern; + else + value &= ~pattern; + sm_writel(sm, EIM_EDGE, value); + value = sm_readl(sm, EIM_LEVEL); + if (type & IRQ_LEVEL_HIGH) + value |= pattern; + else + value &= ~pattern; + sm_writel(sm, EIM_LEVEL, value); + + spin_unlock_irqrestore(&sm->lock, flags); + + return 0; +} + +static unsigned int eim_get_type(struct irq_controller *irqc, + unsigned int irq) +{ + struct at32_sm *sm = to_eim(irqc); + unsigned long flags; + unsigned int type = 0; + u32 mode, edge, level, pattern; + + pattern = 1 << (irq - sm->irqc.first_irq); + + spin_lock_irqsave(&sm->lock, flags); + mode = sm_readl(sm, EIM_MODE); + edge = sm_readl(sm, EIM_EDGE); + level = sm_readl(sm, EIM_LEVEL); + spin_unlock_irqrestore(&sm->lock, flags); + + if (mode & pattern) + type |= IRQ_TYPE_LEVEL; + if (edge & pattern) + type |= IRQ_EDGE_RISING; + if (level & pattern) + type |= IRQ_LEVEL_HIGH; + + return type; +} + +static struct irq_controller_class eim_irq_class = { + .typename = "EIM", + .handle = eim_handle_irq, + .setup = eim_setup, + .free = eim_free, + .mask = eim_mask, + .unmask = eim_unmask, + .set_type = eim_set_type, + .get_type = eim_get_type, +}; + +static int __init eim_init(void) +{ + struct at32_sm *sm = &system_manager; + unsigned int i; + u32 pattern; + int ret; + + /* + * The EIM is really the same module as SM, so register + * mapping, etc. has been taken care of already. + */ + + /* + * Find out how many interrupt lines that are actually + * implemented in hardware. + */ + sm_writel(sm, EIM_IDR, ~0UL); + sm_writel(sm, EIM_MODE, ~0UL); + pattern = sm_readl(sm, EIM_MODE); + sm->irqc.nr_irqs = fls(pattern); + + ret = -ENOMEM; + sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs, + GFP_KERNEL); + if (!sm->action) + goto out; + + for (i = 0; i < sm->irqc.nr_irqs; i++) + sm->action[i] = &eim_spurious_action; + + spin_lock_init(&sm->lock); + sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start; + sm->irqc.class = &eim_irq_class; + + ret = intc_register_controller(&sm->irqc); + if (ret < 0) + goto out_free_actions; + + printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n", + sm->regs, sm->irqc.irq_group); + printk("EIM: Handling %u external IRQs, starting with IRQ%u\n", + sm->irqc.nr_irqs, sm->irqc.first_irq); + + return 0; + +out_free_actions: + kfree(sm->action); +out: + return ret; +} +arch_initcall(eim_init); diff --git a/trunk/arch/cris/arch-v10/drivers/axisflashmap.c b/trunk/arch/cris/arch-v10/drivers/axisflashmap.c index ffade19a14e6..4fa81abab0c7 100644 --- a/trunk/arch/cris/arch-v10/drivers/axisflashmap.c +++ b/trunk/arch/cris/arch-v10/drivers/axisflashmap.c @@ -516,7 +516,7 @@ static int __init init_axis_flash(void) #else struct mtd_info *mtd_ram; - mtd_ram = kmalloc(sizeof(struct mtd_info), + mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL); if (!mtd_ram) { panic("axisflashmap couldn't allocate memory for " diff --git a/trunk/arch/cris/arch-v10/drivers/gpio.c b/trunk/arch/cris/arch-v10/drivers/gpio.c index 9aba18b931dd..fcba6632ed7b 100644 --- a/trunk/arch/cris/arch-v10/drivers/gpio.c +++ b/trunk/arch/cris/arch-v10/drivers/gpio.c @@ -440,7 +440,7 @@ gpio_open(struct inode *inode, struct file *filp) if (p > GPIO_MINOR_LAST) return -EINVAL; - priv = kmalloc(sizeof(struct gpio_private), + priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private), GFP_KERNEL); if (!priv) diff --git a/trunk/arch/cris/arch-v32/drivers/axisflashmap.c b/trunk/arch/cris/arch-v32/drivers/axisflashmap.c index 5180d45412fc..41952320e00a 100644 --- a/trunk/arch/cris/arch-v32/drivers/axisflashmap.c +++ b/trunk/arch/cris/arch-v32/drivers/axisflashmap.c @@ -427,7 +427,7 @@ static int __init init_axis_flash(void) #else struct mtd_info *mtd_ram; - mtd_ram = kmalloc(sizeof(struct mtd_info), + mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL); if (!mtd_ram) { panic("axisflashmap couldn't allocate memory for " diff --git a/trunk/arch/cris/arch-v32/drivers/gpio.c b/trunk/arch/cris/arch-v32/drivers/gpio.c index 08d36f0955c6..c3f876b4da6b 100644 --- a/trunk/arch/cris/arch-v32/drivers/gpio.c +++ b/trunk/arch/cris/arch-v32/drivers/gpio.c @@ -423,7 +423,7 @@ gpio_open(struct inode *inode, struct file *filp) if (p > GPIO_MINOR_LAST) return -EINVAL; - priv = kmalloc(sizeof(struct gpio_private), + priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private), GFP_KERNEL); if (!priv) diff --git a/trunk/arch/cris/arch-v32/kernel/signal.c b/trunk/arch/cris/arch-v32/kernel/signal.c index 7cd6ac803409..99e59b3eacf8 100644 --- a/trunk/arch/cris/arch-v32/kernel/signal.c +++ b/trunk/arch/cris/arch-v32/kernel/signal.c @@ -686,7 +686,7 @@ keep_debug_flags(unsigned long oldccs, unsigned long oldspc, int __init cris_init_signal(void) { - u16* data = kmalloc(PAGE_SIZE, GFP_KERNEL); + u16* data = (u16*)kmalloc(PAGE_SIZE, GFP_KERNEL); /* This is movu.w __NR_sigreturn, r9; break 13; */ data[0] = 0x9c5f; diff --git a/trunk/arch/cris/kernel/profile.c b/trunk/arch/cris/kernel/profile.c index f60ab785f235..69c52189f044 100644 --- a/trunk/arch/cris/kernel/profile.c +++ b/trunk/arch/cris/kernel/profile.c @@ -59,7 +59,7 @@ static int __init init_cris_profile(void) { struct proc_dir_entry *entry; - sample_buffer = kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL); + sample_buffer = (char*)kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL); sample_buffer_pos = sample_buffer; entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL); if (entry) { diff --git a/trunk/arch/frv/kernel/pm.c b/trunk/arch/frv/kernel/pm.c index ee677ced7b68..c1d9fc8f1a85 100644 --- a/trunk/arch/frv/kernel/pm.c +++ b/trunk/arch/frv/kernel/pm.c @@ -223,7 +223,7 @@ static int cmode_procctl(ctl_table *ctl, int write, struct file *filp, static int cmode_sysctl(ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, - void __user *newval, size_t newlen) + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; @@ -326,7 +326,7 @@ static int p0_procctl(ctl_table *ctl, int write, struct file *filp, static int p0_sysctl(ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, - void __user *newval, size_t newlen) + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; @@ -370,7 +370,7 @@ static int cm_procctl(ctl_table *ctl, int write, struct file *filp, static int cm_sysctl(ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, - void __user *newval, size_t newlen) + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; diff --git a/trunk/arch/h8300/kernel/ints.c b/trunk/arch/h8300/kernel/ints.c index 587ef7f4fcc7..1bfc77e391d5 100644 --- a/trunk/arch/h8300/kernel/ints.c +++ b/trunk/arch/h8300/kernel/ints.c @@ -141,7 +141,7 @@ int request_irq(unsigned int irq, return -EBUSY; if (use_kmalloc) - irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC); + irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC); else { /* use bootmem allocater */ irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t)); diff --git a/trunk/arch/h8300/platform/h8s/ints.c b/trunk/arch/h8300/platform/h8s/ints.c index 567f681ddfec..270440de4610 100644 --- a/trunk/arch/h8300/platform/h8s/ints.c +++ b/trunk/arch/h8300/platform/h8s/ints.c @@ -176,7 +176,7 @@ int request_irq(unsigned int irq, } if (use_kmalloc) - irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC); + irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC); else { /* use bootmem allocater */ irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t)); diff --git a/trunk/arch/i386/kernel/apm.c b/trunk/arch/i386/kernel/apm.c index b75cff25de4b..a97847da9ed5 100644 --- a/trunk/arch/i386/kernel/apm.c +++ b/trunk/arch/i386/kernel/apm.c @@ -1604,7 +1604,7 @@ static int do_open(struct inode * inode, struct file * filp) { struct apm_user * as; - as = kmalloc(sizeof(*as), GFP_KERNEL); + as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); if (as == NULL) { printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", sizeof(*as)); diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/Kconfig b/trunk/arch/i386/kernel/cpu/cpufreq/Kconfig index 5299c5bf4454..ccc1edff5c97 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/Kconfig +++ b/trunk/arch/i386/kernel/cpu/cpufreq/Kconfig @@ -17,7 +17,6 @@ config X86_ACPI_CPUFREQ help This driver adds a CPUFreq driver which utilizes the ACPI Processor Performance States. - This driver also supports Intel Enhanced Speedstep. For details, take a look at . @@ -122,14 +121,11 @@ config X86_SPEEDSTEP_CENTRINO If in doubt, say N. config X86_SPEEDSTEP_CENTRINO_ACPI - bool "Use ACPI tables to decode valid frequency/voltage (deprecated)" + bool "Use ACPI tables to decode valid frequency/voltage pairs" depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m) default y help - This is deprecated and this functionality is now merged into - acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of - speedstep_centrino. Use primarily the information provided in the BIOS ACPI tables to determine valid CPU frequency and voltage pairings. It is required for the driver to work on non-Banias CPUs. diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/Makefile b/trunk/arch/i386/kernel/cpu/cpufreq/Makefile index 8de3abe322a9..2e894f1c8910 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/Makefile +++ b/trunk/arch/i386/kernel/cpu/cpufreq/Makefile @@ -7,9 +7,9 @@ obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o obj-$(CONFIG_X86_LONGRUN) += longrun.o obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o +obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o -obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/trunk/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 18f4715c655d..57c880bf0bd6 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -1,10 +1,9 @@ /* - * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.4 $) + * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.3 $) * * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh * Copyright (C) 2002 - 2004 Dominik Brodowski - * Copyright (C) 2006 Denis Sadykov * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -28,387 +27,202 @@ #include #include #include -#include -#include #include +#include +#include #include +#include /* current */ #include - -#include -#include - #include -#include -#include -#include #include #include +#include +#include + #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg) MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski"); MODULE_DESCRIPTION("ACPI Processor P-States Driver"); MODULE_LICENSE("GPL"); -enum { - UNDEFINED_CAPABLE = 0, - SYSTEM_INTEL_MSR_CAPABLE, - SYSTEM_IO_CAPABLE, -}; - -#define INTEL_MSR_RANGE (0xffff) -#define CPUID_6_ECX_APERFMPERF_CAPABILITY (0x1) -struct acpi_cpufreq_data { - struct acpi_processor_performance *acpi_data; - struct cpufreq_frequency_table *freq_table; - unsigned int max_freq; - unsigned int resume; - unsigned int cpu_feature; +struct cpufreq_acpi_io { + struct acpi_processor_performance *acpi_data; + struct cpufreq_frequency_table *freq_table; + unsigned int resume; }; -static struct acpi_cpufreq_data *drv_data[NR_CPUS]; -static struct acpi_processor_performance *acpi_perf_data[NR_CPUS]; +static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS]; +static struct acpi_processor_performance *acpi_perf_data[NR_CPUS]; static struct cpufreq_driver acpi_cpufreq_driver; static unsigned int acpi_pstate_strict; -static int check_est_cpu(unsigned int cpuid) -{ - struct cpuinfo_x86 *cpu = &cpu_data[cpuid]; - - if (cpu->x86_vendor != X86_VENDOR_INTEL || - !cpu_has(cpu, X86_FEATURE_EST)) - return 0; - - return 1; -} - -static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data) -{ - struct acpi_processor_performance *perf; - int i; - - perf = data->acpi_data; - - for (i=0; istate_count; i++) { - if (value == perf->states[i].status) - return data->freq_table[i].frequency; - } - return 0; -} - -static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data) +static int +acpi_processor_write_port( + u16 port, + u8 bit_width, + u32 value) { - int i; - struct acpi_processor_performance *perf; - - msr &= INTEL_MSR_RANGE; - perf = data->acpi_data; - - for (i=0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { - if (msr == perf->states[data->freq_table[i].index].status) - return data->freq_table[i].frequency; - } - return data->freq_table[0].frequency; -} - -static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data) -{ - switch (data->cpu_feature) { - case SYSTEM_INTEL_MSR_CAPABLE: - return extract_msr(val, data); - case SYSTEM_IO_CAPABLE: - return extract_io(val, data); - default: - return 0; - } -} - -static void wrport(u16 port, u8 bit_width, u32 value) -{ - if (bit_width <= 8) + if (bit_width <= 8) { outb(value, port); - else if (bit_width <= 16) + } else if (bit_width <= 16) { outw(value, port); - else if (bit_width <= 32) + } else if (bit_width <= 32) { outl(value, port); + } else { + return -ENODEV; + } + return 0; } -static void rdport(u16 port, u8 bit_width, u32 * ret) +static int +acpi_processor_read_port( + u16 port, + u8 bit_width, + u32 *ret) { *ret = 0; - if (bit_width <= 8) + if (bit_width <= 8) { *ret = inb(port); - else if (bit_width <= 16) + } else if (bit_width <= 16) { *ret = inw(port); - else if (bit_width <= 32) + } else if (bit_width <= 32) { *ret = inl(port); -} - -struct msr_addr { - u32 reg; -}; - -struct io_addr { - u16 port; - u8 bit_width; -}; - -typedef union { - struct msr_addr msr; - struct io_addr io; -} drv_addr_union; - -struct drv_cmd { - unsigned int type; - cpumask_t mask; - drv_addr_union addr; - u32 val; -}; - -static void do_drv_read(struct drv_cmd *cmd) -{ - u32 h; - - switch (cmd->type) { - case SYSTEM_INTEL_MSR_CAPABLE: - rdmsr(cmd->addr.msr.reg, cmd->val, h); - break; - case SYSTEM_IO_CAPABLE: - rdport(cmd->addr.io.port, cmd->addr.io.bit_width, &cmd->val); - break; - default: - break; - } -} - -static void do_drv_write(struct drv_cmd *cmd) -{ - u32 h = 0; - - switch (cmd->type) { - case SYSTEM_INTEL_MSR_CAPABLE: - wrmsr(cmd->addr.msr.reg, cmd->val, h); - break; - case SYSTEM_IO_CAPABLE: - wrport(cmd->addr.io.port, cmd->addr.io.bit_width, cmd->val); - break; - default: - break; - } -} - -static void drv_read(struct drv_cmd *cmd) -{ - cpumask_t saved_mask = current->cpus_allowed; - cmd->val = 0; - - set_cpus_allowed(current, cmd->mask); - do_drv_read(cmd); - set_cpus_allowed(current, saved_mask); -} - -static void drv_write(struct drv_cmd *cmd) -{ - cpumask_t saved_mask = current->cpus_allowed; - unsigned int i; - - for_each_cpu_mask(i, cmd->mask) { - set_cpus_allowed(current, cpumask_of_cpu(i)); - do_drv_write(cmd); - } - - set_cpus_allowed(current, saved_mask); - return; -} - -static u32 get_cur_val(cpumask_t mask) -{ - struct acpi_processor_performance *perf; - struct drv_cmd cmd; - - if (unlikely(cpus_empty(mask))) - return 0; - - switch (drv_data[first_cpu(mask)]->cpu_feature) { - case SYSTEM_INTEL_MSR_CAPABLE: - cmd.type = SYSTEM_INTEL_MSR_CAPABLE; - cmd.addr.msr.reg = MSR_IA32_PERF_STATUS; - break; - case SYSTEM_IO_CAPABLE: - cmd.type = SYSTEM_IO_CAPABLE; - perf = drv_data[first_cpu(mask)]->acpi_data; - cmd.addr.io.port = perf->control_register.address; - cmd.addr.io.bit_width = perf->control_register.bit_width; - break; - default: - return 0; + } else { + return -ENODEV; } - - cmd.mask = mask; - - drv_read(&cmd); - - dprintk("get_cur_val = %u\n", cmd.val); - - return cmd.val; + return 0; } -/* - * Return the measured active (C0) frequency on this CPU since last call - * to this function. - * Input: cpu number - * Return: Average CPU frequency in terms of max frequency (zero on error) - * - * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance - * over a period of time, while CPU is in C0 state. - * IA32_MPERF counts at the rate of max advertised frequency - * IA32_APERF counts at the rate of actual CPU frequency - * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and - * no meaning should be associated with absolute values of these MSRs. - */ -static unsigned int get_measured_perf(unsigned int cpu) +static int +acpi_processor_set_performance ( + struct cpufreq_acpi_io *data, + unsigned int cpu, + int state) { - union { - struct { - u32 lo; - u32 hi; - } split; - u64 whole; - } aperf_cur, mperf_cur; - - cpumask_t saved_mask; - unsigned int perf_percent; - unsigned int retval; - - saved_mask = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - if (get_cpu() != cpu) { - /* We were not able to run on requested processor */ - put_cpu(); - return 0; + u16 port = 0; + u8 bit_width = 0; + int i = 0; + int ret = 0; + u32 value = 0; + int retval; + struct acpi_processor_performance *perf; + + dprintk("acpi_processor_set_performance\n"); + + retval = 0; + perf = data->acpi_data; + if (state == perf->state) { + if (unlikely(data->resume)) { + dprintk("Called after resume, resetting to P%d\n", state); + data->resume = 0; + } else { + dprintk("Already at target state (P%d)\n", state); + return (retval); + } } - rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi); - rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi); - - wrmsr(MSR_IA32_APERF, 0,0); - wrmsr(MSR_IA32_MPERF, 0,0); + dprintk("Transitioning from P%d to P%d\n", perf->state, state); -#ifdef __i386__ /* - * We dont want to do 64 bit divide with 32 bit kernel - * Get an approximate value. Return failure in case we cannot get - * an approximate value. + * First we write the target state's 'control' value to the + * control_register. */ - if (unlikely(aperf_cur.split.hi || mperf_cur.split.hi)) { - int shift_count; - u32 h; - h = max_t(u32, aperf_cur.split.hi, mperf_cur.split.hi); - shift_count = fls(h); + port = perf->control_register.address; + bit_width = perf->control_register.bit_width; + value = (u32) perf->states[state].control; - aperf_cur.whole >>= shift_count; - mperf_cur.whole >>= shift_count; - } + dprintk("Writing 0x%08x to port 0x%04x\n", value, port); - if (((unsigned long)(-1) / 100) < aperf_cur.split.lo) { - int shift_count = 7; - aperf_cur.split.lo >>= shift_count; - mperf_cur.split.lo >>= shift_count; + ret = acpi_processor_write_port(port, bit_width, value); + if (ret) { + dprintk("Invalid port width 0x%04x\n", bit_width); + return (ret); } - if (aperf_cur.split.lo && mperf_cur.split.lo) - perf_percent = (aperf_cur.split.lo * 100) / mperf_cur.split.lo; - else - perf_percent = 0; - -#else - if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) { - int shift_count = 7; - aperf_cur.whole >>= shift_count; - mperf_cur.whole >>= shift_count; + /* + * Assume the write went through when acpi_pstate_strict is not used. + * As read status_register is an expensive operation and there + * are no specific error cases where an IO port write will fail. + */ + if (acpi_pstate_strict) { + /* Then we read the 'status_register' and compare the value + * with the target state's 'status' to make sure the + * transition was successful. + * Note that we'll poll for up to 1ms (100 cycles of 10us) + * before giving up. + */ + + port = perf->status_register.address; + bit_width = perf->status_register.bit_width; + + dprintk("Looking for 0x%08x from port 0x%04x\n", + (u32) perf->states[state].status, port); + + for (i = 0; i < 100; i++) { + ret = acpi_processor_read_port(port, bit_width, &value); + if (ret) { + dprintk("Invalid port width 0x%04x\n", bit_width); + return (ret); + } + if (value == (u32) perf->states[state].status) + break; + udelay(10); + } + } else { + value = (u32) perf->states[state].status; } - if (aperf_cur.whole && mperf_cur.whole) - perf_percent = (aperf_cur.whole * 100) / mperf_cur.whole; - else - perf_percent = 0; - -#endif - - retval = drv_data[cpu]->max_freq * perf_percent / 100; - - put_cpu(); - set_cpus_allowed(current, saved_mask); - - dprintk("cpu %d: performance percent %d\n", cpu, perf_percent); - return retval; -} - -static unsigned int get_cur_freq_on_cpu(unsigned int cpu) -{ - struct acpi_cpufreq_data *data = drv_data[cpu]; - unsigned int freq; - - dprintk("get_cur_freq_on_cpu (%d)\n", cpu); - - if (unlikely(data == NULL || - data->acpi_data == NULL || data->freq_table == NULL)) { - return 0; + if (unlikely(value != (u32) perf->states[state].status)) { + printk(KERN_WARNING "acpi-cpufreq: Transition failed\n"); + retval = -ENODEV; + return (retval); } - freq = extract_freq(get_cur_val(cpumask_of_cpu(cpu)), data); - dprintk("cur freq = %u\n", freq); + dprintk("Transition successful after %d microseconds\n", i * 10); - return freq; + perf->state = state; + return (retval); } -static unsigned int check_freqs(cpumask_t mask, unsigned int freq, - struct acpi_cpufreq_data *data) -{ - unsigned int cur_freq; - unsigned int i; - - for (i=0; i<100; i++) { - cur_freq = extract_freq(get_cur_val(mask), data); - if (cur_freq == freq) - return 1; - udelay(10); - } - return 0; -} -static int acpi_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, unsigned int relation) +static int +acpi_cpufreq_target ( + struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) { - struct acpi_cpufreq_data *data = drv_data[policy->cpu]; + struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; struct acpi_processor_performance *perf; struct cpufreq_freqs freqs; cpumask_t online_policy_cpus; - struct drv_cmd cmd; - unsigned int msr; + cpumask_t saved_mask; + cpumask_t set_mask; + cpumask_t covered_cpus; + unsigned int cur_state = 0; unsigned int next_state = 0; - unsigned int next_perf_state = 0; - unsigned int i; - int result = 0; - - dprintk("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu); + unsigned int result = 0; + unsigned int j; + unsigned int tmp; - if (unlikely(data == NULL || - data->acpi_data == NULL || data->freq_table == NULL)) { - return -ENODEV; - } + dprintk("acpi_cpufreq_setpolicy\n"); - perf = data->acpi_data; result = cpufreq_frequency_table_target(policy, - data->freq_table, - target_freq, - relation, &next_state); + data->freq_table, + target_freq, + relation, + &next_state); if (unlikely(result)) - return -ENODEV; + return (result); + + perf = data->acpi_data; + cur_state = perf->state; + freqs.old = data->freq_table[cur_state].frequency; + freqs.new = data->freq_table[next_state].frequency; #ifdef CONFIG_HOTPLUG_CPU /* cpufreq holds the hotplug lock, so we are safe from here on */ @@ -417,84 +231,106 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, online_policy_cpus = policy->cpus; #endif - next_perf_state = data->freq_table[next_state].index; - if (perf->state == next_perf_state) { - if (unlikely(data->resume)) { - dprintk("Called after resume, resetting to P%d\n", - next_perf_state); - data->resume = 0; - } else { - dprintk("Already at target state (P%d)\n", - next_perf_state); - return 0; - } - } - - switch (data->cpu_feature) { - case SYSTEM_INTEL_MSR_CAPABLE: - cmd.type = SYSTEM_INTEL_MSR_CAPABLE; - cmd.addr.msr.reg = MSR_IA32_PERF_CTL; - msr = - (u32) perf->states[next_perf_state]. - control & INTEL_MSR_RANGE; - cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr; - break; - case SYSTEM_IO_CAPABLE: - cmd.type = SYSTEM_IO_CAPABLE; - cmd.addr.io.port = perf->control_register.address; - cmd.addr.io.bit_width = perf->control_register.bit_width; - cmd.val = (u32) perf->states[next_perf_state].control; - break; - default: - return -ENODEV; + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } - cpus_clear(cmd.mask); + /* + * We need to call driver->target() on all or any CPU in + * policy->cpus, depending on policy->shared_type. + */ + saved_mask = current->cpus_allowed; + cpus_clear(covered_cpus); + for_each_cpu_mask(j, online_policy_cpus) { + /* + * Support for SMP systems. + * Make sure we are running on CPU that wants to change freq + */ + cpus_clear(set_mask); + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + cpus_or(set_mask, set_mask, online_policy_cpus); + else + cpu_set(j, set_mask); + + set_cpus_allowed(current, set_mask); + if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) { + dprintk("couldn't limit to CPUs in this domain\n"); + result = -EAGAIN; + break; + } - if (policy->shared_type != CPUFREQ_SHARED_TYPE_ANY) - cmd.mask = online_policy_cpus; - else - cpu_set(policy->cpu, cmd.mask); + result = acpi_processor_set_performance (data, j, next_state); + if (result) { + result = -EAGAIN; + break; + } - freqs.old = data->freq_table[perf->state].frequency; - freqs.new = data->freq_table[next_perf_state].frequency; - for_each_cpu_mask(i, cmd.mask) { - freqs.cpu = i; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + break; + + cpu_set(j, covered_cpus); } - drv_write(&cmd); + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } - if (acpi_pstate_strict) { - if (!check_freqs(cmd.mask, freqs.new, data)) { - dprintk("acpi_cpufreq_target failed (%d)\n", - policy->cpu); - return -EAGAIN; + if (unlikely(result)) { + /* + * We have failed halfway through the frequency change. + * We have sent callbacks to online_policy_cpus and + * acpi_processor_set_performance() has been called on + * coverd_cpus. Best effort undo.. + */ + + if (!cpus_empty(covered_cpus)) { + for_each_cpu_mask(j, covered_cpus) { + policy->cpu = j; + acpi_processor_set_performance (data, + j, + cur_state); + } } - } - for_each_cpu_mask(i, cmd.mask) { - freqs.cpu = i; - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + tmp = freqs.new; + freqs.new = freqs.old; + freqs.old = tmp; + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } } - perf->state = next_perf_state; - return result; + set_cpus_allowed(current, saved_mask); + return (result); } -static int acpi_cpufreq_verify(struct cpufreq_policy *policy) + +static int +acpi_cpufreq_verify ( + struct cpufreq_policy *policy) { - struct acpi_cpufreq_data *data = drv_data[policy->cpu]; + unsigned int result = 0; + struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; dprintk("acpi_cpufreq_verify\n"); - return cpufreq_frequency_table_verify(policy, data->freq_table); + result = cpufreq_frequency_table_verify(policy, + data->freq_table); + + return (result); } + static unsigned long -acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu) +acpi_cpufreq_guess_freq ( + struct cpufreq_acpi_io *data, + unsigned int cpu) { - struct acpi_processor_performance *perf = data->acpi_data; + struct acpi_processor_performance *perf = data->acpi_data; if (cpu_khz) { /* search the closest match to cpu_khz */ @@ -502,16 +338,16 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu) unsigned long freq; unsigned long freqn = perf->states[0].core_frequency * 1000; - for (i=0; i<(perf->state_count-1); i++) { + for (i = 0; i < (perf->state_count - 1); i++) { freq = freqn; freqn = perf->states[i+1].core_frequency * 1000; if ((2 * cpu_khz) > (freqn + freq)) { perf->state = i; - return freq; + return (freq); } } - perf->state = perf->state_count-1; - return freqn; + perf->state = perf->state_count - 1; + return (freqn); } else { /* assume CPU is at P0... */ perf->state = 0; @@ -519,6 +355,7 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu) } } + /* * acpi_cpufreq_early_init - initialize ACPI P-States library * @@ -527,34 +364,30 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu) * do _PDC and _PSD and find out the processor dependency for the * actual init that will happen later... */ -static int acpi_cpufreq_early_init(void) +static int acpi_cpufreq_early_init_acpi(void) { - struct acpi_processor_performance *data; - cpumask_t covered; - unsigned int i, j; + struct acpi_processor_performance *data; + unsigned int i, j; dprintk("acpi_cpufreq_early_init\n"); for_each_possible_cpu(i) { - data = kzalloc(sizeof(struct acpi_processor_performance), - GFP_KERNEL); + data = kzalloc(sizeof(struct acpi_processor_performance), + GFP_KERNEL); if (!data) { - for_each_cpu_mask(j, covered) { + for_each_possible_cpu(j) { kfree(acpi_perf_data[j]); acpi_perf_data[j] = NULL; } - return -ENOMEM; + return (-ENOMEM); } acpi_perf_data[i] = data; - cpu_set(i, covered); } /* Do initialization in ACPI core */ - acpi_processor_preregister_performance(acpi_perf_data); - return 0; + return acpi_processor_preregister_performance(acpi_perf_data); } -#ifdef CONFIG_SMP /* * Some BIOSes do SW_ANY coordination internally, either set it up in hw * or do it in BIOS firmware and won't inform about it to OS. If not @@ -581,42 +414,39 @@ static struct dmi_system_id sw_any_bug_dmi_table[] = { }, { } }; -#endif -static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) +static int +acpi_cpufreq_cpu_init ( + struct cpufreq_policy *policy) { - unsigned int i; - unsigned int valid_states = 0; - unsigned int cpu = policy->cpu; - struct acpi_cpufreq_data *data; - unsigned int result = 0; + unsigned int i; + unsigned int cpu = policy->cpu; + struct cpufreq_acpi_io *data; + unsigned int result = 0; struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; - struct acpi_processor_performance *perf; + struct acpi_processor_performance *perf; dprintk("acpi_cpufreq_cpu_init\n"); if (!acpi_perf_data[cpu]) - return -ENODEV; + return (-ENODEV); - data = kzalloc(sizeof(struct acpi_cpufreq_data), GFP_KERNEL); + data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); if (!data) - return -ENOMEM; + return (-ENOMEM); data->acpi_data = acpi_perf_data[cpu]; - drv_data[cpu] = data; - - if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) - acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; + acpi_io_data[cpu] = data; result = acpi_processor_register_performance(data->acpi_data, cpu); + if (result) goto err_free; perf = data->acpi_data; policy->shared_type = perf->shared_type; - /* - * Will let policy->cpus know about dependency only when software + * Will let policy->cpus know about dependency only when software * coordination is required. */ if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || @@ -632,6 +462,10 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) } #endif + if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { + acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; + } + /* capability check */ if (perf->state_count <= 1) { dprintk("No P-States\n"); @@ -639,33 +473,17 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) goto err_unreg; } - if (perf->control_register.space_id != perf->status_register.space_id) { - result = -ENODEV; - goto err_unreg; - } - - switch (perf->control_register.space_id) { - case ACPI_ADR_SPACE_SYSTEM_IO: - dprintk("SYSTEM IO addr space\n"); - data->cpu_feature = SYSTEM_IO_CAPABLE; - break; - case ACPI_ADR_SPACE_FIXED_HARDWARE: - dprintk("HARDWARE addr space\n"); - if (!check_est_cpu(cpu)) { - result = -ENODEV; - goto err_unreg; - } - data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE; - break; - default: - dprintk("Unknown addr space %d\n", - (u32) (perf->control_register.space_id)); + if ((perf->control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) || + (perf->status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { + dprintk("Unsupported address space [%d, %d]\n", + (u32) (perf->control_register.space_id), + (u32) (perf->status_register.space_id)); result = -ENODEV; goto err_unreg; } - data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * - (perf->state_count+1), GFP_KERNEL); + /* alloc freq_table */ + data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (perf->state_count + 1), GFP_KERNEL); if (!data->freq_table) { result = -ENOMEM; goto err_unreg; @@ -674,140 +492,129 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) /* detect transition latency */ policy->cpuinfo.transition_latency = 0; for (i=0; istate_count; i++) { - if ((perf->states[i].transition_latency * 1000) > - policy->cpuinfo.transition_latency) - policy->cpuinfo.transition_latency = - perf->states[i].transition_latency * 1000; + if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) + policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000; } policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - data->max_freq = perf->states[0].core_frequency * 1000; + /* The current speed is unknown and not detectable by ACPI... */ + policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); + /* table init */ - for (i=0; istate_count; i++) { - if (i>0 && perf->states[i].core_frequency == - perf->states[i-1].core_frequency) - continue; - - data->freq_table[valid_states].index = i; - data->freq_table[valid_states].frequency = - perf->states[i].core_frequency * 1000; - valid_states++; + for (i=0; i<=perf->state_count; i++) + { + data->freq_table[i].index = i; + if (istate_count) + data->freq_table[i].frequency = perf->states[i].core_frequency * 1000; + else + data->freq_table[i].frequency = CPUFREQ_TABLE_END; } - data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END; result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table); - if (result) + if (result) { goto err_freqfree; - - switch (data->cpu_feature) { - case ACPI_ADR_SPACE_SYSTEM_IO: - /* Current speed is unknown and not detectable by IO port */ - policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); - break; - case ACPI_ADR_SPACE_FIXED_HARDWARE: - acpi_cpufreq_driver.get = get_cur_freq_on_cpu; - get_cur_freq_on_cpu(cpu); - break; - default: - break; } /* notify BIOS that we exist */ acpi_processor_notify_smm(THIS_MODULE); - /* Check for APERF/MPERF support in hardware */ - if (c->x86_vendor == X86_VENDOR_INTEL && c->cpuid_level >= 6) { - unsigned int ecx; - ecx = cpuid_ecx(6); - if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY) - acpi_cpufreq_driver.getavg = get_measured_perf; - } - - dprintk("CPU%u - ACPI performance management activated.\n", cpu); + printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n", + cpu); for (i = 0; i < perf->state_count; i++) dprintk(" %cP%d: %d MHz, %d mW, %d uS\n", - (i == perf->state ? '*' : ' '), i, + (i == perf->state?'*':' '), i, (u32) perf->states[i].core_frequency, (u32) perf->states[i].power, (u32) perf->states[i].transition_latency); cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); - + /* * the first call to ->target() should result in us actually * writing something to the appropriate registers. */ data->resume = 1; + + return (result); - return result; - -err_freqfree: + err_freqfree: kfree(data->freq_table); -err_unreg: + err_unreg: acpi_processor_unregister_performance(perf, cpu); -err_free: + err_free: kfree(data); - drv_data[cpu] = NULL; + acpi_io_data[cpu] = NULL; - return result; + return (result); } -static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) + +static int +acpi_cpufreq_cpu_exit ( + struct cpufreq_policy *policy) { - struct acpi_cpufreq_data *data = drv_data[policy->cpu]; + struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; + dprintk("acpi_cpufreq_cpu_exit\n"); if (data) { cpufreq_frequency_table_put_attr(policy->cpu); - drv_data[policy->cpu] = NULL; - acpi_processor_unregister_performance(data->acpi_data, - policy->cpu); + acpi_io_data[policy->cpu] = NULL; + acpi_processor_unregister_performance(data->acpi_data, policy->cpu); kfree(data); } - return 0; + return (0); } -static int acpi_cpufreq_resume(struct cpufreq_policy *policy) +static int +acpi_cpufreq_resume ( + struct cpufreq_policy *policy) { - struct acpi_cpufreq_data *data = drv_data[policy->cpu]; + struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; + dprintk("acpi_cpufreq_resume\n"); data->resume = 1; - return 0; + return (0); } -static struct freq_attr *acpi_cpufreq_attr[] = { + +static struct freq_attr* acpi_cpufreq_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, }; static struct cpufreq_driver acpi_cpufreq_driver = { - .verify = acpi_cpufreq_verify, - .target = acpi_cpufreq_target, - .init = acpi_cpufreq_cpu_init, - .exit = acpi_cpufreq_cpu_exit, - .resume = acpi_cpufreq_resume, - .name = "acpi-cpufreq", - .owner = THIS_MODULE, - .attr = acpi_cpufreq_attr, + .verify = acpi_cpufreq_verify, + .target = acpi_cpufreq_target, + .init = acpi_cpufreq_cpu_init, + .exit = acpi_cpufreq_cpu_exit, + .resume = acpi_cpufreq_resume, + .name = "acpi-cpufreq", + .owner = THIS_MODULE, + .attr = acpi_cpufreq_attr, }; -static int __init acpi_cpufreq_init(void) + +static int __init +acpi_cpufreq_init (void) { dprintk("acpi_cpufreq_init\n"); - acpi_cpufreq_early_init(); + acpi_cpufreq_early_init_acpi(); return cpufreq_register_driver(&acpi_cpufreq_driver); } -static void __exit acpi_cpufreq_exit(void) + +static void __exit +acpi_cpufreq_exit (void) { - unsigned int i; + unsigned int i; dprintk("acpi_cpufreq_exit\n"); cpufreq_unregister_driver(&acpi_cpufreq_driver); @@ -820,9 +627,7 @@ static void __exit acpi_cpufreq_exit(void) } module_param(acpi_pstate_strict, uint, 0644); -MODULE_PARM_DESC(acpi_pstate_strict, - "value 0 or non-zero. non-zero -> strict ACPI checks are " - "performed during frequency changes."); +MODULE_PARM_DESC(acpi_pstate_strict, "value 0 or non-zero. non-zero -> strict ACPI checks are performed during frequency changes."); late_initcall(acpi_cpufreq_init); module_exit(acpi_cpufreq_exit); diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/trunk/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c index 6667e9cceb9f..92afa3bc84f1 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c @@ -447,6 +447,7 @@ static int __init cpufreq_gx_init(void) int ret; struct gxfreq_params *params; struct pci_dev *gx_pci; + u32 class_rev; /* Test if we have the right hardware */ if ((gx_pci = gx_detect_chipset()) == NULL) @@ -471,7 +472,8 @@ static int __init cpufreq_gx_init(void) pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2)); pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration)); pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration)); - pci_read_config_byte(params->cs55x0, PCI_REVISION_ID, ¶ms->pci_rev); + pci_read_config_dword(params->cs55x0, PCI_CLASS_REVISION, &class_rev); + params->pci_rev = class_rev && 0xff; if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) { kfree(params); diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c b/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c index c548daad3476..7233abe5d695 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -410,7 +410,7 @@ static int __init longhaul_get_ranges(void) maxmult=longhaul_get_cpu_mult(); /* Starting with the 1.2GHz parts, theres a 200MHz bus. */ - if ((cpu_khz/maxmult) > 13400) + if ((cpu_khz/1000) > 1200) fsb = 200; else fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; @@ -583,10 +583,6 @@ static int enable_arbiter_disable(void) if (dev == NULL) { reg = 0x76; dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_862X_0, NULL); - /* Find CN400 V-Link host bridge */ - if (dev == NULL) - dev = pci_find_device(PCI_VENDOR_ID_VIA, 0x7259, NULL); - } if (dev != NULL) { /* Enable access to port 0x22 */ @@ -738,7 +734,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) return 0; err_acpi: - printk(KERN_ERR PFX "No ACPI support. Unsupported northbridge. Aborting.\n"); + printk(KERN_ERR PFX "No ACPI support. No VT8601 or VT8623 northbridge. Aborting.\n"); return -ENODEV; } diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/trunk/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index bec50170b75a..304d2eaa4a1b 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -163,27 +163,29 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy) static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) { - if (c->x86 == 0x06) { - if (cpu_has(c, X86_FEATURE_EST)) - printk(KERN_WARNING PFX "Warning: EST-capable CPU detected. " - "The acpi-cpufreq module offers voltage scaling" - " in addition of frequency scaling. You should use " - "that instead of p4-clockmod, if possible.\n"); - switch (c->x86_model) { - case 0x0E: /* Core */ - case 0x0F: /* Core Duo */ - p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; - return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE); - case 0x0D: /* Pentium M (Dothan) */ - p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; - /* fall through */ - case 0x09: /* Pentium M (Banias) */ - return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); - } + if ((c->x86 == 0x06) && (c->x86_model == 0x09)) { + /* Pentium M (Banias) */ + printk(KERN_WARNING PFX "Warning: Pentium M detected. " + "The speedstep_centrino module offers voltage scaling" + " in addition of frequency scaling. You should use " + "that instead of p4-clockmod, if possible.\n"); + return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); + } + + if ((c->x86 == 0x06) && (c->x86_model == 0x0D)) { + /* Pentium M (Dothan) */ + printk(KERN_WARNING PFX "Warning: Pentium M detected. " + "The speedstep_centrino module offers voltage scaling" + " in addition of frequency scaling. You should use " + "that instead of p4-clockmod, if possible.\n"); + /* on P-4s, the TSC runs with constant frequency independent whether + * throttling is active or not. */ + p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); } if (c->x86 != 0xF) { - printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); + printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); return 0; } diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/trunk/arch/i386/kernel/cpu/cpufreq/sc520_freq.c index b8fb4b521c62..ef457d50f4ac 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/sc520_freq.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/sc520_freq.c @@ -153,7 +153,6 @@ static struct cpufreq_driver sc520_freq_driver = { static int __init sc520_freq_init(void) { struct cpuinfo_x86 *c = cpu_data; - int err; /* Test if we have the right hardware */ if(c->x86_vendor != X86_VENDOR_AMD || @@ -167,11 +166,7 @@ static int __init sc520_freq_init(void) return -ENOMEM; } - err = cpufreq_register_driver(&sc520_freq_driver); - if (err) - iounmap(cpuctl); - - return err; + return cpufreq_register_driver(&sc520_freq_driver); } diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 5113e9231634..e8993baf3d14 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -36,7 +36,6 @@ #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) -#define INTEL_MSR_RANGE (0xffff) struct cpu_id { @@ -380,7 +379,6 @@ static int centrino_cpu_early_init_acpi(void) } -#ifdef CONFIG_SMP /* * Some BIOSes do SW_ANY coordination internally, either set it up in hw * or do it in BIOS firmware and won't inform about it to OS. If not @@ -394,6 +392,7 @@ static int sw_any_bug_found(struct dmi_system_id *d) return 0; } + static struct dmi_system_id sw_any_bug_dmi_table[] = { { .callback = sw_any_bug_found, @@ -406,7 +405,7 @@ static struct dmi_system_id sw_any_bug_dmi_table[] = { }, { } }; -#endif + /* * centrino_cpu_init_acpi - register with ACPI P-States library @@ -464,9 +463,8 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) } for (i=0; istate_count; i++) { - if ((p->states[i].control & INTEL_MSR_RANGE) != - (p->states[i].status & INTEL_MSR_RANGE)) { - dprintk("Different MSR bits in control (%llu) and status (%llu)\n", + if (p->states[i].control != p->states[i].status) { + dprintk("Different control (%llu) and status values (%llu)\n", p->states[i].control, p->states[i].status); result = -EINVAL; goto err_unreg; @@ -502,7 +500,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) } for (i=0; istate_count; i++) { - centrino_model[cpu]->op_points[i].index = p->states[i].control & INTEL_MSR_RANGE; + centrino_model[cpu]->op_points[i].index = p->states[i].control; centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000; dprintk("adding state %i with frequency %u and control value %04x\n", i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index); @@ -533,9 +531,6 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) /* notify BIOS that we exist */ acpi_processor_notify_smm(THIS_MODULE); - printk("speedstep-centrino with X86_SPEEDSTEP_CENTRINO_ACPI" - "config is deprecated.\n " - "Use X86_ACPI_CPUFREQ (acpi-cpufreq instead.\n" ); return 0; diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index d59277c00911..4f46cac155c4 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c @@ -123,36 +123,6 @@ static unsigned int pentiumM_get_frequency(void) return (msr_tmp * 100 * 1000); } -static unsigned int pentium_core_get_frequency(void) -{ - u32 fsb = 0; - u32 msr_lo, msr_tmp; - - rdmsr(MSR_FSB_FREQ, msr_lo, msr_tmp); - /* see table B-2 of 25366920.pdf */ - switch (msr_lo & 0x07) { - case 5: - fsb = 100000; - break; - case 1: - fsb = 133333; - break; - case 3: - fsb = 166667; - break; - default: - printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value"); - } - - rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); - dprintk("PCORE - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); - - msr_tmp = (msr_lo >> 22) & 0x1f; - dprintk("bits 22-26 are 0x%x, speed is %u\n", msr_tmp, (msr_tmp * fsb)); - - return (msr_tmp * fsb); -} - static unsigned int pentium4_get_frequency(void) { @@ -204,8 +174,6 @@ static unsigned int pentium4_get_frequency(void) unsigned int speedstep_get_processor_frequency(unsigned int processor) { switch (processor) { - case SPEEDSTEP_PROCESSOR_PCORE: - return pentium_core_get_frequency(); case SPEEDSTEP_PROCESSOR_PM: return pentiumM_get_frequency(); case SPEEDSTEP_PROCESSOR_P4D: diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h index b11bcc608cac..b735429c50b4 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h +++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h @@ -22,7 +22,6 @@ * the speedstep_get_processor_frequency() call. */ #define SPEEDSTEP_PROCESSOR_PM 0xFFFFFF03 /* Pentium M */ #define SPEEDSTEP_PROCESSOR_P4D 0xFFFFFF04 /* desktop P4 */ -#define SPEEDSTEP_PROCESSOR_PCORE 0xFFFFFF05 /* Core */ /* speedstep states -- only two of them */ diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index ff0d89806114..c28333d53646 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -360,6 +360,9 @@ static int __init speedstep_init(void) case SPEEDSTEP_PROCESSOR_PIII_C: case SPEEDSTEP_PROCESSOR_PIII_C_EARLY: break; + case SPEEDSTEP_PROCESSOR_P4M: + printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n"); + break; default: speedstep_processor = 0; } diff --git a/trunk/arch/i386/kernel/microcode.c b/trunk/arch/i386/kernel/microcode.c index 47ffec57c0cb..972346604f9d 100644 --- a/trunk/arch/i386/kernel/microcode.c +++ b/trunk/arch/i386/kernel/microcode.c @@ -1,7 +1,7 @@ /* * Intel CPU Microcode Update Driver for Linux * - * Copyright (C) 2000-2006 Tigran Aivazian + * Copyright (C) 2000-2004 Tigran Aivazian * 2006 Shaohua Li * * This driver allows to upgrade microcode on Intel processors @@ -92,7 +92,7 @@ #include MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); -MODULE_AUTHOR("Tigran Aivazian "); +MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); #define MICROCODE_VERSION "1.14a" @@ -752,7 +752,7 @@ static int __init microcode_init (void) register_hotcpu_notifier(&mc_cpu_notifier); printk(KERN_INFO - "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); + "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); return 0; } diff --git a/trunk/arch/i386/kernel/smpboot.c b/trunk/arch/i386/kernel/smpboot.c index aef39be81361..b0f84e5778ad 100644 --- a/trunk/arch/i386/kernel/smpboot.c +++ b/trunk/arch/i386/kernel/smpboot.c @@ -69,7 +69,9 @@ static int __devinitdata smp_b_stepping; /* Number of siblings per CPU package */ int smp_num_siblings = 1; +#ifdef CONFIG_SMP EXPORT_SYMBOL(smp_num_siblings); +#endif /* Last level cache ID of each logical CPU */ int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID}; diff --git a/trunk/arch/ia64/hp/sim/simserial.c b/trunk/arch/ia64/hp/sim/simserial.c index 324ea7565e2c..1f16ebb9a800 100644 --- a/trunk/arch/ia64/hp/sim/simserial.c +++ b/trunk/arch/ia64/hp/sim/simserial.c @@ -488,7 +488,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) -static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) { unsigned int cflag = tty->termios->c_cflag; diff --git a/trunk/arch/ia64/kernel/Makefile b/trunk/arch/ia64/kernel/Makefile index 098ee605bf5e..8ae384eb5357 100644 --- a/trunk/arch/ia64/kernel/Makefile +++ b/trunk/arch/ia64/kernel/Makefile @@ -29,7 +29,6 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o -obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_PCI_MSI) += msi_ia64.o diff --git a/trunk/arch/ia64/kernel/crash.c b/trunk/arch/ia64/kernel/crash.c index bc2f64d72244..0aabedf95dad 100644 --- a/trunk/arch/ia64/kernel/crash.c +++ b/trunk/arch/ia64/kernel/crash.c @@ -19,11 +19,29 @@ #include #include +#include int kdump_status[NR_CPUS]; atomic_t kdump_cpu_freezed; atomic_t kdump_in_progress; int kdump_on_init = 1; +ssize_t +copy_oldmem_page(unsigned long pfn, char *buf, + size_t csize, unsigned long offset, int userbuf) +{ + void *vaddr; + + if (!csize) + return 0; + vaddr = __va(pfn< -#include /* * void jprobe_break(void) */ .section .kprobes.text, "ax" ENTRY(jprobe_break) - break.m __IA64_BREAK_JPROBE + break.m 0x80300 END(jprobe_break) /* diff --git a/trunk/arch/ia64/kernel/kprobes.c b/trunk/arch/ia64/kernel/kprobes.c index 6cb56dd4056d..76e778951e20 100644 --- a/trunk/arch/ia64/kernel/kprobes.c +++ b/trunk/arch/ia64/kernel/kprobes.c @@ -88,7 +88,6 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot, { p->ainsn.inst_flag = 0; p->ainsn.target_br_reg = 0; - p->ainsn.slot = slot; /* Check for Break instruction * Bits 37:40 Major opcode to be zero @@ -128,6 +127,48 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot, return; } +/* + * In this function we check to see if the instruction + * on which we are inserting kprobe is supported. + * Returns 0 if supported + * Returns -EINVAL if unsupported + */ +static int __kprobes unsupported_inst(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst, + unsigned long addr) +{ + if (bundle_encoding[template][slot] == I) { + switch (major_opcode) { + case 0x0: //I_UNIT_MISC_OPCODE: + /* + * Check for Integer speculation instruction + * - Bit 33-35 to be equal to 0x1 + */ + if (((kprobe_inst >> 33) & 0x7) == 1) { + printk(KERN_WARNING + "Kprobes on speculation inst at <0x%lx> not supported\n", + addr); + return -EINVAL; + } + + /* + * IP relative mov instruction + * - Bit 27-35 to be equal to 0x30 + */ + if (((kprobe_inst >> 27) & 0x1FF) == 0x30) { + printk(KERN_WARNING + "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n", + addr); + return -EINVAL; + + } + } + } + return 0; +} + + /* * In this function we check to see if the instruction * (qp) cmpx.crel.ctype p1,p2=r2,r3 @@ -164,119 +205,6 @@ static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot, return ctype_unc; } -/* - * In this function we check to see if the instruction - * on which we are inserting kprobe is supported. - * Returns qp value if supported - * Returns -EINVAL if unsupported - */ -static int __kprobes unsupported_inst(uint template, uint slot, - uint major_opcode, - unsigned long kprobe_inst, - unsigned long addr) -{ - int qp; - - qp = kprobe_inst & 0x3f; - if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) { - if (slot == 1 && qp) { - printk(KERN_WARNING "Kprobes on cmp unc" - "instruction on slot 1 at <0x%lx>" - "is not supported\n", addr); - return -EINVAL; - - } - qp = 0; - } - else if (bundle_encoding[template][slot] == I) { - if (major_opcode == 0) { - /* - * Check for Integer speculation instruction - * - Bit 33-35 to be equal to 0x1 - */ - if (((kprobe_inst >> 33) & 0x7) == 1) { - printk(KERN_WARNING - "Kprobes on speculation inst at <0x%lx> not supported\n", - addr); - return -EINVAL; - } - /* - * IP relative mov instruction - * - Bit 27-35 to be equal to 0x30 - */ - if (((kprobe_inst >> 27) & 0x1FF) == 0x30) { - printk(KERN_WARNING - "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n", - addr); - return -EINVAL; - - } - } - else if ((major_opcode == 5) && !(kprobe_inst & (0xFUl << 33)) && - (kprobe_inst & (0x1UL << 12))) { - /* test bit instructions, tbit,tnat,tf - * bit 33-36 to be equal to 0 - * bit 12 to be equal to 1 - */ - if (slot == 1 && qp) { - printk(KERN_WARNING "Kprobes on test bit" - "instruction on slot at <0x%lx>" - "is not supported\n", addr); - return -EINVAL; - } - qp = 0; - } - } - else if (bundle_encoding[template][slot] == B) { - if (major_opcode == 7) { - /* IP-Relative Predict major code is 7 */ - printk(KERN_WARNING "Kprobes on IP-Relative" - "Predict is not supported\n"); - return -EINVAL; - } - else if (major_opcode == 2) { - /* Indirect Predict, major code is 2 - * bit 27-32 to be equal to 10 or 11 - */ - int x6=(kprobe_inst >> 27) & 0x3F; - if ((x6 == 0x10) || (x6 == 0x11)) { - printk(KERN_WARNING "Kprobes on" - "Indirect Predict is not supported\n"); - return -EINVAL; - } - } - } - /* kernel does not use float instruction, here for safety kprobe - * will judge whether it is fcmp/flass/float approximation instruction - */ - else if (unlikely(bundle_encoding[template][slot] == F)) { - if ((major_opcode == 4 || major_opcode == 5) && - (kprobe_inst & (0x1 << 12))) { - /* fcmp/fclass unc instruction */ - if (slot == 1 && qp) { - printk(KERN_WARNING "Kprobes on fcmp/fclass " - "instruction on slot at <0x%lx> " - "is not supported\n", addr); - return -EINVAL; - - } - qp = 0; - } - if ((major_opcode == 0 || major_opcode == 1) && - (kprobe_inst & (0x1UL << 33))) { - /* float Approximation instruction */ - if (slot == 1 && qp) { - printk(KERN_WARNING "Kprobes on float Approx " - "instr at <0x%lx> is not supported\n", - addr); - return -EINVAL; - } - qp = 0; - } - } - return qp; -} - /* * In this function we override the bundle with * the break instruction at the given slot. @@ -284,17 +212,20 @@ static int __kprobes unsupported_inst(uint template, uint slot, static void __kprobes prepare_break_inst(uint template, uint slot, uint major_opcode, unsigned long kprobe_inst, - struct kprobe *p, - int qp) + struct kprobe *p) { unsigned long break_inst = BREAK_INST; bundle_t *bundle = &p->opcode.bundle; /* * Copy the original kprobe_inst qualifying predicate(qp) - * to the break instruction + * to the break instruction iff !is_cmp_ctype_unc_inst + * because for cmp instruction with ctype equal to unc, + * which is a special instruction always needs to be + * executed regradless of qp */ - break_inst |= qp; + if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) + break_inst |= (0x3f & kprobe_inst); switch (slot) { case 0: @@ -365,6 +296,12 @@ static int __kprobes valid_kprobe_addr(int template, int slot, return -EINVAL; } + if (slot == 1 && bundle_encoding[template][1] != L) { + printk(KERN_WARNING "Inserting kprobes on slot #1 " + "is not supported\n"); + return -EINVAL; + } + return 0; } @@ -490,7 +427,6 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) unsigned long kprobe_inst=0; unsigned int slot = addr & 0xf, template, major_opcode = 0; bundle_t *bundle; - int qp; bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle; template = bundle->quad0.template; @@ -505,9 +441,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) /* Get kprobe_inst and major_opcode from the bundle */ get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode); - qp = unsupported_inst(template, slot, major_opcode, kprobe_inst, addr); - if (qp < 0) - return -EINVAL; + if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr)) + return -EINVAL; + p->ainsn.insn = get_insn_slot(); if (!p->ainsn.insn) @@ -515,56 +451,30 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t)); memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t)); - prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp); + prepare_break_inst(template, slot, major_opcode, kprobe_inst, p); return 0; } void __kprobes arch_arm_kprobe(struct kprobe *p) { - unsigned long arm_addr; - bundle_t *src, *dest; - - arm_addr = ((unsigned long)p->addr) & ~0xFUL; - dest = &((kprobe_opcode_t *)arm_addr)->bundle; - src = &p->opcode.bundle; + unsigned long addr = (unsigned long)p->addr; + unsigned long arm_addr = addr & ~0xFULL; flush_icache_range((unsigned long)p->ainsn.insn, (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t)); - switch (p->ainsn.slot) { - case 0: - dest->quad0.slot0 = src->quad0.slot0; - break; - case 1: - dest->quad1.slot1_p1 = src->quad1.slot1_p1; - break; - case 2: - dest->quad1.slot2 = src->quad1.slot2; - break; - } + memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t)); flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t)); } void __kprobes arch_disarm_kprobe(struct kprobe *p) { - unsigned long arm_addr; - bundle_t *src, *dest; + unsigned long addr = (unsigned long)p->addr; + unsigned long arm_addr = addr & ~0xFULL; - arm_addr = ((unsigned long)p->addr) & ~0xFUL; - dest = &((kprobe_opcode_t *)arm_addr)->bundle; /* p->ainsn.insn contains the original unaltered kprobe_opcode_t */ - src = &p->ainsn.insn->bundle; - switch (p->ainsn.slot) { - case 0: - dest->quad0.slot0 = src->quad0.slot0; - break; - case 1: - dest->quad1.slot1_p1 = src->quad1.slot1_p1; - break; - case 2: - dest->quad1.slot2 = src->quad1.slot2; - break; - } + memcpy((char *) arm_addr, (char *) p->ainsn.insn, + sizeof(kprobe_opcode_t)); flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t)); } @@ -897,9 +807,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, switch(val) { case DIE_BREAK: /* err is break number from ia64_bad_break() */ - if ((args->err >> 12) == (__IA64_BREAK_KPROBE >> 12) - || args->err == __IA64_BREAK_JPROBE - || args->err == 0) + if (args->err == 0x80200 || args->err == 0x80300 || args->err == 0) if (pre_kprobes_handler(args)) ret = NOTIFY_STOP; break; diff --git a/trunk/arch/ia64/kernel/machine_kexec.c b/trunk/arch/ia64/kernel/machine_kexec.c index e2ccc9f660c5..468233fa2cee 100644 --- a/trunk/arch/ia64/kernel/machine_kexec.c +++ b/trunk/arch/ia64/kernel/machine_kexec.c @@ -19,11 +19,8 @@ #include #include -typedef NORET_TYPE void (*relocate_new_kernel_t)( - unsigned long indirection_page, - unsigned long start_address, - struct ia64_boot_param *boot_param, - unsigned long pal_addr) ATTRIB_NORET; +typedef void (*relocate_new_kernel_t)(unsigned long, unsigned long, + struct ia64_boot_param *, unsigned long); struct kimage *ia64_kimage; diff --git a/trunk/arch/ia64/kernel/mca.c b/trunk/arch/ia64/kernel/mca.c index a76add3e76a2..87c1c4f42872 100644 --- a/trunk/arch/ia64/kernel/mca.c +++ b/trunk/arch/ia64/kernel/mca.c @@ -1239,7 +1239,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, } else { /* Dump buffered message to console */ ia64_mlogbuf_finish(1); -#ifdef CONFIG_KEXEC +#ifdef CONFIG_CRASH_DUMP atomic_set(&kdump_in_progress, 1); monarch_cpu = -1; #endif diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index ad567b8d432e..14e1200376a9 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -256,7 +256,7 @@ reserve_memory (void) #ifdef CONFIG_KEXEC /* crashkernel=size@offset specifies the size to reserve for a crash - * kernel. If offset is 0, then it is determined automatically. + * kernel.(offset is ingored for keep compatibility with other archs) * By reserving this memory we guarantee that linux never set's it * up as a DMA target.Useful for holding code to do something * appropriate after a kernel panic. @@ -266,16 +266,10 @@ reserve_memory (void) unsigned long base, size; if (from) { size = memparse(from + 12, &from); - if (*from == '@') - base = memparse(from+1, &from); - else - base = 0; if (size) { - if (!base) { - sort_regions(rsvd_region, n); - base = kdump_find_rsvd_region(size, - rsvd_region, n); - } + sort_regions(rsvd_region, n); + base = kdump_find_rsvd_region(size, + rsvd_region, n); if (base != ~0UL) { rsvd_region[n].start = (unsigned long)__va(base); @@ -440,21 +434,6 @@ static __init int setup_nomca(char *s) } early_param("nomca", setup_nomca); -#ifdef CONFIG_PROC_VMCORE -/* elfcorehdr= specifies the location of elf core header - * stored by the crashed kernel. - */ -static int __init parse_elfcorehdr(char *arg) -{ - if (!arg) - return -EINVAL; - - elfcorehdr_addr = memparse(arg, &arg); - return 0; -} -early_param("elfcorehdr", parse_elfcorehdr); -#endif /* CONFIG_PROC_VMCORE */ - void __init setup_arch (char **cmdline_p) { @@ -674,7 +653,6 @@ get_model_name(__u8 family, __u8 model) { char brand[128]; - memcpy(brand, "Unknown", 8); if (ia64_pal_get_brand_info(brand)) { if (family == 0x7) memcpy(brand, "Merced", 7); @@ -682,7 +660,8 @@ get_model_name(__u8 family, __u8 model) case 0: memcpy(brand, "McKinley", 9); break; case 1: memcpy(brand, "Madison", 8); break; case 2: memcpy(brand, "Madison up to 9M cache", 23); break; - } + } else + memcpy(brand, "Unknown", 8); } if (brandname[0] == '\0') return strcpy(brandname, brand); diff --git a/trunk/arch/ia64/kernel/smp.c b/trunk/arch/ia64/kernel/smp.c index f4c7f7769cf7..b1b9aa4364b9 100644 --- a/trunk/arch/ia64/kernel/smp.c +++ b/trunk/arch/ia64/kernel/smp.c @@ -157,7 +157,7 @@ handle_IPI (int irq, void *dev_id) case IPI_CPU_STOP: stop_this_cpu(); break; -#ifdef CONFIG_KEXEC +#ifdef CONFIG_CRASH_DUMP case IPI_KDUMP_CPU_STOP: unw_init_running(kdump_cpu_freeze, NULL); break; @@ -219,7 +219,7 @@ send_IPI_self (int op) send_IPI_single(smp_processor_id(), op); } -#ifdef CONFIG_KEXEC +#ifdef CONFIG_CRASH_DUMP void kdump_smp_send_stop() { diff --git a/trunk/arch/ia64/kernel/traps.c b/trunk/arch/ia64/kernel/traps.c index ab684747036f..fffa9e0826bc 100644 --- a/trunk/arch/ia64/kernel/traps.c +++ b/trunk/arch/ia64/kernel/traps.c @@ -307,15 +307,6 @@ fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long return ret.status; } -struct fpu_swa_msg { - unsigned long count; - unsigned long time; -}; -static DEFINE_PER_CPU(struct fpu_swa_msg, cpulast); -DECLARE_PER_CPU(struct fpu_swa_msg, cpulast); -static struct fpu_swa_msg last __cacheline_aligned; - - /* * Handle floating-point assist faults and traps. */ @@ -325,6 +316,8 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) long exception, bundle[2]; unsigned long fault_ip; struct siginfo siginfo; + static int fpu_swa_count = 0; + static unsigned long last_time; fault_ip = regs->cr_iip; if (!fp_fault && (ia64_psr(regs)->ri == 0)) @@ -332,37 +325,14 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle))) return -1; - if (!(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) { - unsigned long count, current_jiffies = jiffies; - struct fpu_swa_msg *cp = &__get_cpu_var(cpulast); - - if (unlikely(current_jiffies > cp->time)) - cp->count = 0; - if (unlikely(cp->count < 5)) { - cp->count++; - cp->time = current_jiffies + 5 * HZ; - - /* minimize races by grabbing a copy of count BEFORE checking last.time. */ - count = last.count; - barrier(); - - /* - * Lower 4 bits are used as a count. Upper bits are a sequence - * number that is updated when count is reset. The cmpxchg will - * fail is seqno has changed. This minimizes mutiple cpus - * reseting the count. - */ - if (current_jiffies > last.time) - (void) cmpxchg_acq(&last.count, count, 16 + (count & ~15)); - - /* used fetchadd to atomically update the count */ - if ((last.count & 15) < 5 && (ia64_fetchadd(1, &last.count, acq) & 15) < 5) { - last.time = current_jiffies + 5 * HZ; - printk(KERN_WARNING - "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n", - current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr); - } - } + if (jiffies - last_time > 5*HZ) + fpu_swa_count = 0; + if ((fpu_swa_count < 4) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) { + last_time = jiffies; + ++fpu_swa_count; + printk(KERN_WARNING + "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n", + current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr); } exception = fp_emulate(fp_fault, bundle, ®s->cr_ipsr, ®s->ar_fpsr, &isr, ®s->pr, diff --git a/trunk/arch/ia64/mm/contig.c b/trunk/arch/ia64/mm/contig.c index 1e79551231b9..82deaa3a7c48 100644 --- a/trunk/arch/ia64/mm/contig.c +++ b/trunk/arch/ia64/mm/contig.c @@ -174,12 +174,6 @@ find_memory (void) reserve_bootmem(bootmap_start, bootmap_size); find_initrd(); - -#ifdef CONFIG_CRASH_DUMP - /* If we are doing a crash dump, we still need to know the real mem - * size before original memory map is * reset. */ - saved_max_pfn = max_pfn; -#endif } #ifdef CONFIG_SMP @@ -232,6 +226,7 @@ void __init paging_init (void) { unsigned long max_dma; + unsigned long nid = 0; unsigned long max_zone_pfns[MAX_NR_ZONES]; num_physpages = 0; @@ -243,7 +238,7 @@ paging_init (void) max_zone_pfns[ZONE_NORMAL] = max_low_pfn; #ifdef CONFIG_VIRTUAL_MEM_MAP - efi_memmap_walk(register_active_ranges, NULL); + efi_memmap_walk(register_active_ranges, &nid); efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); if (max_gap < LARGE_GAP) { vmem_map = (struct page *) 0; diff --git a/trunk/arch/ia64/mm/init.c b/trunk/arch/ia64/mm/init.c index 1a3d8a2feb94..56dc2024220e 100644 --- a/trunk/arch/ia64/mm/init.c +++ b/trunk/arch/ia64/mm/init.c @@ -595,9 +595,14 @@ find_largest_hole (u64 start, u64 end, void *arg) } int __init -register_active_ranges(u64 start, u64 end, void *arg) +register_active_ranges(u64 start, u64 end, void *nid) { - add_active_range(0, __pa(start) >> PAGE_SHIFT, __pa(end) >> PAGE_SHIFT); + BUG_ON(nid == NULL); + BUG_ON(*(unsigned long *)nid >= MAX_NUMNODES); + + add_active_range(*(unsigned long *)nid, + __pa(start) >> PAGE_SHIFT, + __pa(end) >> PAGE_SHIFT); return 0; } #endif /* CONFIG_VIRTUAL_MEM_MAP */ diff --git a/trunk/arch/ia64/sn/kernel/setup.c b/trunk/arch/ia64/sn/kernel/setup.c index 8571e52c2efd..a934ad069425 100644 --- a/trunk/arch/ia64/sn/kernel/setup.c +++ b/trunk/arch/ia64/sn/kernel/setup.c @@ -580,7 +580,7 @@ void __cpuinit sn_cpu_init(void) int slice; int cnode; int i; - static int wars_have_been_checked, set_cpu0_number; + static int wars_have_been_checked; cpuid = smp_processor_id(); if (cpuid == 0 && IS_MEDUSA()) { @@ -605,16 +605,8 @@ void __cpuinit sn_cpu_init(void) /* * Don't check status. The SAL call is not supported on all PROMs * but a failure is harmless. - * Architechtuallly, cpu_init is always called twice on cpu 0. We - * should set cpu_number on cpu 0 once. */ - if (cpuid == 0) { - if (!set_cpu0_number) { - (void) ia64_sn_set_cpu_number(cpuid); - set_cpu0_number = 1; - } - } else - (void) ia64_sn_set_cpu_number(cpuid); + (void) ia64_sn_set_cpu_number(cpuid); /* * The boot cpu makes this call again after platform initialization is diff --git a/trunk/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/trunk/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 33367996d72d..462ea178f49a 100644 --- a/trunk/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/trunk/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -189,7 +189,7 @@ static void print_pci_topology(struct seq_file *s) int e; for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) { - if (!(p = kmalloc(sz, GFP_KERNEL))) + if (!(p = (char *)kmalloc(sz, GFP_KERNEL))) break; e = ia64_sn_ioif_get_pci_topology(__pa(p), sz); if (e == SALRET_OK) diff --git a/trunk/arch/ia64/sn/kernel/xpc_channel.c b/trunk/arch/ia64/sn/kernel/xpc_channel.c index c08db9c2375d..1f3540826e68 100644 --- a/trunk/arch/ia64/sn/kernel/xpc_channel.c +++ b/trunk/arch/ia64/sn/kernel/xpc_channel.c @@ -632,7 +632,7 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags) ch->number, ch->partid); spin_unlock_irqrestore(&ch->lock, *irq_flags); - xpc_create_kthreads(ch, 1, 0); + xpc_create_kthreads(ch, 1); spin_lock_irqsave(&ch->lock, *irq_flags); } @@ -754,12 +754,12 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) /* make sure all activity has settled down first */ - if (atomic_read(&ch->kthreads_assigned) > 0 || - atomic_read(&ch->references) > 0) { + if (atomic_read(&ch->references) > 0 || + ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && + !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE))) { return; } - DBUG_ON((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && - !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE)); + DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0); if (part->act_state == XPC_P_DEACTIVATING) { /* can't proceed until the other side disengages from us */ @@ -1651,11 +1651,6 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch, /* wake all idle kthreads so they can exit */ if (atomic_read(&ch->kthreads_idle) > 0) { wake_up_all(&ch->idle_wq); - - } else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && - !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { - /* start a kthread that will do the xpcDisconnecting callout */ - xpc_create_kthreads(ch, 1, 1); } /* wake those waiting to allocate an entry from the local msg queue */ diff --git a/trunk/arch/ia64/sn/kernel/xpc_main.c b/trunk/arch/ia64/sn/kernel/xpc_main.c index 7a387d237363..fa96dfc0e1aa 100644 --- a/trunk/arch/ia64/sn/kernel/xpc_main.c +++ b/trunk/arch/ia64/sn/kernel/xpc_main.c @@ -681,7 +681,7 @@ xpc_activate_kthreads(struct xpc_channel *ch, int needed) dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n", needed, ch->partid, ch->number); - xpc_create_kthreads(ch, needed, 0); + xpc_create_kthreads(ch, needed); } @@ -775,28 +775,26 @@ xpc_daemonize_kthread(void *args) xpc_kthread_waitmsgs(part, ch); } - /* let registerer know that connection is disconnecting */ - - spin_lock_irqsave(&ch->lock, irq_flags); - if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && - !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { - ch->flags |= XPC_C_DISCONNECTINGCALLOUT; - spin_unlock_irqrestore(&ch->lock, irq_flags); - - xpc_disconnect_callout(ch, xpcDisconnecting); - + if (atomic_dec_return(&ch->kthreads_assigned) == 0) { spin_lock_irqsave(&ch->lock, irq_flags); - ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; - } - spin_unlock_irqrestore(&ch->lock, irq_flags); + if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && + !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { + ch->flags |= XPC_C_DISCONNECTINGCALLOUT; + spin_unlock_irqrestore(&ch->lock, irq_flags); - if (atomic_dec_return(&ch->kthreads_assigned) == 0) { + xpc_disconnect_callout(ch, xpcDisconnecting); + + spin_lock_irqsave(&ch->lock, irq_flags); + ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; + } + spin_unlock_irqrestore(&ch->lock, irq_flags); if (atomic_dec_return(&part->nchannels_engaged) == 0) { xpc_mark_partition_disengaged(part); xpc_IPI_send_disengage(part); } } + xpc_msgqueue_deref(ch); dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n", @@ -820,8 +818,7 @@ xpc_daemonize_kthread(void *args) * partition. */ void -xpc_create_kthreads(struct xpc_channel *ch, int needed, - int ignore_disconnecting) +xpc_create_kthreads(struct xpc_channel *ch, int needed) { unsigned long irq_flags; pid_t pid; @@ -836,38 +833,16 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed, * kthread. That kthread is responsible for doing the * counterpart to the following before it exits. */ - if (ignore_disconnecting) { - if (!atomic_inc_not_zero(&ch->kthreads_assigned)) { - /* kthreads assigned had gone to zero */ - BUG_ON(!(ch->flags & - XPC_C_DISCONNECTINGCALLOUT_MADE)); - break; - } - - } else if (ch->flags & XPC_C_DISCONNECTING) { - break; - - } else if (atomic_inc_return(&ch->kthreads_assigned) == 1) { - if (atomic_inc_return(&part->nchannels_engaged) == 1) - xpc_mark_partition_engaged(part); - } (void) xpc_part_ref(part); xpc_msgqueue_ref(ch); + if (atomic_inc_return(&ch->kthreads_assigned) == 1 && + atomic_inc_return(&part->nchannels_engaged) == 1) { + xpc_mark_partition_engaged(part); + } pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0); if (pid < 0) { /* the fork failed */ - - /* - * NOTE: if (ignore_disconnecting && - * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true, - * then we'll deadlock if all other kthreads assigned - * to this channel are blocked in the channel's - * registerer, because the only thing that will unblock - * them is the xpcDisconnecting callout that this - * failed kernel_thread would have made. - */ - if (atomic_dec_return(&ch->kthreads_assigned) == 0 && atomic_dec_return(&part->nchannels_engaged) == 0) { xpc_mark_partition_disengaged(part); @@ -882,6 +857,9 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed, * Flag this as an error only if we have an * insufficient #of kthreads for the channel * to function. + * + * No xpc_msgqueue_ref() is needed here since + * the channel mgr is doing this. */ spin_lock_irqsave(&ch->lock, irq_flags); XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources, diff --git a/trunk/arch/m68k/mm/kmap.c b/trunk/arch/m68k/mm/kmap.c index 46b7d6035aab..b54ef1726c55 100644 --- a/trunk/arch/m68k/mm/kmap.c +++ b/trunk/arch/m68k/mm/kmap.c @@ -59,7 +59,7 @@ static struct vm_struct *get_io_area(unsigned long size) unsigned long addr; struct vm_struct **p, *tmp, *area; - area = kmalloc(sizeof(*area), GFP_KERNEL); + area = (struct vm_struct *)kmalloc(sizeof(*area), GFP_KERNEL); if (!area) return NULL; addr = KMAP_START; diff --git a/trunk/arch/mips/configs/malta_defconfig b/trunk/arch/mips/configs/malta_defconfig index 96e941084c04..1f9300f37f52 100644 --- a/trunk/arch/mips/configs/malta_defconfig +++ b/trunk/arch/mips/configs/malta_defconfig @@ -644,85 +644,7 @@ CONFIG_CONNECTOR=m # # Memory Technology Devices (MTD) # -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=0 -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# OneNAND Flash Device Drivers -# -# CONFIG_MTD_ONENAND is not set +# CONFIG_MTD is not set # # Parallel port support diff --git a/trunk/arch/mips/kernel/apm.c b/trunk/arch/mips/kernel/apm.c index ba16d07588cb..528e731049c1 100644 --- a/trunk/arch/mips/kernel/apm.c +++ b/trunk/arch/mips/kernel/apm.c @@ -356,7 +356,7 @@ static int apm_open(struct inode * inode, struct file * filp) { struct apm_user *as; - as = kzalloc(sizeof(*as), GFP_KERNEL); + as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL); if (as) { /* * XXX - this is a tiny bit broken, when we consider BSD diff --git a/trunk/arch/mips/kernel/kspd.c b/trunk/arch/mips/kernel/kspd.c index 5929f883e46b..2c82412b9efe 100644 --- a/trunk/arch/mips/kernel/kspd.c +++ b/trunk/arch/mips/kernel/kspd.c @@ -301,7 +301,7 @@ static void sp_cleanup(void) for (;;) { unsigned long set; i = j * __NFDBITS; - if (i >= fdt->max_fds) + if (i >= fdt->max_fdset || i >= fdt->max_fds) break; set = fdt->open_fds->fds_bits[j++]; while (set) { diff --git a/trunk/arch/mips/kernel/reset.c b/trunk/arch/mips/kernel/reset.c index 060563a712b6..621037db2290 100644 --- a/trunk/arch/mips/kernel/reset.c +++ b/trunk/arch/mips/kernel/reset.c @@ -23,8 +23,6 @@ void (*_machine_restart)(char *command); void (*_machine_halt)(void); void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - void machine_restart(char *command) { if (_machine_restart) diff --git a/trunk/arch/mips/kernel/vmlinux.lds.S b/trunk/arch/mips/kernel/vmlinux.lds.S index cecff24cc972..79f0317d84ac 100644 --- a/trunk/arch/mips/kernel/vmlinux.lds.S +++ b/trunk/arch/mips/kernel/vmlinux.lds.S @@ -112,7 +112,6 @@ SECTIONS /* .exit.text is discarded at runtime, not link time, to deal with references from .rodata */ .exit.text : { *(.exit.text) } - .exit.data : { *(.exit.data) } . = ALIGN(_PAGE_SIZE); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } @@ -140,6 +139,7 @@ SECTIONS /* Sections to be discarded */ /DISCARD/ : { + *(.exit.data) *(.exitcall.exit) /* ABI crap starts here */ diff --git a/trunk/arch/mips/lasat/sysctl.c b/trunk/arch/mips/lasat/sysctl.c index 12878359f2c8..da35d4555491 100644 --- a/trunk/arch/mips/lasat/sysctl.c +++ b/trunk/arch/mips/lasat/sysctl.c @@ -40,12 +40,12 @@ static DEFINE_MUTEX(lasat_info_mutex); /* Strategy function to write EEPROM after changing string entry */ int sysctl_lasatstring(ctl_table *table, int *name, int nlen, void *oldval, size_t *oldlenp, - void *newval, size_t newlen) + void *newval, size_t newlen, void **context) { int r; mutex_lock(&lasat_info_mutex); r = sysctl_string(table, name, - nlen, oldval, oldlenp, newval, newlen); + nlen, oldval, oldlenp, newval, newlen, context); if (r < 0) { mutex_unlock(&lasat_info_mutex); return r; @@ -119,11 +119,11 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, /* Sysctl for setting the IP addresses */ int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen, void *oldval, size_t *oldlenp, - void *newval, size_t newlen) + void *newval, size_t newlen, void **context) { int r; mutex_lock(&lasat_info_mutex); - r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen); + r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); if (r < 0) { mutex_unlock(&lasat_info_mutex); return r; @@ -139,14 +139,14 @@ int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen, /* Same for RTC */ int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen, void *oldval, size_t *oldlenp, - void *newval, size_t newlen) + void *newval, size_t newlen, void **context) { int r; mutex_lock(&lasat_info_mutex); rtctmp = ds1603_read(); if (rtctmp < 0) rtctmp = 0; - r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen); + r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); if (r < 0) { mutex_unlock(&lasat_info_mutex); return r; @@ -251,12 +251,13 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp, static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen, void *oldval, size_t *oldlenp, - void *newval, size_t newlen) + void *newval, size_t newlen, + void **context) { int r; mutex_lock(&lasat_info_mutex); - r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen); + r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); if (r < 0) { mutex_unlock(&lasat_info_mutex); return r; diff --git a/trunk/arch/mips/lib/csum_partial_copy.c b/trunk/arch/mips/lib/csum_partial_copy.c index 06771040a267..1720f2ceeeae 100644 --- a/trunk/arch/mips/lib/csum_partial_copy.c +++ b/trunk/arch/mips/lib/csum_partial_copy.c @@ -7,7 +7,6 @@ * Copyright (C) 1998, 1999 Ralf Baechle */ #include -#include #include #include #include @@ -30,8 +29,6 @@ __wsum csum_partial_copy_nocheck(const void *src, return sum; } -EXPORT_SYMBOL(csum_partial_copy_nocheck); - /* * Copy from userspace and compute checksum. If we catch an exception * then zero the rest of the buffer. diff --git a/trunk/arch/mips/mips-boards/malta/Makefile b/trunk/arch/mips/mips-boards/malta/Makefile index b662c75fb28e..77ee5c6d33c1 100644 --- a/trunk/arch/mips/mips-boards/malta/Makefile +++ b/trunk/arch/mips/mips-boards/malta/Makefile @@ -19,5 +19,5 @@ # under Linux. # -obj-y := malta_int.o malta_mtd.o malta_setup.o +obj-y := malta_int.o malta_setup.o obj-$(CONFIG_SMP) += malta_smp.o diff --git a/trunk/arch/mips/mips-boards/malta/malta_setup.c b/trunk/arch/mips/mips-boards/malta/malta_setup.c index 56ea76679cd4..282f3e52eea3 100644 --- a/trunk/arch/mips/mips-boards/malta/malta_setup.c +++ b/trunk/arch/mips/mips-boards/malta/malta_setup.c @@ -21,6 +21,13 @@ #include #include +#ifdef CONFIG_MTD +#include +#include +#include +#include +#endif + #include #include #include @@ -51,6 +58,30 @@ struct resource standard_io_resources[] = { { .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY }, }; +#ifdef CONFIG_MTD +static struct mtd_partition malta_mtd_partitions[] = { + { + .name = "YAMON", + .offset = 0x0, + .size = 0x100000, + .mask_flags = MTD_WRITEABLE + }, + { + .name = "User FS", + .offset = 0x100000, + .size = 0x2e0000 + }, + { + .name = "Board Config", + .offset = 0x3e0000, + .size = 0x020000, + .mask_flags = MTD_WRITEABLE + } +}; + +#define number_partitions (sizeof(malta_mtd_partitions)/sizeof(struct mtd_partition)) +#endif + const char *get_system_type(void) { return "MIPS Malta"; @@ -180,6 +211,14 @@ void __init plat_mem_setup(void) #endif #endif +#ifdef CONFIG_MTD + /* + * Support for MTD on Malta. Use the generic physmap driver + */ + physmap_configure(0x1e000000, 0x400000, 4, NULL); + physmap_set_partitions(malta_mtd_partitions, number_partitions); +#endif + mips_reboot_setup(); board_time_init = mips_time_init; diff --git a/trunk/arch/mips/mm/cache.c b/trunk/arch/mips/mm/cache.c index 1f954a238a63..caf807ded514 100644 --- a/trunk/arch/mips/mm/cache.c +++ b/trunk/arch/mips/mm/cache.c @@ -32,7 +32,6 @@ void (*local_flush_data_cache_page)(void * addr); void (*flush_data_cache_page)(unsigned long addr); void (*flush_icache_all)(void); -EXPORT_SYMBOL_GPL(local_flush_data_cache_page); EXPORT_SYMBOL(flush_data_cache_page); #ifdef CONFIG_DMA_NONCOHERENT diff --git a/trunk/arch/mips/mm/init.c b/trunk/arch/mips/mm/init.c index ea2d15370bb7..9e29ba9205f0 100644 --- a/trunk/arch/mips/mm/init.c +++ b/trunk/arch/mips/mm/init.c @@ -316,7 +316,7 @@ static int __init page_is_ram(unsigned long pagenr) void __init paging_init(void) { unsigned long zones_size[MAX_NR_ZONES] = { 0, }; - unsigned long max_dma, low; + unsigned long max_dma, high, low; #ifndef CONFIG_FLATMEM unsigned long zholes_size[MAX_NR_ZONES] = { 0, }; unsigned long i, j, pfn; @@ -331,6 +331,7 @@ void __init paging_init(void) max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; + high = highend_pfn; #ifdef CONFIG_ISA if (low < max_dma) @@ -343,13 +344,13 @@ void __init paging_init(void) zones_size[ZONE_DMA] = low; #endif #ifdef CONFIG_HIGHMEM - zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn; - - if (cpu_has_dc_aliases && zones_size[ZONE_HIGHMEM]) { - printk(KERN_WARNING "This processor doesn't support highmem." - " %ldk highmem ignored\n", zones_size[ZONE_HIGHMEM]); - zones_size[ZONE_HIGHMEM] = 0; - } + if (cpu_has_dc_aliases) { + printk(KERN_WARNING "This processor doesn't support highmem."); + if (high - low) + printk(" %ldk highmem ignored", high - low); + printk("\n"); + } else + zones_size[ZONE_HIGHMEM] = high - low; #endif #ifdef CONFIG_FLATMEM diff --git a/trunk/arch/parisc/hpux/sys_hpux.c b/trunk/arch/parisc/hpux/sys_hpux.c index 04c2ff444396..d88309209f56 100644 --- a/trunk/arch/parisc/hpux/sys_hpux.c +++ b/trunk/arch/parisc/hpux/sys_hpux.c @@ -475,7 +475,7 @@ int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2) printk(KERN_DEBUG "len of arg1 = %d\n", len); if (len == 0) return 0; - fsname = kmalloc(len, GFP_KERNEL); + fsname = (char *) kmalloc(len, GFP_KERNEL); if ( !fsname ) { printk(KERN_DEBUG "failed to kmalloc fsname\n"); return 0; diff --git a/trunk/arch/parisc/kernel/unwind.c b/trunk/arch/parisc/kernel/unwind.c index c10ab47d81fa..920bdbf8404f 100644 --- a/trunk/arch/parisc/kernel/unwind.c +++ b/trunk/arch/parisc/kernel/unwind.c @@ -343,7 +343,7 @@ void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct struct pt_regs *r = &t->thread.regs; struct pt_regs *r2; - r2 = kmalloc(sizeof(struct pt_regs), GFP_KERNEL); + r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL); if (!r2) return; *r2 = *r; diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index 8699dadcd096..56c3c4065eb0 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -107,11 +107,6 @@ config AUDIT_ARCH bool default y -config GENERIC_BUG - bool - default y - depends on BUG - config DEFAULT_UIMAGE bool help @@ -483,7 +478,6 @@ config PPC_MAPLE select PPC_UDBG_16550 select PPC_970_NAP select PPC_NATIVE - select PPC_RTAS default n help This option enables support for the Maple 970FX Evaluation Board. @@ -720,7 +714,7 @@ config FORCE_MAX_ZONEORDER config MATH_EMULATION bool "Math emulation" - depends on 4xx || 8xx || E200 || PPC_83xx || E500 + depends on 4xx || 8xx || E200 || E500 ---help--- Some PowerPC chips designed for embedded applications do not have a floating-point unit and therefore do not implement the diff --git a/trunk/arch/powerpc/configs/ps3_defconfig b/trunk/arch/powerpc/configs/ps3_defconfig index 70ed61337f5c..f2d888e014a9 100644 --- a/trunk/arch/powerpc/configs/ps3_defconfig +++ b/trunk/arch/powerpc/configs/ps3_defconfig @@ -157,7 +157,6 @@ CONFIG_SPU_BASE=y CONFIG_PS3_HTAB_SIZE=20 CONFIG_PS3_DYNAMIC_DMA=y CONFIG_PS3_USE_LPAR_ADDR=y -CONFIG_PS3_VUART=y # # Kernel options diff --git a/trunk/arch/powerpc/kernel/Makefile b/trunk/arch/powerpc/kernel/Makefile index d2ded19e4064..4fe53d08ab81 100644 --- a/trunk/arch/powerpc/kernel/Makefile +++ b/trunk/arch/powerpc/kernel/Makefile @@ -77,7 +77,6 @@ endif ifeq ($(CONFIG_PPC_ISERIES),y) extra-y += lparmap.s -$(obj)/head_64.o: $(obj)/lparmap.s AFLAGS_head_64.o += -I$(obj) endif diff --git a/trunk/arch/powerpc/kernel/cputable.c b/trunk/arch/powerpc/kernel/cputable.c index b742013bb9da..9d1614c3ce67 100644 --- a/trunk/arch/powerpc/kernel/cputable.c +++ b/trunk/arch/powerpc/kernel/cputable.c @@ -833,7 +833,7 @@ static struct cpu_spec cpu_specs[] = { .pvr_mask = 0x7fff0000, .pvr_value = 0x00840000, .cpu_name = "e300c2", - .cpu_features = CPU_FTRS_E300C2, + .cpu_features = CPU_FTRS_E300, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, @@ -1136,7 +1136,8 @@ static struct cpu_spec cpu_specs[] = { .pvr_mask = 0xff000fff, .pvr_value = 0x53000890, .cpu_name = "440SPe Rev. A", - .cpu_features = CPU_FTRS_44X, + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, diff --git a/trunk/arch/powerpc/kernel/head_32.S b/trunk/arch/powerpc/kernel/head_32.S index 9417cf5b4b7e..d88e182e40b3 100644 --- a/trunk/arch/powerpc/kernel/head_32.S +++ b/trunk/arch/powerpc/kernel/head_32.S @@ -437,13 +437,6 @@ Alignment: /* Floating-point unavailable */ . = 0x800 FPUnavailable: -BEGIN_FTR_SECTION -/* - * Certain Freescale cores don't have a FPU and treat fp instructions - * as a FP Unavailable exception. Redirect to illegal/emulation handling. - */ - b ProgramCheck -END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE) EXCEPTION_PROLOG bne load_up_fpu /* if from user, just load it up */ addi r3,r1,STACK_FRAME_OVERHEAD diff --git a/trunk/arch/powerpc/kernel/module_32.c b/trunk/arch/powerpc/kernel/module_32.c index 8339fd609de0..e2c3c6a85f33 100644 --- a/trunk/arch/powerpc/kernel/module_32.c +++ b/trunk/arch/powerpc/kernel/module_32.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "setup.h" @@ -291,11 +290,23 @@ int module_finalize(const Elf_Ehdr *hdr, struct module *me) { const Elf_Shdr *sect; - int err; - err = module_bug_finalize(hdr, sechdrs, me); - if (err) /* never true, currently */ - return err; + me->arch.bug_table = NULL; + me->arch.num_bugs = 0; + + /* Find the __bug_table section, if present */ + sect = find_section(hdr, sechdrs, "__bug_table"); + if (sect != NULL) { + me->arch.bug_table = (void *) sect->sh_addr; + me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); + } + + /* + * Strictly speaking this should have a spinlock to protect against + * traversals, but since we only traverse on BUG()s, a spinlock + * could potentially lead to deadlock and thus be counter-productive. + */ + list_add(&me->arch.bug_list, &module_bug_list); /* Apply feature fixups */ sect = find_section(hdr, sechdrs, "__ftr_fixup"); @@ -309,7 +320,7 @@ int module_finalize(const Elf_Ehdr *hdr, void module_arch_cleanup(struct module *mod) { - module_bug_cleanup(mod); + list_del(&mod->arch.bug_list); } struct bug_entry *module_find_bug(unsigned long bugaddr) diff --git a/trunk/arch/powerpc/kernel/module_64.c b/trunk/arch/powerpc/kernel/module_64.c index 75c7c4f19280..8dd1f0aae5d6 100644 --- a/trunk/arch/powerpc/kernel/module_64.c +++ b/trunk/arch/powerpc/kernel/module_64.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -440,11 +439,23 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { const Elf_Shdr *sect; - int err; - err = module_bug_finalize(hdr, sechdrs, me); - if (err) - return err; + me->arch.bug_table = NULL; + me->arch.num_bugs = 0; + + /* Find the __bug_table section, if present */ + sect = find_section(hdr, sechdrs, "__bug_table"); + if (sect != NULL) { + me->arch.bug_table = (void *) sect->sh_addr; + me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); + } + + /* + * Strictly speaking this should have a spinlock to protect against + * traversals, but since we only traverse on BUG()s, a spinlock + * could potentially lead to deadlock and thus be counter-productive. + */ + list_add(&me->arch.bug_list, &module_bug_list); /* Apply feature fixups */ sect = find_section(hdr, sechdrs, "__ftr_fixup"); @@ -464,7 +475,7 @@ int module_finalize(const Elf_Ehdr *hdr, void module_arch_cleanup(struct module *mod) { - module_bug_cleanup(mod); + list_del(&mod->arch.bug_list); } struct bug_entry *module_find_bug(unsigned long bugaddr) diff --git a/trunk/arch/powerpc/kernel/nvram_64.c b/trunk/arch/powerpc/kernel/nvram_64.c index 869cebbba967..6960f090991e 100644 --- a/trunk/arch/powerpc/kernel/nvram_64.c +++ b/trunk/arch/powerpc/kernel/nvram_64.c @@ -505,7 +505,7 @@ static int nvram_scan_partitions(void) return -ENODEV; total_size = ppc_md.nvram_size(); - header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL); + header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL); if (!header) { printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n"); return -ENOMEM; @@ -574,7 +574,7 @@ static int __init nvram_init(void) } /* initialize our anchor for the nvram partition list */ - nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); if (!nvram_part) { printk(KERN_ERR "nvram_init: Failed kmalloc\n"); return -ENOMEM; diff --git a/trunk/arch/powerpc/kernel/of_device.c b/trunk/arch/powerpc/kernel/of_device.c index e921514e655b..8a06724e029e 100644 --- a/trunk/arch/powerpc/kernel/of_device.c +++ b/trunk/arch/powerpc/kernel/of_device.c @@ -109,7 +109,9 @@ int of_device_register(struct of_device *ofdev) if (rc) return rc; - return device_create_file(&ofdev->dev, &dev_attr_devspec); + device_create_file(&ofdev->dev, &dev_attr_devspec); + + return 0; } void of_device_unregister(struct of_device *ofdev) diff --git a/trunk/arch/powerpc/kernel/of_platform.c b/trunk/arch/powerpc/kernel/of_platform.c index 3002ea3a61a2..b3189d0161b8 100644 --- a/trunk/arch/powerpc/kernel/of_platform.c +++ b/trunk/arch/powerpc/kernel/of_platform.c @@ -169,7 +169,7 @@ static void of_platform_make_bus_id(struct of_device *dev) char *name = dev->dev.bus_id; const u32 *reg; u64 addr; - int magic; + long magic; /* * If it's a DCR based device, use 'd' for native DCRs diff --git a/trunk/arch/powerpc/kernel/pci_32.c b/trunk/arch/powerpc/kernel/pci_32.c index 2847cd51a2d7..2f54cd81dea5 100644 --- a/trunk/arch/powerpc/kernel/pci_32.c +++ b/trunk/arch/powerpc/kernel/pci_32.c @@ -670,7 +670,7 @@ pcibios_make_OF_bus_map(void) struct pci_controller* hose; struct property *map_prop; - pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL); + pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL); if (!pci_to_OF_bus_map) { printk(KERN_ERR "Can't allocate OF bus map !\n"); return; @@ -736,51 +736,25 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* return NULL; } -static struct device_node *scan_OF_for_pci_dev(struct device_node *parent, - unsigned int devfn) +static int +scan_OF_pci_childs_iterator(struct device_node* node, void* data) { - struct device_node *np = NULL; - const u32 *reg; - unsigned int psize; - - while ((np = of_get_next_child(parent, np)) != NULL) { - reg = get_property(np, "reg", &psize); - if (reg == NULL || psize < 4) - continue; - if (((reg[0] >> 8) & 0xff) == devfn) - return np; - } - return NULL; + const unsigned int *reg; + u8* fdata = (u8*)data; + + reg = get_property(node, "reg", NULL); + if (reg && ((reg[0] >> 8) & 0xff) == fdata[1] + && ((reg[0] >> 16) & 0xff) == fdata[0]) + return 1; + return 0; } - -static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus) +static struct device_node* +scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn) { - struct device_node *parent, *np; - - /* Are we a root bus ? */ - if (bus->self == NULL || bus->parent == NULL) { - struct pci_controller *hose = pci_bus_to_hose(bus->number); - if (hose == NULL) - return NULL; - return of_node_get(hose->arch_data); - } - - /* not a root bus, we need to get our parent */ - parent = scan_OF_for_pci_bus(bus->parent); - if (parent == NULL) - return NULL; - - /* now iterate for children for a match */ - np = scan_OF_for_pci_dev(parent, bus->self->devfn); - of_node_put(parent); + u8 filter_data[2] = {bus, dev_fn}; - /* sanity check */ - if (strcmp(np->type, "pci") != 0) - printk(KERN_WARNING "pci: wrong type \"%s\" for bridge %s\n", - np->type, np->full_name); - - return np; + return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data); } /* @@ -789,25 +763,43 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus) struct device_node * pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) { - struct device_node *parent, *np; + struct pci_controller *hose; + struct device_node *node; + int busnr; if (!have_of) return NULL; + + /* Lookup the hose */ + busnr = bus->number; + hose = pci_bus_to_hose(busnr); + if (!hose) + return NULL; - DBG("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn); - parent = scan_OF_for_pci_bus(bus); - if (parent == NULL) + /* Check it has an OF node associated */ + node = (struct device_node *) hose->arch_data; + if (!node) return NULL; - DBG(" parent is %s\n", parent ? parent->full_name : ""); - np = scan_OF_for_pci_dev(parent, devfn); - of_node_put(parent); - DBG(" result is %s\n", np ? np->full_name : ""); - - /* XXX most callers don't release the returned node - * mostly because ppc64 doesn't increase the refcount, - * we need to fix that. + + /* Fixup bus number according to what OF think it is. */ +#ifdef CONFIG_PPC_PMAC + /* The G5 need a special case here. Basically, we don't remap all + * busses on it so we don't create the pci-OF-map. However, we do + * remap the AGP bus and so have to deal with it. A future better + * fix has to be done by making the remapping per-host and always + * filling the pci_to_OF map. --BenH */ - return np; + if (machine_is(powermac) && busnr >= 0xf0) + busnr -= 0xf0; + else +#endif + if (pci_to_OF_bus_map) + busnr = pci_to_OF_bus_map[busnr]; + if (busnr == 0xff) + return NULL; + + /* Now, lookup childs of the hose */ + return scan_OF_childs_for_device(node->child, busnr, devfn); } EXPORT_SYMBOL(pci_busdev_to_OF_node); @@ -1552,7 +1544,7 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, - resource_size_t *offset, + unsigned long *offset, enum pci_mmap_state mmap_state) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); @@ -1564,9 +1556,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, /* If memory, add on the PCI bridge address offset */ if (mmap_state == pci_mmap_mem) { -#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ *offset += hose->pci_mem_offset; -#endif res_bit = IORESOURCE_MEM; } else { io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; @@ -1634,6 +1624,9 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, else prot |= _PAGE_GUARDED; + printk("PCI map for %s:%llx, prot: %lx\n", pci_name(dev), + (unsigned long long)rp->start, prot); + return __pgprot(prot); } @@ -1702,7 +1695,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { - resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct resource *rp; int ret; @@ -1815,42 +1808,22 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, resource_size_t *start, resource_size_t *end) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); - resource_size_t offset = 0; + unsigned long offset = 0; if (hose == NULL) return; if (rsrc->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - _IO_BASE; - - /* We pass a fully fixed up address to userland for MMIO instead of - * a BAR value because X is lame and expects to be able to use that - * to pass to /dev/mem ! - * - * That means that we'll have potentially 64 bits values where some - * userland apps only expect 32 (like X itself since it thinks only - * Sparc has 64 bits MMIO) but if we don't do that, we break it on - * 32 bits CHRPs :-( - * - * Hopefully, the sysfs insterface is immune to that gunk. Once X - * has been fixed (and the fix spread enough), we can re-enable the - * 2 lines below and pass down a BAR value to userland. In that case - * we'll also have to re-enable the matching code in - * __pci_mmap_make_offset(). - * - * BenH. - */ -#if 0 - else if (rsrc->flags & IORESOURCE_MEM) - offset = hose->pci_mem_offset; -#endif + offset = (void __iomem *)_IO_BASE - hose->io_base_virt + + hose->io_base_phys; - *start = rsrc->start - offset; - *end = rsrc->end - offset; + *start = rsrc->start + offset; + *end = rsrc->end + offset; } -void __init pci_init_resource(struct resource *res, resource_size_t start, - resource_size_t end, int flags, char *name) +void __init +pci_init_resource(struct resource *res, unsigned long start, unsigned long end, + int flags, char *name) { res->start = start; res->end = end; diff --git a/trunk/arch/powerpc/kernel/pci_64.c b/trunk/arch/powerpc/kernel/pci_64.c index a6b7692c7269..6fa9a0a5c8db 100644 --- a/trunk/arch/powerpc/kernel/pci_64.c +++ b/trunk/arch/powerpc/kernel/pci_64.c @@ -682,7 +682,7 @@ int pci_proc_domain(struct pci_bus *bus) * Returns negative error code on failure, zero on success. */ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, - resource_size_t *offset, + unsigned long *offset, enum pci_mmap_state mmap_state) { struct pci_controller *hose = pci_bus_to_host(dev->bus); @@ -694,9 +694,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, /* If memory, add on the PCI bridge address offset */ if (mmap_state == pci_mmap_mem) { -#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ *offset += hose->pci_mem_offset; -#endif res_bit = IORESOURCE_MEM; } else { io_offset = (unsigned long)hose->io_base_virt - pci_io_base; @@ -764,6 +762,9 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, else prot |= _PAGE_GUARDED; + printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, + prot); + return __pgprot(prot); } @@ -831,7 +832,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file, int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { - resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct resource *rp; int ret; @@ -1332,41 +1333,20 @@ EXPORT_SYMBOL(pci_read_irq_line); void pci_resource_to_user(const struct pci_dev *dev, int bar, const struct resource *rsrc, - resource_size_t *start, resource_size_t *end) + u64 *start, u64 *end) { struct pci_controller *hose = pci_bus_to_host(dev->bus); - resource_size_t offset = 0; + unsigned long offset = 0; if (hose == NULL) return; if (rsrc->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - pci_io_base; - - /* We pass a fully fixed up address to userland for MMIO instead of - * a BAR value because X is lame and expects to be able to use that - * to pass to /dev/mem ! - * - * That means that we'll have potentially 64 bits values where some - * userland apps only expect 32 (like X itself since it thinks only - * Sparc has 64 bits MMIO) but if we don't do that, we break it on - * 32 bits CHRPs :-( - * - * Hopefully, the sysfs insterface is immune to that gunk. Once X - * has been fixed (and the fix spread enough), we can re-enable the - * 2 lines below and pass down a BAR value to userland. In that case - * we'll also have to re-enable the matching code in - * __pci_mmap_make_offset(). - * - * BenH. - */ -#if 0 - else if (rsrc->flags & IORESOURCE_MEM) - offset = hose->pci_mem_offset; -#endif + offset = pci_io_base - (unsigned long)hose->io_base_virt + + hose->io_base_phys; - *start = rsrc->start - offset; - *end = rsrc->end - offset; + *start = rsrc->start + offset; + *end = rsrc->end + offset; } struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) diff --git a/trunk/arch/powerpc/kernel/ppc_ksyms.c b/trunk/arch/powerpc/kernel/ppc_ksyms.c index 95776b6af4e2..9179f0739ea2 100644 --- a/trunk/arch/powerpc/kernel/ppc_ksyms.c +++ b/trunk/arch/powerpc/kernel/ppc_ksyms.c @@ -208,7 +208,7 @@ EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */ extern long *intercept_table; EXPORT_SYMBOL(intercept_table); #endif /* CONFIG_PPC_STD_MMU_32 */ -#ifdef CONFIG_PPC_DCR_NATIVE +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) EXPORT_SYMBOL(__mtdcr); EXPORT_SYMBOL(__mfdcr); #endif diff --git a/trunk/arch/powerpc/kernel/prom.c b/trunk/arch/powerpc/kernel/prom.c index 1fc732a552db..c18dbe77fdc2 100644 --- a/trunk/arch/powerpc/kernel/prom.c +++ b/trunk/arch/powerpc/kernel/prom.c @@ -804,56 +804,6 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) return of_read_ulong(p, s); } -#ifdef CONFIG_PPC_PSERIES -/* - * Interpret the ibm,dynamic-memory property in the - * /ibm,dynamic-reconfiguration-memory node. - * This contains a list of memory blocks along with NUMA affinity - * information. - */ -static int __init early_init_dt_scan_drconf_memory(unsigned long node) -{ - cell_t *dm, *ls; - unsigned long l, n; - unsigned long base, size, lmb_size, flags; - - ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l); - if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) - return 0; - lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls); - - dm = (cell_t *)of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l); - if (dm == NULL || l < sizeof(cell_t)) - return 0; - - n = *dm++; /* number of entries */ - if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) - return 0; - - for (; n != 0; --n) { - base = dt_mem_next_cell(dt_root_addr_cells, &dm); - flags = dm[3]; - /* skip DRC index, pad, assoc. list index, flags */ - dm += 4; - /* skip this block if the reserved bit is set in flags (0x80) - or if the block is not assigned to this partition (0x8) */ - if ((flags & 0x80) || !(flags & 0x8)) - continue; - size = lmb_size; - if (iommu_is_off) { - if (base >= 0x80000000ul) - continue; - if ((base + size) > 0x80000000ul) - size = 0x80000000ul - base; - } - lmb_add(base, size); - } - lmb_dump_all(); - return 0; -} -#else -#define early_init_dt_scan_drconf_memory(node) 0 -#endif /* CONFIG_PPC_PSERIES */ static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) @@ -862,11 +812,6 @@ static int __init early_init_dt_scan_memory(unsigned long node, cell_t *reg, *endp; unsigned long l; - /* Look for the ibm,dynamic-reconfiguration-memory node */ - if (depth == 1 && - strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) - return early_init_dt_scan_drconf_memory(node); - /* We are scanning "memory" nodes only */ if (type == NULL) { /* diff --git a/trunk/arch/powerpc/kernel/prom_init.c b/trunk/arch/powerpc/kernel/prom_init.c index 520ef42f642e..46cf32670ddb 100644 --- a/trunk/arch/powerpc/kernel/prom_init.c +++ b/trunk/arch/powerpc/kernel/prom_init.c @@ -679,7 +679,7 @@ static unsigned char ibm_architecture_vec[] = { /* option vector 5: PAPR/OF options */ 3 - 2, /* length */ 0, /* don't ignore, don't halt */ - OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY, + OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES, }; /* Old method - ELF header with PT_NOTE sections */ diff --git a/trunk/arch/powerpc/kernel/rtas.c b/trunk/arch/powerpc/kernel/rtas.c index 76b5d7ebdcc6..387ed0d9ad61 100644 --- a/trunk/arch/powerpc/kernel/rtas.c +++ b/trunk/arch/powerpc/kernel/rtas.c @@ -303,12 +303,6 @@ int rtas_token(const char *service) } EXPORT_SYMBOL(rtas_token); -int rtas_service_present(const char *service) -{ - return rtas_token(service) != RTAS_UNKNOWN_SERVICE; -} -EXPORT_SYMBOL(rtas_service_present); - #ifdef CONFIG_RTAS_ERROR_LOGGING /* * Return the firmware-specified size of the error log buffer @@ -816,6 +810,32 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) return 0; } +#ifdef CONFIG_HOTPLUG_CPU +/* This version can't take the spinlock, because it never returns */ +static struct rtas_args rtas_stop_self_args = { + /* The token is initialized for real in setup_system() */ + .token = RTAS_UNKNOWN_SERVICE, + .nargs = 0, + .nret = 1, + .rets = &rtas_stop_self_args.args[0], +}; + +void rtas_stop_self(void) +{ + struct rtas_args *rtas_args = &rtas_stop_self_args; + + local_irq_disable(); + + BUG_ON(rtas_args->token == RTAS_UNKNOWN_SERVICE); + + printk("cpu %u (hwid %u) Ready to die...\n", + smp_processor_id(), hard_smp_processor_id()); + enter_rtas(__pa(rtas_args)); + + panic("Alas, I survived.\n"); +} +#endif + /* * Call early during boot, before mem init or bootmem, to retrieve the RTAS * informations from the device-tree and allocate the RMO buffer for userland @@ -860,6 +880,9 @@ void __init rtas_initialize(void) #endif rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); +#ifdef CONFIG_HOTPLUG_CPU + rtas_stop_self_args.token = rtas_token("stop-self"); +#endif /* CONFIG_HOTPLUG_CPU */ #ifdef CONFIG_RTAS_ERROR_LOGGING rtas_last_error_token = rtas_token("rtas-last-error"); #endif diff --git a/trunk/arch/powerpc/kernel/sysfs.c b/trunk/arch/powerpc/kernel/sysfs.c index 400ab2b946e7..63ed265b7f09 100644 --- a/trunk/arch/powerpc/kernel/sysfs.c +++ b/trunk/arch/powerpc/kernel/sysfs.c @@ -181,8 +181,6 @@ SYSFS_PMCSETUP(pmc6, SPRN_PMC6); SYSFS_PMCSETUP(pmc7, SPRN_PMC7); SYSFS_PMCSETUP(pmc8, SPRN_PMC8); SYSFS_PMCSETUP(purr, SPRN_PURR); -SYSFS_PMCSETUP(spurr, SPRN_SPURR); -SYSFS_PMCSETUP(dscr, SPRN_DSCR); static SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0); static SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1); @@ -196,8 +194,6 @@ static SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6); static SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7); static SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8); static SYSDEV_ATTR(purr, 0600, show_purr, NULL); -static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL); -static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr); static void register_cpu_online(unsigned int cpu) { @@ -235,12 +231,6 @@ static void register_cpu_online(unsigned int cpu) if (cpu_has_feature(CPU_FTR_PURR)) sysdev_create_file(s, &attr_purr); - - if (cpu_has_feature(CPU_FTR_SPURR)) - sysdev_create_file(s, &attr_spurr); - - if (cpu_has_feature(CPU_FTR_DSCR)) - sysdev_create_file(s, &attr_dscr); } #ifdef CONFIG_HOTPLUG_CPU @@ -282,12 +272,6 @@ static void unregister_cpu_online(unsigned int cpu) if (cpu_has_feature(CPU_FTR_PURR)) sysdev_remove_file(s, &attr_purr); - - if (cpu_has_feature(CPU_FTR_SPURR)) - sysdev_remove_file(s, &attr_spurr); - - if (cpu_has_feature(CPU_FTR_DSCR)) - sysdev_remove_file(s, &attr_dscr); } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/trunk/arch/powerpc/kernel/traps.c b/trunk/arch/powerpc/kernel/traps.c index 535f50665647..0d4e203fa7a0 100644 --- a/trunk/arch/powerpc/kernel/traps.c +++ b/trunk/arch/powerpc/kernel/traps.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -728,9 +727,54 @@ static int emulate_instruction(struct pt_regs *regs) return -EINVAL; } -int is_valid_bugaddr(unsigned long addr) +/* + * Look through the list of trap instructions that are used for BUG(), + * BUG_ON() and WARN_ON() and see if we hit one. At this point we know + * that the exception was caused by a trap instruction of some kind. + * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0 + * otherwise. + */ +extern struct bug_entry __start___bug_table[], __stop___bug_table[]; + +#ifndef CONFIG_MODULES +#define module_find_bug(x) NULL +#endif + +struct bug_entry *find_bug(unsigned long bugaddr) { - return is_kernel_addr(addr); + struct bug_entry *bug; + + for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) + if (bugaddr == bug->bug_addr) + return bug; + return module_find_bug(bugaddr); +} + +static int check_bug_trap(struct pt_regs *regs) +{ + struct bug_entry *bug; + unsigned long addr; + + if (regs->msr & MSR_PR) + return 0; /* not in kernel */ + addr = regs->nip; /* address of trap instruction */ + if (addr < PAGE_OFFSET) + return 0; + bug = find_bug(regs->nip); + if (bug == NULL) + return 0; + if (bug->line & BUG_WARNING_TRAP) { + /* this is a WARN_ON rather than BUG/BUG_ON */ + printk(KERN_ERR "Badness in %s at %s:%ld\n", + bug->function, bug->file, + bug->line & ~BUG_WARNING_TRAP); + dump_stack(); + return 1; + } + printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", + bug->function, bug->file, bug->line); + + return 0; } void __kprobes program_check_exception(struct pt_regs *regs) @@ -738,8 +782,6 @@ void __kprobes program_check_exception(struct pt_regs *regs) unsigned int reason = get_reason(regs); extern int do_mathemu(struct pt_regs *regs); - /* We can now get here via a FP Unavailable exception if the core - * has no FPU, in that case no reason flags will be set */ #ifdef CONFIG_MATH_EMULATION /* (reason & REASON_ILLEGAL) would be the obvious thing here, * but there seems to be a hardware bug on the 405GP (RevD) @@ -766,9 +808,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) return; if (debugger_bpt(regs)) return; - - if (!(regs->msr & MSR_PR) && /* not user-mode */ - report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) { + if (check_bug_trap(regs)) { regs->nip += 4; return; } diff --git a/trunk/arch/powerpc/kernel/vmlinux.lds.S b/trunk/arch/powerpc/kernel/vmlinux.lds.S index 04b8e71bf5b0..04b98671a060 100644 --- a/trunk/arch/powerpc/kernel/vmlinux.lds.S +++ b/trunk/arch/powerpc/kernel/vmlinux.lds.S @@ -62,7 +62,11 @@ SECTIONS __stop___ex_table = .; } - BUG_TABLE + __bug_table : { + __start___bug_table = .; + *(__bug_table) + __stop___bug_table = .; + } /* * Init sections discarded at runtime diff --git a/trunk/arch/powerpc/mm/imalloc.c b/trunk/arch/powerpc/mm/imalloc.c index c831815c31f0..add8c1a9af68 100644 --- a/trunk/arch/powerpc/mm/imalloc.c +++ b/trunk/arch/powerpc/mm/imalloc.c @@ -138,7 +138,7 @@ static struct vm_struct * split_im_region(unsigned long v_addr, struct vm_struct *vm2 = NULL; struct vm_struct *new_vm = NULL; - vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL); + vm1 = (struct vm_struct *) kmalloc(sizeof(*vm1), GFP_KERNEL); if (vm1 == NULL) { printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); return NULL; @@ -172,7 +172,7 @@ static struct vm_struct * split_im_region(unsigned long v_addr, * uppermost remainder, and use existing parent one for the * lower remainder of parent range */ - vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL); + vm2 = (struct vm_struct *) kmalloc(sizeof(*vm2), GFP_KERNEL); if (vm2 == NULL) { printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); kfree(vm1); @@ -206,7 +206,7 @@ static struct vm_struct * __add_new_im_area(unsigned long req_addr, break; } - area = kmalloc(sizeof(*area), GFP_KERNEL); + area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); if (!area) return NULL; area->flags = 0; diff --git a/trunk/arch/powerpc/mm/numa.c b/trunk/arch/powerpc/mm/numa.c index 262790910ff2..9da01dc8cfd9 100644 --- a/trunk/arch/powerpc/mm/numa.c +++ b/trunk/arch/powerpc/mm/numa.c @@ -295,63 +295,6 @@ static unsigned long __init numa_enforce_memory_limit(unsigned long start, return lmb_end_of_DRAM() - start; } -/* - * Extract NUMA information from the ibm,dynamic-reconfiguration-memory - * node. This assumes n_mem_{addr,size}_cells have been set. - */ -static void __init parse_drconf_memory(struct device_node *memory) -{ - const unsigned int *lm, *dm, *aa; - unsigned int ls, ld, la; - unsigned int n, aam, aalen; - unsigned long lmb_size, size; - int nid, default_nid = 0; - unsigned int start, ai, flags; - - lm = get_property(memory, "ibm,lmb-size", &ls); - dm = get_property(memory, "ibm,dynamic-memory", &ld); - aa = get_property(memory, "ibm,associativity-lookup-arrays", &la); - if (!lm || !dm || !aa || - ls < sizeof(unsigned int) || ld < sizeof(unsigned int) || - la < 2 * sizeof(unsigned int)) - return; - - lmb_size = read_n_cells(n_mem_size_cells, &lm); - n = *dm++; /* number of LMBs */ - aam = *aa++; /* number of associativity lists */ - aalen = *aa++; /* length of each associativity list */ - if (ld < (n * (n_mem_addr_cells + 4) + 1) * sizeof(unsigned int) || - la < (aam * aalen + 2) * sizeof(unsigned int)) - return; - - for (; n != 0; --n) { - start = read_n_cells(n_mem_addr_cells, &dm); - ai = dm[2]; - flags = dm[3]; - dm += 4; - /* 0x80 == reserved, 0x8 = assigned to us */ - if ((flags & 0x80) || !(flags & 0x8)) - continue; - nid = default_nid; - /* flags & 0x40 means associativity index is invalid */ - if (min_common_depth > 0 && min_common_depth <= aalen && - (flags & 0x40) == 0 && ai < aam) { - /* this is like of_node_to_nid_single */ - nid = aa[ai * aalen + min_common_depth - 1]; - if (nid == 0xffff || nid >= MAX_NUMNODES) - nid = default_nid; - } - node_set_online(nid); - - size = numa_enforce_memory_limit(start, lmb_size); - if (!size) - continue; - - add_active_range(nid, start >> PAGE_SHIFT, - (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT)); - } -} - static int __init parse_numa_properties(void) { struct device_node *cpu = NULL; @@ -442,14 +385,6 @@ static int __init parse_numa_properties(void) goto new_range; } - /* - * Now do the same thing for each LMB listed in the ibm,dynamic-memory - * property in the ibm,dynamic-reconfiguration-memory node. - */ - memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); - if (memory) - parse_drconf_memory(memory); - return 0; } diff --git a/trunk/arch/powerpc/platforms/4xx/Kconfig b/trunk/arch/powerpc/platforms/4xx/Kconfig index 2f2a13ed7667..ed39d6a3d22a 100644 --- a/trunk/arch/powerpc/platforms/4xx/Kconfig +++ b/trunk/arch/powerpc/platforms/4xx/Kconfig @@ -179,7 +179,7 @@ config BIOS_FIXUP # OAK doesn't exist but wanted to keep this around for any future 403GCX boards config 403GCX bool - depends on OAK + depends OAK default y config 405EP diff --git a/trunk/arch/powerpc/platforms/52xx/lite5200.c b/trunk/arch/powerpc/platforms/52xx/lite5200.c index eaff71e74fb0..a375c15b4315 100644 --- a/trunk/arch/powerpc/platforms/52xx/lite5200.c +++ b/trunk/arch/powerpc/platforms/52xx/lite5200.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include diff --git a/trunk/arch/powerpc/platforms/cell/cbe_thermal.c b/trunk/arch/powerpc/platforms/cell/cbe_thermal.c index 70e0d968d30f..616a0a3fd0e2 100644 --- a/trunk/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/trunk/arch/powerpc/platforms/cell/cbe_thermal.c @@ -115,7 +115,6 @@ static struct sysdev_attribute attr_spu_temperature = { static struct attribute *spu_attributes[] = { &attr_spu_temperature.attr, - NULL, }; static struct attribute_group spu_attribute_group = { @@ -136,7 +135,6 @@ static struct sysdev_attribute attr_ppe_temperature1 = { static struct attribute *ppe_attributes[] = { &attr_ppe_temperature0.attr, &attr_ppe_temperature1.attr, - NULL, }; static struct attribute_group ppe_attribute_group = { diff --git a/trunk/arch/powerpc/platforms/cell/pmu.c b/trunk/arch/powerpc/platforms/cell/pmu.c index d04ae1671e6c..99c612025e8f 100644 --- a/trunk/arch/powerpc/platforms/cell/pmu.c +++ b/trunk/arch/powerpc/platforms/cell/pmu.c @@ -382,14 +382,11 @@ static irqreturn_t cbe_pm_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init cbe_init_pm_irq(void) +int __init cbe_init_pm_irq(void) { unsigned int irq; int rc, node; - if (!machine_is(cell)) - return 0; - for_each_node(node) { irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI | (node << IIC_IRQ_NODE_SHIFT)); diff --git a/trunk/arch/powerpc/platforms/cell/spufs/coredump.c b/trunk/arch/powerpc/platforms/cell/spufs/coredump.c index 725e19561159..26945c491f6b 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/coredump.c @@ -147,7 +147,7 @@ static int spufs_arch_notes_size(void) struct fdtable *fdt = files_fdtable(current->files); int size = 0, fd; - for (fd = 0; fd < fdt->max_fds; fd++) { + for (fd = 0; fd < fdt->max_fdset && fd < fdt->max_fds; fd++) { if (FD_ISSET(fd, fdt->open_fds)) { struct file *file = fcheck(fd); diff --git a/trunk/arch/powerpc/platforms/embedded6xx/Kconfig b/trunk/arch/powerpc/platforms/embedded6xx/Kconfig index b3c2ce4cb7a8..ddbe398fbd48 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/trunk/arch/powerpc/platforms/embedded6xx/Kconfig @@ -35,7 +35,7 @@ config HDPU Select HDPU if configuring a Sky Computers Compute Blade. config HDPU_FEATURES - depends on HDPU + depends HDPU tristate "HDPU-Features" help Select to enable HDPU enhanced features. diff --git a/trunk/arch/powerpc/platforms/maple/pci.c b/trunk/arch/powerpc/platforms/maple/pci.c index 3f6a69f67195..3a32deda765d 100644 --- a/trunk/arch/powerpc/platforms/maple/pci.c +++ b/trunk/arch/powerpc/platforms/maple/pci.c @@ -562,7 +562,7 @@ void __init maple_pci_init(void) for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { if (np->name == NULL) continue; - if (!strcmp(np->name, "pci") || !strcmp(np->name, "pcie")) { + if (strcmp(np->name, "pci") == 0) { if (add_bridge(np) == 0) of_node_get(np); } diff --git a/trunk/arch/powerpc/platforms/maple/setup.c b/trunk/arch/powerpc/platforms/maple/setup.c index f12d5c69e74d..094989d50bab 100644 --- a/trunk/arch/powerpc/platforms/maple/setup.c +++ b/trunk/arch/powerpc/platforms/maple/setup.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include "maple.h" @@ -167,16 +166,6 @@ struct smp_ops_t maple_smp_ops = { }; #endif /* CONFIG_SMP */ -static void __init maple_use_rtas_reboot_and_halt_if_present(void) -{ - if (rtas_service_present("system-reboot") && - rtas_service_present("power-off")) { - ppc_md.restart = rtas_restart; - ppc_md.power_off = rtas_power_off; - ppc_md.halt = rtas_halt; - } -} - void __init maple_setup_arch(void) { /* init to some ~sane value until calibrate_delay() runs */ @@ -192,7 +181,6 @@ void __init maple_setup_arch(void) #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif - maple_use_rtas_reboot_and_halt_if_present(); printk(KERN_DEBUG "Using native/NAP idle loop\n"); } diff --git a/trunk/arch/powerpc/platforms/ps3/Kconfig b/trunk/arch/powerpc/platforms/ps3/Kconfig index de52ec4e9e58..451bfcd5502e 100644 --- a/trunk/arch/powerpc/platforms/ps3/Kconfig +++ b/trunk/arch/powerpc/platforms/ps3/Kconfig @@ -40,15 +40,4 @@ config PS3_USE_LPAR_ADDR If you have any doubt, choose the default y. -config PS3_VUART - depends on PPC_PS3 - bool "PS3 Virtual UART support" - default y - help - Include support for the PS3 Virtual UART. - - This support is required for several system services - including the System Manager and AV Settings. In - general, all users will say Y. - endmenu diff --git a/trunk/arch/powerpc/platforms/pseries/Makefile b/trunk/arch/powerpc/platforms/pseries/Makefile index 69590fbf83da..997243a91be8 100644 --- a/trunk/arch/powerpc/platforms/pseries/Makefile +++ b/trunk/arch/powerpc/platforms/pseries/Makefile @@ -10,8 +10,6 @@ obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o - obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_HVCS) += hvcserver.o obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o diff --git a/trunk/arch/powerpc/platforms/pseries/eeh.c b/trunk/arch/powerpc/platforms/pseries/eeh.c index da6e5362e7cd..3c2d63ebf787 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh.c @@ -337,7 +337,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n", pdn->eeh_check_count); dump_stack(); - msleep(5000); /* re-read the slot reset state */ if (read_slot_reset_state(pdn, rets) != 0) diff --git a/trunk/arch/powerpc/platforms/pseries/eeh_cache.c b/trunk/arch/powerpc/platforms/pseries/eeh_cache.c index f2bae04424f8..b6b462d3c604 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh_cache.c @@ -153,7 +153,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, return piar; } } - piar = kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC); + piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC); if (!piar) return NULL; diff --git a/trunk/arch/powerpc/platforms/pseries/eeh_driver.c b/trunk/arch/powerpc/platforms/pseries/eeh_driver.c index cbd6b0711ab4..c2bc9904f1cb 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh_driver.c @@ -170,19 +170,14 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata) static void eeh_report_resume(struct pci_dev *dev, void *userdata) { struct pci_driver *driver = dev->driver; - struct device_node *dn = pci_device_to_OF_node(dev); dev->error_state = pci_channel_io_normal; if (!driver) return; - - if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) { - PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED; - enable_irq(dev->irq); - } - if (!driver->err_handler || - !driver->err_handler->resume) + if (!driver->err_handler) + return; + if (!driver->err_handler->resume) return; driver->err_handler->resume(dev); @@ -412,8 +407,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) if (rc) result = PCI_ERS_RESULT_NEED_RESET; - else - result = PCI_ERS_RESULT_RECOVERED; } /* If any device has a hard failure, then shut off everything. */ diff --git a/trunk/arch/powerpc/platforms/pseries/hotplug-cpu.c b/trunk/arch/powerpc/platforms/pseries/hotplug-cpu.c deleted file mode 100644 index f460b9cbfd46..000000000000 --- a/trunk/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * pseries CPU Hotplug infrastructure. - * - * Split out from arch/powerpc/platforms/pseries/setup.c - * arch/powerpc/kernel/rtas.c, and arch/powerpc/platforms/pseries/smp.c - * - * Peter Bergner, IBM March 2001. - * Copyright (C) 2001 IBM. - * Dave Engebretsen, Peter Bergner, and - * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com - * Plus various changes from other IBM teams... - * - * Copyright (C) 2006 Michael Ellerman, IBM Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "xics.h" - -/* This version can't take the spinlock, because it never returns */ -static struct rtas_args rtas_stop_self_args = { - .token = RTAS_UNKNOWN_SERVICE, - .nargs = 0, - .nret = 1, - .rets = &rtas_stop_self_args.args[0], -}; - -static void rtas_stop_self(void) -{ - struct rtas_args *args = &rtas_stop_self_args; - - local_irq_disable(); - - BUG_ON(args->token == RTAS_UNKNOWN_SERVICE); - - printk("cpu %u (hwid %u) Ready to die...\n", - smp_processor_id(), hard_smp_processor_id()); - enter_rtas(__pa(args)); - - panic("Alas, I survived.\n"); -} - -static void pseries_mach_cpu_die(void) -{ - local_irq_disable(); - idle_task_exit(); - xics_teardown_cpu(0); - rtas_stop_self(); - /* Should never get here... */ - BUG(); - for(;;); -} - -static int qcss_tok; /* query-cpu-stopped-state token */ - -/* Get state of physical CPU. - * Return codes: - * 0 - The processor is in the RTAS stopped state - * 1 - stop-self is in progress - * 2 - The processor is not in the RTAS stopped state - * -1 - Hardware Error - * -2 - Hardware Busy, Try again later. - */ -static int query_cpu_stopped(unsigned int pcpu) -{ - int cpu_status, status; - - status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu); - if (status != 0) { - printk(KERN_ERR - "RTAS query-cpu-stopped-state failed: %i\n", status); - return status; - } - - return cpu_status; -} - -static int pseries_cpu_disable(void) -{ - int cpu = smp_processor_id(); - - cpu_clear(cpu, cpu_online_map); - vdso_data->processorCount--; - - /*fix boot_cpuid here*/ - if (cpu == boot_cpuid) - boot_cpuid = any_online_cpu(cpu_online_map); - - /* FIXME: abstract this to not be platform specific later on */ - xics_migrate_irqs_away(); - return 0; -} - -static void pseries_cpu_die(unsigned int cpu) -{ - int tries; - int cpu_status; - unsigned int pcpu = get_hard_smp_processor_id(cpu); - - for (tries = 0; tries < 25; tries++) { - cpu_status = query_cpu_stopped(pcpu); - if (cpu_status == 0 || cpu_status == -1) - break; - msleep(200); - } - if (cpu_status != 0) { - printk("Querying DEAD? cpu %i (%i) shows %i\n", - cpu, pcpu, cpu_status); - } - - /* Isolation and deallocation are definatly done by - * drslot_chrp_cpu. If they were not they would be - * done here. Change isolate state to Isolate and - * change allocation-state to Unusable. - */ - paca[cpu].cpu_start = 0; -} - -/* - * Update cpu_present_map and paca(s) for a new cpu node. The wrinkle - * here is that a cpu device node may represent up to two logical cpus - * in the SMT case. We must honor the assumption in other code that - * the logical ids for sibling SMT threads x and y are adjacent, such - * that x^1 == y and y^1 == x. - */ -static int pseries_add_processor(struct device_node *np) -{ - unsigned int cpu; - cpumask_t candidate_map, tmp = CPU_MASK_NONE; - int err = -ENOSPC, len, nthreads, i; - const u32 *intserv; - - intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); - if (!intserv) - return 0; - - nthreads = len / sizeof(u32); - for (i = 0; i < nthreads; i++) - cpu_set(i, tmp); - - lock_cpu_hotplug(); - - BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map)); - - /* Get a bitmap of unoccupied slots. */ - cpus_xor(candidate_map, cpu_possible_map, cpu_present_map); - if (cpus_empty(candidate_map)) { - /* If we get here, it most likely means that NR_CPUS is - * less than the partition's max processors setting. - */ - printk(KERN_ERR "Cannot add cpu %s; this system configuration" - " supports %d logical cpus.\n", np->full_name, - cpus_weight(cpu_possible_map)); - goto out_unlock; - } - - while (!cpus_empty(tmp)) - if (cpus_subset(tmp, candidate_map)) - /* Found a range where we can insert the new cpu(s) */ - break; - else - cpus_shift_left(tmp, tmp, nthreads); - - if (cpus_empty(tmp)) { - printk(KERN_ERR "Unable to find space in cpu_present_map for" - " processor %s with %d thread(s)\n", np->name, - nthreads); - goto out_unlock; - } - - for_each_cpu_mask(cpu, tmp) { - BUG_ON(cpu_isset(cpu, cpu_present_map)); - cpu_set(cpu, cpu_present_map); - set_hard_smp_processor_id(cpu, *intserv++); - } - err = 0; -out_unlock: - unlock_cpu_hotplug(); - return err; -} - -/* - * Update the present map for a cpu node which is going away, and set - * the hard id in the paca(s) to -1 to be consistent with boot time - * convention for non-present cpus. - */ -static void pseries_remove_processor(struct device_node *np) -{ - unsigned int cpu; - int len, nthreads, i; - const u32 *intserv; - - intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); - if (!intserv) - return; - - nthreads = len / sizeof(u32); - - lock_cpu_hotplug(); - for (i = 0; i < nthreads; i++) { - for_each_present_cpu(cpu) { - if (get_hard_smp_processor_id(cpu) != intserv[i]) - continue; - BUG_ON(cpu_online(cpu)); - cpu_clear(cpu, cpu_present_map); - set_hard_smp_processor_id(cpu, -1); - break; - } - if (cpu == NR_CPUS) - printk(KERN_WARNING "Could not find cpu to remove " - "with physical id 0x%x\n", intserv[i]); - } - unlock_cpu_hotplug(); -} - -static int pseries_smp_notifier(struct notifier_block *nb, - unsigned long action, void *node) -{ - int err = NOTIFY_OK; - - switch (action) { - case PSERIES_RECONFIG_ADD: - if (pseries_add_processor(node)) - err = NOTIFY_BAD; - break; - case PSERIES_RECONFIG_REMOVE: - pseries_remove_processor(node); - break; - default: - err = NOTIFY_DONE; - break; - } - return err; -} - -static struct notifier_block pseries_smp_nb = { - .notifier_call = pseries_smp_notifier, -}; - -static int __init pseries_cpu_hotplug_init(void) -{ - rtas_stop_self_args.token = rtas_token("stop-self"); - qcss_tok = rtas_token("query-cpu-stopped-state"); - - if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE || - qcss_tok == RTAS_UNKNOWN_SERVICE) { - printk(KERN_INFO "CPU Hotplug not supported by firmware " - "- disabling.\n"); - return 0; - } - - ppc_md.cpu_die = pseries_mach_cpu_die; - smp_ops->cpu_disable = pseries_cpu_disable; - smp_ops->cpu_die = pseries_cpu_die; - - /* Processors can be added/removed only on LPAR */ - if (firmware_has_feature(FW_FEATURE_LPAR)) - pSeries_reconfig_notifier_register(&pseries_smp_nb); - - return 0; -} -arch_initcall(pseries_cpu_hotplug_init); diff --git a/trunk/arch/powerpc/platforms/pseries/setup.c b/trunk/arch/powerpc/platforms/pseries/setup.c index 042ecae107ac..0dc2548ca9bc 100644 --- a/trunk/arch/powerpc/platforms/pseries/setup.c +++ b/trunk/arch/powerpc/platforms/pseries/setup.c @@ -347,6 +347,21 @@ static int __init pSeries_init_panel(void) } arch_initcall(pSeries_init_panel); +#ifdef CONFIG_HOTPLUG_CPU +static void pSeries_mach_cpu_die(void) +{ + local_irq_disable(); + idle_task_exit(); + xics_teardown_cpu(0); + rtas_stop_self(); + /* Should never get here... */ + BUG(); + for(;;); +} +#else +#define pSeries_mach_cpu_die NULL +#endif + static int pseries_set_dabr(unsigned long dabr) { return plpar_hcall_norets(H_SET_DABR, dabr); @@ -422,14 +437,19 @@ static int __init pSeries_probe_hypertas(unsigned long node, if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL) powerpc_firmware_features |= FW_FEATURE_LPAR; + if (firmware_has_feature(FW_FEATURE_LPAR)) + hpte_init_lpar(); + else + hpte_init_native(); + return 1; } static int __init pSeries_probe(void) { unsigned long root = of_get_flat_dt_root(); - char *dtype = of_get_flat_dt_prop(root, "device_type", NULL); - + char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), + "device_type", NULL); if (dtype == NULL) return 0; if (strcmp(dtype, "chrp")) @@ -447,11 +467,6 @@ static int __init pSeries_probe(void) /* Now try to figure out if we are running on LPAR */ of_scan_flat_dt(pSeries_probe_hypertas, NULL); - if (firmware_has_feature(FW_FEATURE_LPAR)) - hpte_init_lpar(); - else - hpte_init_native(); - DBG("Machine is%s LPAR !\n", (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); @@ -546,6 +561,7 @@ define_machine(pseries) { .power_off = rtas_power_off, .halt = rtas_halt, .panic = rtas_os_term, + .cpu_die = pSeries_mach_cpu_die, .get_boot_time = rtas_get_boot_time, .get_rtc_time = rtas_get_rtc_time, .set_rtc_time = rtas_set_rtc_time, diff --git a/trunk/arch/powerpc/platforms/pseries/smp.c b/trunk/arch/powerpc/platforms/pseries/smp.c index 4408518eaebe..c6624b8a0e77 100644 --- a/trunk/arch/powerpc/platforms/pseries/smp.c +++ b/trunk/arch/powerpc/platforms/pseries/smp.c @@ -64,6 +64,197 @@ static cpumask_t of_spin_map; extern void generic_secondary_smp_init(unsigned long); +#ifdef CONFIG_HOTPLUG_CPU + +/* Get state of physical CPU. + * Return codes: + * 0 - The processor is in the RTAS stopped state + * 1 - stop-self is in progress + * 2 - The processor is not in the RTAS stopped state + * -1 - Hardware Error + * -2 - Hardware Busy, Try again later. + */ +static int query_cpu_stopped(unsigned int pcpu) +{ + int cpu_status; + int status, qcss_tok; + + qcss_tok = rtas_token("query-cpu-stopped-state"); + if (qcss_tok == RTAS_UNKNOWN_SERVICE) + return -1; + status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu); + if (status != 0) { + printk(KERN_ERR + "RTAS query-cpu-stopped-state failed: %i\n", status); + return status; + } + + return cpu_status; +} + +static int pSeries_cpu_disable(void) +{ + int cpu = smp_processor_id(); + + cpu_clear(cpu, cpu_online_map); + vdso_data->processorCount--; + + /*fix boot_cpuid here*/ + if (cpu == boot_cpuid) + boot_cpuid = any_online_cpu(cpu_online_map); + + /* FIXME: abstract this to not be platform specific later on */ + xics_migrate_irqs_away(); + return 0; +} + +static void pSeries_cpu_die(unsigned int cpu) +{ + int tries; + int cpu_status; + unsigned int pcpu = get_hard_smp_processor_id(cpu); + + for (tries = 0; tries < 25; tries++) { + cpu_status = query_cpu_stopped(pcpu); + if (cpu_status == 0 || cpu_status == -1) + break; + msleep(200); + } + if (cpu_status != 0) { + printk("Querying DEAD? cpu %i (%i) shows %i\n", + cpu, pcpu, cpu_status); + } + + /* Isolation and deallocation are definatly done by + * drslot_chrp_cpu. If they were not they would be + * done here. Change isolate state to Isolate and + * change allocation-state to Unusable. + */ + paca[cpu].cpu_start = 0; +} + +/* + * Update cpu_present_map and paca(s) for a new cpu node. The wrinkle + * here is that a cpu device node may represent up to two logical cpus + * in the SMT case. We must honor the assumption in other code that + * the logical ids for sibling SMT threads x and y are adjacent, such + * that x^1 == y and y^1 == x. + */ +static int pSeries_add_processor(struct device_node *np) +{ + unsigned int cpu; + cpumask_t candidate_map, tmp = CPU_MASK_NONE; + int err = -ENOSPC, len, nthreads, i; + const u32 *intserv; + + intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); + if (!intserv) + return 0; + + nthreads = len / sizeof(u32); + for (i = 0; i < nthreads; i++) + cpu_set(i, tmp); + + lock_cpu_hotplug(); + + BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map)); + + /* Get a bitmap of unoccupied slots. */ + cpus_xor(candidate_map, cpu_possible_map, cpu_present_map); + if (cpus_empty(candidate_map)) { + /* If we get here, it most likely means that NR_CPUS is + * less than the partition's max processors setting. + */ + printk(KERN_ERR "Cannot add cpu %s; this system configuration" + " supports %d logical cpus.\n", np->full_name, + cpus_weight(cpu_possible_map)); + goto out_unlock; + } + + while (!cpus_empty(tmp)) + if (cpus_subset(tmp, candidate_map)) + /* Found a range where we can insert the new cpu(s) */ + break; + else + cpus_shift_left(tmp, tmp, nthreads); + + if (cpus_empty(tmp)) { + printk(KERN_ERR "Unable to find space in cpu_present_map for" + " processor %s with %d thread(s)\n", np->name, + nthreads); + goto out_unlock; + } + + for_each_cpu_mask(cpu, tmp) { + BUG_ON(cpu_isset(cpu, cpu_present_map)); + cpu_set(cpu, cpu_present_map); + set_hard_smp_processor_id(cpu, *intserv++); + } + err = 0; +out_unlock: + unlock_cpu_hotplug(); + return err; +} + +/* + * Update the present map for a cpu node which is going away, and set + * the hard id in the paca(s) to -1 to be consistent with boot time + * convention for non-present cpus. + */ +static void pSeries_remove_processor(struct device_node *np) +{ + unsigned int cpu; + int len, nthreads, i; + const u32 *intserv; + + intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); + if (!intserv) + return; + + nthreads = len / sizeof(u32); + + lock_cpu_hotplug(); + for (i = 0; i < nthreads; i++) { + for_each_present_cpu(cpu) { + if (get_hard_smp_processor_id(cpu) != intserv[i]) + continue; + BUG_ON(cpu_online(cpu)); + cpu_clear(cpu, cpu_present_map); + set_hard_smp_processor_id(cpu, -1); + break; + } + if (cpu == NR_CPUS) + printk(KERN_WARNING "Could not find cpu to remove " + "with physical id 0x%x\n", intserv[i]); + } + unlock_cpu_hotplug(); +} + +static int pSeries_smp_notifier(struct notifier_block *nb, unsigned long action, void *node) +{ + int err = NOTIFY_OK; + + switch (action) { + case PSERIES_RECONFIG_ADD: + if (pSeries_add_processor(node)) + err = NOTIFY_BAD; + break; + case PSERIES_RECONFIG_REMOVE: + pSeries_remove_processor(node); + break; + default: + err = NOTIFY_DONE; + break; + } + return err; +} + +static struct notifier_block pSeries_smp_nb = { + .notifier_call = pSeries_smp_notifier, +}; + +#endif /* CONFIG_HOTPLUG_CPU */ + /** * smp_startup_cpu() - start the given cpu * @@ -231,6 +422,15 @@ static void __init smp_init_pseries(void) DBG(" -> smp_init_pSeries()\n"); +#ifdef CONFIG_HOTPLUG_CPU + smp_ops->cpu_disable = pSeries_cpu_disable; + smp_ops->cpu_die = pSeries_cpu_die; + + /* Processors can be added/removed only on LPAR */ + if (firmware_has_feature(FW_FEATURE_LPAR)) + pSeries_reconfig_notifier_register(&pSeries_smp_nb); +#endif + /* Mark threads which are still spinning in hold loops. */ if (cpu_has_feature(CPU_FTR_SMT)) { for_each_present_cpu(i) { diff --git a/trunk/arch/powerpc/sysdev/Makefile b/trunk/arch/powerpc/sysdev/Makefile index 04d4917eb303..6cc34597a620 100644 --- a/trunk/arch/powerpc/sysdev/Makefile +++ b/trunk/arch/powerpc/sysdev/Makefile @@ -5,8 +5,7 @@ endif obj-$(CONFIG_MPIC) += mpic.o obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPC_MPC106) += grackle.o -obj-$(CONFIG_PPC_DCR) += dcr.o -obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o +obj-$(CONFIG_PPC_DCR) += dcr.o dcr-low.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o diff --git a/trunk/arch/powerpc/sysdev/dcr.S b/trunk/arch/powerpc/sysdev/dcr.S new file mode 100644 index 000000000000..2078f39e2f17 --- /dev/null +++ b/trunk/arch/powerpc/sysdev/dcr.S @@ -0,0 +1,39 @@ +/* + * "Indirect" DCR access + * + * Copyright (c) 2004 Eugene Surovegin + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +#define DCR_ACCESS_PROLOG(table) \ + rlwinm r3,r3,4,18,27; \ + lis r5,table@h; \ + ori r5,r5,table@l; \ + add r3,r3,r5; \ + mtctr r3; \ + bctr + +_GLOBAL(__mfdcr) + DCR_ACCESS_PROLOG(__mfdcr_table) + +_GLOBAL(__mtdcr) + DCR_ACCESS_PROLOG(__mtdcr_table) + +__mfdcr_table: + mfdcr r3,0; blr +__mtdcr_table: + mtdcr 0,r4; blr + +dcr = 1 + .rept 1023 + mfdcr r3,dcr; blr + mtdcr dcr,r4; blr + dcr = dcr + 1 + .endr diff --git a/trunk/arch/powerpc/sysdev/qe_lib/qe_ic.c b/trunk/arch/powerpc/sysdev/qe_lib/qe_ic.c index 74e48d94f27c..6995f51b9488 100644 --- a/trunk/arch/powerpc/sysdev/qe_lib/qe_ic.c +++ b/trunk/arch/powerpc/sysdev/qe_lib/qe_ic.c @@ -223,15 +223,23 @@ static void qe_ic_mask_irq(unsigned int virq) qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg, temp & ~qe_ic_info[src].mask); - /* Flush the above write before enabling interrupts; otherwise, - * spurious interrupts will sometimes happen. To be 100% sure - * that the write has reached the device before interrupts are - * enabled, the mask register would have to be read back; however, - * this is not required for correctness, only to avoid wasting - * time on a large number of spurious interrupts. In testing, - * a sync reduced the observed spurious interrupts to zero. - */ - mb(); + spin_unlock_irqrestore(&qe_ic_lock, flags); +} + +static void qe_ic_mask_irq_and_ack(unsigned int virq) +{ + struct qe_ic *qe_ic = qe_ic_from_irq(virq); + unsigned int src = virq_to_hw(virq); + unsigned long flags; + u32 temp; + + spin_lock_irqsave(&qe_ic_lock, flags); + + temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg); + qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg, + temp & ~qe_ic_info[src].mask); + + /* There is nothing to do for ack here, ack is handled in ISR */ spin_unlock_irqrestore(&qe_ic_lock, flags); } @@ -240,7 +248,7 @@ static struct irq_chip qe_ic_irq_chip = { .typename = " QEIC ", .unmask = qe_ic_unmask_irq, .mask = qe_ic_mask_irq, - .mask_ack = qe_ic_mask_irq, + .mask_ack = qe_ic_mask_irq_and_ack, }; static int qe_ic_host_match(struct irq_host *h, struct device_node *node) @@ -323,22 +331,34 @@ unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) return irq_linear_revmap(qe_ic->irqhost, irq); } +/* FIXME: We mask all the QE Low interrupts while handling. We should + * let other interrupt come in, but BAD interrupts are generated */ void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc) { struct qe_ic *qe_ic = desc->handler_data; + struct irq_chip *chip = irq_desc[irq].chip; + unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic); + chip->mask_ack(irq); if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); + chip->unmask(irq); } +/* FIXME: We mask all the QE High interrupts while handling. We should + * let other interrupt come in, but BAD interrupts are generated */ void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc) { struct qe_ic *qe_ic = desc->handler_data; + struct irq_chip *chip = irq_desc[irq].chip; + unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic); + chip->mask_ack(irq); if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); + chip->unmask(irq); } void __init qe_ic_init(struct device_node *node, unsigned int flags) diff --git a/trunk/arch/powerpc/sysdev/rom.c b/trunk/arch/powerpc/sysdev/rom.c index c855a3b298a3..bf5b3f10e6c6 100644 --- a/trunk/arch/powerpc/sysdev/rom.c +++ b/trunk/arch/powerpc/sysdev/rom.c @@ -9,7 +9,6 @@ #include #include -#include static int __init powerpc_flash_init(void) { diff --git a/trunk/arch/powerpc/xmon/xmon.c b/trunk/arch/powerpc/xmon/xmon.c index 77540a2f7704..a34ed49e0356 100644 --- a/trunk/arch/powerpc/xmon/xmon.c +++ b/trunk/arch/powerpc/xmon/xmon.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -1346,7 +1346,7 @@ static void backtrace(struct pt_regs *excp) static void print_bug_trap(struct pt_regs *regs) { - const struct bug_entry *bug; + struct bug_entry *bug; unsigned long addr; if (regs->msr & MSR_PR) @@ -1357,11 +1357,11 @@ static void print_bug_trap(struct pt_regs *regs) bug = find_bug(regs->nip); if (bug == NULL) return; - if (is_warning_bug(bug)) + if (bug->line & BUG_WARNING_TRAP) return; - printf("kernel BUG at %s:%u!\n", - bug->file, bug->line); + printf("kernel BUG in %s at %s:%d!\n", + bug->function, bug->file, (unsigned int)bug->line); } void excprint(struct pt_regs *fp) diff --git a/trunk/arch/ppc/8260_io/fcc_enet.c b/trunk/arch/ppc/8260_io/fcc_enet.c index 06b84c372e58..709952c25f29 100644 --- a/trunk/arch/ppc/8260_io/fcc_enet.c +++ b/trunk/arch/ppc/8260_io/fcc_enet.c @@ -1892,10 +1892,10 @@ init_fcc_param(fcc_info_t *fip, struct net_device *dev, /* Allocate space for the buffer descriptors from regular memory. * Initialize base addresses for the buffer descriptors. */ - cep->rx_bd_base = kmalloc(sizeof(cbd_t) * RX_RING_SIZE, + cep->rx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * RX_RING_SIZE, GFP_KERNEL | GFP_DMA); ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base); - cep->tx_bd_base = kmalloc(sizeof(cbd_t) * TX_RING_SIZE, + cep->tx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * TX_RING_SIZE, GFP_KERNEL | GFP_DMA); ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base); diff --git a/trunk/arch/ppc/8xx_io/cs4218_tdm.c b/trunk/arch/ppc/8xx_io/cs4218_tdm.c index b7bb5f0b3c5f..c71ef3c2e7bf 100644 --- a/trunk/arch/ppc/8xx_io/cs4218_tdm.c +++ b/trunk/arch/ppc/8xx_io/cs4218_tdm.c @@ -2601,7 +2601,7 @@ int __init tdm8xx_sound_init(void) /* Initialize beep stuff */ orig_mksound = kd_mksound; kd_mksound = cs_mksound; - beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); + beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); if (beep_buf == NULL) printk(KERN_WARNING "dmasound: no memory for " "beep buffer\n"); diff --git a/trunk/arch/ppc/Kconfig b/trunk/arch/ppc/Kconfig index 8eb82efe05a1..692b5ba53209 100644 --- a/trunk/arch/ppc/Kconfig +++ b/trunk/arch/ppc/Kconfig @@ -624,7 +624,7 @@ config HDPU Select HDPU if configuring a Sky Computers Compute Blade. config HDPU_FEATURES - depends on HDPU + depends HDPU tristate "HDPU-Features" help Select to enable HDPU enhanced features. @@ -735,7 +735,7 @@ config LITE5200 config LITE5200B bool "Freescale LITE5200B" - depends on LITE5200 + depends LITE5200 help Support for the LITE5200B dev board for the MPC5200 from Freescale. This is the new board with 2 PCI slots. diff --git a/trunk/arch/ppc/kernel/pci.c b/trunk/arch/ppc/kernel/pci.c index 5e723c4c2571..63808e01cb0b 100644 --- a/trunk/arch/ppc/kernel/pci.c +++ b/trunk/arch/ppc/kernel/pci.c @@ -879,7 +879,7 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, - resource_size_t *offset, + unsigned long *offset, enum pci_mmap_state mmap_state) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); @@ -891,9 +891,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, /* If memory, add on the PCI bridge address offset */ if (mmap_state == pci_mmap_mem) { -#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ *offset += hose->pci_mem_offset; -#endif res_bit = IORESOURCE_MEM; } else { io_offset = hose->io_base_virt - ___IO_BASE; @@ -1032,7 +1030,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { - resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct resource *rp; int ret; @@ -1134,42 +1132,21 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, resource_size_t *start, resource_size_t *end) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); - resource_size_t offset = 0; + unsigned long offset = 0; if (hose == NULL) return; if (rsrc->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - _IO_BASE; - - /* We pass a fully fixed up address to userland for MMIO instead of - * a BAR value because X is lame and expects to be able to use that - * to pass to /dev/mem ! - * - * That means that we'll have potentially 64 bits values where some - * userland apps only expect 32 (like X itself since it thinks only - * Sparc has 64 bits MMIO) but if we don't do that, we break it on - * 32 bits CHRPs :-( - * - * Hopefully, the sysfs insterface is immune to that gunk. Once X - * has been fixed (and the fix spread enough), we can re-enable the - * 2 lines below and pass down a BAR value to userland. In that case - * we'll also have to re-enable the matching code in - * __pci_mmap_make_offset(). - * - * BenH. - */ -#if 0 - else if (rsrc->flags & IORESOURCE_MEM) - offset = hose->pci_mem_offset; -#endif + offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; - *start = rsrc->start - offset; - *end = rsrc->end - offset; + *start = rsrc->start + offset; + *end = rsrc->end + offset; } -void __init pci_init_resource(struct resource *res, resource_size_t start, - resource_size_t end, int flags, char *name) +void __init +pci_init_resource(struct resource *res, unsigned long start, unsigned long end, + int flags, char *name) { res->start = start; res->end = end; diff --git a/trunk/arch/ppc/platforms/4xx/Kconfig b/trunk/arch/ppc/platforms/4xx/Kconfig index 6980de420e92..293bd489e7d9 100644 --- a/trunk/arch/ppc/platforms/4xx/Kconfig +++ b/trunk/arch/ppc/platforms/4xx/Kconfig @@ -189,7 +189,7 @@ config BIOS_FIXUP # OAK doesn't exist but wanted to keep this around for any future 403GCX boards config 403GCX bool - depends on OAK + depends OAK default y config 405EP diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index 12272361c018..ff690564edbd 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -407,7 +407,7 @@ config APPLDATA_BASE config APPLDATA_MEM tristate "Monitor memory management statistics" - depends on APPLDATA_BASE && VM_EVENT_COUNTERS + depends on APPLDATA_BASE help This provides memory management related data to the Linux - VM Monitor Stream, like paging/swapping rate, memory utilisation, etc. diff --git a/trunk/arch/s390/kernel/debug.c b/trunk/arch/s390/kernel/debug.c index bb57bc0e3fc8..ef5266fbce62 100644 --- a/trunk/arch/s390/kernel/debug.c +++ b/trunk/arch/s390/kernel/debug.c @@ -191,13 +191,13 @@ debug_areas_alloc(int pages_per_area, int nr_areas) debug_entry_t*** areas; int i,j; - areas = kmalloc(nr_areas * + areas = (debug_entry_t ***) kmalloc(nr_areas * sizeof(debug_entry_t**), GFP_KERNEL); if (!areas) goto fail_malloc_areas; for (i = 0; i < nr_areas; i++) { - areas[i] = kmalloc(pages_per_area * + areas[i] = (debug_entry_t**) kmalloc(pages_per_area * sizeof(debug_entry_t*),GFP_KERNEL); if (!areas[i]) { goto fail_malloc_areas2; @@ -242,7 +242,7 @@ debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size, /* alloc everything */ - rc = kmalloc(sizeof(debug_info_t), GFP_KERNEL); + rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_KERNEL); if(!rc) goto fail_malloc_rc; rc->active_entries = kcalloc(nr_areas, sizeof(int), GFP_KERNEL); @@ -634,7 +634,7 @@ debug_open(struct inode *inode, struct file *file) rc = -ENOMEM; goto out; } - p_info = kmalloc(sizeof(file_private_info_t), + p_info = (file_private_info_t *) kmalloc(sizeof(file_private_info_t), GFP_KERNEL); if(!p_info){ if(debug_info_snapshot) diff --git a/trunk/arch/s390/kernel/s390_ext.c b/trunk/arch/s390/kernel/s390_ext.c index bc5beaa8f98e..4faf96f8a834 100644 --- a/trunk/arch/s390/kernel/s390_ext.c +++ b/trunk/arch/s390/kernel/s390_ext.c @@ -37,7 +37,7 @@ int register_external_interrupt(__u16 code, ext_int_handler_t handler) ext_int_info_t *p; int index; - p = kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC); + p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC); if (p == NULL) return -ENOMEM; p->code = code; diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 3aa3b885ab36..8e24c40662e3 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -479,7 +479,7 @@ config SH_CLK_MD int "CPU Mode Pin Setting" depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206 help - MD2 - MD0 pin setting. + MD2 - MD0 Setting. menu "CPU Frequency scaling" @@ -580,6 +580,18 @@ config NR_CPUS source "kernel/Kconfig.preempt" +config CPU_HAS_SR_RB + bool "CPU has SR.RB" + depends on CPU_SH3 || CPU_SH4 + default y + help + This will enable the use of SR.RB register bank usage. Processors + that are lacking this bit must have another method in place for + accomplishing what is taken care of by the banked registers. + + See for further + information on SR.RB and register banking in the kernel in general. + config NODES_SHIFT int default "1" diff --git a/trunk/arch/sh/Kconfig.debug b/trunk/arch/sh/Kconfig.debug index 87902e0298e2..66a25ef4ef1b 100644 --- a/trunk/arch/sh/Kconfig.debug +++ b/trunk/arch/sh/Kconfig.debug @@ -31,8 +31,7 @@ config EARLY_SCIF_CONSOLE_PORT hex "SCIF port for early console" depends on EARLY_SCIF_CONSOLE default "0xffe00000" if CPU_SUBTYPE_SH7780 - default "0xfffe9800" if CPU_SUBTYPE_SH7206 - default "0xf8420000" if CPU_SUBTYPE_SH7619 + default "0xfffe9800" if CPU_SUBTYPE_SH72060 default "0xffe80000" if CPU_SH4 config EARLY_PRINTK diff --git a/trunk/arch/sh/Makefile b/trunk/arch/sh/Makefile index c1dbef212634..d10bba5e1074 100644 --- a/trunk/arch/sh/Makefile +++ b/trunk/arch/sh/Makefile @@ -179,7 +179,7 @@ maketools: include/linux/version.h FORCE all: zImage -zImage uImage uImage.srec vmlinux.srec: vmlinux +zImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ compressed: zImage @@ -190,8 +190,5 @@ archclean: CLEAN_FILES += include/asm-sh/machtypes.h define archhelp - @echo '* zImage - Compressed kernel image' - @echo ' vmlinux.srec - Create an ELF S-record' - @echo ' uImage - Create a bootable image for U-Boot' - @echo ' uImage.srec - Create an S-record for U-Boot' + @echo ' zImage - Compressed kernel image (arch/sh/boot/zImage)' endef diff --git a/trunk/arch/sh/boards/landisk/irq.c b/trunk/arch/sh/boards/landisk/irq.c index 3eba6d086d7f..8f2e1c68b90f 100644 --- a/trunk/arch/sh/boards/landisk/irq.c +++ b/trunk/arch/sh/boards/landisk/irq.c @@ -16,8 +16,8 @@ */ #include #include -#include -#include +#include +#include #include static void enable_landisk_irq(unsigned int irq); diff --git a/trunk/arch/sh/boards/se/7206/irq.c b/trunk/arch/sh/boards/se/7206/irq.c index 27da88486f73..3fb0c5f5b23a 100644 --- a/trunk/arch/sh/boards/se/7206/irq.c +++ b/trunk/arch/sh/boards/se/7206/irq.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #define INTSTS0 0x31800000 @@ -19,13 +18,6 @@ #define INTMSK1 0x31800006 #define INTSEL 0x31800008 -#define IRQ0_IRQ 64 -#define IRQ1_IRQ 65 -#define IRQ3_IRQ 67 - -#define INTC_IPR01 0xfffe0818 -#define INTC_ICR1 0xfffe0802 - static void disable_se7206_irq(unsigned int irq) { unsigned short val; @@ -47,7 +39,7 @@ static void disable_se7206_irq(unsigned int irq) case IRQ1_IRQ: msk0 |= 0x000f; break; - case IRQ3_IRQ: + case IRQ2_IRQ: msk0 |= 0x0f00; msk1 |= 0x00ff; break; @@ -78,7 +70,7 @@ static void enable_se7206_irq(unsigned int irq) case IRQ1_IRQ: msk0 &= ~0x000f; break; - case IRQ3_IRQ: + case IRQ2_IRQ: msk0 &= ~0x0f00; msk1 &= ~0x00ff; break; @@ -104,7 +96,7 @@ static void eoi_se7206_irq(unsigned int irq) case IRQ1_IRQ: sts0 &= ~0x000f; break; - case IRQ3_IRQ: + case IRQ2_IRQ: sts0 &= ~0x0f00; sts1 &= ~0x00ff; break; @@ -114,7 +106,7 @@ static void eoi_se7206_irq(unsigned int irq) } static struct irq_chip se7206_irq_chip __read_mostly = { - .name = "SE7206-FPGA", + .name = "SE7206-FPGA-IRQ", .mask = disable_se7206_irq, .unmask = enable_se7206_irq, .mask_ack = disable_se7206_irq, diff --git a/trunk/arch/sh/boards/se/7619/Makefile b/trunk/arch/sh/boards/se/7619/Makefile index d21775c28cda..3666eca8a658 100644 --- a/trunk/arch/sh/boards/se/7619/Makefile +++ b/trunk/arch/sh/boards/se/7619/Makefile @@ -2,4 +2,4 @@ # Makefile for the 7619 SolutionEngine specific parts of the kernel # -obj-y := setup.o +obj-y := setup.o io.o diff --git a/trunk/arch/sh/boards/se/7619/io.c b/trunk/arch/sh/boards/se/7619/io.c new file mode 100644 index 000000000000..176f1f39cd9d --- /dev/null +++ b/trunk/arch/sh/boards/se/7619/io.c @@ -0,0 +1,102 @@ +/* + * + * linux/arch/sh/boards/se/7619/io.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * I/O routine for Hitachi 7619 SolutionEngine. + * + */ + +#include +#include +#include +#include +#include + +/* FIXME: M3A-ZAB7 Compact Flash Slot support */ + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); /* Uncached ROM area (P2) */ +} + +#define badio(name,port) \ + printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +unsigned char se7619___inb(unsigned long port) +{ + badio(inb, port); + return 0; +} + +unsigned char se7619___inb_p(unsigned long port) +{ + badio(inb_p, port); + delay(); + return 0; +} + +unsigned short se7619___inw(unsigned long port) +{ + badio(inw, port); + return 0; +} + +unsigned int se7619___inl(unsigned long port) +{ + badio(inl, port); + return 0; +} + +void se7619___outb(unsigned char value, unsigned long port) +{ + badio(outb, port); +} + +void se7619___outb_p(unsigned char value, unsigned long port) +{ + badio(outb_p, port); + delay(); +} + +void se7619___outw(unsigned short value, unsigned long port) +{ + badio(outw, port); +} + +void se7619___outl(unsigned int value, unsigned long port) +{ + badio(outl, port); +} + +void se7619___insb(unsigned long port, void *addr, unsigned long count) +{ + badio(inw, port); +} + +void se7619___insw(unsigned long port, void *addr, unsigned long count) +{ + badio(inw, port); +} + +void se7619___insl(unsigned long port, void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsb(unsigned long port, const void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsw(unsigned long port, const void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsl(unsigned long port, const void *addr, unsigned long count) +{ + badio(outsw, port); +} diff --git a/trunk/arch/sh/boards/se/7619/setup.c b/trunk/arch/sh/boards/se/7619/setup.c index 52d2c4d5d2fa..e627b26de0d0 100644 --- a/trunk/arch/sh/boards/se/7619/setup.c +++ b/trunk/arch/sh/boards/se/7619/setup.c @@ -9,6 +9,7 @@ #include #include #include +#include #include /* @@ -18,5 +19,25 @@ struct sh_machine_vector mv_se __initmv = { .mv_name = "SolutionEngine", .mv_nr_irqs = 108, + .mv_inb = se7619___inb, + .mv_inw = se7619___inw, + .mv_inl = se7619___inl, + .mv_outb = se7619___outb, + .mv_outw = se7619___outw, + .mv_outl = se7619___outl, + + .mv_inb_p = se7619___inb_p, + .mv_inw_p = se7619___inw, + .mv_inl_p = se7619___inl, + .mv_outb_p = se7619___outb_p, + .mv_outw_p = se7619___outw, + .mv_outl_p = se7619___outl, + + .mv_insb = se7619___insb, + .mv_insw = se7619___insw, + .mv_insl = se7619___insl, + .mv_outsb = se7619___outsb, + .mv_outsw = se7619___outsw, + .mv_outsl = se7619___outsl, }; ALIAS_MV(se) diff --git a/trunk/arch/sh/boot/Makefile b/trunk/arch/sh/boot/Makefile index 11dc272c618e..60797b31089c 100644 --- a/trunk/arch/sh/boot/Makefile +++ b/trunk/arch/sh/boot/Makefile @@ -8,49 +8,13 @@ # Copyright (C) 1999 Stuart Menefy # -MKIMAGE := $(srctree)/scripts/mkuboot.sh - -# -# Assign safe dummy values if these variables are not defined, -# in order to suppress error message. -# -CONFIG_PAGE_OFFSET ?= 0x80000000 -CONFIG_MEMORY_START ?= 0x0c000000 -CONFIG_BOOT_LINK_OFFSET ?= 0x00800000 -CONFIG_ZERO_PAGE_OFFSET ?= 0x00001000 - -export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \ - CONFIG_ZERO_PAGE_OFFSET - -targets := zImage vmlinux.srec uImage uImage.srec +targets := zImage subdir- := compressed $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) - @echo ' Kernel: $@ is ready' + @echo 'Kernel: $@ is ready' $(obj)/compressed/vmlinux: FORCE $(Q)$(MAKE) $(build)=$(obj)/compressed $@ -KERNEL_LOAD := $(shell printf "0x%8x" $$[$(CONFIG_PAGE_OFFSET) + \ - $(CONFIG_MEMORY_START) + \ - $(CONFIG_ZERO_PAGE_OFFSET)+0x1000]) - -quiet_cmd_uimage = UIMAGE $@ - cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \ - -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_LOAD) \ - -n 'Linux-$(KERNELRELEASE)' -d $< $@ - -$(obj)/uImage: $(obj)/zImage FORCE - $(call if_changed,uimage) - @echo ' Image $@ is ready' - -OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec -$(obj)/vmlinux.srec: $(obj)/compressed/vmlinux - $(call if_changed,objcopy) - -OBJCOPYFLAGS_uImage.srec := -I binary -O srec -$(obj)/uImage.srec: $(obj)/uImage - $(call if_changed,objcopy) - -clean-files += uImage uImage.srec vmlinux.srec diff --git a/trunk/arch/sh/boot/compressed/Makefile b/trunk/arch/sh/boot/compressed/Makefile index d9512416f885..e5f443790079 100644 --- a/trunk/arch/sh/boot/compressed/Makefile +++ b/trunk/arch/sh/boot/compressed/Makefile @@ -15,7 +15,13 @@ endif # # IMAGE_OFFSET is the load offset of the compression loader +# Assign dummy values if these 2 variables are not defined, +# in order to suppress error message. # +CONFIG_PAGE_OFFSET ?= 0x80000000 +CONFIG_MEMORY_START ?= 0x0c000000 +CONFIG_BOOT_LINK_OFFSET ?= 0x00800000 + IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_PAGE_OFFSET) + \ $(CONFIG_MEMORY_START) + \ $(CONFIG_BOOT_LINK_OFFSET)]) diff --git a/trunk/arch/sh/boot/compressed/head.S b/trunk/arch/sh/boot/compressed/head.S index a8399b013729..4c26a192277d 100644 --- a/trunk/arch/sh/boot/compressed/head.S +++ b/trunk/arch/sh/boot/compressed/head.S @@ -8,7 +8,6 @@ .text #include -#include .global startup startup: @@ -98,7 +97,7 @@ init_stack_addr: decompress_kernel_addr: .long decompress_kernel kernel_start_addr: - .long _text+PAGE_SIZE + .long _text+0x1000 .align 9 fake_headers_as_bzImage: diff --git a/trunk/arch/sh/boot/compressed/misc.c b/trunk/arch/sh/boot/compressed/misc.c index df65e305acf7..35452d85b7f7 100644 --- a/trunk/arch/sh/boot/compressed/misc.c +++ b/trunk/arch/sh/boot/compressed/misc.c @@ -13,7 +13,6 @@ #include #include -#include #ifdef CONFIG_SH_STANDARD_BIOS #include #endif @@ -230,7 +229,7 @@ long* stack_start = &user_stack[STACK_SIZE]; void decompress_kernel(void) { output_data = 0; - output_ptr = P2SEGADDR((unsigned long)&_text+PAGE_SIZE); + output_ptr = P2SEGADDR((unsigned long)&_text+0x1000); free_mem_ptr = (unsigned long)&_end; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; diff --git a/trunk/arch/sh/configs/landisk_defconfig b/trunk/arch/sh/configs/landisk_defconfig index e7f8ddb0ada4..238c0f109907 100644 --- a/trunk/arch/sh/configs/landisk_defconfig +++ b/trunk/arch/sh/configs/landisk_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19 -# Thu Dec 7 17:13:04 2006 +# Linux kernel version: 2.6.18 +# Tue Oct 3 11:14:13 2006 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y @@ -10,9 +10,6 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y -# CONFIG_GENERIC_TIME is not set -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -36,7 +33,6 @@ CONFIG_SYSVIPC=y # CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set -CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -118,8 +114,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_SH_LANDISK=y # CONFIG_SH_TITAN is not set # CONFIG_SH_SHMIN is not set -# CONFIG_SH_7206_SOLUTION_ENGINE is not set -# CONFIG_SH_7619_SOLUTION_ENGINE is not set # CONFIG_SH_UNKNOWN is not set # @@ -131,12 +125,6 @@ CONFIG_CPU_SH4=y # SH-2 Processor Support # # CONFIG_CPU_SUBTYPE_SH7604 is not set -# CONFIG_CPU_SUBTYPE_SH7619 is not set - -# -# SH-2A Processor Support -# -# CONFIG_CPU_SUBTYPE_SH7206 is not set # # SH-3 Processor Support @@ -172,7 +160,6 @@ CONFIG_CPU_SUBTYPE_SH7751R=y # # CONFIG_CPU_SUBTYPE_SH7770 is not set # CONFIG_CPU_SUBTYPE_SH7780 is not set -# CONFIG_CPU_SUBTYPE_SH7785 is not set # # SH4AL-DSP Processor Support @@ -188,9 +175,6 @@ CONFIG_PAGE_OFFSET=0x80000000 CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_VSYSCALL=y -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_64KB is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -212,21 +196,16 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # Processor features # CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y # CONFIG_SH_DSP is not set # CONFIG_SH_STORE_QUEUES is not set CONFIG_CPU_HAS_INTEVT=y -CONFIG_CPU_HAS_IPR_IRQ=y CONFIG_CPU_HAS_SR_RB=y -CONFIG_CPU_HAS_PTEA=y # # Timer support # CONFIG_SH_TMU=y -CONFIG_SH_TIMER_IRQ=16 -# CONFIG_NO_IDLE_HZ is not set CONFIG_SH_PCLK_FREQ=33333333 # @@ -237,7 +216,9 @@ CONFIG_SH_PCLK_FREQ=33333333 # # DMA support # -# CONFIG_SH_DMA is not set +CONFIG_SH_DMA=y +CONFIG_NR_ONCHIP_DMA_CHANNELS=4 +# CONFIG_NR_DMA_CHANNELS_BOOL is not set # # Companion Chips @@ -245,11 +226,6 @@ CONFIG_SH_PCLK_FREQ=33333333 # CONFIG_HD6446X_SERIES is not set CONFIG_HEARTBEAT=y -# -# Additional SuperH Device Drivers -# -# CONFIG_PUSH_SWITCH is not set - # # Kernel features # @@ -364,13 +340,11 @@ CONFIG_IP_PNP=y # CONFIG_INET_TUNNEL is not set CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set # # IP: Virtual Server Configuration @@ -387,12 +361,24 @@ CONFIG_NETFILTER=y # Core Netfilter Configuration # # CONFIG_NETFILTER_NETLINK is not set -# CONFIG_NF_CONNTRACK_ENABLED is not set # CONFIG_NETFILTER_XTABLES is not set # # IP: Netfilter Configuration # +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +# CONFIG_IP_NF_SIP is not set CONFIG_IP_NF_QUEUE=m # @@ -490,12 +476,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set -# -# Misc devices -# -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set - # # ATA/ATAPI/MFM/RLL support # @@ -539,7 +519,6 @@ CONFIG_BLK_DEV_AEC62XX=y # CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set # CONFIG_BLK_DEV_IT821X is not set @@ -563,7 +542,6 @@ CONFIG_IDEDMA_AUTO=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y -# CONFIG_SCSI_TGT is not set # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y @@ -583,7 +561,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set # # SCSI Transports @@ -625,12 +602,12 @@ CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_STEX is not set # CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC395x is not set @@ -638,7 +615,6 @@ CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_SRP is not set # # PCMCIA SCSI adapter support @@ -781,7 +757,6 @@ CONFIG_8139CP=y # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set -# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -896,6 +871,10 @@ CONFIG_HW_RANDOM=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# # CONFIG_DRM is not set # @@ -910,6 +889,7 @@ CONFIG_HW_RANDOM=y # TPM devices # # CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set # # I2C support @@ -925,7 +905,6 @@ CONFIG_HW_RANDOM=y # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support @@ -937,6 +916,10 @@ CONFIG_HWMON=y # CONFIG_SENSORS_VT1211 is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# +# Misc devices +# + # # Multimedia devices # @@ -1054,7 +1037,6 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_MULTITHREAD_PROBE is not set # CONFIG_USB_OTG is not set # @@ -1124,6 +1106,7 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set +# CONFIG_USB_TRANCEVIBRATOR is not set # # USB Imaging devices @@ -1138,7 +1121,6 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_KAWETH is not set CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m -# CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set CONFIG_USB_MON=y @@ -1174,7 +1156,6 @@ CONFIG_USB_SERIAL_FTDI_SIO=m # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_KOBIL_SCT is not set # CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_MOS7720 is not set # CONFIG_USB_SERIAL_MOS7840 is not set # CONFIG_USB_SERIAL_NAVMAN is not set CONFIG_USB_SERIAL_PL2303=m @@ -1186,7 +1167,6 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_XIRCOM is not set # CONFIG_USB_SERIAL_OPTION is not set # CONFIG_USB_SERIAL_OMNINET is not set -# CONFIG_USB_SERIAL_DEBUG is not set # # USB Miscellaneous drivers @@ -1208,7 +1188,6 @@ CONFIG_USB_EMI26=m CONFIG_USB_SISUSBVGA=m CONFIG_USB_SISUSBVGA_CON=y # CONFIG_USB_LD is not set -# CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_TEST is not set # @@ -1275,7 +1254,6 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1286,7 +1264,6 @@ CONFIG_REISERFS_FS=y # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y @@ -1437,7 +1414,6 @@ CONFIG_NLS_CODEPAGE_932=y # # Kernel hacking # -CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set CONFIG_ENABLE_MUST_CHECK=y # CONFIG_MAGIC_SYSRQ is not set @@ -1446,7 +1422,6 @@ CONFIG_ENABLE_MUST_CHECK=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_FS is not set -# CONFIG_HEADERS_CHECK is not set CONFIG_SH_STANDARD_BIOS=y # CONFIG_EARLY_SCIF_CONSOLE is not set # CONFIG_EARLY_PRINTK is not set @@ -1470,4 +1445,6 @@ CONFIG_SH_STANDARD_BIOS=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m CONFIG_PLIST=y diff --git a/trunk/arch/sh/configs/se7206_defconfig b/trunk/arch/sh/configs/se7206_defconfig index 87ab9080fd1d..36cec0b6e7c1 100644 --- a/trunk/arch/sh/configs/se7206_defconfig +++ b/trunk/arch/sh/configs/se7206_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19 -# Wed Dec 6 14:40:15 2006 +# Linux kernel version: 2.6.19-rc4 +# Sun Nov 5 16:20:10 2006 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y @@ -11,8 +11,6 @@ CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y # CONFIG_GENERIC_TIME is not set -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -36,23 +34,24 @@ CONFIG_LOCALVERSION="" # CONFIG_IKCONFIG is not set # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_EMBEDDED=y -# CONFIG_UID16 is not set +CONFIG_UID16=y # CONFIG_SYSCTL_SYSCALL is not set -# CONFIG_KALLSYMS is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set # CONFIG_HOTPLUG is not set CONFIG_PRINTK=y CONFIG_BUG=y -# CONFIG_ELF_CORE is not set -# CONFIG_BASE_FULL is not set +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set CONFIG_SLAB=y -# CONFIG_VM_EVENT_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y CONFIG_TINY_SHMEM=y -CONFIG_BASE_SMALL=1 +CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set # @@ -161,7 +160,6 @@ CONFIG_CPU_SUBTYPE_SH7206=y # # CONFIG_CPU_SUBTYPE_SH7770 is not set # CONFIG_CPU_SUBTYPE_SH7780 is not set -# CONFIG_CPU_SUBTYPE_SH7785 is not set # # SH4AL-DSP Processor Support @@ -174,10 +172,7 @@ CONFIG_CPU_SUBTYPE_SH7206=y # CONFIG_PAGE_OFFSET=0x00000000 CONFIG_MEMORY_START=0x0c000000 -CONFIG_MEMORY_SIZE=0x04000000 -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_MEMORY_SIZE=0x02000000 CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -199,7 +194,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # Processor features # # CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_CPU_BIG_ENDIAN=y # CONFIG_SH_FPU is not set # CONFIG_SH_FPU_EMU is not set # CONFIG_SH_DSP is not set @@ -209,8 +203,6 @@ CONFIG_CPU_BIG_ENDIAN=y # CONFIG_SH_CMT=y # CONFIG_SH_MTU2 is not set -CONFIG_SH_TIMER_IRQ=140 -# CONFIG_NO_IDLE_HZ is not set CONFIG_SH_PCLK_FREQ=33333333 CONFIG_SH_CLK_MD=6 @@ -229,11 +221,6 @@ CONFIG_SH_CLK_MD=6 # # CONFIG_HD6446X_SERIES is not set -# -# Additional SuperH Device Drivers -# -# CONFIG_PUSH_SWITCH is not set - # # Kernel features # @@ -292,6 +279,9 @@ CONFIG_NET=y # CONFIG_NETDEBUG is not set # CONFIG_PACKET is not set # CONFIG_UNIX is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -307,9 +297,9 @@ CONFIG_IP_FIB_HASH=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y @@ -381,7 +371,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set -CONFIG_MTD_CONCAT=y +# CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y CONFIG_MTD_REDBOOT_PARTS=y CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 @@ -432,7 +422,7 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y CONFIG_MTD_PHYSMAP_START=0x20000000 -CONFIG_MTD_PHYSMAP_LEN=0x01000000 +CONFIG_MTD_PHYSMAP_LEN=0x1000000 CONFIG_MTD_PHYSMAP_BANKWIDTH=4 # CONFIG_MTD_SOLUTIONENGINE is not set # CONFIG_MTD_UCLINUX is not set @@ -478,7 +468,10 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4 # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -526,50 +519,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4 # # Network device support # -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# PHY device support -# -# CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_STNIC is not set -CONFIG_SMC91X=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +# CONFIG_NETDEVICES is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -586,26 +536,7 @@ CONFIG_SMC91X=y # # Input device support # -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT is not set # # Hardware I/O ports @@ -633,7 +564,8 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_UNIX98_PTYS is not set -# CONFIG_LEGACY_PTYS is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # # IPMI @@ -644,7 +576,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_HW_RANDOM is not set +CONFIG_HW_RANDOM=y # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -678,8 +610,12 @@ CONFIG_SERIAL_CORE_CONSOLE=y # # Hardware Monitoring support # -# CONFIG_HWMON is not set +CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Multimedia devices @@ -694,7 +630,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set +CONFIG_FIRMWARE_EDID=y # CONFIG_FB is not set # @@ -765,7 +701,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y # # File systems # -# CONFIG_EXT2_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4DEV_FS is not set # CONFIG_REISERFS_FS is not set @@ -818,7 +755,7 @@ CONFIG_RAMFS=y # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set # CONFIG_JFFS2_FS is not set -# CONFIG_CRAMFS is not set +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set @@ -856,9 +793,8 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # -CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set -# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_ENABLE_MUST_CHECK=y # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_DEBUG_KERNEL is not set @@ -883,7 +819,7 @@ CONFIG_LOG_BUF_SHIFT=14 # # Library routines # -# CONFIG_CRC_CCITT is not set +CONFIG_CRC_CCITT=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set diff --git a/trunk/arch/sh/configs/se7619_defconfig b/trunk/arch/sh/configs/se7619_defconfig deleted file mode 100644 index 20ac7f4c53fb..000000000000 --- a/trunk/arch/sh/configs/se7619_defconfig +++ /dev/null @@ -1,744 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.19 -# Wed Dec 6 16:35:36 2006 -# -CONFIG_SUPERH=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -# CONFIG_GENERIC_TIME is not set -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_UTS_NS is not set -# CONFIG_IKCONFIG is not set -# CONFIG_RELAY is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_EMBEDDED=y -# CONFIG_UID16 is not set -# CONFIG_SYSCTL_SYSCALL is not set -# CONFIG_KALLSYMS is not set -# CONFIG_HOTPLUG is not set -CONFIG_PRINTK=y -CONFIG_BUG=y -# CONFIG_ELF_CORE is not set -# CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -CONFIG_SLAB=y -# CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_TINY_SHMEM=y -CONFIG_BASE_SMALL=1 -# CONFIG_SLOB is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Block layer -# -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_LSF is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -# CONFIG_DEFAULT_AS is not set -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -CONFIG_DEFAULT_NOOP=y -CONFIG_DEFAULT_IOSCHED="noop" - -# -# System type -# -# CONFIG_SH_SOLUTION_ENGINE is not set -# CONFIG_SH_7751_SOLUTION_ENGINE is not set -# CONFIG_SH_7300_SOLUTION_ENGINE is not set -# CONFIG_SH_7343_SOLUTION_ENGINE is not set -# CONFIG_SH_73180_SOLUTION_ENGINE is not set -# CONFIG_SH_7751_SYSTEMH is not set -# CONFIG_SH_HP6XX is not set -# CONFIG_SH_EC3104 is not set -# CONFIG_SH_SATURN is not set -# CONFIG_SH_DREAMCAST is not set -# CONFIG_SH_BIGSUR is not set -# CONFIG_SH_MPC1211 is not set -# CONFIG_SH_SH03 is not set -# CONFIG_SH_SECUREEDGE5410 is not set -# CONFIG_SH_HS7751RVOIP is not set -# CONFIG_SH_7710VOIPGW is not set -# CONFIG_SH_RTS7751R2D is not set -# CONFIG_SH_R7780RP is not set -# CONFIG_SH_EDOSK7705 is not set -# CONFIG_SH_SH4202_MICRODEV is not set -# CONFIG_SH_LANDISK is not set -# CONFIG_SH_TITAN is not set -# CONFIG_SH_SHMIN is not set -# CONFIG_SH_7206_SOLUTION_ENGINE is not set -CONFIG_SH_7619_SOLUTION_ENGINE=y -# CONFIG_SH_UNKNOWN is not set - -# -# Processor selection -# -CONFIG_CPU_SH2=y - -# -# SH-2 Processor Support -# -# CONFIG_CPU_SUBTYPE_SH7604 is not set -CONFIG_CPU_SUBTYPE_SH7619=y - -# -# SH-2A Processor Support -# -# CONFIG_CPU_SUBTYPE_SH7206 is not set - -# -# SH-3 Processor Support -# -# CONFIG_CPU_SUBTYPE_SH7300 is not set -# CONFIG_CPU_SUBTYPE_SH7705 is not set -# CONFIG_CPU_SUBTYPE_SH7706 is not set -# CONFIG_CPU_SUBTYPE_SH7707 is not set -# CONFIG_CPU_SUBTYPE_SH7708 is not set -# CONFIG_CPU_SUBTYPE_SH7709 is not set -# CONFIG_CPU_SUBTYPE_SH7710 is not set - -# -# SH-4 Processor Support -# -# CONFIG_CPU_SUBTYPE_SH7750 is not set -# CONFIG_CPU_SUBTYPE_SH7091 is not set -# CONFIG_CPU_SUBTYPE_SH7750R is not set -# CONFIG_CPU_SUBTYPE_SH7750S is not set -# CONFIG_CPU_SUBTYPE_SH7751 is not set -# CONFIG_CPU_SUBTYPE_SH7751R is not set -# CONFIG_CPU_SUBTYPE_SH7760 is not set -# CONFIG_CPU_SUBTYPE_SH4_202 is not set - -# -# ST40 Processor Support -# -# CONFIG_CPU_SUBTYPE_ST40STB1 is not set -# CONFIG_CPU_SUBTYPE_ST40GX1 is not set - -# -# SH-4A Processor Support -# -# CONFIG_CPU_SUBTYPE_SH7770 is not set -# CONFIG_CPU_SUBTYPE_SH7780 is not set -# CONFIG_CPU_SUBTYPE_SH7785 is not set - -# -# SH4AL-DSP Processor Support -# -# CONFIG_CPU_SUBTYPE_SH73180 is not set -# CONFIG_CPU_SUBTYPE_SH7343 is not set - -# -# Memory management options -# -CONFIG_PAGE_OFFSET=0x00000000 -CONFIG_MEMORY_START=0x0c000000 -CONFIG_MEMORY_SIZE=0x04000000 -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set - -# -# Cache configuration -# -# CONFIG_SH_DIRECT_MAPPED is not set -CONFIG_SH_WRITETHROUGH=y -# CONFIG_SH_OCRAM is not set - -# -# Processor features -# -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_CPU_BIG_ENDIAN=y -# CONFIG_SH_FPU is not set -# CONFIG_SH_FPU_EMU is not set -# CONFIG_SH_DSP is not set - -# -# Timer support -# -CONFIG_SH_CMT=y -CONFIG_SH_TIMER_IRQ=86 -# CONFIG_NO_IDLE_HZ is not set -CONFIG_SH_PCLK_FREQ=31250000 -CONFIG_SH_CLK_MD=5 - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set - -# -# DMA support -# -# CONFIG_SH_DMA is not set - -# -# Companion Chips -# -# CONFIG_HD6446X_SERIES is not set - -# -# Additional SuperH Device Drivers -# -# CONFIG_PUSH_SWITCH is not set - -# -# Kernel features -# -CONFIG_HZ_100=y -# CONFIG_HZ_250 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=100 -# CONFIG_KEXEC is not set -# CONFIG_SMP is not set -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set - -# -# Boot options -# -CONFIG_ZERO_PAGE_OFFSET=0x00001000 -CONFIG_BOOT_LINK_OFFSET=0x00800000 -# CONFIG_UBC_WAKEUP is not set -# CONFIG_CMDLINE_BOOL is not set - -# -# Bus options -# -# CONFIG_PCI is not set - -# -# PCCARD (PCMCIA/CardBus) support -# - -# -# PCI Hotplug Support -# - -# -# Executable file formats -# -CONFIG_BINFMT_FLAT=y -CONFIG_BINFMT_ZFLAT=y -# CONFIG_BINFMT_SHARED_FLAT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Power management options (EXPERIMENTAL) -# -# CONFIG_PM is not set - -# -# Networking -# -# CONFIG_NET is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -# CONFIG_STANDALONE is not set -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_REDBOOT_PARTS=y -CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set -# CONFIG_MTD_CMDLINE_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0xa0000000 -CONFIG_MTD_PHYSMAP_LEN=0x01000000 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 -# CONFIG_MTD_SOLUTIONENGINE is not set -# CONFIG_MTD_UCLINUX is not set -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# OneNAND Flash Device Drivers -# -# CONFIG_MTD_ONENAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_CDROM_PKTCDVD is not set - -# -# Misc devices -# -# CONFIG_TIFM_CORE is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_NETLINK is not set - -# -# Serial ATA (prod) and Parallel ATA (experimental) drivers -# -# CONFIG_ATA is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# ISDN subsystem -# - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=3 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_UNIX98_PTYS is not set -# CONFIG_LEGACY_PTYS is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Hardware Monitoring support -# -# CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# - -# -# Graphics support -# -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_ARCH_HAS_HCD is not set -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB_ARCH_HAS_EHCI is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# LED devices -# -# CONFIG_NEW_LEDS is not set - -# -# LED drivers -# - -# -# LED Triggers -# - -# -# InfiniBand support -# - -# -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - -# -# Real Time Clock -# -# CONFIG_RTC_CLASS is not set - -# -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices -# - -# -# File systems -# -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_EXT4DEV_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=y -# CONFIG_INOTIFY is not set -# CONFIG_QUOTA is not set -# CONFIG_DNOTIFY is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_SYSCTL=y -# CONFIG_SYSFS is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# -# CONFIG_NLS is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -# CONFIG_PRINTK_TIME is not set -# CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_KERNEL is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_UNWIND_INFO is not set -# CONFIG_HEADERS_CHECK is not set -# CONFIG_SH_STANDARD_BIOS is not set -# CONFIG_EARLY_SCIF_CONSOLE is not set -# CONFIG_KGDB is not set - -# -# Security options -# -# CONFIG_KEYS is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y diff --git a/trunk/arch/sh/drivers/push-switch.c b/trunk/arch/sh/drivers/push-switch.c index b3d20c0e021f..f2b9157c314f 100644 --- a/trunk/arch/sh/drivers/push-switch.c +++ b/trunk/arch/sh/drivers/push-switch.c @@ -14,7 +14,7 @@ #include #define DRV_NAME "push-switch" -#define DRV_VERSION "0.1.1" +#define DRV_VERSION "0.1.0" static ssize_t switch_show(struct device *dev, struct device_attribute *attr, @@ -32,10 +32,10 @@ static void switch_timer(unsigned long data) schedule_work(&psw->work); } -static void switch_work_handler(struct work_struct *work) +static void switch_work_handler(void *data) { - struct push_switch *psw = container_of(work, struct push_switch, work); - struct platform_device *pdev = psw->pdev; + struct platform_device *pdev = data; + struct push_switch *psw = platform_get_drvdata(pdev); psw->state = 0; @@ -76,15 +76,12 @@ static int switch_drv_probe(struct platform_device *pdev) } } - INIT_WORK(&psw->work, switch_work_handler); + INIT_WORK(&psw->work, switch_work_handler, pdev); init_timer(&psw->debounce); psw->debounce.function = switch_timer; psw->debounce.data = (unsigned long)psw; - /* Workqueue API brain-damage */ - psw->pdev = pdev; - platform_set_drvdata(pdev, psw); return 0; diff --git a/trunk/arch/sh/kernel/cpu/Makefile b/trunk/arch/sh/kernel/cpu/Makefile index d055a3ea6b4b..0582e6712b79 100644 --- a/trunk/arch/sh/kernel/cpu/Makefile +++ b/trunk/arch/sh/kernel/cpu/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_CPU_SH2) = sh2/ obj-$(CONFIG_CPU_SH2A) = sh2a/ obj-$(CONFIG_CPU_SH3) = sh3/ obj-$(CONFIG_CPU_SH4) = sh4/ -obj-$(CONFIG_CPU_SH4A) += sh4a/ obj-$(CONFIG_UBC_WAKEUP) += ubc.o obj-$(CONFIG_SH_ADC) += adc.o diff --git a/trunk/arch/sh/kernel/cpu/sh2/entry.S b/trunk/arch/sh/kernel/cpu/sh2/entry.S index d51fa5e9904a..34d51b3745ea 100644 --- a/trunk/arch/sh/kernel/cpu/sh2/entry.S +++ b/trunk/arch/sh/kernel/cpu/sh2/entry.S @@ -177,21 +177,15 @@ interrupt_entry: 7: .long do_IRQ 8: .long do_exception_error -trap_entry: - /* verbose BUG trapa entry check */ - mov #0x3e,r8 - cmp/ge r8,r9 - bf/s 1f - add #-0x10,r9 - add #0x10,r9 -1: +trap_entry: + add #-0x10,r9 shll2 r9 ! TRA mov #OFF_TRA,r8 add r15,r8 mov.l r9,@r8 mov r9,r8 #ifdef CONFIG_TRACE_IRQFLAGS - mov.l 2f, r9 + mov.l 5f, r9 jsr @r9 nop #endif @@ -200,8 +194,12 @@ trap_entry: nop .align 2 +1: .long syscall_exit +2: .long break_point_trap_software +3: .long NR_syscalls +4: .long sys_call_table #ifdef CONFIG_TRACE_IRQFLAGS -2: .long trace_hardirqs_on +5: .long trace_hardirqs_on #endif #if defined(CONFIG_SH_STANDARD_BIOS) @@ -266,7 +264,7 @@ ENTRY(address_error_handler) restore_all: cli #ifdef CONFIG_TRACE_IRQFLAGS - mov.l 1f, r0 + mov.l 3f, r0 jsr @r0 nop #endif @@ -311,14 +309,20 @@ restore_all: mov.l @r15,r15 rte nop +2: + mov.l 1f,r8 + mov.l 2f,r9 + jmp @r9 + lds r8,pr -#ifdef CONFIG_TRACE_IRQFLAGS -1: .long trace_hardirqs_off -#endif + .align 2 $current_thread_info: .long __current_thread_info $cpu_mode: .long __cpu_mode +#ifdef CONFIG_TRACE_IRQFLAGS +3: .long trace_hardirqs_off +#endif ! common exception handler #include "../../entry-common.S" diff --git a/trunk/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/trunk/arch/sh/kernel/cpu/sh2/setup-sh7619.c index 79283e6c1d8f..82c2d905152f 100644 --- a/trunk/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/trunk/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -51,44 +51,3 @@ static int __init sh7619_devices_setup(void) ARRAY_SIZE(sh7619_devices)); } __initcall(sh7619_devices_setup); - -#define INTC_IPRC 0xf8080000UL -#define INTC_IPRD 0xf8080002UL - -#define CMI0_IRQ 86 - -#define SCIF0_ERI_IRQ 88 -#define SCIF0_RXI_IRQ 89 -#define SCIF0_BRI_IRQ 90 -#define SCIF0_TXI_IRQ 91 - -#define SCIF1_ERI_IRQ 92 -#define SCIF1_RXI_IRQ 93 -#define SCIF1_BRI_IRQ 94 -#define SCIF1_TXI_IRQ 95 - -#define SCIF2_BRI_IRQ 96 -#define SCIF2_ERI_IRQ 97 -#define SCIF2_RXI_IRQ 98 -#define SCIF2_TXI_IRQ 99 - -static struct ipr_data sh7619_ipr_map[] = { - { CMI0_IRQ, INTC_IPRC, 1, 2 }, - { SCIF0_ERI_IRQ, INTC_IPRD, 3, 3 }, - { SCIF0_RXI_IRQ, INTC_IPRD, 3, 3 }, - { SCIF0_BRI_IRQ, INTC_IPRD, 3, 3 }, - { SCIF0_TXI_IRQ, INTC_IPRD, 3, 3 }, - { SCIF1_ERI_IRQ, INTC_IPRD, 2, 3 }, - { SCIF1_RXI_IRQ, INTC_IPRD, 2, 3 }, - { SCIF1_BRI_IRQ, INTC_IPRD, 2, 3 }, - { SCIF1_TXI_IRQ, INTC_IPRD, 2, 3 }, - { SCIF2_ERI_IRQ, INTC_IPRD, 1, 3 }, - { SCIF2_RXI_IRQ, INTC_IPRD, 1, 3 }, - { SCIF2_BRI_IRQ, INTC_IPRD, 1, 3 }, - { SCIF2_TXI_IRQ, INTC_IPRD, 1, 3 }, -}; - -void __init init_IRQ_ipr(void) -{ - make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map)); -} diff --git a/trunk/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/trunk/arch/sh/kernel/cpu/sh2a/setup-sh7206.c index 4b60fcc7d667..cdfeef49e62e 100644 --- a/trunk/arch/sh/kernel/cpu/sh2a/setup-sh7206.c +++ b/trunk/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -17,22 +17,22 @@ static struct plat_sci_port sci_platform_data[] = { .mapbase = 0xfffe8000, .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, - .irqs = { 241, 242, 243, 240}, + .irqs = { 240, 241, 242, 243}, }, { .mapbase = 0xfffe8800, .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, - .irqs = { 247, 244, 245, 246}, + .irqs = { 244, 245, 246, 247}, }, { .mapbase = 0xfffe9000, .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, - .irqs = { 249, 250, 251, 248}, + .irqs = { 248, 249, 250, 251}, }, { .mapbase = 0xfffe9800, .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, - .irqs = { 253, 254, 255, 252}, + .irqs = { 252, 253, 254, 255}, }, { .flags = 0, } @@ -56,57 +56,3 @@ static int __init sh7206_devices_setup(void) ARRAY_SIZE(sh7206_devices)); } __initcall(sh7206_devices_setup); - -#define INTC_IPR08 0xfffe0c04UL -#define INTC_IPR09 0xfffe0c06UL -#define INTC_IPR14 0xfffe0c10UL - -#define CMI0_IRQ 140 - -#define MTU1_TGI1A 164 - -#define SCIF0_BRI_IRQ 240 -#define SCIF0_ERI_IRQ 241 -#define SCIF0_RXI_IRQ 242 -#define SCIF0_TXI_IRQ 243 - -#define SCIF1_BRI_IRQ 244 -#define SCIF1_ERI_IRQ 245 -#define SCIF1_RXI_IRQ 246 -#define SCIF1_TXI_IRQ 247 - -#define SCIF2_BRI_IRQ 248 -#define SCIF2_ERI_IRQ 249 -#define SCIF2_RXI_IRQ 250 -#define SCIF2_TXI_IRQ 251 - -#define SCIF3_BRI_IRQ 252 -#define SCIF3_ERI_IRQ 253 -#define SCIF3_RXI_IRQ 254 -#define SCIF3_TXI_IRQ 255 - -static struct ipr_data sh7206_ipr_map[] = { - { CMI0_IRQ, INTC_IPR08, 3, 2 }, - { MTU2_TGI1A, INTC_IPR09, 1, 2 }, - { SCIF0_ERI_IRQ, INTC_IPR14, 3, 3 }, - { SCIF0_RXI_IRQ, INTC_IPR14, 3, 3 }, - { SCIF0_BRI_IRQ, INTC_IPR14, 3, 3 }, - { SCIF0_TXI_IRQ, INTC_IPR14, 3, 3 }, - { SCIF1_ERI_IRQ, INTC_IPR14, 2, 3 }, - { SCIF1_RXI_IRQ, INTC_IPR14, 2, 3 }, - { SCIF1_BRI_IRQ, INTC_IPR14, 2, 3 }, - { SCIF1_TXI_IRQ, INTC_IPR14, 2, 3 }, - { SCIF2_ERI_IRQ, INTC_IPR14, 1, 3 }, - { SCIF2_RXI_IRQ, INTC_IPR14, 1, 3 }, - { SCIF2_BRI_IRQ, INTC_IPR14, 1, 3 }, - { SCIF2_TXI_IRQ, INTC_IPR14, 1, 3 }, - { SCIF3_ERI_IRQ, INTC_IPR14, 0, 3 }, - { SCIF3_RXI_IRQ, INTC_IPR14, 0, 3 }, - { SCIF3_BRI_IRQ, INTC_IPR14, 0, 3 }, - { SCIF3_TXI_IRQ, INTC_IPR14, 0, 3 }, -}; - -void __init init_IRQ_ipr(void) -{ - make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map)); -} diff --git a/trunk/arch/sh/kernel/cpu/sh4/Makefile b/trunk/arch/sh/kernel/cpu/sh4/Makefile index 19ca68c71884..6e415baf04b4 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/Makefile +++ b/trunk/arch/sh/kernel/cpu/sh4/Makefile @@ -12,12 +12,17 @@ obj-$(CONFIG_SH_STORE_QUEUES) += sq.o obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o +obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o +obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o +obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o +obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o # Primary on-chip clocks (common) -ifndef CONFIG_CPU_SH4A clock-$(CONFIG_CPU_SH4) := clock-sh4.o -endif +clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o +clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o +clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o # Additional clocks by subtype clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c b/trunk/arch/sh/kernel/cpu/sh4/clock-sh73180.c similarity index 100% rename from trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c rename to trunk/arch/sh/kernel/cpu/sh4/clock-sh73180.c diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c b/trunk/arch/sh/kernel/cpu/sh4/clock-sh7770.c similarity index 100% rename from trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c rename to trunk/arch/sh/kernel/cpu/sh4/clock-sh7770.c diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/trunk/arch/sh/kernel/cpu/sh4/clock-sh7780.c similarity index 100% rename from trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c rename to trunk/arch/sh/kernel/cpu/sh4/clock-sh7780.c diff --git a/trunk/arch/sh/kernel/cpu/sh4/probe.c b/trunk/arch/sh/kernel/cpu/sh4/probe.c index 9031a22a2ce7..afe0f1b1c030 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/probe.c +++ b/trunk/arch/sh/kernel/cpu/sh4/probe.c @@ -119,20 +119,11 @@ int __init detect_cpu_and_cache_system(void) break; case 0x3000: case 0x3003: - case 0x3009: cpu_data->type = CPU_SH7343; cpu_data->icache.ways = 4; cpu_data->dcache.ways = 4; cpu_data->flags |= CPU_HAS_LLSC; break; - case 0x3008: - if (prr == 0xa0) { - cpu_data->type = CPU_SH7722; - cpu_data->icache.ways = 4; - cpu_data->dcache.ways = 4; - cpu_data->flags |= CPU_HAS_LLSC; - } - break; case 0x8000: cpu_data->type = CPU_ST40RA; cpu_data->flags |= CPU_HAS_FPU; diff --git a/trunk/arch/sh/kernel/cpu/sh4a/setup-sh73180.c b/trunk/arch/sh/kernel/cpu/sh4/setup-sh73180.c similarity index 100% rename from trunk/arch/sh/kernel/cpu/sh4a/setup-sh73180.c rename to trunk/arch/sh/kernel/cpu/sh4/setup-sh73180.c diff --git a/trunk/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7343.c similarity index 100% rename from trunk/arch/sh/kernel/cpu/sh4a/setup-sh7343.c rename to trunk/arch/sh/kernel/cpu/sh4/setup-sh7343.c diff --git a/trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c index cbac27634c0b..bbcb06f18b04 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -14,36 +14,6 @@ #include #include -static struct resource rtc_resources[] = { - [0] = { - .start = 0xffc80000, - .end = 0xffc80000 + 0x58 - 1, - .flags = IORESOURCE_IO, - }, - [1] = { - /* Period IRQ */ - .start = 21, - .flags = IORESOURCE_IRQ, - }, - [2] = { - /* Carry IRQ */ - .start = 22, - .flags = IORESOURCE_IRQ, - }, - [3] = { - /* Alarm IRQ */ - .start = 20, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device rtc_device = { - .name = "sh-rtc", - .id = -1, - .num_resources = ARRAY_SIZE(rtc_resources), - .resource = rtc_resources, -}; - static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -69,7 +39,6 @@ static struct platform_device sci_device = { }; static struct platform_device *sh7750_devices[] __initdata = { - &rtc_device, &sci_device, }; diff --git a/trunk/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7770.c similarity index 100% rename from trunk/arch/sh/kernel/cpu/sh4a/setup-sh7770.c rename to trunk/arch/sh/kernel/cpu/sh4/setup-sh7770.c diff --git a/trunk/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7780.c similarity index 100% rename from trunk/arch/sh/kernel/cpu/sh4a/setup-sh7780.c rename to trunk/arch/sh/kernel/cpu/sh4/setup-sh7780.c diff --git a/trunk/arch/sh/kernel/cpu/sh4/sq.c b/trunk/arch/sh/kernel/cpu/sh4/sq.c index d7fff752e569..0c9ea38d2caa 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/sq.c +++ b/trunk/arch/sh/kernel/cpu/sh4/sq.c @@ -111,9 +111,8 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags) vma->phys_addr = map->addr; - if (ioremap_page_range((unsigned long)vma->addr, - (unsigned long)vma->addr + map->size, - vma->phys_addr, __pgprot(flags))) { + if (remap_area_pages((unsigned long)vma->addr, vma->phys_addr, + map->size, flags)) { vunmap(vma->addr); return -EAGAIN; } @@ -177,7 +176,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size, map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT); - ret = __sq_remap(map, pgprot_val(PAGE_KERNEL_NOCACHE) | flags); + ret = __sq_remap(map, flags); if (unlikely(ret != 0)) goto out; diff --git a/trunk/arch/sh/kernel/cpu/sh4a/Makefile b/trunk/arch/sh/kernel/cpu/sh4a/Makefile deleted file mode 100644 index a8f493f2f21f..000000000000 --- a/trunk/arch/sh/kernel/cpu/sh4a/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# -# Makefile for the Linux/SuperH SH-4 backends. -# - -# CPU subtype setup -obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o -obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o -obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o -obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o -obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o - -# Primary on-chip clocks (common) -clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o -clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o -clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o -clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o -clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7343.o - -obj-y += $(clock-y) diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c deleted file mode 100644 index 1707a213f0cf..000000000000 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * arch/sh/kernel/cpu/sh4/clock-sh7343.c - * - * SH7343/SH7722 support for the clock framework - * - * Copyright (C) 2006 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include - -/* - * SH7343/SH7722 uses a common set of multipliers and divisors, so this - * is quite simple.. - */ -static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; - -#define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1) - -static void master_clk_init(struct clk *clk) -{ - clk->parent = clk_get(NULL, "cpu_clk"); -} - -static void master_clk_recalc(struct clk *clk) -{ - int idx = (ctrl_inl(FRQCR) & 0x000f); - clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx]; -} - -static struct clk_ops sh7343_master_clk_ops = { - .init = master_clk_init, - .recalc = master_clk_recalc, -}; - -static void module_clk_init(struct clk *clk) -{ - clk->parent = NULL; - clk->rate = CONFIG_SH_PCLK_FREQ; -} - -static struct clk_ops sh7343_module_clk_ops = { - .init = module_clk_init, -}; - -static void bus_clk_init(struct clk *clk) -{ - clk->parent = clk_get(NULL, "cpu_clk"); -} - -static void bus_clk_recalc(struct clk *clk) -{ - int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f; - clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx]; -} - -static struct clk_ops sh7343_bus_clk_ops = { - .init = bus_clk_init, - .recalc = bus_clk_recalc, -}; - -static void cpu_clk_init(struct clk *clk) -{ - clk->parent = clk_get(NULL, "module_clk"); - clk->flags |= CLK_RATE_PROPAGATES; - clk_set_rate(clk, clk_get_rate(clk)); -} - -static void cpu_clk_recalc(struct clk *clk) -{ - int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f; - clk->rate = clk->parent->rate * pll_calc() * - multipliers[idx] / divisors[idx]; -} - -static struct clk_ops sh7343_cpu_clk_ops = { - .init = cpu_clk_init, - .recalc = cpu_clk_recalc, -}; - -static struct clk_ops *sh7343_clk_ops[] = { - &sh7343_master_clk_ops, - &sh7343_module_clk_ops, - &sh7343_bus_clk_ops, - &sh7343_cpu_clk_ops, -}; - -void __init arch_init_clk_ops(struct clk_ops **ops, int idx) -{ - if (idx < ARRAY_SIZE(sh7343_clk_ops)) - *ops = sh7343_clk_ops[idx]; -} diff --git a/trunk/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/trunk/arch/sh/kernel/cpu/sh4a/setup-sh7722.c deleted file mode 100644 index 1143fbf65faf..000000000000 --- a/trunk/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SH7722 Setup - * - * Copyright (C) 2006 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include - -static struct plat_sci_port sci_platform_data[] = { - { - .mapbase = 0xffe00000, - .flags = UPF_BOOT_AUTOCONF, - .type = PORT_SCIF, - .irqs = { 80, 81, 83, 82 }, - }, { - .flags = 0, - } -}; - -static struct platform_device sci_device = { - .name = "sh-sci", - .id = -1, - .dev = { - .platform_data = sci_platform_data, - }, -}; - -static struct platform_device *sh7722_devices[] __initdata = { - &sci_device, -}; - -static int __init sh7722_devices_setup(void) -{ - return platform_add_devices(sh7722_devices, - ARRAY_SIZE(sh7722_devices)); -} -__initcall(sh7722_devices_setup); - -static struct ipr_data sh7722_ipr_map[] = { - /* IRQ, IPR-idx, shift, prio */ - { 16, 0, 12, 2 }, /* TMU0 */ - { 17, 0, 8, 2 }, /* TMU1 */ - { 80, 6, 12, 3 }, /* SCIF ERI */ - { 81, 6, 12, 3 }, /* SCIF RXI */ - { 82, 6, 12, 3 }, /* SCIF BRI */ - { 83, 6, 12, 3 }, /* SCIF TXI */ -}; - -static unsigned long ipr_offsets[] = { - 0xa4080000, /* 0: IPRA */ - 0xa4080004, /* 1: IPRB */ - 0xa4080008, /* 2: IPRC */ - 0xa408000c, /* 3: IPRD */ - 0xa4080010, /* 4: IPRE */ - 0xa4080014, /* 5: IPRF */ - 0xa4080018, /* 6: IPRG */ - 0xa408001c, /* 7: IPRH */ - 0xa4080020, /* 8: IPRI */ - 0xa4080024, /* 9: IPRJ */ - 0xa4080028, /* 10: IPRK */ - 0xa408002c, /* 11: IPRL */ -}; - -unsigned int map_ipridx_to_addr(int idx) -{ - if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) - return 0; - return ipr_offsets[idx]; -} - -void __init init_IRQ_ipr(void) -{ - make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map)); -} diff --git a/trunk/arch/sh/kernel/early_printk.c b/trunk/arch/sh/kernel/early_printk.c index 560b91cdd15c..60340823798a 100644 --- a/trunk/arch/sh/kernel/early_printk.c +++ b/trunk/arch/sh/kernel/early_printk.c @@ -144,16 +144,16 @@ static struct console *early_console = ; static int __initdata keep_early; -static int early_console_initialized; -int __init setup_early_printk(char *buf) +int __init setup_early_printk(char *opt) { - if (!buf) - return 0; + char *space; + char buf[256]; - if (early_console_initialized) - return 0; - early_console_initialized = 1; + strlcpy(buf, opt, sizeof(buf)); + space = strchr(buf, ' '); + if (space) + *space = 0; if (strstr(buf, "keep")) keep_early = 1; @@ -175,14 +175,12 @@ int __init setup_early_printk(char *buf) if (likely(early_console)) register_console(early_console); - return 0; + return 1; } -early_param("earlyprintk", setup_early_printk); +__setup("earlyprintk=", setup_early_printk); void __init disable_early_printk(void) { - if (!early_console_initialized || !early_console) - return; if (!keep_early) { printk("disabling early console\n"); unregister_console(early_console); diff --git a/trunk/arch/sh/kernel/entry-common.S b/trunk/arch/sh/kernel/entry-common.S index fc279aeb73ab..29136a35d7c7 100644 --- a/trunk/arch/sh/kernel/entry-common.S +++ b/trunk/arch/sh/kernel/entry-common.S @@ -79,29 +79,18 @@ debug_kernel_sw: .align 2 3: .long kgdb_handle_exception #endif /* CONFIG_SH_KGDB */ -#ifdef CONFIG_SH_STANDARD_BIOS - bra debug_kernel_fw - nop -#endif + #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ + .align 2 debug_trap: #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) - mov r8, r0 - shlr2 r0 - cmp/eq #0x3f, r0 ! sh_bios() trap - bf 1f -#ifdef CONFIG_SH_KGDB - cmp/eq #0xff, r0 ! XXX: KGDB trap, fix for SH-2. - bf 1f -#endif mov #OFF_SR, r0 mov.l @(r0,r15), r0 ! get status register shll r0 shll r0 ! kernel space? bt/s debug_kernel -1: #endif mov.l @r15, r0 ! Restore R0 value mov.l 1f, r8 diff --git a/trunk/arch/sh/kernel/head.S b/trunk/arch/sh/kernel/head.S index 71a3ad7d283e..6aca4bc6ec5d 100644 --- a/trunk/arch/sh/kernel/head.S +++ b/trunk/arch/sh/kernel/head.S @@ -33,8 +33,7 @@ ENTRY(empty_zero_page) .long 0x00360000 /* INITRD_START */ .long 0x000a0000 /* INITRD_SIZE */ .long 0 -1: - .skip PAGE_SIZE - empty_zero_page - 1b + .balign PAGE_SIZE,0,PAGE_SIZE .text /* diff --git a/trunk/arch/sh/kernel/process.c b/trunk/arch/sh/kernel/process.c index 486c06e18033..f3e2631be144 100644 --- a/trunk/arch/sh/kernel/process.c +++ b/trunk/arch/sh/kernel/process.c @@ -470,10 +470,9 @@ unsigned long get_wchan(struct task_struct *p) */ pc = thread_saved_pc(p); if (in_sched_functions(pc)) { - schedule_frame = (unsigned long)p->thread.sp; - return ((unsigned long *)schedule_frame)[21]; + schedule_frame = ((unsigned long *)(long)p->thread.sp)[1]; + return (unsigned long)((unsigned long *)schedule_frame)[1]; } - return pc; } @@ -499,16 +498,6 @@ asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, { struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - /* Rewind */ regs->pc -= 2; - -#ifdef CONFIG_BUG - if (__kernel_text_address(instruction_pointer(regs))) { - u16 insn = *(u16 *)instruction_pointer(regs); - if (insn == TRAPA_BUG_OPCODE) - handle_BUG(regs); - } -#endif - force_sig(SIGTRAP, current); } diff --git a/trunk/arch/sh/kernel/setup.c b/trunk/arch/sh/kernel/setup.c index 225f9ea5cdd7..f8dd6b7bfab0 100644 --- a/trunk/arch/sh/kernel/setup.c +++ b/trunk/arch/sh/kernel/setup.c @@ -84,7 +84,8 @@ unsigned long memory_start, memory_end; static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], struct sh_machine_vector** mvp, - unsigned long *mv_io_base) + unsigned long *mv_io_base, + int *mv_mmio_enable) { char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; @@ -111,6 +112,23 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], } } +#ifdef CONFIG_EARLY_PRINTK + if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) { + char *ep_end; + + if (to != command_line) + to--; + + from += 12; + ep_end = strchr(from, ' '); + + setup_early_printk(from); + printk("early console enabled\n"); + + from = ep_end; + } +#endif + if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { char* mv_end; char* mv_comma; @@ -127,6 +145,7 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], int ints[3]; get_options(mv_comma+1, ARRAY_SIZE(ints), ints); *mv_io_base = ints[1]; + *mv_mmio_enable = ints[2]; mv_len = mv_comma - from; } else { mv_len = mv_end - from; @@ -139,7 +158,6 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], *mvp = get_mv_byname(mv_name); } - c = *(from++); if (!c) break; @@ -159,8 +177,9 @@ static int __init sh_mv_setup(char **cmdline_p) struct sh_machine_vector *mv = NULL; char mv_name[MV_NAME_SIZE] = ""; unsigned long mv_io_base = 0; + int mv_mmio_enable = 0; - parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base); + parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable); #ifdef CONFIG_SH_UNKNOWN if (mv == NULL) { @@ -239,7 +258,6 @@ void __init setup_arch(char **cmdline_p) sh_mv_setup(cmdline_p); - /* * Find the highest page frame number we have available */ @@ -287,7 +305,6 @@ void __init setup_arch(char **cmdline_p) PFN_PHYS(pages)); } - /* * Reserve the kernel text and * Reserve the bootmem bitmap. We do this in two steps (first step @@ -308,18 +325,14 @@ void __init setup_arch(char **cmdline_p) ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); if (&__rd_start != &__rd_end) { LOADER_TYPE = 1; - INITRD_START = PHYSADDR((unsigned long)&__rd_start) - - __MEMORY_START; - INITRD_SIZE = (unsigned long)&__rd_end - - (unsigned long)&__rd_start; + INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START; + INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start; } if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { - reserve_bootmem_node(NODE_DATA(0), INITRD_START + - __MEMORY_START, INITRD_SIZE); - initrd_start = INITRD_START + PAGE_OFFSET + - __MEMORY_START; + reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE); + initrd_start = INITRD_START + PAGE_OFFSET + __MEMORY_START; initrd_end = initrd_start + INITRD_SIZE; } else { printk("initrd extends beyond end of memory " @@ -391,7 +404,7 @@ static const char *cpu_name[] = { [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", - [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", + [CPU_SH7785] = "SH7785", [CPU_SH_NONE] = "Unknown" }; diff --git a/trunk/arch/sh/kernel/sh_ksyms.c b/trunk/arch/sh/kernel/sh_ksyms.c index e6106239a0fe..ceee79143401 100644 --- a/trunk/arch/sh/kernel/sh_ksyms.c +++ b/trunk/arch/sh/kernel/sh_ksyms.c @@ -70,26 +70,13 @@ DECLARE_EXPORT(__sdivsi3); DECLARE_EXPORT(__ashrdi3); DECLARE_EXPORT(__ashldi3); DECLARE_EXPORT(__lshrdi3); -DECLARE_EXPORT(__movstrSI16); -#if __GNUC__ == 4 -DECLARE_EXPORT(__movmem); -#else DECLARE_EXPORT(__movstr); -#endif +DECLARE_EXPORT(__movstrSI16); #ifdef CONFIG_CPU_SH4 -#if __GNUC__ == 4 -DECLARE_EXPORT(__movmem_i4_even); -DECLARE_EXPORT(__movmem_i4_odd); -DECLARE_EXPORT(__movmemSI12_i4); -DECLARE_EXPORT(__sdivsi3_i4i); -DECLARE_EXPORT(__udiv_qrnnd_16); -DECLARE_EXPORT(__udivsi3_i4i); -#else /* GCC 3.x */ DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); DECLARE_EXPORT(__movstrSI12_i4); -#endif /* __GNUC__ == 4 */ #endif #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) diff --git a/trunk/arch/sh/kernel/signal.c b/trunk/arch/sh/kernel/signal.c index 379c88bf5d9a..bb1c480a59c7 100644 --- a/trunk/arch/sh/kernel/signal.c +++ b/trunk/arch/sh/kernel/signal.c @@ -101,7 +101,7 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, */ #define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ -#if defined(CONFIG_CPU_SH2) +#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) #define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */ #else #define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */ diff --git a/trunk/arch/sh/kernel/sys_sh.c b/trunk/arch/sh/kernel/sys_sh.c index e18f183e1035..5083b6ed4b39 100644 --- a/trunk/arch/sh/kernel/sys_sh.c +++ b/trunk/arch/sh/kernel/sys_sh.c @@ -314,12 +314,6 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1, #endif } -#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) -#define SYSCALL_ARG3 "trapa #0x23" -#else -#define SYSCALL_ARG3 "trapa #0x13" -#endif - /* * Do a system call from kernel instead of calling sys_execve so we * end up with proper pt_regs. @@ -330,7 +324,7 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]) register long __sc4 __asm__ ("r4") = (long) filename; register long __sc5 __asm__ ("r5") = (long) argv; register long __sc6 __asm__ ("r6") = (long) envp; - __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0) + __asm__ __volatile__ ("trapa #0x13" : "=z" (__sc0) : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) : "memory"); return __sc0; diff --git a/trunk/arch/sh/kernel/traps.c b/trunk/arch/sh/kernel/traps.c index ec110157992d..3762d9dc2046 100644 --- a/trunk/arch/sh/kernel/traps.c +++ b/trunk/arch/sh/kernel/traps.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -130,40 +129,6 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) return -EFAULT; } -#ifdef CONFIG_BUG -#ifdef CONFIG_DEBUG_BUGVERBOSE -static inline void do_bug_verbose(struct pt_regs *regs) -{ - struct bug_frame f; - long len; - - if (__copy_from_user(&f, (const void __user *)regs->pc, - sizeof(struct bug_frame))) - return; - - len = __strnlen_user(f.file, PATH_MAX) - 1; - if (unlikely(len < 0 || len >= PATH_MAX)) - f.file = ""; - len = __strnlen_user(f.func, PATH_MAX) - 1; - if (unlikely(len < 0 || len >= PATH_MAX)) - f.func = ""; - - printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n", - f.func, f.file, f.line); -} -#else -static inline void do_bug_verbose(struct pt_regs *regs) -{ -} -#endif /* CONFIG_DEBUG_BUGVERBOSE */ -#endif /* CONFIG_BUG */ - -void handle_BUG(struct pt_regs *regs) -{ - do_bug_verbose(regs); - die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); -} - /* * handle an instruction that does an unaligned memory access by emulating the * desired behaviour diff --git a/trunk/arch/sh/kernel/vmlinux.lds.S b/trunk/arch/sh/kernel/vmlinux.lds.S index f34bdcc33a7d..77b4026d5688 100644 --- a/trunk/arch/sh/kernel/vmlinux.lds.S +++ b/trunk/arch/sh/kernel/vmlinux.lds.S @@ -51,7 +51,7 @@ SECTIONS } . = ALIGN(PAGE_SIZE); - .data.page_aligned : { *(.data.page_aligned) } + .data.page_aligned : { *(.data.idt) } . = ALIGN(32); __per_cpu_start = .; diff --git a/trunk/arch/sh/mm/Kconfig b/trunk/arch/sh/mm/Kconfig index 29f4ee35c6dc..4e0362f50384 100644 --- a/trunk/arch/sh/mm/Kconfig +++ b/trunk/arch/sh/mm/Kconfig @@ -35,9 +35,6 @@ config CPU_SUBTYPE_ST40 select CPU_SH4 select CPU_HAS_INTC2_IRQ -config CPU_SHX2 - bool - # # Processor subtypes # @@ -183,7 +180,6 @@ config CPU_SUBTYPE_SH7780 config CPU_SUBTYPE_SH7785 bool "Support SH7785 processor" select CPU_SH4A - select CPU_SHX2 select CPU_HAS_INTC2_IRQ comment "SH4AL-DSP Processor Support" @@ -196,12 +192,6 @@ config CPU_SUBTYPE_SH7343 bool "Support SH7343 processor" select CPU_SH4AL_DSP -config CPU_SUBTYPE_SH7722 - bool "Support SH7722 processor" - select CPU_SH4AL_DSP - select CPU_SHX2 - select CPU_HAS_IPR_IRQ - endmenu menu "Memory management options" @@ -260,7 +250,7 @@ config 32BIT config X2TLB bool "Enable extended TLB mode" - depends on CPU_SHX2 && MMU && EXPERIMENTAL + depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL help Selecting this option will enable the extended mode of the SH-X2 TLB. For legacy SH-X behaviour and interoperability, say N. For diff --git a/trunk/arch/sh/mm/cache-sh4.c b/trunk/arch/sh/mm/cache-sh4.c index c6955157c989..ae531affccbd 100644 --- a/trunk/arch/sh/mm/cache-sh4.c +++ b/trunk/arch/sh/mm/cache-sh4.c @@ -107,7 +107,7 @@ void __init p3_cache_init(void) emit_cache_params(); - if (ioremap_page_range(P3SEG, P3SEG + (PAGE_SIZE * 4), 0, PAGE_KERNEL)) + if (remap_area_pages(P3SEG, 0, PAGE_SIZE * 4, _PAGE_CACHABLE)) panic("%s failed.", __FUNCTION__); for (i = 0; i < cpu_data->dcache.n_aliases; i++) diff --git a/trunk/arch/sh/mm/init.c b/trunk/arch/sh/mm/init.c index 29bd37b1488e..59f4cc18235b 100644 --- a/trunk/arch/sh/mm/init.c +++ b/trunk/arch/sh/mm/init.c @@ -77,7 +77,6 @@ void show_mem(void) printk("%d pages swap cached\n",cached); } -#ifdef CONFIG_MMU static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) { pgd_t *pgd; @@ -140,7 +139,6 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) set_pte_phys(address, phys, prot); } -#endif /* CONFIG_MMU */ /* References to section boundaries */ diff --git a/trunk/arch/sparc/kernel/ioport.c b/trunk/arch/sparc/kernel/ioport.c index cbbc98846b00..54d51b404603 100644 --- a/trunk/arch/sparc/kernel/ioport.c +++ b/trunk/arch/sparc/kernel/ioport.c @@ -317,8 +317,9 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) if ((va = __get_free_pages(GFP_KERNEL|__GFP_COMP, order)) == 0) goto err_nopages; - if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) + if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) goto err_nomem; + memset((char*)res, 0, sizeof(struct resource)); if (allocate_resource(&_sparc_dvma, res, len_total, _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) { @@ -588,11 +589,12 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba) return NULL; } - if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { + if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { free_pages(va, order); printk("pci_alloc_consistent: no core\n"); return NULL; } + memset((char*)res, 0, sizeof(struct resource)); if (allocate_resource(&_sparc_dvma, res, len_total, _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) { diff --git a/trunk/arch/sparc/kernel/irq.c b/trunk/arch/sparc/kernel/irq.c index 5b4841d067c1..c8cb211b9072 100644 --- a/trunk/arch/sparc/kernel/irq.c +++ b/trunk/arch/sparc/kernel/irq.c @@ -425,7 +425,7 @@ int request_fast_irq(unsigned int irq, } if (action == NULL) - action = kmalloc(sizeof(struct irqaction), + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) { @@ -528,7 +528,7 @@ int request_irq(unsigned int irq, } if (action == NULL) - action = kmalloc(sizeof(struct irqaction), + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) { diff --git a/trunk/arch/sparc/kernel/of_device.c b/trunk/arch/sparc/kernel/of_device.c index dab6169e31ca..46200c43ffb1 100644 --- a/trunk/arch/sparc/kernel/of_device.c +++ b/trunk/arch/sparc/kernel/of_device.c @@ -793,9 +793,10 @@ struct of_device* of_platform_device_create(struct device_node *np, { struct of_device *dev; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; + memset(dev, 0, sizeof(*dev)); dev->dev.parent = parent; dev->dev.bus = bus; diff --git a/trunk/arch/sparc/kernel/ptrace.c b/trunk/arch/sparc/kernel/ptrace.c index 003f8eed32f4..1baf13ed5c3a 100644 --- a/trunk/arch/sparc/kernel/ptrace.c +++ b/trunk/arch/sparc/kernel/ptrace.c @@ -289,10 +289,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) if (request == PTRACE_TRACEME) { ret = ptrace_traceme(); - if (ret < 0) - pt_error_return(regs, -ret); - else - pt_succ_return(regs, 0); + pt_succ_return(regs, 0); goto out; } diff --git a/trunk/arch/sparc/kernel/sun4d_irq.c b/trunk/arch/sparc/kernel/sun4d_irq.c index 0e27e226e0e2..d4f9da8170c5 100644 --- a/trunk/arch/sparc/kernel/sun4d_irq.c +++ b/trunk/arch/sparc/kernel/sun4d_irq.c @@ -327,7 +327,7 @@ int sun4d_request_irq(unsigned int irq, } if (action == NULL) - action = kmalloc(sizeof(struct irqaction), + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) { @@ -545,11 +545,8 @@ void __init sun4d_init_sbi_irq(void) nsbi = 0; for_each_sbus(sbus) nsbi++; - sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); - if (!sbus_actions) { - prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n"); - prom_halt(); - } + sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); + memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action))); for_each_sbus(sbus) { #ifdef CONFIG_SMP extern unsigned char boot_cpu_id; diff --git a/trunk/arch/sparc/mm/io-unit.c b/trunk/arch/sparc/mm/io-unit.c index 4ccda77d08d6..2bb1309003dd 100644 --- a/trunk/arch/sparc/mm/io-unit.c +++ b/trunk/arch/sparc/mm/io-unit.c @@ -22,7 +22,6 @@ #include #include #include -#include /* #define IOUNIT_DEBUG */ #ifdef IOUNIT_DEBUG @@ -42,12 +41,9 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus) struct linux_prom_registers iommu_promregs[PROMREG_MAX]; struct resource r; - iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC); - if (!iounit) { - prom_printf("SUN4D: Cannot alloc iounit, halting.\n"); - prom_halt(); - } + iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC); + memset(iounit, 0, sizeof(*iounit)); iounit->limit[0] = IOUNIT_BMAP1_START; iounit->limit[1] = IOUNIT_BMAP2_START; iounit->limit[2] = IOUNIT_BMAPM_START; diff --git a/trunk/arch/sparc64/Kconfig b/trunk/arch/sparc64/Kconfig index d41f66ac7fff..d391d11f245a 100644 --- a/trunk/arch/sparc64/Kconfig +++ b/trunk/arch/sparc64/Kconfig @@ -26,14 +26,6 @@ config MMU bool default y -config STACKTRACE_SUPPORT - bool - default y - -config LOCKDEP_SUPPORT - bool - default y - config TIME_INTERPOLATION bool default y diff --git a/trunk/arch/sparc64/Kconfig.debug b/trunk/arch/sparc64/Kconfig.debug index 1f130f3b6c24..afe0a7720a26 100644 --- a/trunk/arch/sparc64/Kconfig.debug +++ b/trunk/arch/sparc64/Kconfig.debug @@ -1,9 +1,5 @@ menu "Kernel hacking" -config TRACE_IRQFLAGS_SUPPORT - bool - default y - source "lib/Kconfig.debug" config DEBUG_STACK_USAGE diff --git a/trunk/arch/sparc64/defconfig b/trunk/arch/sparc64/defconfig index 0f0d38f6197c..2f4612fa81f2 100644 --- a/trunk/arch/sparc64/defconfig +++ b/trunk/arch/sparc64/defconfig @@ -1,29 +1,24 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19 -# Sat Dec 9 15:41:30 2006 +# Linux kernel version: 2.6.19-rc2 +# Tue Oct 17 19:29:20 2006 # CONFIG_SPARC=y CONFIG_SPARC64=y CONFIG_64BIT=y CONFIG_MMU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y CONFIG_TIME_INTERPOLATION=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_AUDIT_ARCH=y CONFIG_SPARC64_PAGE_SIZE_8KB=y # CONFIG_SPARC64_PAGE_SIZE_64KB is not set # CONFIG_SPARC64_PAGE_SIZE_512KB is not set # CONFIG_SPARC64_PAGE_SIZE_4MB is not set CONFIG_SECCOMP=y -CONFIG_HZ_100=y -# CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y # CONFIG_HZ_1000 is not set -CONFIG_HZ=100 +CONFIG_HZ=250 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -47,14 +42,13 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set -CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -209,7 +203,6 @@ CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y @@ -226,6 +219,7 @@ CONFIG_INET6_XFRM_MODE_BEET=m # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_SIT=m CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set @@ -244,8 +238,6 @@ CONFIG_IP_DCCP_CCID2=m # CONFIG_IP_DCCP_CCID2_DEBUG is not set CONFIG_IP_DCCP_CCID3=m CONFIG_IP_DCCP_TFRC_LIB=m -# CONFIG_IP_DCCP_CCID3_DEBUG is not set -CONFIG_IP_DCCP_CCID3_RTO=100 # # DCCP Kernel Hacking @@ -413,7 +405,6 @@ CONFIG_IDEDMA_AUTO=y # CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -# CONFIG_SCSI_TGT is not set CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y @@ -434,7 +425,6 @@ CONFIG_CHR_DEV_SG=m CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set # # SCSI Transports @@ -478,7 +468,6 @@ CONFIG_ISCSI_TCP=m # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SUNESP is not set -# CONFIG_SCSI_SRP is not set # # Serial ATA (prod) and Parallel ATA (experimental) drivers @@ -609,7 +598,6 @@ CONFIG_BNX2=m # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set -# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -736,6 +724,10 @@ CONFIG_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -1046,11 +1038,6 @@ CONFIG_SND_SUN_CS4231=m # # CONFIG_SOUND_PRIME is not set -# -# HID Devices -# -CONFIG_HID=y - # # USB support # @@ -1066,7 +1053,6 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_MULTITHREAD_PROBE is not set # CONFIG_USB_OTG is not set # @@ -1103,7 +1089,8 @@ CONFIG_USB_UHCI_HCD=m # USB Input Devices # CONFIG_USB_HID=y -# CONFIG_USB_HID_POWERBOOK is not set +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set @@ -1132,7 +1119,6 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set # CONFIG_USB_MON is not set @@ -1377,11 +1363,6 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set -# -# Distributed Lock Manager -# -# CONFIG_DLM is not set - # # Instrumentation Support # @@ -1392,7 +1373,6 @@ CONFIG_KPROBES=y # # Kernel hacking # -CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_PRINTK_TIME=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y @@ -1407,8 +1387,6 @@ CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_RWSEMS is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1442,9 +1420,8 @@ CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER=m CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y @@ -1453,10 +1430,8 @@ CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_GF128MUL=m CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m @@ -1481,7 +1456,6 @@ CONFIG_CRYPTO_TEST=m # # Library routines # -CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m CONFIG_CRC16=m CONFIG_CRC32=y diff --git a/trunk/arch/sparc64/kernel/Makefile b/trunk/arch/sparc64/kernel/Makefile index eff0c01d3579..e1eabebaed39 100644 --- a/trunk/arch/sparc64/kernel/Makefile +++ b/trunk/arch/sparc64/kernel/Makefile @@ -14,7 +14,6 @@ obj-y := process.o setup.o cpu.o idprom.o \ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ visemul.o prom.o of_device.o -obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ pci_sun4v.o pci_sun4v_asm.o diff --git a/trunk/arch/sparc64/kernel/chmc.c b/trunk/arch/sparc64/kernel/chmc.c index 9699abeb9907..259f37e516f5 100644 --- a/trunk/arch/sparc64/kernel/chmc.c +++ b/trunk/arch/sparc64/kernel/chmc.c @@ -341,7 +341,7 @@ static void fetch_decode_regs(struct mctrl_info *mp) static int init_one_mctrl(struct device_node *dp) { - struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL); + struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL); int portid = of_getintprop_default(dp, "portid", -1); struct linux_prom64_registers *regs; void *pval; @@ -349,6 +349,7 @@ static int init_one_mctrl(struct device_node *dp) if (!mp) return -1; + memset(mp, 0, sizeof(*mp)); if (portid == -1) goto fail; diff --git a/trunk/arch/sparc64/kernel/entry.S b/trunk/arch/sparc64/kernel/entry.S index c15a3edcb826..6f28bec0a9bf 100644 --- a/trunk/arch/sparc64/kernel/entry.S +++ b/trunk/arch/sparc64/kernel/entry.S @@ -597,12 +597,7 @@ __spitfire_cee_trap_continue: 1: ba,pt %xcc, etrap_irq rd %pc, %g7 -2: -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif - mov %l4, %o1 +2: mov %l4, %o1 mov %l5, %o2 call spitfire_access_error add %sp, PTREGS_OFF, %o0 @@ -829,10 +824,6 @@ do_cheetah_plus_data_parity: wrpr %g0, 15, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif mov 0x0, %o0 call cheetah_plus_parity_error add %sp, PTREGS_OFF, %o1 @@ -864,10 +855,6 @@ do_cheetah_plus_insn_parity: wrpr %g0, 15, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif mov 0x1, %o0 call cheetah_plus_parity_error add %sp, PTREGS_OFF, %o1 @@ -1196,10 +1183,6 @@ c_fast_ecc: wrpr %g0, 15, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif mov %l4, %o1 mov %l5, %o2 call cheetah_fecc_handler @@ -1228,10 +1211,6 @@ c_cee: wrpr %g0, 15, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif mov %l4, %o1 mov %l5, %o2 call cheetah_cee_handler @@ -1260,10 +1239,6 @@ c_deferred: wrpr %g0, 15, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif mov %l4, %o1 mov %l5, %o2 call cheetah_deferred_handler diff --git a/trunk/arch/sparc64/kernel/head.S b/trunk/arch/sparc64/kernel/head.S index 03ffaf895a22..c8e9dc9d68a9 100644 --- a/trunk/arch/sparc64/kernel/head.S +++ b/trunk/arch/sparc64/kernel/head.S @@ -489,14 +489,6 @@ tlb_fixup_done: call __bzero sub %o1, %o0, %o1 -#ifdef CONFIG_LOCKDEP - /* We have this call this super early, as even prom_init can grab - * spinlocks and thus call into the lockdep code. - */ - call lockdep_init - nop -#endif - mov %l6, %o1 ! OpenPROM stack call prom_init mov %l7, %o0 ! OpenPROM cif handler diff --git a/trunk/arch/sparc64/kernel/isa.c b/trunk/arch/sparc64/kernel/isa.c index ad1c4f55420f..f028e68b23f2 100644 --- a/trunk/arch/sparc64/kernel/isa.c +++ b/trunk/arch/sparc64/kernel/isa.c @@ -72,12 +72,14 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) struct linux_prom_registers *regs; struct sparc_isa_device *isa_dev; - isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); + isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { fatal_err("cannot allocate child isa_dev"); prom_halt(); } + memset(isa_dev, 0, sizeof(*isa_dev)); + /* Link it in to parent. */ isa_dev->next = parent_isa_dev->child; parent_isa_dev->child = isa_dev; @@ -102,12 +104,14 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) struct linux_prom_registers *regs; struct sparc_isa_device *isa_dev; - isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); + isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { printk(KERN_DEBUG "ISA: cannot allocate isa_dev"); return; } + memset(isa_dev, 0, sizeof(*isa_dev)); + isa_dev->ofdev.node = dp; isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; isa_dev->ofdev.dev.bus = &isa_bus_type; @@ -176,12 +180,14 @@ void __init isa_init(void) pbm = pdev_cookie->pbm; dp = pdev_cookie->prom_node; - isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL); + isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); if (!isa_br) { printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge"); return; } + memset(isa_br, 0, sizeof(*isa_br)); + isa_br->ofdev.node = dp; isa_br->ofdev.dev.parent = &pdev->dev; isa_br->ofdev.dev.bus = &isa_bus_type; diff --git a/trunk/arch/sparc64/kernel/kprobes.c b/trunk/arch/sparc64/kernel/kprobes.c index ae221f0d4a6f..8e75ed762fd8 100644 --- a/trunk/arch/sparc64/kernel/kprobes.c +++ b/trunk/arch/sparc64/kernel/kprobes.c @@ -45,11 +45,7 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); int __kprobes arch_prepare_kprobe(struct kprobe *p) { p->ainsn.insn[0] = *p->addr; - flushi(&p->ainsn.insn[0]); - p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2; - flushi(&p->ainsn.insn[1]); - p->opcode = *p->addr; return 0; } @@ -189,19 +185,16 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) /* If INSN is a relative control transfer instruction, * return the corrected branch destination value. * - * regs->tpc and regs->tnpc still hold the values of the - * program counters at the time of trap due to the execution - * of the BREAKPOINT_INSTRUCTION_2 at p->ainsn.insn[1] - * + * The original INSN location was REAL_PC, it actually + * executed at PC and produced destination address NPC. */ -static unsigned long __kprobes relbranch_fixup(u32 insn, struct kprobe *p, - struct pt_regs *regs) +static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc, + unsigned long pc, + unsigned long npc) { - unsigned long real_pc = (unsigned long) p->addr; - /* Branch not taken, no mods necessary. */ - if (regs->tnpc == regs->tpc + 0x4UL) - return real_pc + 0x8UL; + if (npc == pc + 0x4UL) + return real_pc + 0x4UL; /* The three cases are call, branch w/prediction, * and traditional branch. @@ -209,21 +202,14 @@ static unsigned long __kprobes relbranch_fixup(u32 insn, struct kprobe *p, if ((insn & 0xc0000000) == 0x40000000 || (insn & 0xc1c00000) == 0x00400000 || (insn & 0xc1c00000) == 0x00800000) { - unsigned long ainsn_addr; - - ainsn_addr = (unsigned long) &p->ainsn.insn[0]; - /* The instruction did all the work for us * already, just apply the offset to the correct * instruction location. */ - return (real_pc + (regs->tnpc - ainsn_addr)); + return (real_pc + (npc - pc)); } - /* It is jmpl or some other absolute PC modification instruction, - * leave NPC as-is. - */ - return regs->tnpc; + return real_pc + 0x4UL; } /* If INSN is an instruction which writes it's PC location @@ -234,12 +220,12 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn, { unsigned long *slot = NULL; - /* Simplest case is 'call', which always uses %o7 */ + /* Simplest cast is call, which always uses %o7 */ if ((insn & 0xc0000000) == 0x40000000) { slot = ®s->u_regs[UREG_I7]; } - /* 'jmpl' encodes the register inside of the opcode */ + /* Jmpl encodes the register inside of the opcode */ if ((insn & 0xc1f80000) == 0x81c00000) { unsigned long rd = ((insn >> 25) & 0x1f); @@ -261,11 +247,11 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn, /* * Called after single-stepping. p->addr is the address of the - * instruction which has been replaced by the breakpoint + * instruction whose first byte has been replaced by the breakpoint * instruction. To avoid the SMP problems that can occur when we * temporarily put back the original opcode to single-step, we * single-stepped a copy of the instruction. The address of this - * copy is &p->ainsn.insn[0]. + * copy is p->ainsn.insn. * * This function prepares to return from the post-single-step * breakpoint trap. @@ -275,11 +261,11 @@ static void __kprobes resume_execution(struct kprobe *p, { u32 insn = p->ainsn.insn[0]; - regs->tnpc = relbranch_fixup(insn, p, regs); - - /* This assignment must occur after relbranch_fixup() */ regs->tpc = kcb->kprobe_orig_tnpc; - + regs->tnpc = relbranch_fixup(insn, + (unsigned long) p->addr, + (unsigned long) &p->ainsn.insn[0], + regs->tnpc); retpc_fixup(regs, insn, (unsigned long) p->addr); regs->tstate = ((regs->tstate & ~TSTATE_PIL) | @@ -444,8 +430,17 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) struct jprobe *jp = container_of(p, struct jprobe, kp); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + kcb->jprobe_saved_regs_location = regs; memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs)); + /* Save a whole stack frame, this gets arguments + * pushed onto the stack after using up all the + * arg registers. + */ + memcpy(&(kcb->jprobe_saved_stack), + (char *) (regs->u_regs[UREG_FP] + STACK_BIAS), + sizeof(kcb->jprobe_saved_stack)); + regs->tpc = (unsigned long) jp->entry; regs->tnpc = ((unsigned long) jp->entry) + 0x4UL; regs->tstate |= TSTATE_PIL; @@ -455,19 +450,10 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) void __kprobes jprobe_return(void) { - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - register unsigned long orig_fp asm("g1"); - - orig_fp = kcb->jprobe_saved_regs.u_regs[UREG_FP]; - __asm__ __volatile__("\n" -"1: cmp %%sp, %0\n\t" - "blu,a,pt %%xcc, 1b\n\t" - " restore\n\t" - ".globl jprobe_return_trap_instruction\n" + __asm__ __volatile__( + ".globl jprobe_return_trap_instruction\n" "jprobe_return_trap_instruction:\n\t" - "ta 0x70" - : /* no outputs */ - : "r" (orig_fp)); + "ta 0x70"); } extern void jprobe_return_trap_instruction(void); @@ -480,7 +466,26 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); if (addr == (u32 *) jprobe_return_trap_instruction) { + if (kcb->jprobe_saved_regs_location != regs) { + printk("JPROBE: Current regs (%p) does not match " + "saved regs (%p).\n", + regs, kcb->jprobe_saved_regs_location); + printk("JPROBE: Saved registers\n"); + __show_regs(kcb->jprobe_saved_regs_location); + printk("JPROBE: Current registers\n"); + __show_regs(regs); + BUG(); + } + /* Restore old register state. Do pt_regs + * first so that UREG_FP is the original one for + * the stack frame restore. + */ memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs)); + + memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS), + &(kcb->jprobe_saved_stack), + sizeof(kcb->jprobe_saved_stack)); + preempt_enable_no_resched(); return 1; } diff --git a/trunk/arch/sparc64/kernel/of_device.c b/trunk/arch/sparc64/kernel/of_device.c index cec0eceae552..8cc14fc6b6f1 100644 --- a/trunk/arch/sparc64/kernel/of_device.c +++ b/trunk/arch/sparc64/kernel/of_device.c @@ -1007,9 +1007,10 @@ struct of_device* of_platform_device_create(struct device_node *np, { struct of_device *dev; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; + memset(dev, 0, sizeof(*dev)); dev->dev.parent = parent; dev->dev.bus = bus; diff --git a/trunk/arch/sparc64/kernel/pci_sun4v.c b/trunk/arch/sparc64/kernel/pci_sun4v.c index 6b04794b7a97..03ad4c06758e 100644 --- a/trunk/arch/sparc64/kernel/pci_sun4v.c +++ b/trunk/arch/sparc64/kernel/pci_sun4v.c @@ -798,7 +798,7 @@ static struct pci_ops pci_sun4v_ops = { static void pbm_scan_bus(struct pci_controller_info *p, struct pci_pbm_info *pbm) { - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); + struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL); if (!cookie) { prom_printf("%s: Critical allocation failure.\n", pbm->name); @@ -806,6 +806,7 @@ static void pbm_scan_bus(struct pci_controller_info *p, } /* All we care about is the PBM. */ + memset(cookie, 0, sizeof(*cookie)); cookie->pbm = pbm; pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm); @@ -1047,11 +1048,12 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) /* Allocate and initialize the free area map. */ sz = num_tsb_entries / 8; sz = (sz + 7UL) & ~7UL; - iommu->arena.map = kzalloc(sz, GFP_KERNEL); + iommu->arena.map = kmalloc(sz, GFP_KERNEL); if (!iommu->arena.map) { prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); prom_halt(); } + memset(iommu->arena.map, 0, sz); iommu->arena.limit = num_tsb_entries; sz = probe_existing_entries(pbm, iommu); @@ -1162,20 +1164,24 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) per_cpu(pci_iommu_batch, i).pglist = (u64 *) page; } - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); + p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) goto fatal_memory_error; - iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); + memset(p, 0, sizeof(*p)); + + iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC); if (!iommu) goto fatal_memory_error; + memset(iommu, 0, sizeof(*iommu)); p->pbm_A.iommu = iommu; - iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); + iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC); if (!iommu) goto fatal_memory_error; + memset(iommu, 0, sizeof(*iommu)); p->pbm_B.iommu = iommu; p->next = pci_controller_root; diff --git a/trunk/arch/sparc64/kernel/ptrace.c b/trunk/arch/sparc64/kernel/ptrace.c index 81111a12f0a8..d31975e6d6f6 100644 --- a/trunk/arch/sparc64/kernel/ptrace.c +++ b/trunk/arch/sparc64/kernel/ptrace.c @@ -202,10 +202,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) #endif if (request == PTRACE_TRACEME) { ret = ptrace_traceme(); - if (ret < 0) - pt_error_return(regs, -ret); - else - pt_succ_return(regs, 0); + pt_succ_return(regs, 0); goto out; } diff --git a/trunk/arch/sparc64/kernel/rtrap.S b/trunk/arch/sparc64/kernel/rtrap.S index 079d18a11d24..3522cd66f3bb 100644 --- a/trunk/arch/sparc64/kernel/rtrap.S +++ b/trunk/arch/sparc64/kernel/rtrap.S @@ -165,26 +165,14 @@ rtrap: __handle_softirq_continue: rtrap_xcall: sethi %hi(0xf << 20), %l4 - and %l1, %l4, %l4 - andn %l1, %l4, %l1 - srl %l4, 20, %l4 -#ifdef CONFIG_TRACE_IRQFLAGS - brnz,pn %l4, rtrap_no_irq_enable - nop - call trace_hardirqs_on - nop - wrpr %l4, %pil -rtrap_no_irq_enable: -#endif andcc %l1, TSTATE_PRIV, %l3 + and %l1, %l4, %l4 bne,pn %icc, to_kernel - nop + andn %l1, %l4, %l1 /* We must hold IRQs off and atomically test schedule+signal * state, then hold them off all the way back to userspace. - * If we are returning to kernel, none of this matters. Note - * that we are disabling interrupts via PSTATE_IE, not using - * %pil. + * If we are returning to kernel, none of this matters. * * If we do not do this, there is a window where we would do * the tests, later the signal/resched event arrives but we do @@ -268,6 +256,7 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ld [%sp + PTREGS_OFF + PT_V9_Y], %o3 wr %o3, %g0, %y + srl %l4, 20, %l4 wrpr %l4, 0x0, %pil wrpr %g0, 0x1, %tl wrpr %l1, %g0, %tstate @@ -385,8 +374,8 @@ to_kernel: ldx [%g6 + TI_FLAGS], %l5 andcc %l5, _TIF_NEED_RESCHED, %g0 be,pt %xcc, kern_fpucheck - nop - cmp %l4, 0 + srl %l4, 20, %l5 + cmp %l5, 0 bne,pn %xcc, kern_fpucheck sethi %hi(PREEMPT_ACTIVE), %l6 stw %l6, [%g6 + TI_PRE_COUNT] diff --git a/trunk/arch/sparc64/kernel/stacktrace.c b/trunk/arch/sparc64/kernel/stacktrace.c deleted file mode 100644 index c4d15f2762b9..000000000000 --- a/trunk/arch/sparc64/kernel/stacktrace.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include -#include - -void save_stack_trace(struct stack_trace *trace, struct task_struct *task) -{ - unsigned long ksp, fp, thread_base; - struct thread_info *tp; - - if (!task) - task = current; - tp = task_thread_info(task); - if (task == current) { - flushw_all(); - __asm__ __volatile__( - "mov %%fp, %0" - : "=r" (ksp) - ); - } else - ksp = tp->ksp; - - fp = ksp + STACK_BIAS; - thread_base = (unsigned long) tp; - do { - struct reg_window *rw; - - /* Bogus frame pointer? */ - if (fp < (thread_base + sizeof(struct thread_info)) || - fp >= (thread_base + THREAD_SIZE)) - break; - - rw = (struct reg_window *) fp; - if (trace->skip > 0) - trace->skip--; - else - trace->entries[trace->nr_entries++] = rw->ins[7]; - - fp = rw->ins[6] + STACK_BIAS; - } while (trace->nr_entries < trace->max_entries); -} diff --git a/trunk/arch/sparc64/kernel/sun4v_ivec.S b/trunk/arch/sparc64/kernel/sun4v_ivec.S index 405855dd886b..49703c3c5769 100644 --- a/trunk/arch/sparc64/kernel/sun4v_ivec.S +++ b/trunk/arch/sparc64/kernel/sun4v_ivec.S @@ -190,10 +190,7 @@ sun4v_res_mondo: mov %g1, %g4 ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif + /* Log the event. */ add %sp, PTREGS_OFF, %o0 call sun4v_resum_error @@ -219,10 +216,7 @@ sun4v_res_mondo_queue_full: wrpr %g0, 15, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif + call sun4v_resum_overflow add %sp, PTREGS_OFF, %o0 @@ -301,10 +295,7 @@ sun4v_nonres_mondo: mov %g1, %g4 ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif + /* Log the event. */ add %sp, PTREGS_OFF, %o0 call sun4v_nonresum_error @@ -330,10 +321,7 @@ sun4v_nonres_mondo_queue_full: wrpr %g0, 15, %pil ba,pt %xcc, etrap_irq rd %pc, %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif + call sun4v_nonresum_overflow add %sp, PTREGS_OFF, %o0 diff --git a/trunk/arch/sparc64/kernel/sys_sunos32.c b/trunk/arch/sparc64/kernel/sys_sunos32.c index 2ebc2c051383..4446f66590fa 100644 --- a/trunk/arch/sparc64/kernel/sys_sunos32.c +++ b/trunk/arch/sparc64/kernel/sys_sunos32.c @@ -1055,7 +1055,7 @@ asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4) break; case 2: rval = -EFAULT; - kmbuf = kmalloc(sizeof(struct msgbuf) + arg3, + kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3, GFP_KERNEL); if (!kmbuf) break; @@ -1078,7 +1078,7 @@ asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4) break; case 3: rval = -EFAULT; - kmbuf = kmalloc(sizeof(struct msgbuf) + arg3, + kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3, GFP_KERNEL); if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2, kmbuf, arg3)) diff --git a/trunk/arch/sparc64/kernel/traps.c b/trunk/arch/sparc64/kernel/traps.c index ad67784292db..fe1796c939c3 100644 --- a/trunk/arch/sparc64/kernel/traps.c +++ b/trunk/arch/sparc64/kernel/traps.c @@ -10,7 +10,7 @@ */ #include -#include +#include /* for jiffies */ #include #include #include @@ -1873,16 +1873,6 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) put_cpu(); - if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) { - /* If err_type is 0x4, it's a powerdown request. Do - * not do the usual resumable error log because that - * makes it look like some abnormal error. - */ - printk(KERN_INFO "Power down request...\n"); - kill_cad_pid(SIGINT, 1); - return; - } - sun4v_log_error(regs, &local_copy, cpu, KERN_ERR "RESUMABLE ERROR", &sun4v_resum_oflow_cnt); @@ -2271,12 +2261,8 @@ void die_if_kernel(char *str, struct pt_regs *regs) do_exit(SIGSEGV); } -#define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19)) -#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19)) - extern int handle_popc(u32 insn, struct pt_regs *regs); extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); -extern int vis_emul(struct pt_regs *, unsigned int); void do_illegal_instruction(struct pt_regs *regs) { @@ -2301,18 +2287,10 @@ void do_illegal_instruction(struct pt_regs *regs) if (handle_ldf_stq(insn, regs)) return; } else if (tlb_type == hypervisor) { - if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) { - if (!vis_emul(regs, insn)) - return; - } else { - struct fpustate *f = FPUSTATE; + extern int vis_emul(struct pt_regs *, unsigned int); - /* XXX maybe verify XFSR bits like - * XXX do_fpother() does? - */ - if (do_mathemu(regs, f)) - return; - } + if (!vis_emul(regs, insn)) + return; } } info.si_signo = SIGILL; diff --git a/trunk/arch/sparc64/kernel/unaligned.c b/trunk/arch/sparc64/kernel/unaligned.c index bc18d480dd1c..a9b765271b85 100644 --- a/trunk/arch/sparc64/kernel/unaligned.c +++ b/trunk/arch/sparc64/kernel/unaligned.c @@ -243,7 +243,7 @@ static inline int ok_for_kernel(unsigned int insn) return !floating_point_load_or_store_p(insn); } -static void kernel_mna_trap_fault(int fixup_tstate_asi) +static void kernel_mna_trap_fault(void) { struct pt_regs *regs = current_thread_info()->kern_una_regs; unsigned int insn = current_thread_info()->kern_una_insn; @@ -274,15 +274,18 @@ static void kernel_mna_trap_fault(int fixup_tstate_asi) regs->tpc = entry->fixup; regs->tnpc = regs->tpc + 4; - if (fixup_tstate_asi) { - regs->tstate &= ~TSTATE_ASI; - regs->tstate |= (ASI_AIUS << 24UL); - } + regs->tstate &= ~TSTATE_ASI; + regs->tstate |= (ASI_AIUS << 24UL); } -static void log_unaligned(struct pt_regs *regs) +asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) { static unsigned long count, last_time; + enum direction dir = decode_direction(insn); + int size = decode_access_size(insn); + + current_thread_info()->kern_una_regs = regs; + current_thread_info()->kern_una_insn = insn; if (jiffies - last_time > 5 * HZ) count = 0; @@ -292,28 +295,6 @@ static void log_unaligned(struct pt_regs *regs) printk("Kernel unaligned access at TPC[%lx] ", regs->tpc); print_symbol("%s\n", regs->tpc); } -} - -asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) -{ - enum direction dir = decode_direction(insn); - int size = decode_access_size(insn); - int orig_asi, asi; - - current_thread_info()->kern_una_regs = regs; - current_thread_info()->kern_una_insn = insn; - - orig_asi = asi = decode_asi(insn, regs); - - /* If this is a {get,put}_user() on an unaligned userspace pointer, - * just signal a fault and do not log the event. - */ - if (asi == ASI_AIUS) { - kernel_mna_trap_fault(0); - return; - } - - log_unaligned(regs); if (!ok_for_kernel(insn) || dir == both) { printk("Unsupported unaligned load/store trap for kernel " @@ -321,10 +302,10 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) unaligned_panic("Kernel does fpu/atomic " "unaligned load/store.", regs); - kernel_mna_trap_fault(0); + kernel_mna_trap_fault(); } else { unsigned long addr, *reg_addr; - int err; + int orig_asi, asi, err; addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); @@ -334,6 +315,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]); #endif + orig_asi = asi = decode_asi(insn, regs); switch (asi) { case ASI_NL: case ASI_AIUPL: @@ -383,7 +365,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) /* Not reached... */ } if (unlikely(err)) - kernel_mna_trap_fault(1); + kernel_mna_trap_fault(); else advance(regs); } diff --git a/trunk/arch/sparc64/kernel/visemul.c b/trunk/arch/sparc64/kernel/visemul.c index c3fd64706b53..84fedaa38aae 100644 --- a/trunk/arch/sparc64/kernel/visemul.c +++ b/trunk/arch/sparc64/kernel/visemul.c @@ -128,6 +128,9 @@ /* 001001100 - Permute bytes as specified by GSR.MASK */ #define BSHUFFLE_OPF 0x04c +#define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19)) +#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19)) + #define VIS_OPF_SHIFT 5 #define VIS_OPF_MASK (0x1ff << VIS_OPF_SHIFT) @@ -807,6 +810,9 @@ int vis_emul(struct pt_regs *regs, unsigned int insn) if (get_user(insn, (u32 __user *) pc)) return -EFAULT; + if ((insn & VIS_OPCODE_MASK) != VIS_OPCODE_VAL) + return -EINVAL; + opf = (insn & VIS_OPF_MASK) >> VIS_OPF_SHIFT; switch (opf) { default: diff --git a/trunk/arch/sparc64/mm/ultra.S b/trunk/arch/sparc64/mm/ultra.S index 737c26923c09..d70b60a3bbcc 100644 --- a/trunk/arch/sparc64/mm/ultra.S +++ b/trunk/arch/sparc64/mm/ultra.S @@ -477,10 +477,6 @@ xcall_sync_tick: sethi %hi(109f), %g7 b,pt %xcc, etrap_irq 109: or %g7, %lo(109b), %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif call smp_synchronize_tick_client nop clr %l6 @@ -512,10 +508,6 @@ xcall_report_regs: sethi %hi(109f), %g7 b,pt %xcc, etrap_irq 109: or %g7, %lo(109b), %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif call __show_regs add %sp, PTREGS_OFF, %o0 clr %l6 diff --git a/trunk/arch/um/drivers/net_kern.c b/trunk/arch/um/drivers/net_kern.c index afe3d427ddfa..286bc0b3207f 100644 --- a/trunk/arch/um/drivers/net_kern.c +++ b/trunk/arch/um/drivers/net_kern.c @@ -72,11 +72,9 @@ static int uml_net_rx(struct net_device *dev) return pkt_len; } -static void uml_dev_close(struct work_struct *work) +static void uml_dev_close(void* dev) { - struct uml_net_private *lp = - container_of(work, struct uml_net_private, work); - dev_close(lp->dev); + dev_close( (struct net_device *) dev); } irqreturn_t uml_net_interrupt(int irq, void *dev_id) @@ -91,6 +89,7 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) spin_lock(&lp->lock); while((err = uml_net_rx(dev)) > 0) ; if(err < 0) { + DECLARE_WORK(close_work, uml_dev_close, dev); printk(KERN_ERR "Device '%s' read returned %d, shutting it down\n", dev->name, err); @@ -98,10 +97,9 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) * again lp->lock. * And dev_close() can be safely called multiple times on the * same device, since it tests for (dev->flags & IFF_UP). So - * there's no harm in delaying the device shutdown. - * Furthermore, the workqueue will not re-enqueue an already - * enqueued work item. */ - schedule_work(&lp->work); + * there's no harm in delaying the device shutdown. */ + schedule_work(&close_work); +#error this is not permitted - close_work will go out of scope goto out; } reactivate_fd(lp->fd, UM_ETH_IRQ); @@ -336,12 +334,13 @@ static int eth_configure(int n, void *init, char *mac, size = transport->private_size + sizeof(struct uml_net_private) + sizeof(((struct uml_net_private *) 0)->user); - device = kzalloc(sizeof(*device), GFP_KERNEL); + device = kmalloc(sizeof(*device), GFP_KERNEL); if (device == NULL) { printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); return(1); } + memset(device, 0, sizeof(*device)); INIT_LIST_HEAD(&device->list); device->index = n; @@ -367,7 +366,6 @@ static int eth_configure(int n, void *init, char *mac, /* This points to the transport private data. It's still clear, but we * must memset it to 0 *now*. Let's help the drivers. */ memset(lp, 0, size); - INIT_WORK(&lp->work, uml_dev_close); /* sysfs register */ if (!driver_registered) { diff --git a/trunk/arch/um/include/net_kern.h b/trunk/arch/um/include/net_kern.h index 218f8b47fdcd..280459fb0b26 100644 --- a/trunk/arch/um/include/net_kern.h +++ b/trunk/arch/um/include/net_kern.h @@ -11,7 +11,6 @@ #include #include #include -#include struct uml_net { struct list_head list; @@ -27,7 +26,6 @@ struct uml_net_private { struct net_device *dev; struct timer_list tl; struct net_device_stats stats; - struct work_struct work; int fd; unsigned char mac[ETH_ALEN]; unsigned short (*protocol)(struct sk_buff *); diff --git a/trunk/arch/um/sys-i386/ldt.c b/trunk/arch/um/sys-i386/ldt.c index 5db7737df0ff..49057d8bc668 100644 --- a/trunk/arch/um/sys-i386/ldt.c +++ b/trunk/arch/um/sys-i386/ldt.c @@ -166,7 +166,7 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) { .func = 0, .bytecount = bytecount, - .ptr = kmalloc(bytecount, GFP_KERNEL)}; + .ptr = (void *)kmalloc(bytecount, GFP_KERNEL)}; u32 cpu; if(ptrace_ldt.ptr == NULL) @@ -426,7 +426,7 @@ void ldt_get_host_info(void) host_ldt_entries = dummy_list; else { size = (size + 1) * sizeof(dummy_list[0]); - host_ldt_entries = kmalloc(size, GFP_KERNEL); + host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL); if(host_ldt_entries == NULL) { printk("ldt_get_host_info: couldn't allocate host ldt list\n"); goto out_free; diff --git a/trunk/arch/v850/Kconfig b/trunk/arch/v850/Kconfig index f0d4d72e560f..bcf825875d17 100644 --- a/trunk/arch/v850/Kconfig +++ b/trunk/arch/v850/Kconfig @@ -105,17 +105,17 @@ menu "Processor type and features" # currently support config V850E_MA1 bool - depends on RTE_CB_MA1 + depends RTE_CB_MA1 default y # Similarly for the RTE-V850E/NB85E-CB - V850E/TEG config V850E_TEG bool - depends on RTE_CB_NB85E + depends RTE_CB_NB85E default y # ... and the RTE-V850E/ME2-CB - V850E/ME2 config V850E_ME2 bool - depends on RTE_CB_ME2 + depends RTE_CB_ME2 default y @@ -123,7 +123,7 @@ menu "Processor type and features" config V850E2_SIM85E2 bool - depends on V850E2_SIM85E2C || V850E2_SIM85E2S + depends V850E2_SIM85E2C || V850E2_SIM85E2S default y @@ -132,7 +132,7 @@ menu "Processor type and features" # V850E2 processors config V850E2 bool - depends on V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA + depends V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA default y @@ -141,7 +141,7 @@ menu "Processor type and features" # Boards in the RTE-x-CB series config RTE_CB bool - depends on RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2 + depends RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2 default y config RTE_CB_MULTI @@ -149,28 +149,28 @@ menu "Processor type and features" # RTE_CB_NB85E can either have multi ROM support or not, but # other platforms (currently only RTE_CB_MA1) require it. prompt "Multi monitor ROM support" if RTE_CB_NB85E - depends on RTE_CB_MA1 || RTE_CB_NB85E + depends RTE_CB_MA1 || RTE_CB_NB85E default y config RTE_CB_MULTI_DBTRAP bool "Pass illegal insn trap / dbtrap to kernel" - depends on RTE_CB_MULTI + depends RTE_CB_MULTI default n config RTE_CB_MA1_KSRAM bool "Kernel in SRAM (limits size of kernel)" - depends on RTE_CB_MA1 && RTE_CB_MULTI + depends RTE_CB_MA1 && RTE_CB_MULTI default n config RTE_MB_A_PCI bool "Mother-A PCI support" - depends on RTE_CB + depends RTE_CB default y # The GBUS is used to talk to the RTE-MOTHER-A board config RTE_GBUS_INT bool - depends on RTE_MB_A_PCI + depends RTE_MB_A_PCI default y # The only PCI bus we support is on the RTE-MOTHER-A board @@ -209,7 +209,7 @@ menu "Processor type and features" config ROM_KERNEL bool "Kernel in ROM" - depends on V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2 + depends V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2 # Some platforms pre-zero memory, in which case the kernel doesn't need to config ZERO_BSS @@ -225,10 +225,10 @@ menu "Processor type and features" config V850E_HIGHRES_TIMER bool "High resolution timer support" - depends on V850E_TIMER_D + depends V850E_TIMER_D config TIME_BOOTUP bool "Time bootup" - depends on V850E_HIGHRES_TIMER + depends V850E_HIGHRES_TIMER config RESET_GUARD bool "Reset Guard" diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig index d4275537b25b..3ac581d17202 100644 --- a/trunk/arch/x86_64/Kconfig +++ b/trunk/arch/x86_64/Kconfig @@ -584,7 +584,7 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. config CC_STACKPROTECTOR - bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" + bool "Enable -fstack-protector buffer overflow detection (EXPRIMENTAL)" depends on EXPERIMENTAL help This option turns on the -fstack-protector GCC feature. This diff --git a/trunk/arch/x86_64/kernel/cpufreq/Kconfig b/trunk/arch/x86_64/kernel/cpufreq/Kconfig index 3abcfa3e1ed7..81f1562e5393 100644 --- a/trunk/arch/x86_64/kernel/cpufreq/Kconfig +++ b/trunk/arch/x86_64/kernel/cpufreq/Kconfig @@ -27,13 +27,10 @@ config X86_POWERNOW_K8_ACPI default y config X86_SPEEDSTEP_CENTRINO - tristate "Intel Enhanced SpeedStep (deprecated)" + tristate "Intel Enhanced SpeedStep" select CPU_FREQ_TABLE depends on ACPI_PROCESSOR help - This is deprecated and this functionality is now merged into - acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of - speedstep_centrino. This adds the CPUFreq driver for Enhanced SpeedStep enabled mobile CPUs. This means Intel Pentium M (Centrino) CPUs or 64bit enabled Intel Xeons. @@ -53,7 +50,6 @@ config X86_ACPI_CPUFREQ help This driver adds a CPUFreq driver which utilizes the ACPI Processor Performance States. - This driver also supports Intel Enhanced Speedstep. For details, take a look at . diff --git a/trunk/arch/x86_64/kernel/cpufreq/Makefile b/trunk/arch/x86_64/kernel/cpufreq/Makefile index 753ce1dd418e..d8b593879224 100644 --- a/trunk/arch/x86_64/kernel/cpufreq/Makefile +++ b/trunk/arch/x86_64/kernel/cpufreq/Makefile @@ -5,8 +5,8 @@ SRCDIR := ../../../i386/kernel/cpu/cpufreq obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o -obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o +obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o diff --git a/trunk/arch/x86_64/kernel/vsyscall.c b/trunk/arch/x86_64/kernel/vsyscall.c index 2433d6fc68b1..4a673f5397a0 100644 --- a/trunk/arch/x86_64/kernel/vsyscall.c +++ b/trunk/arch/x86_64/kernel/vsyscall.c @@ -225,7 +225,8 @@ static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp, static int vsyscall_sysctl_nostrat(ctl_table *t, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, - void __user *newval, size_t newlen) + void __user *newval, size_t newlen, + void **context) { return -ENOSYS; } diff --git a/trunk/arch/xtensa/Kconfig b/trunk/arch/xtensa/Kconfig index 2e74cb0b7807..9eccfbd1b536 100644 --- a/trunk/arch/xtensa/Kconfig +++ b/trunk/arch/xtensa/Kconfig @@ -48,10 +48,25 @@ menu "Processor type and features" choice prompt "Xtensa Processor Configuration" - default XTENSA_VARIANT_FSF + default XTENSA_CPU_LINUX_BE -config XTENSA_VARIANT_FSF - bool "fsf" +config XTENSA_CPU_LINUX_BE + bool "linux_be" + ---help--- + The linux_be processor configuration is the baseline Xtensa + configurations included in this kernel and also used by + binutils, gcc, and gdb. It contains no TIE, no coprocessors, + and the following configuration options: + + Code Density Option 2 Misc Special Registers + NSA/NSAU Instructions 128-bit Data Bus Width + Processor ID 8K, 2-way I and D Caches + Zero-Overhead Loops 2 Inst Address Break Registers + Big Endian 2 Data Address Break Registers + 64 General-Purpose Registers JTAG Interface and Trace Port + 17 Interrupts MMU w/ TLBs and Autorefill + 3 Interrupt Levels 8 Autorefill Ways (I/D TLBs) + 3 Timers Unaligned Exceptions endchoice config MMU diff --git a/trunk/arch/xtensa/Makefile b/trunk/arch/xtensa/Makefile index 95f836db38fa..3a3a4c66ef87 100644 --- a/trunk/arch/xtensa/Makefile +++ b/trunk/arch/xtensa/Makefile @@ -11,13 +11,13 @@ # this architecture # Core configuration. -# (Use VAR= to use another default compiler.) +# (Use CPU= to use another default compiler.) -variant-$(CONFIG_XTENSA_VARIANT_FSF) := fsf -variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM) := custom +cpu-$(CONFIG_XTENSA_CPU_LINUX_BE) := linux_be +cpu-$(CONFIG_XTENSA_CPU_LINUX_CUSTOM) := linux_custom -VARIANT = $(variant-y) -export VARIANT +CPU = $(cpu-y) +export CPU # Platform configuration @@ -27,6 +27,8 @@ platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss PLATFORM = $(platform-y) export PLATFORM +CPPFLAGS += $(if $(KBUILD_SRC),-I$(srctree)/include/asm-xtensa/) +CPPFLAGS += -Iinclude/asm CFLAGS += -pipe -mlongcalls KBUILD_DEFCONFIG := iss_defconfig @@ -39,12 +41,12 @@ core-$(CONFIG_EMBEDDED_RAMDISK) += arch/xtensa/boot/ramdisk/ # Test for cross compiling -ifneq ($(VARIANT),) +ifneq ($(CPU),) COMPILE_ARCH = $(shell uname -m) ifneq ($(COMPILE_ARCH), xtensa) ifndef CROSS_COMPILE - CROSS_COMPILE = xtensa_$(VARIANT)- + CROSS_COMPILE = xtensa_$(CPU)- endif endif endif @@ -66,13 +68,14 @@ archinc := include/asm-xtensa archprepare: $(archinc)/.platform -# Update processor variant and platform symlinks if something which affects +# Update machine cpu and platform symlinks if something which affects # them changed. $(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/auto.conf - @echo ' SYMLINK $(archinc)/variant -> $(archinc)/variant-$(VARIANT)' + @echo ' SYMLINK $(archinc)/xtensa/config -> $(archinc)/xtensa/config-$(CPU)' $(Q)mkdir -p $(archinc) - $(Q)ln -fsn $(srctree)/$(archinc)/variant-$(VARIANT) $(archinc)/variant + $(Q)mkdir -p $(archinc)/xtensa + $(Q)ln -fsn $(srctree)/$(archinc)/xtensa/config-$(CPU) $(archinc)/xtensa/config @echo ' SYMLINK $(archinc)/platform -> $(archinc)/platform-$(PLATFORM)' $(Q)ln -fsn $(srctree)/$(archinc)/platform-$(PLATFORM) $(archinc)/platform @touch $@ @@ -86,7 +89,7 @@ zImage zImage.initrd: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ CLEAN_FILES += arch/xtensa/vmlinux.lds \ - $(archinc)/platform $(archinc)/variant \ + $(archinc)/platform $(archinc)/xtensa/config \ $(archinc)/.platform define archhelp diff --git a/trunk/arch/xtensa/boot/boot-elf/bootstrap.S b/trunk/arch/xtensa/boot/boot-elf/bootstrap.S index 464298bc348b..f857fc760aa8 100644 --- a/trunk/arch/xtensa/boot/boot-elf/bootstrap.S +++ b/trunk/arch/xtensa/boot/boot-elf/bootstrap.S @@ -1,4 +1,7 @@ +#include +#include + #include diff --git a/trunk/arch/xtensa/boot/boot-redboot/bootstrap.S b/trunk/arch/xtensa/boot/boot-redboot/bootstrap.S index 84848123e2a8..ee636b0da81c 100644 --- a/trunk/arch/xtensa/boot/boot-redboot/bootstrap.S +++ b/trunk/arch/xtensa/boot/boot-redboot/bootstrap.S @@ -1,7 +1,9 @@ -#include -#include -#include -#include + +#define _ASMLANGUAGE +#include +#include +#include + /* * RB-Data: RedBoot data/bss * P: Boot-Parameters @@ -75,14 +77,8 @@ _start: /* Note: The assembler cannot relax "addi a0, a0, ..." to an l32r, so we load to a4 first. */ - # addi a4, a0, __start - __start_a0 - # mov a0, a4 - - movi a4, __start - movi a5, __start_a0 - add a4, a0, a4 - sub a0, a4, a5 - + addi a4, a0, __start - __start_a0 + mov a0, a4 movi a4, __start movi a5, __reloc_end @@ -110,13 +106,9 @@ _start: /* We have to flush and invalidate the caches here before we jump. */ #if XCHAL_DCACHE_IS_WRITEBACK - - ___flush_dcache_all a5 a6 - + dcache_writeback_all a5, a6 #endif - - ___invalidate_icache_all a5 a6 - isync + icache_invalidate_all a5, a6 movi a11, _reloc jx a11 @@ -217,14 +209,9 @@ _reloc: /* jump to the kernel */ 2: #if XCHAL_DCACHE_IS_WRITEBACK - - ___flush_dcache_all a5 a6 - + dcache_writeback_all a5, a6 #endif - - ___invalidate_icache_all a5 a6 - - isync + icache_invalidate_all a5, a6 movi a5, __start movi a3, boot_initrd_start diff --git a/trunk/arch/xtensa/configs/iss_defconfig b/trunk/arch/xtensa/configs/iss_defconfig index f19854035e61..802621dd4867 100644 --- a/trunk/arch/xtensa/configs/iss_defconfig +++ b/trunk/arch/xtensa/configs/iss_defconfig @@ -53,7 +53,11 @@ CONFIG_CC_ALIGN_JUMPS=0 # # Processor type and features # -CONFIG_XTENSA_VARIANT_FSF=y +CONFIG_XTENSA_ARCH_LINUX_BE=y +# CONFIG_XTENSA_ARCH_LINUX_LE is not set +# CONFIG_XTENSA_ARCH_LINUX_TEST is not set +# CONFIG_XTENSA_ARCH_S5 is not set +# CONFIG_XTENSA_CUSTOM is not set CONFIG_MMU=y # CONFIG_XTENSA_UNALIGNED_USER is not set # CONFIG_PREEMPT is not set diff --git a/trunk/arch/xtensa/kernel/Makefile b/trunk/arch/xtensa/kernel/Makefile index 71f733c4f66d..d573017a5dde 100644 --- a/trunk/arch/xtensa/kernel/Makefile +++ b/trunk/arch/xtensa/kernel/Makefile @@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \ - setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \ + setup.o signal.o syscalls.o time.o traps.o vectors.o platform.o \ pci-dma.o ## windowspill.o diff --git a/trunk/arch/xtensa/kernel/align.S b/trunk/arch/xtensa/kernel/align.S index 33d6e9d2e83c..a4956578a24d 100644 --- a/trunk/arch/xtensa/kernel/align.S +++ b/trunk/arch/xtensa/kernel/align.S @@ -16,9 +16,14 @@ */ #include +#include +#include #include #include +#include #include +#include +#include #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION @@ -211,7 +216,7 @@ ENTRY(fast_unaligned) extui a5, a4, INSN_OP0, 4 # get insn.op0 nibble -#if XCHAL_HAVE_DENSITY +#if XCHAL_HAVE_NARROW _beqi a5, OP0_L32I_N, .Lload # L32I.N, jump addi a6, a5, -OP0_S32I_N _beqz a6, .Lstore # S32I.N, do a store @@ -246,7 +251,7 @@ ENTRY(fast_unaligned) #endif __src_b a3, a5, a6 # a3 has the data word -#if XCHAL_HAVE_DENSITY +#if XCHAL_HAVE_NARROW addi a7, a7, 2 # increment PC (assume 16-bit insn) extui a5, a4, INSN_OP0, 4 @@ -274,14 +279,14 @@ ENTRY(fast_unaligned) 1: -#if XCHAL_HAVE_LOOPS - rsr a5, LEND # check if we reached LEND - bne a7, a5, 1f - rsr a5, LCOUNT # and LCOUNT != 0 - beqz a5, 1f - addi a5, a5, -1 # decrement LCOUNT and set +#if XCHAL_HAVE_LOOP + rsr a3, LEND # check if we reached LEND + bne a7, a3, 1f + rsr a3, LCOUNT # and LCOUNT != 0 + beqz a3, 1f + addi a3, a3, -1 # decrement LCOUNT and set rsr a7, LBEG # set PC to LBEGIN - wsr a5, LCOUNT + wsr a3, LCOUNT #endif 1: wsr a7, EPC_1 # skip load instruction @@ -331,7 +336,7 @@ ENTRY(fast_unaligned) movi a6, 0 # mask: ffffffff:00000000 -#if XCHAL_HAVE_DENSITY +#if XCHAL_HAVE_NARROW addi a7, a7, 2 # incr. PC,assume 16-bit instruction extui a5, a4, INSN_OP0, 4 # extract OP0 @@ -354,14 +359,14 @@ ENTRY(fast_unaligned) /* Get memory address */ 1: -#if XCHAL_HAVE_LOOPS - rsr a4, LEND # check if we reached LEND - bne a7, a4, 1f - rsr a4, LCOUNT # and LCOUNT != 0 - beqz a4, 1f - addi a4, a4, -1 # decrement LCOUNT and set +#if XCHAL_HAVE_LOOP + rsr a3, LEND # check if we reached LEND + bne a7, a3, 1f + rsr a3, LCOUNT # and LCOUNT != 0 + beqz a3, 1f + addi a3, a3, -1 # decrement LCOUNT and set rsr a7, LBEG # set PC to LBEGIN - wsr a4, LCOUNT + wsr a3, LCOUNT #endif 1: wsr a7, EPC_1 # skip store instruction @@ -411,7 +416,6 @@ ENTRY(fast_unaligned) /* Restore working register */ - l32i a8, a2, PT_AREG8 l32i a7, a2, PT_AREG7 l32i a6, a2, PT_AREG6 l32i a5, a2, PT_AREG5 @@ -442,7 +446,7 @@ ENTRY(fast_unaligned) mov a1, a2 rsr a0, PS - bbsi.l a2, PS_UM_BIT, 1f # jump if user mode + bbsi.l a2, PS_UM_SHIFT, 1f # jump if user mode movi a0, _kernel_exception jx a0 diff --git a/trunk/arch/xtensa/kernel/asm-offsets.c b/trunk/arch/xtensa/kernel/asm-offsets.c index b256cfbef344..7cd1d7f8f608 100644 --- a/trunk/arch/xtensa/kernel/asm-offsets.c +++ b/trunk/arch/xtensa/kernel/asm-offsets.c @@ -87,11 +87,6 @@ int main(void) DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context)); BLANK(); DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT); - - /* constants */ - DEFINE(_CLONE_VM, CLONE_VM); - DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED); - return 0; } diff --git a/trunk/arch/xtensa/kernel/coprocessor.S b/trunk/arch/xtensa/kernel/coprocessor.S index 01bcb9fcfcbd..cf5a93fb6a2e 100644 --- a/trunk/arch/xtensa/kernel/coprocessor.S +++ b/trunk/arch/xtensa/kernel/coprocessor.S @@ -90,6 +90,7 @@ ENTRY(enable_coprocessor) rsync retw +#endif ENTRY(save_coprocessor_extra) entry sp, 16 @@ -196,5 +197,4 @@ _xtensa_reginfo_tables: XCHAL_CP7_SA_CONTENTS_LIBDB .word 0xFC000000 /* invalid register number,marks end of table*/ _xtensa_reginfo_table_end: -#endif diff --git a/trunk/arch/xtensa/kernel/entry.S b/trunk/arch/xtensa/kernel/entry.S index 9e271ba009bf..89e409e9e0de 100644 --- a/trunk/arch/xtensa/kernel/entry.S +++ b/trunk/arch/xtensa/kernel/entry.S @@ -24,7 +24,7 @@ #include #include #include -#include +#include /* Unimplemented features. */ @@ -364,7 +364,7 @@ common_exception: movi a2, 1 extui a3, a3, 0, 1 # a3 = PS.INTLEVEL[0] moveqz a3, a2, a0 # a3 = 1 iff interrupt exception - movi a2, 1 << PS_WOE_BIT + movi a2, PS_WOE_MASK or a3, a3, a2 rsr a0, EXCCAUSE xsr a3, PS @@ -399,7 +399,7 @@ common_exception_return: /* Jump if we are returning from kernel exceptions. */ 1: l32i a3, a1, PT_PS - _bbsi.l a3, PS_UM_BIT, 2f + _bbsi.l a3, PS_UM_SHIFT, 2f j kernel_exception_exit /* Specific to a user exception exit: @@ -422,7 +422,7 @@ common_exception_return: * (Hint: There is only one user exception frame on stack) */ - movi a3, 1 << PS_WOE_BIT + movi a3, PS_WOE_MASK _bbsi.l a4, TIF_NEED_RESCHED, 3f _bbci.l a4, TIF_SIGPENDING, 4f @@ -694,7 +694,7 @@ common_exception_exit: ENTRY(debug_exception) rsr a0, EPS + XCHAL_DEBUGLEVEL - bbsi.l a0, PS_EXCM_BIT, 1f # exception mode + bbsi.l a0, PS_EXCM_SHIFT, 1f # exception mode /* Set EPC_1 and EXCCAUSE */ @@ -707,7 +707,7 @@ ENTRY(debug_exception) /* Restore PS to the value before the debug exc but with PS.EXCM set.*/ - movi a2, 1 << PS_EXCM_BIT + movi a2, 1 << PS_EXCM_SHIFT or a2, a0, a2 movi a0, debug_exception # restore a3, debug jump vector wsr a2, PS @@ -715,7 +715,7 @@ ENTRY(debug_exception) /* Switch to kernel/user stack, restore jump vector, and save a0 */ - bbsi.l a2, PS_UM_BIT, 2f # jump if user mode + bbsi.l a2, PS_UM_SHIFT, 2f # jump if user mode addi a2, a1, -16-PT_SIZE # assume kernel stack s32i a0, a2, PT_AREG0 @@ -778,7 +778,7 @@ ENTRY(unrecoverable_exception) wsr a1, WINDOWBASE rsync - movi a1, (1 << PS_WOE_BIT) | 1 + movi a1, PS_WOE_MASK | 1 wsr a1, PS rsync @@ -1004,10 +1004,13 @@ ENTRY(fast_syscall_kernel) rsr a0, DEPC # get syscall-nr _beqz a0, fast_syscall_spill_registers - _beqi a0, __NR_xtensa, fast_syscall_xtensa + + addi a0, a0, -__NR_sysxtensa + _beqz a0, fast_syscall_sysxtensa j kernel_exception + ENTRY(fast_syscall_user) /* Skip syscall. */ @@ -1021,7 +1024,9 @@ ENTRY(fast_syscall_user) rsr a0, DEPC # get syscall-nr _beqz a0, fast_syscall_spill_registers - _beqi a0, __NR_xtensa, fast_syscall_xtensa + + addi a0, a0, -__NR_sysxtensa + _beqz a0, fast_syscall_sysxtensa j user_exception @@ -1042,19 +1047,18 @@ ENTRY(fast_syscall_unrecoverable) /* * sysxtensa syscall handler * - * int sysxtensa (SYS_XTENSA_ATOMIC_SET, ptr, val, unused); - * int sysxtensa (SYS_XTENSA_ATOMIC_ADD, ptr, val, unused); - * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val, unused); - * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval); - * a2 a6 a3 a4 a5 + * int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused); + * int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused); + * int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused); + * int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval); + * a2 a6 a3 a4 a5 * * Entry condition: * - * a0: a2 (syscall-nr), original value saved on stack (PT_AREG0) + * a0: trashed, original value saved on stack (PT_AREG0) * a1: a1 - * a2: new stack pointer, original in a0 and DEPC - * a3: dispatch table, original in excsave_1 - * a4..a15: unchanged + * a2: new stack pointer, original in DEPC + * a3: dispatch table * depc: a2, original value saved on stack (PT_DEPC) * excsave_1: a3 * @@ -1087,62 +1091,59 @@ ENTRY(fast_syscall_unrecoverable) #define CATCH \ 67: -ENTRY(fast_syscall_xtensa) +ENTRY(fast_syscall_sysxtensa) + + _beqz a6, 1f + _blti a6, SYSXTENSA_COUNT, 2f - xsr a3, EXCSAVE_1 # restore a3, excsave1 +1: j user_exception + +2: xsr a3, EXCSAVE_1 # restore a3, excsave1 + s32i a7, a2, PT_AREG7 - s32i a7, a2, PT_AREG7 # we need an additional register movi a7, 4 # sizeof(unsigned int) - access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp + access_ok a0, a3, a7, a2, .Leac - addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1 - _bgeui a6, SYS_XTENSA_COUNT - 1, .Lill - _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp + _beqi a6, SYSXTENSA_ATOMIC_SET, .Lset + _beqi a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg + _beqi a6, SYSXTENSA_ATOMIC_ADD, .Ladd - /* Fall through for ATOMIC_CMP_SWP. */ + /* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */ .Lswp: /* Atomic compare and swap */ -TRY l32i a0, a3, 0 # read old value - bne a0, a4, 1f # same as old value? jump -TRY s32i a5, a3, 0 # different, modify value - l32i a7, a2, PT_AREG7 # restore a7 - l32i a0, a2, PT_AREG0 # restore a0 - movi a2, 1 # and return 1 - addi a6, a6, 1 # restore a6 (really necessary?) - rfe +TRY l32i a7, a3, 0 # read old value + bne a7, a4, 1f # same as old value? jump + s32i a5, a3, 0 # different, modify value + movi a7, 1 # and return 1 + j .Lret -1: l32i a7, a2, PT_AREG7 # restore a7 - l32i a0, a2, PT_AREG0 # restore a0 - movi a2, 0 # return 0 (note that we cannot set - addi a6, a6, 1 # restore a6 (really necessary?) - rfe +1: movi a7, 0 # same values: return 0 + j .Lret -.Lnswp: /* Atomic set, add, and exg_add. */ +.Ladd: /* Atomic add */ +.Lexg: /* Atomic (exchange) add */ -TRY l32i a7, a3, 0 # orig - add a0, a4, a7 # + arg - moveqz a0, a4, a6 # set -TRY s32i a0, a3, 0 # write new value +TRY l32i a7, a3, 0 + add a4, a4, a7 + s32i a4, a3, 0 + j .Lret - mov a0, a2 - mov a2, a7 - l32i a7, a0, PT_AREG7 # restore a7 - l32i a0, a0, PT_AREG0 # restore a0 - addi a6, a6, 1 # restore a6 (really necessary?) - rfe +.Lset: /* Atomic set */ -CATCH -.Leac: l32i a7, a2, PT_AREG7 # restore a7 - l32i a0, a2, PT_AREG0 # restore a0 - movi a2, -EFAULT - rfe +TRY l32i a7, a3, 0 # read old value as return value + s32i a4, a3, 0 # write new value -.Lill: l32i a7, a2, PT_AREG0 # restore a7 - l32i a0, a2, PT_AREG0 # restore a0 - movi a2, -EINVAL +.Lret: mov a0, a2 + mov a2, a7 + l32i a7, a0, PT_AREG7 + l32i a3, a0, PT_AREG3 + l32i a0, a0, PT_AREG0 rfe +CATCH +.Leac: movi a7, -EFAULT + j .Lret @@ -1490,7 +1491,7 @@ ENTRY(_spill_registers) */ rsr a0, PS - _bbci.l a0, PS_UM_BIT, 1f + _bbci.l a0, PS_UM_SHIFT, 1f /* User space: Setup a dummy frame and kill application. * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer. @@ -1509,7 +1510,7 @@ ENTRY(_spill_registers) l32i a1, a3, EXC_TABLE_KSTK wsr a3, EXCSAVE_1 - movi a4, (1 << PS_WOE_BIT) | 1 + movi a4, PS_WOE_MASK | 1 wsr a4, PS rsync @@ -1611,7 +1612,7 @@ ENTRY(fast_second_level_miss) rsr a1, PTEVADDR srli a1, a1, PAGE_SHIFT slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK - addi a1, a1, DTLB_WAY_PGD # ... + way_number + addi a1, a1, DTLB_WAY_PGTABLE # ... + way_number wdtlb a0, a1 dsync @@ -1653,7 +1654,7 @@ ENTRY(fast_second_level_miss) mov a1, a2 rsr a2, PS - bbsi.l a2, PS_UM_BIT, 1f + bbsi.l a2, PS_UM_SHIFT, 1f j _kernel_exception 1: j _user_exception @@ -1752,7 +1753,7 @@ ENTRY(fast_store_prohibited) mov a1, a2 rsr a2, PS - bbsi.l a2, PS_UM_BIT, 1f + bbsi.l a2, PS_UM_SHIFT, 1f j _kernel_exception 1: j _user_exception @@ -1905,103 +1906,6 @@ ENTRY(fast_coprocessor) #endif /* XCHAL_EXTRA_SA_SIZE */ -/* - * System Calls. - * - * void system_call (struct pt_regs* regs, int exccause) - * a2 a3 - */ - -ENTRY(system_call) - entry a1, 32 - - /* regs->syscall = regs->areg[2] */ - - l32i a3, a2, PT_AREG2 - mov a6, a2 - movi a4, do_syscall_trace_enter - s32i a3, a2, PT_SYSCALL - callx4 a4 - - /* syscall = sys_call_table[syscall_nr] */ - - movi a4, sys_call_table; - movi a5, __NR_syscall_count - movi a6, -ENOSYS - bgeu a3, a5, 1f - - addx4 a4, a3, a4 - l32i a4, a4, 0 - movi a5, sys_ni_syscall; - beq a4, a5, 1f - - /* Load args: arg0 - arg5 are passed via regs. */ - - l32i a6, a2, PT_AREG6 - l32i a7, a2, PT_AREG3 - l32i a8, a2, PT_AREG4 - l32i a9, a2, PT_AREG5 - l32i a10, a2, PT_AREG8 - l32i a11, a2, PT_AREG9 - - /* Pass one additional argument to the syscall: pt_regs (on stack) */ - s32i a2, a1, 0 - - callx4 a4 - -1: /* regs->areg[2] = return_value */ - - s32i a6, a2, PT_AREG2 - movi a4, do_syscall_trace_leave - mov a6, a2 - callx4 a4 - retw - - -/* - * Create a kernel thread - * - * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) - * a2 a2 a3 a4 - */ - -ENTRY(kernel_thread) - entry a1, 16 - - mov a5, a2 # preserve fn over syscall - mov a7, a3 # preserve args over syscall - - movi a3, _CLONE_VM | _CLONE_UNTRACED - movi a2, __NR_clone - or a6, a4, a3 # arg0: flags - mov a3, a1 # arg1: sp - syscall - - beq a3, a1, 1f # branch if parent - mov a6, a7 # args - callx4 a5 # fn(args) - - movi a2, __NR_exit - syscall # return value of fn(args) still in a6 - -1: retw - -/* - * Do a system call from kernel instead of calling sys_execve, so we end up - * with proper pt_regs. - * - * int kernel_execve(const char *fname, char *const argv[], charg *const envp[]) - * a2 a2 a3 a4 - */ - -ENTRY(kernel_execve) - entry a1, 16 - mov a6, a2 # arg0 is in a6 - movi a2, __NR_execve - syscall - - retw - /* * Task switch. * @@ -2020,7 +1924,7 @@ ENTRY(_switch_to) /* Disable ints while we manipulate the stack pointer; spill regs. */ - movi a5, (1 << PS_EXCM_BIT) | LOCKLEVEL + movi a5, PS_EXCM_MASK | LOCKLEVEL xsr a5, PS rsr a3, EXCSAVE_1 rsync @@ -2060,9 +1964,33 @@ ENTRY(ret_from_fork) movi a4, schedule_tail callx4 a4 - movi a4, do_syscall_trace_leave - mov a6, a1 + movi a4, do_syscall_trace callx4 a4 j common_exception_return + + +/* + * Table of syscalls + */ + +.data +.align 4 +.global sys_call_table +sys_call_table: + +#define SYSCALL(call, narg) .word call +#include "syscalls.h" + +/* + * Number of arguments of each syscall + */ + +.global sys_narg_table +sys_narg_table: + +#undef SYSCALL +#define SYSCALL(call, narg) .byte narg +#include "syscalls.h" + diff --git a/trunk/arch/xtensa/kernel/head.S b/trunk/arch/xtensa/kernel/head.S index ea89910efa44..c07cb2522993 100644 --- a/trunk/arch/xtensa/kernel/head.S +++ b/trunk/arch/xtensa/kernel/head.S @@ -15,9 +15,9 @@ * Kevin Chea */ +#include #include #include -#include /* * This module contains the entry code for kernel images. It performs the @@ -32,6 +32,13 @@ * */ + .macro iterate from, to , cmd + .ifeq ((\to - \from) & ~0xfff) + \cmd \from + iterate "(\from+1)", \to, \cmd + .endif + .endm + /* * _start * @@ -57,7 +64,7 @@ _startup: /* Disable interrupts and exceptions. */ - movi a0, LOCKLEVEL + movi a0, XCHAL_PS_EXCM_MASK wsr a0, PS /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ @@ -84,11 +91,11 @@ _startup: movi a1, 15 wsr a0, ICOUNTLEVEL - .set _index, 0 - .rept XCHAL_NUM_DBREAK - 1 - wsr a0, DBREAKC + _index - .set _index, _index + 1 - .endr + .macro reset_dbreak num + wsr a0, DBREAKC + \num + .endm + + iterate 0, XCHAL_NUM_IBREAK-1, reset_dbreak #endif /* Clear CCOUNT (not really necessary, but nice) */ @@ -103,11 +110,10 @@ _startup: /* Disable all timers. */ - .set _index, 0 - .rept XCHAL_NUM_TIMERS - 1 - wsr a0, CCOMPARE + _index - .set _index, _index + 1 - .endr + .macro reset_timer num + wsr a0, CCOMPARE_0 + \num + .endm + iterate 0, XCHAL_NUM_TIMERS-1, reset_timer /* Interrupt initialization. */ @@ -133,21 +139,12 @@ _startup: rsync /* Initialize the caches. - * a2, a3 are just working registers (clobbered). + * Does not include flushing writeback d-cache. + * a6, a7 are just working registers (clobbered). */ -#if XCHAL_DCACHE_LINE_LOCKABLE - ___unlock_dcache_all a2 a3 -#endif - -#if XCHAL_ICACHE_LINE_LOCKABLE - ___unlock_icache_all a2 a3 -#endif - - ___invalidate_dcache_all a2 a3 - ___invalidate_icache_all a2 a3 - - isync + icache_reset a2, a3 + dcache_reset a2, a3 /* Unpack data sections * @@ -184,9 +181,9 @@ _startup: movi a2, _bss_start # start of BSS movi a3, _bss_end # end of BSS - __loopt a2, a3, a4, 2 +1: addi a2, a2, 4 s32i a0, a2, 0 - __endla a2, a4, 4 + blt a2, a3, 1b #if XCHAL_DCACHE_IS_WRITEBACK @@ -194,7 +191,7 @@ _startup: * instructions/data are available. */ - ___flush_dcache_all a2 a3 + dcache_writeback_all a2, a3 #endif /* Setup stack and enable window exceptions (keep irqs disabled) */ diff --git a/trunk/arch/xtensa/kernel/irq.c b/trunk/arch/xtensa/kernel/irq.c index c9ea73b7031b..1cf744ee0959 100644 --- a/trunk/arch/xtensa/kernel/irq.c +++ b/trunk/arch/xtensa/kernel/irq.c @@ -4,7 +4,7 @@ * Xtensa built-in interrupt controller and some generic functions copied * from i386. * - * Copyright (C) 2002 - 2006 Tensilica, Inc. + * Copyright (C) 2002 - 2005 Tensilica, Inc. * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar * * @@ -22,6 +22,11 @@ #include #include +static void enable_xtensa_irq(unsigned int irq); +static void disable_xtensa_irq(unsigned int irq); +static void mask_and_ack_xtensa(unsigned int irq); +static void end_xtensa_irq(unsigned int irq); + static unsigned int cached_irq_mask; atomic_t irq_err_count; @@ -41,16 +46,8 @@ void ack_bad_irq(unsigned int irq) * handlers). */ -asmlinkage void do_IRQ(int irq, struct pt_regs *regs) +unsigned int do_IRQ(int irq, struct pt_regs *regs) { - struct pt_regs *old_regs = set_irq_regs(regs); - struct irq_desc *desc = irq_desc + irq; - - if (irq >= NR_IRQS) { - printk(KERN_EMERG "%s: cannot handle IRQ %d\n", - __FUNCTION__, irq); - } - irq_enter(); #ifdef CONFIG_DEBUG_STACKOVERFLOW @@ -66,10 +63,12 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) sp - sizeof(struct thread_info)); } #endif - desc->handle_irq(irq, desc); + + __do_IRQ(irq, regs); irq_exit(); - set_irq_regs(old_regs); + + return 1; } /* @@ -119,68 +118,72 @@ int show_interrupts(struct seq_file *p, void *v) } return 0; } +/* shutdown is same as "disable" */ +#define shutdown_xtensa_irq disable_xtensa_irq -static void xtensa_irq_mask(unsigned int irq) +static unsigned int startup_xtensa_irq(unsigned int irq) +{ + enable_xtensa_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type xtensa_irq_type = { + "Xtensa-IRQ", + startup_xtensa_irq, + shutdown_xtensa_irq, + enable_xtensa_irq, + disable_xtensa_irq, + mask_and_ack_xtensa, + end_xtensa_irq +}; + +static inline void mask_irq(unsigned int irq) { cached_irq_mask &= ~(1 << irq); set_sr (cached_irq_mask, INTENABLE); } -static void xtensa_irq_unmask(unsigned int irq) +static inline void unmask_irq(unsigned int irq) { cached_irq_mask |= 1 << irq; set_sr (cached_irq_mask, INTENABLE); } -static void xtensa_irq_ack(unsigned int irq) +static void disable_xtensa_irq(unsigned int irq) { - set_sr(1 << irq, INTCLEAR); + unsigned long flags; + local_save_flags(flags); + mask_irq(irq); + local_irq_restore(flags); } -static int xtensa_irq_retrigger(unsigned int irq) +static void enable_xtensa_irq(unsigned int irq) { - set_sr (1 << irq, INTSET); - return 1; + unsigned long flags; + local_save_flags(flags); + unmask_irq(irq); + local_irq_restore(flags); } - -static struct irq_chip xtensa_irq_chip = { - .name = "xtensa", - .mask = xtensa_irq_mask, - .unmask = xtensa_irq_unmask, - .ack = xtensa_irq_ack, - .retrigger = xtensa_irq_retrigger, -}; - -void __init init_IRQ(void) +static void mask_and_ack_xtensa(unsigned int irq) { - int index; - - for (index = 0; index < XTENSA_NR_IRQS; index++) { - int mask = 1 << index; - - if (mask & XCHAL_INTTYPE_MASK_SOFTWARE) - set_irq_chip_and_handler(index, &xtensa_irq_chip, - handle_simple_irq); - - else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE) - set_irq_chip_and_handler(index, &xtensa_irq_chip, - handle_edge_irq); + disable_xtensa_irq(irq); +} - else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL) - set_irq_chip_and_handler(index, &xtensa_irq_chip, - handle_level_irq); +static void end_xtensa_irq(unsigned int irq) +{ + enable_xtensa_irq(irq); +} - else if (mask & XCHAL_INTTYPE_MASK_TIMER) - set_irq_chip_and_handler(index, &xtensa_irq_chip, - handle_edge_irq); - else /* XCHAL_INTTYPE_MASK_WRITE_ERROR */ - /* XCHAL_INTTYPE_MASK_NMI */ +void __init init_IRQ(void) +{ + int i; - set_irq_chip_and_handler(index, &xtensa_irq_chip, - handle_level_irq); - } + for (i=0; i < XTENSA_NR_IRQS; i++) + irq_desc[i].chip = &xtensa_irq_type; cached_irq_mask = 0; + + platform_init_irq(); } diff --git a/trunk/arch/xtensa/kernel/pci-dma.c b/trunk/arch/xtensa/kernel/pci-dma.c index ca76f071666e..6648fa9d9192 100644 --- a/trunk/arch/xtensa/kernel/pci-dma.c +++ b/trunk/arch/xtensa/kernel/pci-dma.c @@ -1,5 +1,5 @@ /* - * arch/xtensa/pci-dma.c + * arch/xtensa/kernel/pci-dma.c * * DMA coherent memory allocation. * @@ -29,48 +29,28 @@ */ void * -dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag) +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) { - unsigned long ret; - unsigned long uncached = 0; + void *ret; /* ignore region speicifiers */ + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); - flag &= ~(__GFP_DMA | __GFP_HIGHMEM); + if (dev == NULL || (*dev->dma_mask < 0xffffffff)) + gfp |= GFP_DMA; + ret = (void *)__get_free_pages(gfp, get_order(size)); - if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) - flag |= GFP_DMA; - ret = (unsigned long)__get_free_pages(flag, get_order(size)); - - if (ret == 0) - return NULL; - - /* We currently don't support coherent memory outside KSEG */ - - if (ret < XCHAL_KSEG_CACHED_VADDR - || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE) - BUG(); - - - if (ret != 0) { - memset((void*) ret, 0, size); - uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR; - *handle = virt_to_bus((void*)ret); - __flush_invalidate_dcache_range(ret, size); + if (ret != NULL) { + memset(ret, 0, size); + *handle = virt_to_bus(ret); } - - return (void*)uncached; + return (void*) BYPASS_ADDR((unsigned long)ret); } void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { - long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR; - - if (addr < 0 || addr >= XCHAL_KSEG_SIZE) - BUG(); - - free_pages(addr, get_order(size)); + free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size)); } diff --git a/trunk/arch/xtensa/kernel/process.c b/trunk/arch/xtensa/kernel/process.c index 795bd5ac6f4c..a7c4178c2a8c 100644 --- a/trunk/arch/xtensa/kernel/process.c +++ b/trunk/arch/xtensa/kernel/process.c @@ -1,3 +1,4 @@ +// TODO verify coprocessor handling /* * arch/xtensa/kernel/process.c * @@ -42,7 +43,7 @@ #include #include #include -#include +#include extern void ret_from_fork(void); @@ -66,6 +67,25 @@ void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); +#if XCHAL_CP_NUM > 0 + +/* + * Coprocessor ownership. + */ + +coprocessor_info_t coprocessor_info[] = { + { 0, XTENSA_CPE_CP0_OFFSET }, + { 0, XTENSA_CPE_CP1_OFFSET }, + { 0, XTENSA_CPE_CP2_OFFSET }, + { 0, XTENSA_CPE_CP3_OFFSET }, + { 0, XTENSA_CPE_CP4_OFFSET }, + { 0, XTENSA_CPE_CP5_OFFSET }, + { 0, XTENSA_CPE_CP6_OFFSET }, + { 0, XTENSA_CPE_CP7_OFFSET }, +}; + +#endif + /* * Powermanagement idle function, if any is provided by the platform. */ @@ -90,10 +110,12 @@ void cpu_idle(void) void exit_thread(void) { + release_coprocessors(current); /* Empty macro if no CPs are defined */ } void flush_thread(void) { + release_coprocessors(current); /* Empty macro if no CPs are defined */ } /* @@ -160,6 +182,36 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, } +/* + * Create a kernel thread + */ + +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + __asm__ __volatile__ + ("mov a5, %4\n\t" /* preserve fn in a5 */ + "mov a6, %3\n\t" /* preserve and setup arg in a6 */ + "movi a2, %1\n\t" /* load __NR_clone for syscall*/ + "mov a3, sp\n\t" /* sp check and sys_clone */ + "mov a4, %5\n\t" /* load flags for syscall */ + "syscall\n\t" + "beq a3, sp, 1f\n\t" /* branch if parent */ + "callx4 a5\n\t" /* call fn */ + "movi a2, %2\n\t" /* load __NR_exit for syscall */ + "mov a3, a6\n\t" /* load fn return value */ + "syscall\n" + "1:\n\t" + "mov %0, a2\n\t" /* parent returns zero */ + :"=r" (retval) + :"i" (__NR_clone), "i" (__NR_exit), + "r" (arg), "r" (fn), + "r" (flags | CLONE_VM) + : "a2", "a3", "a4", "a5", "a6" ); + return retval; +} + + /* * These bracket the sleeping functions.. */ @@ -223,7 +275,7 @@ void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, */ elfregs->pc = regs->pc; - elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT)); + elfregs->ps = (regs->ps & ~XCHAL_PS_EXCM_MASK); elfregs->exccause = regs->exccause; elfregs->excvaddr = regs->excvaddr; elfregs->windowbase = regs->windowbase; @@ -273,7 +325,7 @@ void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, */ regs->pc = elfregs->pc; - regs->ps = (elfregs->ps | (1 << PS_EXCM_BIT)); + regs->ps = (elfregs->ps | XCHAL_PS_EXCM_MASK); regs->exccause = elfregs->exccause; regs->excvaddr = elfregs->excvaddr; regs->windowbase = elfregs->windowbase; @@ -407,7 +459,16 @@ int do_restore_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs, int dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r) { +/* see asm/coprocessor.h for this magic number 16 */ +#if XTENSA_CP_EXTRA_SIZE > 16 + do_save_fpregs (r, regs, task); + + /* For now, bit 16 means some extra state may be present: */ +// FIXME!! need to track to return more accurate mask + return 0x10000 | XCHAL_CP_MASK; +#else return 0; /* no coprocessors active on this processor */ +#endif } /* @@ -422,44 +483,3 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) { return dump_task_fpu(regs, current, r); } - -asmlinkage -long xtensa_clone(unsigned long clone_flags, unsigned long newsp, - void __user *parent_tid, void *child_tls, - void __user *child_tid, long a5, - struct pt_regs *regs) -{ - if (!newsp) - newsp = regs->areg[1]; - return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); -} - -/* - * * xtensa_execve() executes a new program. - * */ - -asmlinkage -long xtensa_execve(char __user *name, char __user * __user *argv, - char __user * __user *envp, - long a3, long a4, long a5, - struct pt_regs *regs) -{ - long error; - char * filename; - - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - // FIXME: release coprocessor?? - error = do_execve(filename, argv, envp, regs); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } - putname(filename); -out: - return error; -} - diff --git a/trunk/arch/xtensa/kernel/ptrace.c b/trunk/arch/xtensa/kernel/ptrace.c index 8b6d3d0623b6..9aea23cc0dc5 100644 --- a/trunk/arch/xtensa/kernel/ptrace.c +++ b/trunk/arch/xtensa/kernel/ptrace.c @@ -96,7 +96,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* Note: PS.EXCM is not set while user task is running; * its being set in regs is for exception handling * convenience. */ - tmp = (regs->ps & ~(1 << PS_EXCM_BIT)); + tmp = (regs->ps & ~XCHAL_PS_EXCM_MASK); break; case REG_WB: tmp = regs->windowbase; @@ -332,6 +332,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) void do_syscall_trace(void) { + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + + if (!(current->ptrace & PT_PTRACED)) + return; + /* * The 0x80 provides a way for the tracing parent to distinguish * between a syscall stop and SIGTRAP delivery @@ -348,23 +354,3 @@ void do_syscall_trace(void) current->exit_code = 0; } } - -void do_syscall_trace_enter(struct pt_regs *regs) -{ - if (test_thread_flag(TIF_SYSCALL_TRACE) - && (current->ptrace & PT_PTRACED)) - do_syscall_trace(); - -#if 0 - if (unlikely(current->audit_context)) - audit_syscall_entry(current, AUDIT_ARCH_XTENSA..); -#endif -} - -void do_syscall_trace_leave(struct pt_regs *regs) -{ - if ((test_thread_flag(TIF_SYSCALL_TRACE)) - && (current->ptrace & PT_PTRACED)) - do_syscall_trace(); -} - diff --git a/trunk/arch/xtensa/kernel/setup.c b/trunk/arch/xtensa/kernel/setup.c index b6374c09de20..c99ab72b41b6 100644 --- a/trunk/arch/xtensa/kernel/setup.c +++ b/trunk/arch/xtensa/kernel/setup.c @@ -42,6 +42,8 @@ #include #include +#include + #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16}; #endif @@ -334,7 +336,7 @@ c_show(struct seq_file *f, void *slot) /* high-level stuff */ seq_printf(f,"processor\t: 0\n" "vendor_id\t: Tensilica\n" - "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n" + "model\t\t: Xtensa " XCHAL_HW_RELEASE_NAME "\n" "core ID\t\t: " XCHAL_CORE_ID "\n" "build ID\t: 0x%x\n" "byte order\t: %s\n" @@ -418,6 +420,25 @@ c_show(struct seq_file *f, void *slot) XCHAL_NUM_TIMERS, XCHAL_DEBUGLEVEL); + /* Coprocessors */ +#if XCHAL_HAVE_CP + seq_printf(f, "coprocessors\t: %d\n", XCHAL_CP_NUM); +#else + seq_printf(f, "coprocessors\t: none\n"); +#endif + + /* {I,D}{RAM,ROM} and XLMI */ + seq_printf(f,"inst ROMs\t: %d\n" + "inst RAMs\t: %d\n" + "data ROMs\t: %d\n" + "data RAMs\t: %d\n" + "XLMI ports\t: %d\n", + XCHAL_NUM_IROM, + XCHAL_NUM_IRAM, + XCHAL_NUM_DROM, + XCHAL_NUM_DRAM, + XCHAL_NUM_XLMI); + /* Cache */ seq_printf(f,"icache line size: %d\n" "icache ways\t: %d\n" @@ -445,6 +466,24 @@ c_show(struct seq_file *f, void *slot) XCHAL_DCACHE_WAYS, XCHAL_DCACHE_SIZE); + /* MMU */ + seq_printf(f,"ASID bits\t: %d\n" + "ASID invalid\t: %d\n" + "ASID kernel\t: %d\n" + "rings\t\t: %d\n" + "itlb ways\t: %d\n" + "itlb AR ways\t: %d\n" + "dtlb ways\t: %d\n" + "dtlb AR ways\t: %d\n", + XCHAL_MMU_ASID_BITS, + XCHAL_MMU_ASID_INVALID, + XCHAL_MMU_ASID_KERNEL, + XCHAL_MMU_RINGS, + XCHAL_ITLB_WAYS, + XCHAL_ITLB_ARF_WAYS, + XCHAL_DTLB_WAYS, + XCHAL_DTLB_ARF_WAYS); + return 0; } diff --git a/trunk/arch/xtensa/kernel/signal.c b/trunk/arch/xtensa/kernel/signal.c index c6d9880a4cdb..c494f0826fc5 100644 --- a/trunk/arch/xtensa/kernel/signal.c +++ b/trunk/arch/xtensa/kernel/signal.c @@ -12,8 +12,8 @@ * */ -#include -#include +#include +#include #include #include #include @@ -46,7 +46,7 @@ extern struct task_struct *coproc_owners[]; * Atomically swap in the new signal mask, and wait for a signal. */ -int xtensa_sigsuspend(struct pt_regs *regs) +int sys_sigsuspend(struct pt_regs *regs) { old_sigset_t mask = (old_sigset_t) regs->areg[3]; sigset_t saveset; @@ -68,7 +68,7 @@ int xtensa_sigsuspend(struct pt_regs *regs) } asmlinkage int -xtensa_rt_sigsuspend(struct pt_regs *regs) +sys_rt_sigsuspend(struct pt_regs *regs) { sigset_t *unewset = (sigset_t *) regs->areg[4]; size_t sigsetsize = (size_t) regs->areg[3]; @@ -96,7 +96,7 @@ xtensa_rt_sigsuspend(struct pt_regs *regs) } asmlinkage int -xtensa_sigaction(int sig, const struct old_sigaction *act, +sys_sigaction(int sig, const struct old_sigaction *act, struct old_sigaction *oact) { struct k_sigaction new_ka, old_ka; @@ -128,7 +128,7 @@ xtensa_sigaction(int sig, const struct old_sigaction *act, } asmlinkage int -xtensa_sigaltstack(struct pt_regs *regs) +sys_sigaltstack(struct pt_regs *regs) { const stack_t *uss = (stack_t *) regs->areg[4]; stack_t *uoss = (stack_t *) regs->areg[3]; @@ -216,8 +216,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) * handler, or the user mode value doesn't matter (e.g. PS.OWB). */ err |= __get_user(ps, &sc->sc_ps); - regs->ps = (regs->ps & ~PS_CALLINC_MASK) - | (ps & PS_CALLINC_MASK); + regs->ps = (regs->ps & ~XCHAL_PS_CALLINC_MASK) + | (ps & XCHAL_PS_CALLINC_MASK); /* Additional corruption checks */ @@ -280,7 +280,7 @@ flush_my_cpstate(struct task_struct *tsk) static int save_cpextra (struct _cpstate *buf) { -#if XCHAL_CP_NUM == 0 +#if (XCHAL_EXTRA_SA_SIZE == 0) && (XCHAL_CP_NUM == 0) return 0; #else @@ -350,7 +350,7 @@ setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate, return err; } -asmlinkage int xtensa_sigreturn(struct pt_regs *regs) +asmlinkage int sys_sigreturn(struct pt_regs *regs) { struct sigframe *frame = (struct sigframe *)regs->areg[1]; sigset_t set; @@ -382,7 +382,7 @@ asmlinkage int xtensa_sigreturn(struct pt_regs *regs) return 0; } -asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs) +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1]; sigset_t set; @@ -497,10 +497,8 @@ gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn) /* Flush generated code out of the data cache */ - if (err == 0) { - __invalidate_icache_range((unsigned long)codemem, 6UL); - __flush_invalidate_dcache_range((unsigned long)codemem, 6UL); - } + if (err == 0) + __flush_invalidate_cache_range((unsigned long)codemem, 6UL); return err; } diff --git a/trunk/arch/xtensa/kernel/syscall.c b/trunk/arch/xtensa/kernel/syscall.c deleted file mode 100644 index fe3834bc1dbf..000000000000 --- a/trunk/arch/xtensa/kernel/syscall.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * arch/xtensa/kernel/syscall.c - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - * Copyright (C) 2000 Silicon Graphics, Inc. - * Copyright (C) 1995 - 2000 by Ralf Baechle - * - * Joe Taylor - * Marc Gauthier - * Chris Zankel - * Kevin Chea - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef void (*syscall_t)(void); - -syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= { - [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, - -#undef __SYSCALL -#define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, -#undef _XTENSA_UNISTD_H -#undef __KERNEL_SYSCALLS__ -#include -}; - -/* - * xtensa_pipe() is the normal C calling standard for creating a pipe. It's not - * the way unix traditional does this, though. - */ - -asmlinkage long xtensa_pipe(int __user *userfds) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(userfds, fd, 2 * sizeof(int))) - error = -EFAULT; - } - return error; -} - - -asmlinkage long xtensa_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) -{ - unsigned long ret; - long err; - - err = do_shmat(shmid, shmaddr, shmflg, &ret); - if (err) - return err; - return (long)ret; -} - diff --git a/trunk/arch/xtensa/kernel/syscalls.c b/trunk/arch/xtensa/kernel/syscalls.c new file mode 100644 index 000000000000..f49cb239e603 --- /dev/null +++ b/trunk/arch/xtensa/kernel/syscalls.c @@ -0,0 +1,288 @@ +/* + * arch/xtensa/kernel/syscalls.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 1995 - 2000 by Ralf Baechle + * + * Joe Taylor + * Marc Gauthier + * Chris Zankel + * Kevin Chea + * + */ + +#define DEBUG 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void do_syscall_trace(void); +typedef int (*syscall_t)(void *a0,...); +extern syscall_t sys_call_table[]; +extern unsigned char sys_narg_table[]; + +/* + * sys_pipe() is the normal C calling standard for creating a pipe. It's not + * the way unix traditional does this, though. + */ + +int sys_pipe(int __user *userfds) +{ + int fd[2]; + int error; + + error = do_pipe(fd); + if (!error) { + if (copy_to_user(userfds, fd, 2 * sizeof(int))) + error = -EFAULT; + } + return error; +} + +/* + * Common code for old and new mmaps. + */ +long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, unsigned long pgoff) +{ + int error = -EBADF; + struct file * file = NULL; + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (!(flags & MAP_ANONYMOUS)) { + file = fget(fd); + if (!file) + goto out; + } + + down_write(¤t->mm->mmap_sem); + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + + if (file) + fput(file); +out: + return error; +} + +int sys_clone(struct pt_regs *regs) +{ + unsigned long clone_flags; + unsigned long newsp; + int __user *parent_tidptr, *child_tidptr; + clone_flags = regs->areg[4]; + newsp = regs->areg[3]; + parent_tidptr = (int __user *)regs->areg[5]; + child_tidptr = (int __user *)regs->areg[6]; + if (!newsp) + newsp = regs->areg[1]; + return do_fork(clone_flags,newsp,regs,0,parent_tidptr,child_tidptr); +} + +/* + * sys_execve() executes a new program. + */ + +int sys_execve(struct pt_regs *regs) +{ + int error; + char * filename; + + filename = getname((char *) (long)regs->areg[5]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename, (char **) (long)regs->areg[3], + (char **) (long)regs->areg[4], regs); + putname(filename); + +out: + return error; +} + +int sys_uname(struct old_utsname * name) +{ + if (name && !copy_to_user(name, utsname(), sizeof (*name))) + return 0; + return -EFAULT; +} + +/* + * Build the string table for the builtin "poor man's strace". + */ + +#if DEBUG +#define SYSCALL(fun, narg) #fun, +static char *sfnames[] = { +#include "syscalls.h" +}; +#undef SYS +#endif + +void system_call (struct pt_regs *regs) +{ + syscall_t syscall; + unsigned long parm0, parm1, parm2, parm3, parm4, parm5; + int nargs, res; + unsigned int syscallnr; + int ps; + +#if DEBUG + int i; + unsigned long parms[6]; + char *sysname; +#endif + + regs->syscall = regs->areg[2]; + + do_syscall_trace(); + + /* Have to load after syscall_trace because strace + * sometimes changes regs->syscall. + */ + syscallnr = regs->syscall; + + parm0 = parm1 = parm2 = parm3 = parm4 = parm5 = 0; + + /* Restore interrupt level to syscall invoker's. + * If this were in assembly, we wouldn't disable + * interrupts in the first place: + */ + local_save_flags (ps); + local_irq_restore((ps & ~XCHAL_PS_INTLEVEL_MASK) | + (regs->ps & XCHAL_PS_INTLEVEL_MASK) ); + + if (syscallnr > __NR_Linux_syscalls) { + regs->areg[2] = -ENOSYS; + return; + } + + syscall = sys_call_table[syscallnr]; + nargs = sys_narg_table[syscallnr]; + + if (syscall == NULL) { + regs->areg[2] = -ENOSYS; + return; + } + + /* There shouldn't be more than six arguments in the table! */ + + if (nargs > 6) + panic("Internal error - too many syscall arguments (%d)!\n", + nargs); + + /* Linux takes system-call arguments in registers. The ABI + * and Xtensa software conventions require the system-call + * number in a2. If an argument exists in a2, we move it to + * the next available register. Note that for improved + * efficiency, we do NOT shift all parameters down one + * register to maintain the original order. + * + * At best case (zero arguments), we just write the syscall + * number to a2. At worst case (1 to 6 arguments), we move + * the argument in a2 to the next available register, then + * write the syscall number to a2. + * + * For clarity, the following truth table enumerates all + * possibilities. + * + * arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5 + * --------- -------------- ---------------------------------- + * 0 a2 + * 1 a2 a3 + * 2 a2 a4, a3 + * 3 a2 a5, a3, a4 + * 4 a2 a6, a3, a4, a5 + * 5 a2 a7, a3, a4, a5, a6 + * 6 a2 a8, a3, a4, a5, a6, a7 + */ + if (nargs) { + parm0 = regs->areg[nargs+2]; + parm1 = regs->areg[3]; + parm2 = regs->areg[4]; + parm3 = regs->areg[5]; + parm4 = regs->areg[6]; + parm5 = regs->areg[7]; + } else /* nargs == 0 */ + parm0 = (unsigned long) regs; + +#if DEBUG + parms[0] = parm0; + parms[1] = parm1; + parms[2] = parm2; + parms[3] = parm3; + parms[4] = parm4; + parms[5] = parm5; + + sysname = sfnames[syscallnr]; + if (strncmp(sysname, "sys_", 4) == 0) + sysname = sysname + 4; + + printk("\017SYSCALL:I:%x:%d:%s %s(", regs->pc, current->pid, + current->comm, sysname); + for (i = 0; i < nargs; i++) + printk((i>0) ? ", %#lx" : "%#lx", parms[i]); + printk(")\n"); +#endif + + res = syscall((void *)parm0, parm1, parm2, parm3, parm4, parm5); + +#if DEBUG + printk("\017SYSCALL:O:%d:%s %s(",current->pid, current->comm, sysname); + for (i = 0; i < nargs; i++) + printk((i>0) ? ", %#lx" : "%#lx", parms[i]); + if (res < 4096) + printk(") = %d\n", res); + else + printk(") = %#x\n", res); +#endif /* DEBUG */ + + regs->areg[2] = res; + do_syscall_trace(); +} + +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +int kernel_execve(const char *filename, char *const argv[], char *const envp[]) +{ + long __res; + asm volatile ( + " mov a5, %2 \n" + " mov a4, %4 \n" + " mov a3, %3 \n" + " movi a2, %1 \n" + " syscall \n" + " mov %0, a2 \n" + : "=a" (__res) + : "i" (__NR_execve), "a" (filename), "a" (argv), "a" (envp) + : "a2", "a3", "a4", "a5"); + return __res; +} diff --git a/trunk/arch/xtensa/kernel/syscalls.h b/trunk/arch/xtensa/kernel/syscalls.h new file mode 100644 index 000000000000..216c10a31501 --- /dev/null +++ b/trunk/arch/xtensa/kernel/syscalls.h @@ -0,0 +1,247 @@ +/* + * arch/xtensa/kernel/syscalls.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 2001 - 2005 Tensilica Inc. + * + * Changes by Joe Taylor + */ + +/* + * This file is being included twice - once to build a list of all + * syscalls and once to build a table of how many arguments each syscall + * accepts. Syscalls that receive a pointer to the saved registers are + * marked as having zero arguments. + * + * The binary compatibility calls are in a separate list. + * + * Entry '0' used to be system_call. It's removed to disable indirect + * system calls for now so user tasks can't recurse. See mips' + * sys_syscall for a comparable example. + */ + +SYSCALL(0, 0) /* 00 */ +SYSCALL(sys_exit, 1) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_read, 3) +SYSCALL(sys_write, 3) +SYSCALL(sys_open, 3) /* 05 */ +SYSCALL(sys_close, 1) +SYSCALL(sys_ni_syscall, 3) +SYSCALL(sys_creat, 2) +SYSCALL(sys_link, 2) +SYSCALL(sys_unlink, 1) /* 10 */ +SYSCALL(sys_execve, 0) +SYSCALL(sys_chdir, 1) +SYSCALL(sys_ni_syscall, 1) +SYSCALL(sys_mknod, 3) +SYSCALL(sys_chmod, 2) /* 15 */ +SYSCALL(sys_lchown, 3) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_newstat, 2) +SYSCALL(sys_lseek, 3) +SYSCALL(sys_getpid, 0) /* 20 */ +SYSCALL(sys_mount, 5) +SYSCALL(sys_ni_syscall, 1) +SYSCALL(sys_setuid, 1) +SYSCALL(sys_getuid, 0) +SYSCALL(sys_ni_syscall, 1) /* 25 */ +SYSCALL(sys_ptrace, 4) +SYSCALL(sys_ni_syscall, 1) +SYSCALL(sys_newfstat, 2) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_utime, 2) /* 30 */ +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_access, 2) +SYSCALL(sys_ni_syscall, 1) +SYSCALL(sys_ni_syscall, 0) /* 35 */ +SYSCALL(sys_sync, 0) +SYSCALL(sys_kill, 2) +SYSCALL(sys_rename, 2) +SYSCALL(sys_mkdir, 2) +SYSCALL(sys_rmdir, 1) /* 40 */ +SYSCALL(sys_dup, 1) +SYSCALL(sys_pipe, 1) +SYSCALL(sys_times, 1) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_brk, 1) /* 45 */ +SYSCALL(sys_setgid, 1) +SYSCALL(sys_getgid, 0) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_geteuid, 0) +SYSCALL(sys_getegid, 0) /* 50 */ +SYSCALL(sys_acct, 1) +SYSCALL(sys_umount, 2) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_ioctl, 3) +SYSCALL(sys_fcntl, 3) /* 55 */ +SYSCALL(sys_ni_syscall, 2) +SYSCALL(sys_setpgid, 2) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_umask, 1) /* 60 */ +SYSCALL(sys_chroot, 1) +SYSCALL(sys_ustat, 2) +SYSCALL(sys_dup2, 2) +SYSCALL(sys_getppid, 0) +SYSCALL(sys_ni_syscall, 0) /* 65 */ +SYSCALL(sys_setsid, 0) +SYSCALL(sys_sigaction, 3) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_ni_syscall, 1) +SYSCALL(sys_setreuid, 2) /* 70 */ +SYSCALL(sys_setregid, 2) +SYSCALL(sys_sigsuspend, 0) +SYSCALL(sys_ni_syscall, 1) +SYSCALL(sys_sethostname, 2) +SYSCALL(sys_setrlimit, 2) /* 75 */ +SYSCALL(sys_getrlimit, 2) +SYSCALL(sys_getrusage, 2) +SYSCALL(sys_gettimeofday, 2) +SYSCALL(sys_settimeofday, 2) +SYSCALL(sys_getgroups, 2) /* 80 */ +SYSCALL(sys_setgroups, 2) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_symlink, 2) +SYSCALL(sys_newlstat, 2) +SYSCALL(sys_readlink, 3) /* 85 */ +SYSCALL(sys_uselib, 1) +SYSCALL(sys_swapon, 2) +SYSCALL(sys_reboot, 3) +SYSCALL(sys_ni_syscall, 3) +SYSCALL(sys_ni_syscall, 6) /* 90 */ +SYSCALL(sys_munmap, 2) +SYSCALL(sys_truncate, 2) +SYSCALL(sys_ftruncate, 2) +SYSCALL(sys_fchmod, 2) +SYSCALL(sys_fchown, 3) /* 95 */ +SYSCALL(sys_getpriority, 2) +SYSCALL(sys_setpriority, 3) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_statfs, 2) +SYSCALL(sys_fstatfs, 2) /* 100 */ +SYSCALL(sys_ni_syscall, 3) +SYSCALL(sys_ni_syscall, 2) +SYSCALL(sys_syslog, 3) +SYSCALL(sys_setitimer, 3) +SYSCALL(sys_getitimer, 2) /* 105 */ +SYSCALL(sys_newstat, 2) +SYSCALL(sys_newlstat, 2) +SYSCALL(sys_newfstat, 2) +SYSCALL(sys_uname, 1) +SYSCALL(sys_ni_syscall, 0) /* 110 */ +SYSCALL(sys_vhangup, 0) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_wait4, 4) +SYSCALL(sys_swapoff, 1) /* 115 */ +SYSCALL(sys_sysinfo, 1) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_fsync, 1) +SYSCALL(sys_sigreturn, 0) +SYSCALL(sys_clone, 0) /* 120 */ +SYSCALL(sys_setdomainname, 2) +SYSCALL(sys_newuname, 1) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_adjtimex, 1) +SYSCALL(sys_mprotect, 3) /* 125 */ +SYSCALL(sys_ni_syscall, 3) +SYSCALL(sys_ni_syscall, 2) +SYSCALL(sys_init_module, 2) +SYSCALL(sys_delete_module, 1) +SYSCALL(sys_ni_syscall, 1) /* 130 */ +SYSCALL(sys_quotactl, 0) +SYSCALL(sys_getpgid, 1) +SYSCALL(sys_fchdir, 1) +SYSCALL(sys_bdflush, 2) +SYSCALL(sys_sysfs, 3) /* 135 */ +SYSCALL(sys_personality, 1) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_setfsuid, 1) +SYSCALL(sys_setfsgid, 1) +SYSCALL(sys_llseek, 5) /* 140 */ +SYSCALL(sys_getdents, 3) +SYSCALL(sys_select, 5) +SYSCALL(sys_flock, 2) +SYSCALL(sys_msync, 3) +SYSCALL(sys_readv, 3) /* 145 */ +SYSCALL(sys_writev, 3) +SYSCALL(sys_ni_syscall, 3) +SYSCALL(sys_ni_syscall, 3) +SYSCALL(sys_ni_syscall, 4) /* handled in fast syscall handler. */ +SYSCALL(sys_ni_syscall, 0) /* 150 */ +SYSCALL(sys_getsid, 1) +SYSCALL(sys_fdatasync, 1) +SYSCALL(sys_sysctl, 1) +SYSCALL(sys_mlock, 2) +SYSCALL(sys_munlock, 2) /* 155 */ +SYSCALL(sys_mlockall, 1) +SYSCALL(sys_munlockall, 0) +SYSCALL(sys_sched_setparam,2) +SYSCALL(sys_sched_getparam,2) +SYSCALL(sys_sched_setscheduler,3) /* 160 */ +SYSCALL(sys_sched_getscheduler,1) +SYSCALL(sys_sched_yield,0) +SYSCALL(sys_sched_get_priority_max,1) +SYSCALL(sys_sched_get_priority_min,1) +SYSCALL(sys_sched_rr_get_interval,2) /* 165 */ +SYSCALL(sys_nanosleep,2) +SYSCALL(sys_mremap,4) +SYSCALL(sys_accept, 3) +SYSCALL(sys_bind, 3) +SYSCALL(sys_connect, 3) /* 170 */ +SYSCALL(sys_getpeername, 3) +SYSCALL(sys_getsockname, 3) +SYSCALL(sys_getsockopt, 5) +SYSCALL(sys_listen, 2) +SYSCALL(sys_recv, 4) /* 175 */ +SYSCALL(sys_recvfrom, 6) +SYSCALL(sys_recvmsg, 3) +SYSCALL(sys_send, 4) +SYSCALL(sys_sendmsg, 3) +SYSCALL(sys_sendto, 6) /* 180 */ +SYSCALL(sys_setsockopt, 5) +SYSCALL(sys_shutdown, 2) +SYSCALL(sys_socket, 3) +SYSCALL(sys_socketpair, 4) +SYSCALL(sys_setresuid, 3) /* 185 */ +SYSCALL(sys_getresuid, 3) +SYSCALL(sys_ni_syscall, 5) +SYSCALL(sys_poll, 3) +SYSCALL(sys_nfsservctl, 3) +SYSCALL(sys_setresgid, 3) /* 190 */ +SYSCALL(sys_getresgid, 3) +SYSCALL(sys_prctl, 5) +SYSCALL(sys_rt_sigreturn, 0) +SYSCALL(sys_rt_sigaction, 4) +SYSCALL(sys_rt_sigprocmask, 4) /* 195 */ +SYSCALL(sys_rt_sigpending, 2) +SYSCALL(sys_rt_sigtimedwait, 4) +SYSCALL(sys_rt_sigqueueinfo, 3) +SYSCALL(sys_rt_sigsuspend, 0) +SYSCALL(sys_pread64, 5) /* 200 */ +SYSCALL(sys_pwrite64, 5) +SYSCALL(sys_chown, 3) +SYSCALL(sys_getcwd, 2) +SYSCALL(sys_capget, 2) +SYSCALL(sys_capset, 2) /* 205 */ +SYSCALL(sys_sigaltstack, 0) +SYSCALL(sys_sendfile, 4) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_ni_syscall, 0) +SYSCALL(sys_mmap, 6) /* 210 */ +SYSCALL(sys_truncate64, 2) +SYSCALL(sys_ftruncate64, 2) +SYSCALL(sys_stat64, 2) +SYSCALL(sys_lstat64, 2) +SYSCALL(sys_fstat64, 2) /* 215 */ +SYSCALL(sys_pivot_root, 2) +SYSCALL(sys_mincore, 3) +SYSCALL(sys_madvise, 3) +SYSCALL(sys_getdents64, 3) +SYSCALL(sys_ni_syscall, 0) /* 220 */ diff --git a/trunk/arch/xtensa/kernel/time.c b/trunk/arch/xtensa/kernel/time.c index a350431363a0..37347e369987 100644 --- a/trunk/arch/xtensa/kernel/time.c +++ b/trunk/arch/xtensa/kernel/time.c @@ -47,7 +47,7 @@ unsigned long long sched_clock(void) return (unsigned long long)jiffies * (1000000000 / HZ); } -static irqreturn_t timer_interrupt(int irq, void *dev_id); +static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct irqaction timer_irqaction = { .handler = timer_interrupt, .flags = IRQF_DISABLED, @@ -150,7 +150,7 @@ EXPORT_SYMBOL(do_gettimeofday); * The timer interrupt is called HZ times per second. */ -irqreturn_t timer_interrupt (int irq, void *dev_id) +irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) { unsigned long next; @@ -160,9 +160,9 @@ irqreturn_t timer_interrupt (int irq, void *dev_id) again: while ((signed long)(get_ccount() - next) > 0) { - profile_tick(CPU_PROFILING); + profile_tick(CPU_PROFILING, regs); #ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); + update_process_times(user_mode(regs)); #endif write_seqlock(&xtime_lock); diff --git a/trunk/arch/xtensa/kernel/traps.c b/trunk/arch/xtensa/kernel/traps.c index 693ab268485e..ce077d6bf3a0 100644 --- a/trunk/arch/xtensa/kernel/traps.c +++ b/trunk/arch/xtensa/kernel/traps.c @@ -75,7 +75,7 @@ extern void system_call (struct pt_regs*); #define USER 0x02 #define COPROCESSOR(x) \ -{ EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor } +{ XCHAL_EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor } typedef struct { int cause; @@ -85,38 +85,38 @@ typedef struct { dispatch_init_table_t __init dispatch_init_table[] = { -{ EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction}, -{ EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel }, -{ EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user }, -{ EXCCAUSE_SYSTEM_CALL, 0, system_call }, -/* EXCCAUSE_INSTRUCTION_FETCH unhandled */ -/* EXCCAUSE_LOAD_STORE_ERROR unhandled*/ -{ EXCCAUSE_LEVEL1_INTERRUPT, 0, do_interrupt }, -{ EXCCAUSE_ALLOCA, USER|KRNL, fast_alloca }, -/* EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */ -/* EXCCAUSE_PRIVILEGED unhandled */ +{ XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction}, +{ XCHAL_EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel }, +{ XCHAL_EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user }, +{ XCHAL_EXCCAUSE_SYSTEM_CALL, 0, system_call }, +/* XCHAL_EXCCAUSE_INSTRUCTION_FETCH unhandled */ +/* XCHAL_EXCCAUSE_LOAD_STORE_ERROR unhandled*/ +{ XCHAL_EXCCAUSE_LEVEL1_INTERRUPT, 0, do_interrupt }, +{ XCHAL_EXCCAUSE_ALLOCA, USER|KRNL, fast_alloca }, +/* XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */ +/* XCHAL_EXCCAUSE_PRIVILEGED unhandled */ #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION #ifdef CONFIG_UNALIGNED_USER -{ EXCCAUSE_UNALIGNED, USER, fast_unaligned }, +{ XCHAL_EXCCAUSE_UNALIGNED, USER, fast_unaligned }, #else -{ EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, +{ XCHAL_EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, #endif -{ EXCCAUSE_UNALIGNED, KRNL, fast_unaligned }, +{ XCHAL_EXCCAUSE_UNALIGNED, KRNL, fast_unaligned }, #endif -{ EXCCAUSE_ITLB_MISS, 0, do_page_fault }, -{ EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss}, -{ EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit }, -{ EXCCAUSE_ITLB_PRIVILEGE, 0, do_page_fault }, -/* EXCCAUSE_SIZE_RESTRICTION unhandled */ -{ EXCCAUSE_FETCH_CACHE_ATTRIBUTE, 0, do_page_fault }, -{ EXCCAUSE_DTLB_MISS, USER|KRNL, fast_second_level_miss}, -{ EXCCAUSE_DTLB_MISS, 0, do_page_fault }, -{ EXCCAUSE_DTLB_MULTIHIT, 0, do_multihit }, -{ EXCCAUSE_DTLB_PRIVILEGE, 0, do_page_fault }, -/* EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */ -{ EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited }, -{ EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault }, -{ EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault }, +{ XCHAL_EXCCAUSE_ITLB_MISS, 0, do_page_fault }, +{ XCHAL_EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss}, +{ XCHAL_EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit }, +{ XCHAL_EXCCAUSE_ITLB_PRIVILEGE, 0, do_page_fault }, +/* XCHAL_EXCCAUSE_SIZE_RESTRICTION unhandled */ +{ XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE, 0, do_page_fault }, +{ XCHAL_EXCCAUSE_DTLB_MISS, USER|KRNL, fast_second_level_miss}, +{ XCHAL_EXCCAUSE_DTLB_MISS, 0, do_page_fault }, +{ XCHAL_EXCCAUSE_DTLB_MULTIHIT, 0, do_multihit }, +{ XCHAL_EXCCAUSE_DTLB_PRIVILEGE, 0, do_page_fault }, +/* XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */ +{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited }, +{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault }, +{ XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault }, /* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */ #if (XCHAL_CP_MASK & 1) COPROCESSOR(0), diff --git a/trunk/arch/xtensa/kernel/vectors.S b/trunk/arch/xtensa/kernel/vectors.S index eb2d7bb69ee0..0e74397bfa2b 100644 --- a/trunk/arch/xtensa/kernel/vectors.S +++ b/trunk/arch/xtensa/kernel/vectors.S @@ -53,8 +53,6 @@ #include #include -#define WINDOW_VECTORS_SIZE 0x180 - /* * User exception vector. (Exceptions with PS.UM == 1, PS.EXCM == 0) @@ -212,7 +210,7 @@ ENTRY(_DoubleExceptionVector) /* Check for kernel double exception (usually fatal). */ rsr a3, PS - _bbci.l a3, PS_UM_BIT, .Lksp + _bbci.l a3, PS_UM_SHIFT, .Lksp /* Check if we are currently handling a window exception. */ /* Note: We don't need to indicate that we enter a critical section. */ @@ -221,7 +219,7 @@ ENTRY(_DoubleExceptionVector) movi a3, XCHAL_WINDOW_VECTORS_VADDR _bltu a0, a3, .Lfixup - addi a3, a3, WINDOW_VECTORS_SIZE + addi a3, a3, XSHAL_WINDOW_VECTORS_SIZE _bgeu a0, a3, .Lfixup /* Window overflow/underflow exception. Get stack pointer. */ @@ -247,7 +245,7 @@ ENTRY(_DoubleExceptionVector) wsr a2, DEPC # save stack pointer temporarily rsr a0, PS - extui a0, a0, PS_OWB_SHIFT, 4 + extui a0, a0, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS wsr a0, WINDOWBASE rsync @@ -314,8 +312,8 @@ ENTRY(_DoubleExceptionVector) .Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */ rsr a3, EXCCAUSE - beqi a3, EXCCAUSE_ITLB_MISS, 1f - addi a3, a3, -EXCCAUSE_DTLB_MISS + beqi a3, XCHAL_EXCCAUSE_ITLB_MISS, 1f + addi a3, a3, -XCHAL_EXCCAUSE_DTLB_MISS bnez a3, .Lunrecoverable 1: movi a3, fast_second_level_miss_double_kernel jx a3 diff --git a/trunk/arch/xtensa/kernel/vmlinux.lds.S b/trunk/arch/xtensa/kernel/vmlinux.lds.S index a36c104c3a52..cfe75f528725 100644 --- a/trunk/arch/xtensa/kernel/vmlinux.lds.S +++ b/trunk/arch/xtensa/kernel/vmlinux.lds.S @@ -16,17 +16,19 @@ #include -#include +#define _NOCLANGUAGE +#include +#include OUTPUT_ARCH(xtensa) ENTRY(_start) -#ifdef __XTENSA_EB__ +#if XCHAL_MEMORY_ORDER == XTHAL_BIGENDIAN jiffies = jiffies_64 + 4; #else jiffies = jiffies_64; #endif -#define KERNELOFFSET 0xd0001000 +#define KERNELOFFSET 0x1000 /* Note: In the following macros, it would be nice to specify only the vector name and section kind and construct "sym" and "section" using @@ -73,7 +75,7 @@ jiffies = jiffies_64; SECTIONS { - . = KERNELOFFSET; + . = XCHAL_KSEG_CACHED_VADDR + KERNELOFFSET; /* .text section */ _text = .; @@ -157,7 +159,7 @@ SECTIONS /* Initialization code and data: */ - . = ALIGN(1 << 12); + . = ALIGN(1< #include -#include +#define _ASMLANGUAGE +#include /* * computes a partial checksum, e.g. for TCP/UDP fragments diff --git a/trunk/arch/xtensa/lib/memcopy.S b/trunk/arch/xtensa/lib/memcopy.S index ddda8f4bc862..e8f6d7eb7222 100644 --- a/trunk/arch/xtensa/lib/memcopy.S +++ b/trunk/arch/xtensa/lib/memcopy.S @@ -9,7 +9,7 @@ * Copyright (C) 2002 - 2005 Tensilica Inc. */ -#include +#include .macro src_b r, w0, w1 #ifdef __XTENSA_EB__ diff --git a/trunk/arch/xtensa/lib/memset.S b/trunk/arch/xtensa/lib/memset.S index 56a17495b2db..4de25134bc62 100644 --- a/trunk/arch/xtensa/lib/memset.S +++ b/trunk/arch/xtensa/lib/memset.S @@ -11,7 +11,7 @@ * Copyright (C) 2002 Tensilica Inc. */ -#include +#include /* * void *memset(void *dst, int c, size_t length) diff --git a/trunk/arch/xtensa/lib/strncpy_user.S b/trunk/arch/xtensa/lib/strncpy_user.S index a834057bda6b..71d55df43893 100644 --- a/trunk/arch/xtensa/lib/strncpy_user.S +++ b/trunk/arch/xtensa/lib/strncpy_user.S @@ -11,7 +11,7 @@ * Copyright (C) 2002 Tensilica Inc. */ -#include +#include #include /* Load or store instructions that may cause exceptions use the EX macro. */ diff --git a/trunk/arch/xtensa/lib/strnlen_user.S b/trunk/arch/xtensa/lib/strnlen_user.S index 5e9c1e709b2e..cdff4d670f3b 100644 --- a/trunk/arch/xtensa/lib/strnlen_user.S +++ b/trunk/arch/xtensa/lib/strnlen_user.S @@ -11,7 +11,7 @@ * Copyright (C) 2002 Tensilica Inc. */ -#include +#include /* Load or store instructions that may cause exceptions use the EX macro. */ diff --git a/trunk/arch/xtensa/lib/usercopy.S b/trunk/arch/xtensa/lib/usercopy.S index a8ab1d4fe0ae..4641ef510f0e 100644 --- a/trunk/arch/xtensa/lib/usercopy.S +++ b/trunk/arch/xtensa/lib/usercopy.S @@ -53,7 +53,7 @@ * a11/ original length */ -#include +#include #ifdef __XTENSA_EB__ #define ALIGN(R, W0, W1) src R, W0, W1 diff --git a/trunk/arch/xtensa/mm/fault.c b/trunk/arch/xtensa/mm/fault.c index 3dc6f2f07bbe..dd0dbec2e57e 100644 --- a/trunk/arch/xtensa/mm/fault.c +++ b/trunk/arch/xtensa/mm/fault.c @@ -21,7 +21,7 @@ #include #include -unsigned long asid_cache = ASID_USER_FIRST; +unsigned long asid_cache = ASID_FIRST_VERSION; void bad_page_fault(struct pt_regs*, unsigned long, int); /* @@ -58,10 +58,10 @@ void do_page_fault(struct pt_regs *regs) return; } - is_write = (exccause == EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0; - is_exec = (exccause == EXCCAUSE_ITLB_PRIVILEGE || - exccause == EXCCAUSE_ITLB_MISS || - exccause == EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0; + is_write = (exccause == XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0; + is_exec = (exccause == XCHAL_EXCCAUSE_ITLB_PRIVILEGE || + exccause == XCHAL_EXCCAUSE_ITLB_MISS || + exccause == XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0; #if 0 printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid, diff --git a/trunk/arch/xtensa/mm/init.c b/trunk/arch/xtensa/mm/init.c index e1ec2d1e8189..660ef058c149 100644 --- a/trunk/arch/xtensa/mm/init.c +++ b/trunk/arch/xtensa/mm/init.c @@ -141,8 +141,8 @@ void __init bootmem_init(void) if (min_low_pfn > max_pfn) panic("No memory found!\n"); - max_low_pfn = max_pfn < MAX_MEM_PFN >> PAGE_SHIFT ? - max_pfn : MAX_MEM_PFN >> PAGE_SHIFT; + max_low_pfn = max_pfn < MAX_LOW_MEMORY >> PAGE_SHIFT ? + max_pfn : MAX_LOW_MEMORY >> PAGE_SHIFT; /* Find an area to use for the bootmem bitmap. */ @@ -215,7 +215,7 @@ void __init init_mmu (void) /* Set rasid register to a known value. */ - set_rasid_register (ASID_USER_FIRST); + set_rasid_register (ASID_ALL_RESERVED); /* Set PTEVADDR special register to the start of the page * table, which is in kernel mappable space (ie. not diff --git a/trunk/arch/xtensa/mm/misc.S b/trunk/arch/xtensa/mm/misc.S index ae085332c607..327c0f17187c 100644 --- a/trunk/arch/xtensa/mm/misc.S +++ b/trunk/arch/xtensa/mm/misc.S @@ -19,8 +19,9 @@ #include #include #include -#include -#include + +#include +#include /* clear_page (page) */ @@ -73,66 +74,104 @@ ENTRY(copy_page) retw + /* - * void __invalidate_icache_page(ulong start) + * void __flush_invalidate_cache_all(void) */ -ENTRY(__invalidate_icache_page) +ENTRY(__flush_invalidate_cache_all) entry sp, 16 - - ___invalidate_icache_page a2 a3 - isync - + dcache_writeback_inv_all a2, a3 + icache_invalidate_all a2, a3 retw /* - * void __invalidate_dcache_page(ulong start) + * void __invalidate_icache_all(void) */ -ENTRY(__invalidate_dcache_page) +ENTRY(__invalidate_icache_all) entry sp, 16 + icache_invalidate_all a2, a3 + retw - ___invalidate_dcache_page a2 a3 - dsync +/* + * void __flush_invalidate_dcache_all(void) + */ +ENTRY(__flush_invalidate_dcache_all) + entry sp, 16 + dcache_writeback_inv_all a2, a3 retw + /* - * void __flush_invalidate_dcache_page(ulong start) + * void __flush_invalidate_cache_range(ulong start, ulong size) */ -ENTRY(__flush_invalidate_dcache_page) +ENTRY(__flush_invalidate_cache_range) entry sp, 16 + mov a4, a2 + mov a5, a3 + dcache_writeback_inv_region a4, a5, a6 + icache_invalidate_region a2, a3, a4 + retw - ___flush_invalidate_dcache_page a2 a3 +/* + * void __invalidate_icache_page(ulong start) + */ - dsync +ENTRY(__invalidate_icache_page) + entry sp, 16 + movi a3, PAGE_SIZE + icache_invalidate_region a2, a3, a4 retw /* - * void __flush_dcache_page(ulong start) + * void __invalidate_dcache_page(ulong start) */ -ENTRY(__flush_dcache_page) +ENTRY(__invalidate_dcache_page) entry sp, 16 + movi a3, PAGE_SIZE + dcache_invalidate_region a2, a3, a4 + retw - ___flush_dcache_page a2 a3 +/* + * void __invalidate_icache_range(ulong start, ulong size) + */ - dsync +ENTRY(__invalidate_icache_range) + entry sp, 16 + icache_invalidate_region a2, a3, a4 retw +/* + * void __invalidate_dcache_range(ulong start, ulong size) + */ +ENTRY(__invalidate_dcache_range) + entry sp, 16 + dcache_invalidate_region a2, a3, a4 + retw /* - * void __invalidate_icache_range(ulong start, ulong size) + * void __flush_dcache_page(ulong start) */ -ENTRY(__invalidate_icache_range) +ENTRY(__flush_dcache_page) entry sp, 16 + movi a3, PAGE_SIZE + dcache_writeback_region a2, a3, a4 + retw - ___invalidate_icache_range a2 a3 a4 - isync +/* + * void __flush_invalidate_dcache_page(ulong start) + */ +ENTRY(__flush_invalidate_dcache_page) + entry sp, 16 + movi a3, PAGE_SIZE + dcache_writeback_inv_region a2, a3, a4 retw /* @@ -141,69 +180,195 @@ ENTRY(__invalidate_icache_range) ENTRY(__flush_invalidate_dcache_range) entry sp, 16 + dcache_writeback_inv_region a2, a3, a4 + retw - ___flush_invalidate_dcache_range a2 a3 a4 - dsync +/* + * void __invalidate_dcache_all(void) + */ +ENTRY(__invalidate_dcache_all) + entry sp, 16 + dcache_invalidate_all a2, a3 retw /* - * void _flush_dcache_range(ulong start, ulong size) + * void __flush_invalidate_dcache_page_phys(ulong start) */ -ENTRY(__flush_dcache_range) +ENTRY(__flush_invalidate_dcache_page_phys) entry sp, 16 - ___flush_dcache_range a2 a3 a4 - dsync + movi a3, XCHAL_DCACHE_SIZE + movi a4, PAGE_MASK | 1 + addi a2, a2, 1 + +1: addi a3, a3, -XCHAL_DCACHE_LINESIZE + ldct a6, a3 + dsync + and a6, a6, a4 + beq a6, a2, 2f + bgeui a3, 2, 1b retw -/* - * void _invalidate_dcache_range(ulong start, ulong size) - */ +2: diwbi a3, 0 + bgeui a3, 2, 1b + retw -ENTRY(__invalidate_dcache_range) +ENTRY(check_dcache_low0) entry sp, 16 - ___invalidate_dcache_range a2 a3 a4 + movi a3, XCHAL_DCACHE_SIZE / 4 + movi a4, PAGE_MASK | 1 + addi a2, a2, 1 +1: addi a3, a3, -XCHAL_DCACHE_LINESIZE + ldct a6, a3 + dsync + and a6, a6, a4 + beq a6, a2, 2f + bgeui a3, 2, 1b retw -/* - * void _invalidate_icache_all(void) - */ +2: j 2b -ENTRY(__invalidate_icache_all) +ENTRY(check_dcache_high0) entry sp, 16 - ___invalidate_icache_all a2 a3 - isync + movi a5, XCHAL_DCACHE_SIZE / 4 + movi a3, XCHAL_DCACHE_SIZE / 2 + movi a4, PAGE_MASK | 1 + addi a2, a2, 1 +1: addi a3, a3, -XCHAL_DCACHE_LINESIZE + addi a5, a5, -XCHAL_DCACHE_LINESIZE + + ldct a6, a3 + dsync + and a6, a6, a4 + beq a6, a2, 2f + bgeui a5, 2, 1b retw -/* - * void _flush_invalidate_dcache_all(void) - */ +2: j 2b -ENTRY(__flush_invalidate_dcache_all) +ENTRY(check_dcache_low1) entry sp, 16 - ___flush_invalidate_dcache_all a2 a3 + movi a5, XCHAL_DCACHE_SIZE / 4 + movi a3, XCHAL_DCACHE_SIZE * 3 / 4 + movi a4, PAGE_MASK | 1 + addi a2, a2, 1 + +1: addi a3, a3, -XCHAL_DCACHE_LINESIZE + addi a5, a5, -XCHAL_DCACHE_LINESIZE + + ldct a6, a3 dsync + and a6, a6, a4 + beq a6, a2, 2f + bgeui a5, 2, 1b + retw + +2: j 2b + +ENTRY(check_dcache_high1) + entry sp, 16 + + movi a5, XCHAL_DCACHE_SIZE / 4 + movi a3, XCHAL_DCACHE_SIZE + movi a4, PAGE_MASK | 1 + addi a2, a2, 1 +1: addi a3, a3, -XCHAL_DCACHE_LINESIZE + addi a5, a5, -XCHAL_DCACHE_LINESIZE + + ldct a6, a3 + dsync + and a6, a6, a4 + beq a6, a2, 2f + bgeui a5, 2, 1b retw +2: j 2b + + /* - * void _invalidate_dcache_all(void) + * void __invalidate_icache_page_phys(ulong start) */ -ENTRY(__invalidate_dcache_all) +ENTRY(__invalidate_icache_page_phys) entry sp, 16 - ___invalidate_dcache_all a2 a3 - dsync + movi a3, XCHAL_ICACHE_SIZE + movi a4, PAGE_MASK | 1 + addi a2, a2, 1 + +1: addi a3, a3, -XCHAL_ICACHE_LINESIZE + + lict a6, a3 + isync + and a6, a6, a4 + beq a6, a2, 2f + bgeui a3, 2, 1b + retw +2: iii a3, 0 + bgeui a3, 2, 1b retw + +#if 0 + + movi a3, XCHAL_DCACHE_WAYS - 1 + movi a4, PAGE_SIZE + +1: mov a5, a2 + add a6, a2, a4 + +2: diwbi a5, 0 + diwbi a5, XCHAL_DCACHE_LINESIZE + diwbi a5, XCHAL_DCACHE_LINESIZE * 2 + diwbi a5, XCHAL_DCACHE_LINESIZE * 3 + + addi a5, a5, XCHAL_DCACHE_LINESIZE * 4 + blt a5, a6, 2b + + addi a3, a3, -1 + addi a2, a2, XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS + bgez a3, 1b + + retw + +ENTRY(__invalidate_icache_page_index) + entry sp, 16 + + movi a3, XCHAL_ICACHE_WAYS - 1 + movi a4, PAGE_SIZE + +1: mov a5, a2 + add a6, a2, a4 + +2: iii a5, 0 + iii a5, XCHAL_ICACHE_LINESIZE + iii a5, XCHAL_ICACHE_LINESIZE * 2 + iii a5, XCHAL_ICACHE_LINESIZE * 3 + + addi a5, a5, XCHAL_ICACHE_LINESIZE * 4 + blt a5, a6, 2b + + addi a3, a3, -1 + addi a2, a2, XCHAL_ICACHE_SIZE / XCHAL_ICACHE_WAYS + bgez a3, 2b + + retw + +#endif + + + + + + diff --git a/trunk/arch/xtensa/mm/tlb.c b/trunk/arch/xtensa/mm/tlb.c index 239461d8ea88..0fefb8666874 100644 --- a/trunk/arch/xtensa/mm/tlb.c +++ b/trunk/arch/xtensa/mm/tlb.c @@ -24,12 +24,12 @@ static inline void __flush_itlb_all (void) { - int w, i; + int way, index; - for (w = 0; w < ITLB_ARF_WAYS; w++) { - for (i = 0; i < (1 << XCHAL_ITLB_ARF_ENTRIES_LOG2); i++) { - int e = w + (i << PAGE_SHIFT); - invalidate_itlb_entry_no_isync(e); + for (way = 0; way < XCHAL_ITLB_ARF_WAYS; way++) { + for (index = 0; index < ITLB_ENTRIES_PER_ARF_WAY; index++) { + int entry = way + (index << PAGE_SHIFT); + invalidate_itlb_entry_no_isync (entry); } } asm volatile ("isync\n"); @@ -37,12 +37,12 @@ static inline void __flush_itlb_all (void) static inline void __flush_dtlb_all (void) { - int w, i; + int way, index; - for (w = 0; w < DTLB_ARF_WAYS; w++) { - for (i = 0; i < (1 << XCHAL_DTLB_ARF_ENTRIES_LOG2); i++) { - int e = w + (i << PAGE_SHIFT); - invalidate_dtlb_entry_no_isync(e); + for (way = 0; way < XCHAL_DTLB_ARF_WAYS; way++) { + for (index = 0; index < DTLB_ENTRIES_PER_ARF_WAY; index++) { + int entry = way + (index << PAGE_SHIFT); + invalidate_dtlb_entry_no_isync (entry); } } asm volatile ("isync\n"); @@ -63,25 +63,21 @@ void flush_tlb_all (void) void flush_tlb_mm(struct mm_struct *mm) { +#if 0 + printk("[tlbmm<%lx>]\n", (unsigned long)mm->context); +#endif + if (mm == current->active_mm) { int flags; local_save_flags(flags); - __get_new_mmu_context(mm); - __load_mmu_context(mm); + get_new_mmu_context(mm, asid_cache); + set_rasid_register(ASID_INSERT(mm->context)); local_irq_restore(flags); } else mm->context = 0; } -#define _ITLB_ENTRIES (ITLB_ARF_WAYS << XCHAL_ITLB_ARF_ENTRIES_LOG2) -#define _DTLB_ENTRIES (DTLB_ARF_WAYS << XCHAL_DTLB_ARF_ENTRIES_LOG2) -#if _ITLB_ENTRIES > _DTLB_ENTRIES -# define _TLB_ENTRIES _ITLB_ENTRIES -#else -# define _TLB_ENTRIES _DTLB_ENTRIES -#endif - void flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end) { @@ -97,7 +93,7 @@ void flush_tlb_range (struct vm_area_struct *vma, #endif local_save_flags(flags); - if (end-start + (PAGE_SIZE-1) <= _TLB_ENTRIES << PAGE_SHIFT) { + if (end-start + (PAGE_SIZE-1) <= SMALLEST_NTLB_ENTRIES << PAGE_SHIFT) { int oldpid = get_rasid_register(); set_rasid_register (ASID_INSERT(mm->context)); start &= PAGE_MASK; @@ -115,7 +111,9 @@ void flush_tlb_range (struct vm_area_struct *vma, set_rasid_register(oldpid); } else { - flush_tlb_mm(mm); + get_new_mmu_context(mm, asid_cache); + if (mm == current->active_mm) + set_rasid_register(ASID_INSERT(mm->context)); } local_irq_restore(flags); } @@ -125,6 +123,10 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) struct mm_struct* mm = vma->vm_mm; unsigned long flags; int oldpid; +#if 0 + printk("[tlbpage<%02lx,%08lx>]\n", + (unsigned long)mm->context, page); +#endif if(mm->context == NO_CONTEXT) return; @@ -140,5 +142,404 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) set_rasid_register(oldpid); local_irq_restore(flags); + +#if 0 + flush_tlb_all(); + return; +#endif +} + + +#ifdef DEBUG_TLB + +#define USE_ITLB 0 +#define USE_DTLB 1 + +struct way_config_t { + int indicies; + int indicies_log2; + int pgsz_log2; + int arf; +}; + +static struct way_config_t itlb[XCHAL_ITLB_WAYS] = +{ + { XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES_LOG2), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, PAGESZ_LOG2_MIN), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ARF) + }, + { XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES_LOG2), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, PAGESZ_LOG2_MIN), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ARF) + }, + { XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES_LOG2), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, PAGESZ_LOG2_MIN), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ARF) + }, + { XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES_LOG2), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, PAGESZ_LOG2_MIN), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ARF) + }, + { XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES_LOG2), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, PAGESZ_LOG2_MIN), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ARF) + }, + { XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES_LOG2), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, PAGESZ_LOG2_MIN), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ARF) + }, + { XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES_LOG2), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, PAGESZ_LOG2_MIN), + XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ARF) + } +}; + +static struct way_config_t dtlb[XCHAL_DTLB_WAYS] = +{ + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ARF) + }, + { XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES_LOG2), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, PAGESZ_LOG2_MIN), + XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ARF) + } +}; + +/* Total number of entries: */ +#define ITLB_TOTAL_ENTRIES \ + XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES) + \ + XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES) + \ + XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES) + \ + XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES) + \ + XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES) + \ + XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES) + \ + XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES) +#define DTLB_TOTAL_ENTRIES \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES) + \ + XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES) + + +typedef struct { + unsigned va; + unsigned pa; + unsigned char asid; + unsigned char ca; + unsigned char way; + unsigned char index; + unsigned char pgsz_log2; /* 0 .. 32 */ + unsigned char type; /* 0=ITLB 1=DTLB */ +} tlb_dump_entry_t; + +/* Return -1 if a precedes b, +1 if a follows b, 0 if same: */ +int cmp_tlb_dump_info( tlb_dump_entry_t *a, tlb_dump_entry_t *b ) +{ + if (a->asid < b->asid) return -1; + if (a->asid > b->asid) return 1; + if (a->va < b->va) return -1; + if (a->va > b->va) return 1; + if (a->pa < b->pa) return -1; + if (a->pa > b->pa) return 1; + if (a->ca < b->ca) return -1; + if (a->ca > b->ca) return 1; + if (a->way < b->way) return -1; + if (a->way > b->way) return 1; + if (a->index < b->index) return -1; + if (a->index > b->index) return 1; + return 0; +} + +void sort_tlb_dump_info( tlb_dump_entry_t *t, int n ) +{ + int i, j; + /* Simple O(n*n) sort: */ + for (i = 0; i < n-1; i++) + for (j = i+1; j < n; j++) + if (cmp_tlb_dump_info(t+i, t+j) > 0) { + tlb_dump_entry_t tmp = t[i]; + t[i] = t[j]; + t[j] = tmp; + } +} + + +static tlb_dump_entry_t itlb_dump_info[ITLB_TOTAL_ENTRIES]; +static tlb_dump_entry_t dtlb_dump_info[DTLB_TOTAL_ENTRIES]; + + +static inline char *way_type (int type) +{ + return type ? "autorefill" : "non-autorefill"; +} + +void print_entry (struct way_config_t *way_info, + unsigned int way, + unsigned int index, + unsigned int virtual, + unsigned int translation) +{ + char valid_chr; + unsigned int va, pa, asid, ca; + + va = virtual & + ~((1 << (way_info->pgsz_log2 + way_info->indicies_log2)) - 1); + asid = virtual & ((1 << XCHAL_MMU_ASID_BITS) - 1); + pa = translation & ~((1 << way_info->pgsz_log2) - 1); + ca = translation & ((1 << XCHAL_MMU_CA_BITS) - 1); + valid_chr = asid ? 'V' : 'I'; + + /* Compute and incorporate the effect of the index bits on the + * va. It's more useful for kernel debugging, since we always + * want to know the effective va anyway. */ + + va += index << way_info->pgsz_log2; + + printk ("\t[%d,%d] (%c) vpn 0x%.8x ppn 0x%.8x asid 0x%.2x am 0x%x\n", + way, index, valid_chr, va, pa, asid, ca); +} + +void print_itlb_entry (struct way_config_t *way_info, int way, int index) +{ + print_entry (way_info, way, index, + read_itlb_virtual (way + (index << way_info->pgsz_log2)), + read_itlb_translation (way + (index << way_info->pgsz_log2))); +} + +void print_dtlb_entry (struct way_config_t *way_info, int way, int index) +{ + print_entry (way_info, way, index, + read_dtlb_virtual (way + (index << way_info->pgsz_log2)), + read_dtlb_translation (way + (index << way_info->pgsz_log2))); +} + +void dump_itlb (void) +{ + int way, index; + + printk ("\nITLB: ways = %d\n", XCHAL_ITLB_WAYS); + + for (way = 0; way < XCHAL_ITLB_WAYS; way++) { + printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n", + way, itlb[way].indicies, + itlb[way].pgsz_log2, way_type(itlb[way].arf)); + for (index = 0; index < itlb[way].indicies; index++) { + print_itlb_entry(&itlb[way], way, index); + } + } +} + +void dump_dtlb (void) +{ + int way, index; + + printk ("\nDTLB: ways = %d\n", XCHAL_DTLB_WAYS); + + for (way = 0; way < XCHAL_DTLB_WAYS; way++) { + printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n", + way, dtlb[way].indicies, + dtlb[way].pgsz_log2, way_type(dtlb[way].arf)); + for (index = 0; index < dtlb[way].indicies; index++) { + print_dtlb_entry(&dtlb[way], way, index); + } + } +} + +void dump_tlb (tlb_dump_entry_t *tinfo, struct way_config_t *config, + int entries, int ways, int type, int show_invalid) +{ + tlb_dump_entry_t *e = tinfo; + int way, i; + + /* Gather all info: */ + for (way = 0; way < ways; way++) { + struct way_config_t *cfg = config + way; + for (i = 0; i < cfg->indicies; i++) { + unsigned wayindex = way + (i << cfg->pgsz_log2); + unsigned vv = (type ? read_dtlb_virtual (wayindex) + : read_itlb_virtual (wayindex)); + unsigned pp = (type ? read_dtlb_translation (wayindex) + : read_itlb_translation (wayindex)); + + /* Compute and incorporate the effect of the index bits on the + * va. It's more useful for kernel debugging, since we always + * want to know the effective va anyway. */ + + e->va = (vv & ~((1 << (cfg->pgsz_log2 + cfg->indicies_log2)) - 1)); + e->va += (i << cfg->pgsz_log2); + e->pa = (pp & ~((1 << cfg->pgsz_log2) - 1)); + e->asid = (vv & ((1 << XCHAL_MMU_ASID_BITS) - 1)); + e->ca = (pp & ((1 << XCHAL_MMU_CA_BITS) - 1)); + e->way = way; + e->index = i; + e->pgsz_log2 = cfg->pgsz_log2; + e->type = type; + e++; + } + } +#if 1 + /* Sort by ASID and VADDR: */ + sort_tlb_dump_info (tinfo, entries); +#endif + + /* Display all sorted info: */ + printk ("\n%cTLB dump:\n", (type ? 'D' : 'I')); + for (e = tinfo, i = 0; i < entries; i++, e++) { +#if 0 + if (e->asid == 0 && !show_invalid) + continue; +#endif + printk ("%c way=%d i=%d ASID=%02X V=%08X -> P=%08X CA=%X (%d %cB)\n", + (e->type ? 'D' : 'I'), e->way, e->index, + e->asid, e->va, e->pa, e->ca, + (1 << (e->pgsz_log2 % 10)), + " kMG"[e->pgsz_log2 / 10] + ); + } +} + +void dump_tlbs2 (int showinv) +{ + dump_tlb (itlb_dump_info, itlb, ITLB_TOTAL_ENTRIES, XCHAL_ITLB_WAYS, 0, showinv); + dump_tlb (dtlb_dump_info, dtlb, DTLB_TOTAL_ENTRIES, XCHAL_DTLB_WAYS, 1, showinv); +} + +void dump_all_tlbs (void) +{ + dump_tlbs2 (1); +} + +void dump_valid_tlbs (void) +{ + dump_tlbs2 (0); } + +void dump_tlbs (void) +{ + dump_itlb(); + dump_dtlb(); +} + +void dump_cache_tag(int dcache, int idx) +{ + int w, i, s, e; + unsigned long tag, index; + unsigned long num_lines, num_ways, cache_size, line_size; + + num_ways = dcache ? XCHAL_DCACHE_WAYS : XCHAL_ICACHE_WAYS; + cache_size = dcache ? XCHAL_DCACHE_SIZE : XCHAL_ICACHE_SIZE; + line_size = dcache ? XCHAL_DCACHE_LINESIZE : XCHAL_ICACHE_LINESIZE; + + num_lines = cache_size / num_ways; + + s = 0; e = num_lines; + + if (idx >= 0) + e = (s = idx * line_size) + 1; + + for (i = s; i < e; i+= line_size) { + printk("\nline %#08x:", i); + for (w = 0; w < num_ways; w++) { + index = w * num_lines + i; + if (dcache) + __asm__ __volatile__("ldct %0, %1\n\t" + : "=a"(tag) : "a"(index)); + else + __asm__ __volatile__("lict %0, %1\n\t" + : "=a"(tag) : "a"(index)); + + printk(" %#010lx", tag); + } + } + printk ("\n"); +} + +void dump_icache(int index) +{ + unsigned long data, addr; + int w, i; + + const unsigned long num_ways = XCHAL_ICACHE_WAYS; + const unsigned long cache_size = XCHAL_ICACHE_SIZE; + const unsigned long line_size = XCHAL_ICACHE_LINESIZE; + const unsigned long num_lines = cache_size / num_ways / line_size; + + for (w = 0; w < num_ways; w++) { + printk ("\nWay %d", w); + + for (i = 0; i < line_size; i+= 4) { + addr = w * num_lines + index * line_size + i; + __asm__ __volatile__("licw %0, %1\n\t" + : "=a"(data) : "a"(addr)); + printk(" %#010lx", data); + } + } + printk ("\n"); +} + +void dump_cache_tags(void) +{ + printk("Instruction cache\n"); + dump_cache_tag(0, -1); + printk("Data cache\n"); + dump_cache_tag(1, -1); +} + +#endif diff --git a/trunk/arch/xtensa/platform-iss/console.c b/trunk/arch/xtensa/platform-iss/console.c index 2f4f20ffe666..5c947cae7520 100644 --- a/trunk/arch/xtensa/platform-iss/console.c +++ b/trunk/arch/xtensa/platform-iss/console.c @@ -25,15 +25,11 @@ #include #include -#include +#include #include #include -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif - #define SERIAL_MAX_NUM_LINES 1 #define SERIAL_TIMER_VALUE (20 * HZ) @@ -195,7 +191,7 @@ static int rs_read_proc(char *page, char **start, off_t off, int count, } -static struct tty_operations serial_ops = { +static const struct tty_operations serial_ops = { .open = rs_open, .close = rs_close, .write = rs_write, diff --git a/trunk/arch/xtensa/platform-iss/network.c b/trunk/arch/xtensa/platform-iss/network.c index 8ebfc8761229..15d64414bd60 100644 --- a/trunk/arch/xtensa/platform-iss/network.c +++ b/trunk/arch/xtensa/platform-iss/network.c @@ -34,7 +34,7 @@ #include #include -#include +#include #define DRIVER_NAME "iss-netdev" #define ETH_MAX_PACKET 1500 diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index a541b42c08e3..4f83fd922377 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -129,6 +128,13 @@ struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev) } EXPORT_SYMBOL(blk_get_backing_dev_info); +void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data) +{ + q->activity_fn = fn; + q->activity_data = data; +} +EXPORT_SYMBOL(blk_queue_activity_fn); + /** * blk_queue_prep_rq - set a prepare_request function for queue * @q: queue @@ -231,6 +237,8 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) * by default assume old behaviour and bounce for any highmem page */ blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); + + blk_queue_activity_fn(q, NULL, NULL); } EXPORT_SYMBOL(blk_queue_make_request); @@ -2687,6 +2695,9 @@ static inline void add_request(request_queue_t * q, struct request * req) { drive_stat_acct(req, req->nr_sectors, 1); + if (q->activity_fn) + q->activity_fn(q->activity_data, rq_data_dir(req)); + /* * elevator indicated where it wants this request to be * inserted at elevator_merge time @@ -3224,12 +3235,10 @@ void submit_bio(int rw, struct bio *bio) BIO_BUG_ON(!bio->bi_size); BIO_BUG_ON(!bio->bi_io_vec); bio->bi_rw |= rw; - if (rw & WRITE) { + if (rw & WRITE) count_vm_events(PGPGOUT, count); - } else { - task_io_account_read(bio->bi_size); + else count_vm_events(PGPGIN, count); - } if (unlikely(block_dump)) { char b[BDEVNAME_SIZE]; diff --git a/trunk/block/scsi_ioctl.c b/trunk/block/scsi_ioctl.c index f322b6a441d8..b3e210723a71 100644 --- a/trunk/block/scsi_ioctl.c +++ b/trunk/block/scsi_ioctl.c @@ -228,7 +228,6 @@ static int sg_io(struct file *file, request_queue_t *q, struct request *rq; char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char cmd[BLK_MAX_CDB]; - struct bio *bio; if (hdr->interface_id != 'S') return -EINVAL; @@ -271,6 +270,13 @@ static int sg_io(struct file *file, request_queue_t *q, rq->cmd_type = REQ_TYPE_BLOCK_PC; + /* + * bounce this after holding a reference to the original bio, it's + * needed for proper unmapping + */ + if (rq->bio) + blk_queue_bounce(q, &rq->bio); + rq->timeout = jiffies_to_msecs(hdr->timeout); if (!rq->timeout) rq->timeout = q->sg_timeout; @@ -302,7 +308,6 @@ static int sg_io(struct file *file, request_queue_t *q, if (ret) goto out; - bio = rq->bio; rq->retries = 0; start_time = jiffies; @@ -333,7 +338,6 @@ static int sg_io(struct file *file, request_queue_t *q, hdr->sb_len_wr = len; } - rq->bio = bio; if (blk_rq_unmap_user(rq)) ret = -EFAULT; diff --git a/trunk/crypto/blkcipher.c b/trunk/crypto/blkcipher.c index 6e93004f2181..034c939bf91a 100644 --- a/trunk/crypto/blkcipher.c +++ b/trunk/crypto/blkcipher.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/crypto/sha512.c b/trunk/crypto/sha512.c index 15eab9db9be4..2dfe7f170b48 100644 --- a/trunk/crypto/sha512.c +++ b/trunk/crypto/sha512.c @@ -24,7 +24,7 @@ #define SHA384_DIGEST_SIZE 48 #define SHA512_DIGEST_SIZE 64 -#define SHA384_HMAC_BLOCK_SIZE 128 +#define SHA384_HMAC_BLOCK_SIZE 96 #define SHA512_HMAC_BLOCK_SIZE 128 struct sha512_ctx { diff --git a/trunk/drivers/Kconfig b/trunk/drivers/Kconfig index e7da9fa724ec..4929e923b5c6 100644 --- a/trunk/drivers/Kconfig +++ b/trunk/drivers/Kconfig @@ -80,6 +80,4 @@ source "drivers/rtc/Kconfig" source "drivers/dma/Kconfig" -source "drivers/kvm/Kconfig" - endmenu diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index 0dd96d1afd39..50f76da598c9 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -43,7 +43,6 @@ obj-$(CONFIG_SPI) += spi/ obj-$(CONFIG_PCCARD) += pcmcia/ obj-$(CONFIG_DIO) += dio/ obj-$(CONFIG_SBUS) += sbus/ -obj-$(CONFIG_KVM) += kvm/ obj-$(CONFIG_ZORRO) += zorro/ obj-$(CONFIG_MAC) += macintosh/ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ diff --git a/trunk/drivers/acorn/block/fd1772.c b/trunk/drivers/acorn/block/fd1772.c index 674bf81c6e66..048542341204 100644 --- a/trunk/drivers/acorn/block/fd1772.c +++ b/trunk/drivers/acorn/block/fd1772.c @@ -1549,12 +1549,12 @@ int fd1772_init(void) #ifdef TRACKBUFFER BufferDrive = BufferSide = BufferTrack = -1; /* Atari uses 512 - I want to eventually cope with 1K sectors */ - DMABuffer = kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL); + DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL); TrackBuffer = DMABuffer + 512; #else /* Allocate memory for the DMAbuffer - on the Atari this takes it out of some special memory... */ - DMABuffer = kmalloc(2048); /* Copes with pretty large sectors */ + DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */ #endif err = -ENOMEM; if (!DMAbuffer) diff --git a/trunk/drivers/acorn/char/i2c.c b/trunk/drivers/acorn/char/i2c.c index 9e584a7af434..bdb9c8b78ed8 100644 --- a/trunk/drivers/acorn/char/i2c.c +++ b/trunk/drivers/acorn/char/i2c.c @@ -360,7 +360,7 @@ static int __init i2c_ioc_init(void) if (ret >= 0){ ret = misc_register(&rtc_dev); if(ret < 0) - i2c_del_adapter(&ioc_ops); + i2c_bit_del_bus(&ioc_ops); } return ret; diff --git a/trunk/drivers/ata/pdc_adma.c b/trunk/drivers/ata/pdc_adma.c index 90786d7a20bb..9021e34d2096 100644 --- a/trunk/drivers/ata/pdc_adma.c +++ b/trunk/drivers/ata/pdc_adma.c @@ -551,7 +551,7 @@ static int adma_port_start(struct ata_port *ap) return rc; adma_enter_reg_mode(ap); rc = -ENOMEM; - pp = kzalloc(sizeof(*pp), GFP_KERNEL); + pp = kcalloc(1, sizeof(*pp), GFP_KERNEL); if (!pp) goto err_out; pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma, @@ -672,7 +672,7 @@ static int adma_ata_init_one(struct pci_dev *pdev, if (rc) goto err_out_iounmap; - probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); + probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL); if (probe_ent == NULL) { rc = -ENOMEM; goto err_out_iounmap; diff --git a/trunk/drivers/atm/.gitignore b/trunk/drivers/atm/.gitignore index fc0ae5eb05d8..a165b7167714 100644 --- a/trunk/drivers/atm/.gitignore +++ b/trunk/drivers/atm/.gitignore @@ -2,4 +2,4 @@ fore200e_mkfirm fore200e_pca_fw.c pca200e.bin -pca200e_ecd.bin2 + diff --git a/trunk/drivers/atm/eni.c b/trunk/drivers/atm/eni.c index 5aab7bd473ac..bc1b13c8f5d7 100644 --- a/trunk/drivers/atm/eni.c +++ b/trunk/drivers/atm/eni.c @@ -1832,7 +1832,7 @@ static int __devinit eni_start(struct atm_dev *dev) /* initialize memory management */ buffer_mem = eni_dev->mem - (buf - eni_dev->ram); eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2; - eni_dev->free_list = kmalloc( + eni_dev->free_list = (struct eni_free *) kmalloc( sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL); if (!eni_dev->free_list) { printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n", @@ -2232,7 +2232,7 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev, goto out0; } - eni_dev = kmalloc(sizeof(struct eni_dev),GFP_KERNEL); + eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL); if (!eni_dev) goto out0; if (!cpu_zeroes) { cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE, diff --git a/trunk/drivers/atm/he.c b/trunk/drivers/atm/he.c index db33f6f4dd2a..7d9b4e52f0bf 100644 --- a/trunk/drivers/atm/he.c +++ b/trunk/drivers/atm/he.c @@ -2351,7 +2351,7 @@ he_open(struct atm_vcc *vcc) cid = he_mkcid(he_dev, vpi, vci); - he_vcc = kmalloc(sizeof(struct he_vcc), GFP_ATOMIC); + he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC); if (he_vcc == NULL) { hprintk("unable to allocate he_vcc during open\n"); return -ENOMEM; diff --git a/trunk/drivers/atm/lanai.c b/trunk/drivers/atm/lanai.c index 09f477d4237a..267825501dfe 100644 --- a/trunk/drivers/atm/lanai.c +++ b/trunk/drivers/atm/lanai.c @@ -2602,7 +2602,7 @@ static int __devinit lanai_init_one(struct pci_dev *pci, struct atm_dev *atmdev; int result; - lanai = kmalloc(sizeof(*lanai), GFP_KERNEL); + lanai = (struct lanai_dev *) kmalloc(sizeof(*lanai), GFP_KERNEL); if (lanai == NULL) { printk(KERN_ERR DEV_LABEL ": couldn't allocate dev_data structure!\n"); diff --git a/trunk/drivers/atm/nicstar.c b/trunk/drivers/atm/nicstar.c index aab9b3733d52..bd0904594805 100644 --- a/trunk/drivers/atm/nicstar.c +++ b/trunk/drivers/atm/nicstar.c @@ -997,7 +997,7 @@ static scq_info *get_scq(int size, u32 scd) if (size != VBR_SCQSIZE && size != CBR_SCQSIZE) return NULL; - scq = kmalloc(sizeof(scq_info), GFP_KERNEL); + scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL); if (scq == NULL) return NULL; scq->org = kmalloc(2 * size, GFP_KERNEL); @@ -1006,7 +1006,7 @@ static scq_info *get_scq(int size, u32 scd) kfree(scq); return NULL; } - scq->skb = kmalloc(sizeof(struct sk_buff *) * + scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) * (size / NS_SCQE_SIZE), GFP_KERNEL); if (scq->skb == NULL) { diff --git a/trunk/drivers/atm/zatm.c b/trunk/drivers/atm/zatm.c index 756d4f760da3..7df0f373188e 100644 --- a/trunk/drivers/atm/zatm.c +++ b/trunk/drivers/atm/zatm.c @@ -996,7 +996,7 @@ static int start_tx(struct atm_dev *dev) DPRINTK("start_tx\n"); zatm_dev = ZATM_DEV(dev); - zatm_dev->tx_map = kmalloc(sizeof(struct atm_vcc *)* + zatm_dev->tx_map = (struct atm_vcc **) kmalloc(sizeof(struct atm_vcc *)* zatm_dev->chans,GFP_KERNEL); if (!zatm_dev->tx_map) return -ENOMEM; zatm_dev->tx_bw = ATM_OC3_PCR; @@ -1591,7 +1591,7 @@ static int __devinit zatm_init_one(struct pci_dev *pci_dev, struct zatm_dev *zatm_dev; int ret = -ENOMEM; - zatm_dev = kmalloc(sizeof(*zatm_dev), GFP_KERNEL); + zatm_dev = (struct zatm_dev *) kmalloc(sizeof(*zatm_dev), GFP_KERNEL); if (!zatm_dev) { printk(KERN_EMERG "%s: memory shortage\n", DEV_LABEL); goto out; diff --git a/trunk/drivers/base/dmapool.c b/trunk/drivers/base/dmapool.c index f95d50277274..dbe0735f8c9e 100644 --- a/trunk/drivers/base/dmapool.c +++ b/trunk/drivers/base/dmapool.c @@ -173,7 +173,7 @@ pool_alloc_page (struct dma_pool *pool, gfp_t mem_flags) mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG; mapsize *= sizeof (long); - page = kmalloc(mapsize + sizeof *page, mem_flags); + page = (struct dma_page *) kmalloc (mapsize + sizeof *page, mem_flags); if (!page) return NULL; page->vaddr = dma_alloc_coherent (pool->dev, diff --git a/trunk/drivers/block/Kconfig b/trunk/drivers/block/Kconfig index 58c1debf86f1..ce9cfcb6071c 100644 --- a/trunk/drivers/block/Kconfig +++ b/trunk/drivers/block/Kconfig @@ -28,6 +28,13 @@ config ATARI_FLOPPY tristate "Atari floppy support" depends on ATARI +config BLK_DEV_SWIM_IOP + bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)" + depends on MAC && EXPERIMENTAL && BROKEN + help + Say Y here to support the SWIM (Super Woz Integrated Machine) IOP + floppy controller on the Macintosh IIfx and Quadra 900/950. + config MAC_FLOPPY tristate "Support for PowerMac floppy" depends on PPC_PMAC && !PPC_PMAC64 diff --git a/trunk/drivers/block/Makefile b/trunk/drivers/block/Makefile index dd88e33c1eb1..410f259a8031 100644 --- a/trunk/drivers/block/Makefile +++ b/trunk/drivers/block/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o +obj-$(CONFIG_BLK_DEV_SWIM_IOP) += swim_iop.o obj-$(CONFIG_ATARI_ACSI) += acsi.o obj-$(CONFIG_ATARI_SLM) += acsi_slm.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index acb2fa9cf6b1..ee159edb6b88 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -1039,7 +1039,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, status = -ENOMEM; goto cleanup1; } - buff_size = kmalloc(MAXSGENTRIES * sizeof(int), + buff_size = (int *)kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL); if (!buff_size) { status = -ENOMEM; @@ -2837,7 +2837,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) if (err) { printk(KERN_ERR "cciss: Cannot obtain PCI resources, " "aborting\n"); - return err; + goto err_out_disable_pdev; } subsystem_vendor_id = pdev->subsystem_vendor; @@ -2865,7 +2865,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) #ifdef CCISS_DEBUG printk("address 0 = %x\n", c->paddr); #endif /* CCISS_DEBUG */ - c->vaddr = remap_pci_mem(c->paddr, 0x250); + c->vaddr = remap_pci_mem(c->paddr, 200); /* Wait for the board to become ready. (PCI hotplug needs this.) * We poll for up to 120 secs, once per 100ms. */ @@ -3005,11 +3005,10 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) return 0; err_out_free_res: - /* - * Deliberately omit pci_disable_device(): it does something nasty to - * Smart Array controllers that pci_enable_device does not undo - */ pci_release_regions(pdev); + + err_out_disable_pdev: + pci_disable_device(pdev); return err; } @@ -3383,11 +3382,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, if (drv->queue) blk_cleanup_queue(drv->queue); } - /* - * Deliberately omit pci_disable_device(): it does something nasty to - * Smart Array controllers that pci_enable_device does not undo - */ pci_release_regions(pdev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_hba(i); return -1; @@ -3456,11 +3452,8 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) #ifdef CONFIG_CISS_SCSI_TAPE kfree(hba[i]->scsi_rejects.complete); #endif - /* - * Deliberately omit pci_disable_device(): it does something nasty to - * Smart Array controllers that pci_enable_device does not undo - */ pci_release_regions(pdev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_hba(i); } diff --git a/trunk/drivers/block/cpqarray.c b/trunk/drivers/block/cpqarray.c index b94cd1c32131..d5f519ebbc08 100644 --- a/trunk/drivers/block/cpqarray.c +++ b/trunk/drivers/block/cpqarray.c @@ -1625,7 +1625,7 @@ static void start_fwbk(int ctlr) " processing\n"); /* Command does not return anything, but idasend command needs a buffer */ - id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL); + id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL); if(id_ctlr_buf==NULL) { printk(KERN_WARNING "cpqarray: Out of memory. " @@ -1660,14 +1660,14 @@ static void getgeometry(int ctlr) info_p->log_drv_map = 0; - id_ldrive = kmalloc(sizeof(id_log_drv_t), GFP_KERNEL); + id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL); if(id_ldrive == NULL) { printk( KERN_ERR "cpqarray: out of memory.\n"); return; } - id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL); + id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL); if(id_ctlr_buf == NULL) { kfree(id_ldrive); @@ -1675,7 +1675,7 @@ static void getgeometry(int ctlr) return; } - id_lstatus_buf = kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL); + id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL); if(id_lstatus_buf == NULL) { kfree(id_ctlr_buf); @@ -1684,7 +1684,7 @@ static void getgeometry(int ctlr) return; } - sense_config_buf = kmalloc(sizeof(config_t), GFP_KERNEL); + sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL); if(sense_config_buf == NULL) { kfree(id_lstatus_buf); diff --git a/trunk/drivers/block/swim_iop.c b/trunk/drivers/block/swim_iop.c new file mode 100644 index 000000000000..ed7b06cf3e68 --- /dev/null +++ b/trunk/drivers/block/swim_iop.c @@ -0,0 +1,578 @@ +/* + * Driver for the SWIM (Super Woz Integrated Machine) IOP + * floppy controller on the Macintosh IIfx and Quadra 900/950 + * + * Written by Joshua M. Thompson (funaho@jurai.org) + * based on the SWIM3 driver (c) 1996 by Paul Mackerras. + * + * 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. + * + * 1999-06-12 (jmt) - Initial implementation. + */ + +/* + * ------------------- + * Theory of Operation + * ------------------- + * + * Since the SWIM IOP is message-driven we implement a simple request queue + * system. One outstanding request may be queued at any given time (this is + * an IOP limitation); only when that request has completed can a new request + * be sent. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "Version 0.1 (1999-06-12)" + +#define MAX_FLOPPIES 4 + +enum swim_state { + idle, + available, + revalidating, + transferring, + ejecting +}; + +struct floppy_state { + enum swim_state state; + int drive_num; /* device number */ + int secpercyl; /* disk geometry information */ + int secpertrack; + int total_secs; + int write_prot; /* 1 if write-protected, 0 if not, -1 dunno */ + int ref_count; + struct timer_list timeout; + int ejected; + struct wait_queue *wait; + int wanted; + int timeout_pending; +}; + +struct swim_iop_req { + int sent; + int complete; + __u8 command[32]; + struct floppy_state *fs; + void (*done)(struct swim_iop_req *); +}; + +static struct swim_iop_req *current_req; +static int floppy_count; + +static struct floppy_state floppy_states[MAX_FLOPPIES]; +static DEFINE_SPINLOCK(swim_iop_lock); + +#define CURRENT elv_next_request(swim_queue) + +static char *drive_names[7] = { + "not installed", /* DRV_NONE */ + "unknown (1)", /* DRV_UNKNOWN */ + "a 400K drive", /* DRV_400K */ + "an 800K drive" /* DRV_800K */ + "unknown (4)", /* ???? */ + "an FDHD", /* DRV_FDHD */ + "unknown (6)", /* ???? */ + "an Apple HD20" /* DRV_HD20 */ +}; + +int swimiop_init(void); +static void swimiop_init_request(struct swim_iop_req *); +static int swimiop_send_request(struct swim_iop_req *); +static void swimiop_receive(struct iop_msg *); +static void swimiop_status_update(int, struct swim_drvstatus *); +static int swimiop_eject(struct floppy_state *fs); + +static int floppy_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long param); +static int floppy_open(struct inode *inode, struct file *filp); +static int floppy_release(struct inode *inode, struct file *filp); +static int floppy_check_change(struct gendisk *disk); +static int floppy_revalidate(struct gendisk *disk); +static int grab_drive(struct floppy_state *fs, enum swim_state state, + int interruptible); +static void release_drive(struct floppy_state *fs); +static void set_timeout(struct floppy_state *fs, int nticks, + void (*proc)(unsigned long)); +static void fd_request_timeout(unsigned long); +static void do_fd_request(request_queue_t * q); +static void start_request(struct floppy_state *fs); + +static struct block_device_operations floppy_fops = { + .open = floppy_open, + .release = floppy_release, + .ioctl = floppy_ioctl, + .media_changed = floppy_check_change, + .revalidate_disk= floppy_revalidate, +}; + +static struct request_queue *swim_queue; +/* + * SWIM IOP initialization + */ + +int swimiop_init(void) +{ + volatile struct swim_iop_req req; + struct swimcmd_status *cmd = (struct swimcmd_status *) &req.command[0]; + struct swim_drvstatus *ds = &cmd->status; + struct floppy_state *fs; + int i; + + current_req = NULL; + floppy_count = 0; + + if (!iop_ism_present) + return -ENODEV; + + if (register_blkdev(FLOPPY_MAJOR, "fd")) + return -EBUSY; + + swim_queue = blk_init_queue(do_fd_request, &swim_iop_lock); + if (!swim_queue) { + unregister_blkdev(FLOPPY_MAJOR, "fd"); + return -ENOMEM; + } + + printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n", + DRIVER_VERSION); + + if (iop_listen(SWIM_IOP, SWIM_CHAN, swimiop_receive, "SWIM") != 0) { + printk(KERN_ERR "SWIM-IOP: IOP channel already in use; can't initialize.\n"); + unregister_blkdev(FLOPPY_MAJOR, "fd"); + blk_cleanup_queue(swim_queue); + return -EBUSY; + } + + printk(KERN_ERR "SWIM_IOP: probing for installed drives.\n"); + + for (i = 0 ; i < MAX_FLOPPIES ; i++) { + memset(&floppy_states[i], 0, sizeof(struct floppy_state)); + fs = &floppy_states[floppy_count]; + + swimiop_init_request(&req); + cmd->code = CMD_STATUS; + cmd->drive_num = i + 1; + if (swimiop_send_request(&req) != 0) continue; + while (!req.complete); + if (cmd->error != 0) { + printk(KERN_ERR "SWIM-IOP: probe on drive %d returned error %d\n", i, (uint) cmd->error); + continue; + } + if (ds->installed != 0x01) continue; + printk("SWIM-IOP: drive %d is %s (%s, %s, %s, %s)\n", i, + drive_names[ds->info.type], + ds->info.external? "ext" : "int", + ds->info.scsi? "scsi" : "floppy", + ds->info.fixed? "fixed" : "removable", + ds->info.secondary? "secondary" : "primary"); + swimiop_status_update(floppy_count, ds); + fs->state = idle; + + init_timer(&fs->timeout); + floppy_count++; + } + printk("SWIM-IOP: detected %d installed drives.\n", floppy_count); + + for (i = 0; i < floppy_count; i++) { + struct gendisk *disk = alloc_disk(1); + if (!disk) + continue; + disk->major = FLOPPY_MAJOR; + disk->first_minor = i; + disk->fops = &floppy_fops; + sprintf(disk->disk_name, "fd%d", i); + disk->private_data = &floppy_states[i]; + disk->queue = swim_queue; + set_capacity(disk, 2880 * 2); + add_disk(disk); + } + + return 0; +} + +static void swimiop_init_request(struct swim_iop_req *req) +{ + req->sent = 0; + req->complete = 0; + req->done = NULL; +} + +static int swimiop_send_request(struct swim_iop_req *req) +{ + unsigned long flags; + int err; + + /* It's doubtful an interrupt routine would try to send */ + /* a SWIM request, but I'd rather play it safe here. */ + + local_irq_save(flags); + + if (current_req != NULL) { + local_irq_restore(flags); + return -ENOMEM; + } + + current_req = req; + + /* Interrupts should be back on for iop_send_message() */ + + local_irq_restore(flags); + + err = iop_send_message(SWIM_IOP, SWIM_CHAN, (void *) req, + sizeof(req->command), (__u8 *) &req->command[0], + swimiop_receive); + + /* No race condition here; we own current_req at this point */ + + if (err) { + current_req = NULL; + } else { + req->sent = 1; + } + return err; +} + +/* + * Receive a SWIM message from the IOP. + * + * This will be called in two cases: + * + * 1. A message has been successfully sent to the IOP. + * 2. An unsolicited message was received from the IOP. + */ + +void swimiop_receive(struct iop_msg *msg) +{ + struct swim_iop_req *req; + struct swimmsg_status *sm; + struct swim_drvstatus *ds; + + req = current_req; + + switch(msg->status) { + case IOP_MSGSTATUS_COMPLETE: + memcpy(&req->command[0], &msg->reply[0], sizeof(req->command)); + req->complete = 1; + if (req->done) (*req->done)(req); + current_req = NULL; + break; + case IOP_MSGSTATUS_UNSOL: + sm = (struct swimmsg_status *) &msg->message[0]; + ds = &sm->status; + swimiop_status_update(sm->drive_num, ds); + iop_complete_message(msg); + break; + } +} + +static void swimiop_status_update(int drive_num, struct swim_drvstatus *ds) +{ + struct floppy_state *fs = &floppy_states[drive_num]; + + fs->write_prot = (ds->write_prot == 0x80); + if ((ds->disk_in_drive != 0x01) && (ds->disk_in_drive != 0x02)) { + fs->ejected = 1; + } else { + fs->ejected = 0; + } + switch(ds->info.type) { + case DRV_400K: + fs->secpercyl = 10; + fs->secpertrack = 10; + fs->total_secs = 800; + break; + case DRV_800K: + fs->secpercyl = 20; + fs->secpertrack = 10; + fs->total_secs = 1600; + break; + case DRV_FDHD: + fs->secpercyl = 36; + fs->secpertrack = 18; + fs->total_secs = 2880; + break; + default: + fs->secpercyl = 0; + fs->secpertrack = 0; + fs->total_secs = 0; + break; + } +} + +static int swimiop_eject(struct floppy_state *fs) +{ + int err, n; + struct swim_iop_req req; + struct swimcmd_eject *cmd = (struct swimcmd_eject *) &req.command[0]; + + err = grab_drive(fs, ejecting, 1); + if (err) return err; + + swimiop_init_request(&req); + cmd->code = CMD_EJECT; + cmd->drive_num = fs->drive_num; + err = swimiop_send_request(&req); + if (err) { + release_drive(fs); + return err; + } + for (n = 2*HZ; n > 0; --n) { + if (req.complete) break; + if (signal_pending(current)) { + err = -EINTR; + break; + } + schedule_timeout_interruptible(1); + } + release_drive(fs); + return cmd->error; +} + +static struct floppy_struct floppy_type = + { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */ + +static int floppy_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long param) +{ + struct floppy_state *fs = inode->i_bdev->bd_disk->private_data; + int err; + + if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + switch (cmd) { + case FDEJECT: + if (fs->ref_count != 1) + return -EBUSY; + err = swimiop_eject(fs); + return err; + case FDGETPRM: + if (copy_to_user((void *) param, (void *) &floppy_type, + sizeof(struct floppy_struct))) + return -EFAULT; + return 0; + } + return -ENOTTY; +} + +static int floppy_open(struct inode *inode, struct file *filp) +{ + struct floppy_state *fs = inode->i_bdev->bd_disk->private_data; + + if (fs->ref_count == -1 || filp->f_flags & O_EXCL) + return -EBUSY; + + if ((filp->f_flags & O_NDELAY) == 0 && (filp->f_mode & 3)) { + check_disk_change(inode->i_bdev); + if (fs->ejected) + return -ENXIO; + } + + if ((filp->f_mode & 2) && fs->write_prot) + return -EROFS; + + if (filp->f_flags & O_EXCL) + fs->ref_count = -1; + else + ++fs->ref_count; + + return 0; +} + +static int floppy_release(struct inode *inode, struct file *filp) +{ + struct floppy_state *fs = inode->i_bdev->bd_disk->private_data; + if (fs->ref_count > 0) + fs->ref_count--; + return 0; +} + +static int floppy_check_change(struct gendisk *disk) +{ + struct floppy_state *fs = disk->private_data; + return fs->ejected; +} + +static int floppy_revalidate(struct gendisk *disk) +{ + struct floppy_state *fs = disk->private_data; + grab_drive(fs, revalidating, 0); + /* yadda, yadda */ + release_drive(fs); + return 0; +} + +static void floppy_off(unsigned int nr) +{ +} + +static int grab_drive(struct floppy_state *fs, enum swim_state state, + int interruptible) +{ + unsigned long flags; + + local_irq_save(flags); + if (fs->state != idle) { + ++fs->wanted; + while (fs->state != available) { + if (interruptible && signal_pending(current)) { + --fs->wanted; + local_irq_restore(flags); + return -EINTR; + } + interruptible_sleep_on(&fs->wait); + } + --fs->wanted; + } + fs->state = state; + local_irq_restore(flags); + return 0; +} + +static void release_drive(struct floppy_state *fs) +{ + unsigned long flags; + + local_irq_save(flags); + fs->state = idle; + start_request(fs); + local_irq_restore(flags); +} + +static void set_timeout(struct floppy_state *fs, int nticks, + void (*proc)(unsigned long)) +{ + unsigned long flags; + + local_irq_save(flags); + if (fs->timeout_pending) + del_timer(&fs->timeout); + init_timer(&fs->timeout); + fs->timeout.expires = jiffies + nticks; + fs->timeout.function = proc; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); + fs->timeout_pending = 1; + local_irq_restore(flags); +} + +static void do_fd_request(request_queue_t * q) +{ + int i; + + for (i = 0 ; i < floppy_count ; i++) { + start_request(&floppy_states[i]); + } +} + +static void fd_request_complete(struct swim_iop_req *req) +{ + struct floppy_state *fs = req->fs; + struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req->command[0]; + + del_timer(&fs->timeout); + fs->timeout_pending = 0; + fs->state = idle; + if (cmd->error) { + printk(KERN_ERR "SWIM-IOP: error %d on read/write request.\n", cmd->error); + end_request(CURRENT, 0); + } else { + CURRENT->sector += cmd->num_blocks; + CURRENT->current_nr_sectors -= cmd->num_blocks; + if (CURRENT->current_nr_sectors <= 0) { + end_request(CURRENT, 1); + return; + } + } + start_request(fs); +} + +static void fd_request_timeout(unsigned long data) +{ + struct floppy_state *fs = (struct floppy_state *) data; + + fs->timeout_pending = 0; + end_request(CURRENT, 0); + fs->state = idle; +} + +static void start_request(struct floppy_state *fs) +{ + volatile struct swim_iop_req req; + struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req.command[0]; + + if (fs->state == idle && fs->wanted) { + fs->state = available; + wake_up(&fs->wait); + return; + } + while (CURRENT && fs->state == idle) { + if (CURRENT->bh && !buffer_locked(CURRENT->bh)) + panic("floppy: block not locked"); +#if 0 + printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", + CURRENT->rq_disk->disk_name, CURRENT->cmd, + CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer); + printk(" errors=%d current_nr_sectors=%ld\n", + CURRENT->errors, CURRENT->current_nr_sectors); +#endif + + if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) { + end_request(CURRENT, 0); + continue; + } + if (CURRENT->current_nr_sectors == 0) { + end_request(CURRENT, 1); + continue; + } + if (fs->ejected) { + end_request(CURRENT, 0); + continue; + } + + swimiop_init_request(&req); + req.fs = fs; + req.done = fd_request_complete; + + if (CURRENT->cmd == WRITE) { + if (fs->write_prot) { + end_request(CURRENT, 0); + continue; + } + cmd->code = CMD_WRITE; + } else { + cmd->code = CMD_READ; + + } + cmd->drive_num = fs->drive_num; + cmd->buffer = CURRENT->buffer; + cmd->first_block = CURRENT->sector; + cmd->num_blocks = CURRENT->current_nr_sectors; + + if (swimiop_send_request(&req)) { + end_request(CURRENT, 0); + continue; + } + + set_timeout(fs, HZ*CURRENT->current_nr_sectors, + fd_request_timeout); + + fs->state = transferring; + } +} diff --git a/trunk/drivers/cdrom/cdrom.c b/trunk/drivers/cdrom/cdrom.c index e4a2f8f3a1d7..2df5cf4ec743 100644 --- a/trunk/drivers/cdrom/cdrom.c +++ b/trunk/drivers/cdrom/cdrom.c @@ -1810,7 +1810,7 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s) size = sizeof(s->disckey.value) + 4; - if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) + if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL) return -ENOMEM; init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); @@ -1861,7 +1861,7 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) size = sizeof(s->manufact.value) + 4; - if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) + if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL) return -ENOMEM; init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); @@ -2849,7 +2849,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, /* FIXME: we need upper bound checking, too!! */ if (lba < 0) return -EINVAL; - cgc.buffer = kmalloc(blocksize, GFP_KERNEL); + cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL); if (cgc.buffer == NULL) return -ENOMEM; memset(&sense, 0, sizeof(sense)); @@ -3031,7 +3031,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, int size = sizeof(dvd_struct); if (!CDROM_CAN(CDC_DVD)) return -ENOSYS; - if ((s = kmalloc(size, GFP_KERNEL)) == NULL) + if ((s = (dvd_struct *) kmalloc(size, GFP_KERNEL)) == NULL) return -ENOMEM; cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); if (copy_from_user(s, (dvd_struct __user *)arg, size)) { diff --git a/trunk/drivers/cdrom/cm206.c b/trunk/drivers/cdrom/cm206.c index b6c61bbb20e1..e6d8e9ededea 100644 --- a/trunk/drivers/cdrom/cm206.c +++ b/trunk/drivers/cdrom/cm206.c @@ -1420,7 +1420,7 @@ int __init cm206_init(void) return -EIO; } printk(" adapter at 0x%x", cm206_base); - cd = kmalloc(size, GFP_KERNEL); + cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL); if (!cd) goto out_base; /* Now we have found the adaptor card, try to reset it. As we have diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index 9e43e39dc35c..b10f4d8fdc7f 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -97,7 +97,7 @@ config SERIAL_NONSTANDARD config COMPUTONE tristate "Computone IntelliPort Plus serial support" - depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) + depends on SERIAL_NONSTANDARD ---help--- This driver supports the entire family of Intelliport II/Plus controllers with the exception of the MicroChannel controllers and @@ -203,7 +203,7 @@ config MOXA_SMARTIO config MOXA_SMARTIO_NEW tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)" - depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) + depends on SERIAL_NONSTANDARD help Say Y here if you have a Moxa SmartIO multiport serial card and/or want to help develop a new version of this driver. @@ -218,7 +218,7 @@ config MOXA_SMARTIO_NEW config ISI tristate "Multi-Tech multiport card support (EXPERIMENTAL)" - depends on SERIAL_NONSTANDARD && PCI + depends on SERIAL_NONSTANDARD select FW_LOADER help This is a driver for the Multi-Tech cards which provide several @@ -312,7 +312,7 @@ config SPECIALIX_RTSCTS config SX tristate "Specialix SX (and SI) card support" - depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) + depends on SERIAL_NONSTANDARD help This is a driver for the SX and SI multiport serial cards. Please read the file for details. @@ -867,7 +867,7 @@ config SONYPI config TANBAC_TB0219 tristate "TANBAC TB0219 base board support" - depends on TANBAC_TB022X + depends TANBAC_TB022X select GPIO_VR41XX source "drivers/char/agp/Kconfig" diff --git a/trunk/drivers/char/agp/Kconfig b/trunk/drivers/char/agp/Kconfig index a9f9c48c2424..c603bf291580 100644 --- a/trunk/drivers/char/agp/Kconfig +++ b/trunk/drivers/char/agp/Kconfig @@ -86,7 +86,7 @@ config AGP_NVIDIA config AGP_SIS tristate "SiS chipset support" - depends on AGP && X86 + depends on AGP help This option gives you AGP support for the GLX component of X on Silicon Integrated Systems [SiS] chipsets. @@ -103,7 +103,7 @@ config AGP_SWORKS config AGP_VIA tristate "VIA chipset support" - depends on AGP && X86 + depends on AGP help This option gives you AGP support for the GLX component of X on VIA MVP3/Apollo Pro chipsets. diff --git a/trunk/drivers/char/agp/generic.c b/trunk/drivers/char/agp/generic.c index 883a36a27833..5ff457b41efb 100644 --- a/trunk/drivers/char/agp/generic.c +++ b/trunk/drivers/char/agp/generic.c @@ -419,31 +419,6 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ *requested_mode &= ~AGP2_RESERVED_MASK; } - /* - * Some dumb bridges are programmed to disobey the AGP2 spec. - * This is likely a BIOS misprogramming rather than poweron default, or - * it would be a lot more common. - * https://bugs.freedesktop.org/show_bug.cgi?id=8816 - * AGPv2 spec 6.1.9 states: - * The RATE field indicates the data transfer rates supported by this - * device. A.G.P. devices must report all that apply. - * Fix them up as best we can. - */ - switch (*bridge_agpstat & 7) { - case 4: - *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X); - printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate" - "Fixing up support for x2 & x1\n"); - break; - case 2: - *bridge_agpstat |= AGPSTAT2_1X; - printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate" - "Fixing up support for x1\n"); - break; - default: - break; - } - /* Check the speed bits make sense. Only one should be set. */ tmp = *requested_mode & 7; switch (tmp) { diff --git a/trunk/drivers/char/consolemap.c b/trunk/drivers/char/consolemap.c index b99b7561260d..04a12027a740 100644 --- a/trunk/drivers/char/consolemap.c +++ b/trunk/drivers/char/consolemap.c @@ -443,7 +443,7 @@ int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui) p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; if (p && p->readonly) return -EIO; if (!p || --p->refcount) { - q = kmalloc(sizeof(*p), GFP_KERNEL); + q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL); if (!q) { if (p) p->refcount++; return -ENOMEM; diff --git a/trunk/drivers/char/ipmi/ipmi_bt_sm.c b/trunk/drivers/char/ipmi/ipmi_bt_sm.c index e736119b6497..6c59baa887a8 100644 --- a/trunk/drivers/char/ipmi/ipmi_bt_sm.c +++ b/trunk/drivers/char/ipmi/ipmi_bt_sm.c @@ -37,10 +37,8 @@ #define BT_DEBUG_ENABLE 1 /* Generic messages */ #define BT_DEBUG_MSG 2 /* Prints all request/response buffers */ #define BT_DEBUG_STATES 4 /* Verbose look at state changes */ -/* BT_DEBUG_OFF must be zero to correspond to the default uninitialized - value */ -static int bt_debug; /* 0 == BT_DEBUG_OFF */ +static int bt_debug = BT_DEBUG_OFF; module_param(bt_debug, int, 0644); MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); diff --git a/trunk/drivers/char/ipmi/ipmi_devintf.c b/trunk/drivers/char/ipmi/ipmi_devintf.c index ff2d052177cb..e257835a9a73 100644 --- a/trunk/drivers/char/ipmi/ipmi_devintf.c +++ b/trunk/drivers/char/ipmi/ipmi_devintf.c @@ -834,7 +834,7 @@ static const struct file_operations ipmi_fops = { #define DEVICE_NAME "ipmidev" -static int ipmi_major; +static int ipmi_major = 0; module_param(ipmi_major, int, 0); MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By" " default, or if you set it to zero, it will choose the next" diff --git a/trunk/drivers/char/ipmi/ipmi_msghandler.c b/trunk/drivers/char/ipmi/ipmi_msghandler.c index 4e4691a53890..5703ee28e1cc 100644 --- a/trunk/drivers/char/ipmi/ipmi_msghandler.c +++ b/trunk/drivers/char/ipmi/ipmi_msghandler.c @@ -53,10 +53,10 @@ static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); -static int initialized; +static int initialized = 0; #ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_ipmi_root; +static struct proc_dir_entry *proc_ipmi_root = NULL; #endif /* CONFIG_PROC_FS */ /* Remain in auto-maintenance mode for this amount of time (in ms). */ @@ -2142,7 +2142,8 @@ cleanup_bmc_device(struct kref *ref) bmc = container_of(ref, struct bmc_device, refcount); remove_files(bmc); - platform_device_unregister(bmc->dev); + if (bmc->dev) + platform_device_unregister(bmc->dev); kfree(bmc); } @@ -2340,7 +2341,8 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, while (ipmi_find_bmc_prod_dev_id(&ipmidriver, bmc->id.product_id, - bmc->id.device_id)) { + bmc->id.device_id)) + { if (!warn_printed) { printk(KERN_WARNING PFX "This machine has two different BMCs" @@ -4041,7 +4043,7 @@ static void send_panic_events(char *str) } #endif /* CONFIG_IPMI_PANIC_EVENT */ -static int has_panicked; +static int has_panicked = 0; static int panic_event(struct notifier_block *this, unsigned long event, diff --git a/trunk/drivers/char/ipmi/ipmi_poweroff.c b/trunk/drivers/char/ipmi/ipmi_poweroff.c index 9d23136e598a..597eb4f88b84 100644 --- a/trunk/drivers/char/ipmi/ipmi_poweroff.c +++ b/trunk/drivers/char/ipmi/ipmi_poweroff.c @@ -58,10 +58,10 @@ static int poweroff_powercycle; static int ifnum_to_use = -1; /* Our local state. */ -static int ready; +static int ready = 0; static ipmi_user_t ipmi_user; static int ipmi_ifnum; -static void (*specific_poweroff_func)(ipmi_user_t user); +static void (*specific_poweroff_func)(ipmi_user_t user) = NULL; /* Holds the old poweroff function so we can restore it on removal. */ static void (*old_poweroff_func)(void); @@ -182,7 +182,7 @@ static int ipmi_request_in_rc_mode(ipmi_user_t user, #define IPMI_MOTOROLA_MANUFACTURER_ID 0x0000A1 #define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID 0x0051 -static void (*atca_oem_poweroff_hook)(ipmi_user_t user); +static void (*atca_oem_poweroff_hook)(ipmi_user_t user) = NULL; static void pps_poweroff_atca (ipmi_user_t user) { diff --git a/trunk/drivers/char/ipmi/ipmi_si_intf.c b/trunk/drivers/char/ipmi/ipmi_si_intf.c index f1afd26a509f..81a0c89598e7 100644 --- a/trunk/drivers/char/ipmi/ipmi_si_intf.c +++ b/trunk/drivers/char/ipmi/ipmi_si_intf.c @@ -845,7 +845,7 @@ static void request_events(void *send_info) atomic_set(&smi_info->req_events, 1); } -static int initialized; +static int initialized = 0; static void smi_timeout(unsigned long data) { @@ -1018,17 +1018,17 @@ static int num_ports; static int irqs[SI_MAX_PARMS]; static int num_irqs; static int regspacings[SI_MAX_PARMS]; -static int num_regspacings; +static int num_regspacings = 0; static int regsizes[SI_MAX_PARMS]; -static int num_regsizes; +static int num_regsizes = 0; static int regshifts[SI_MAX_PARMS]; -static int num_regshifts; +static int num_regshifts = 0; static int slave_addrs[SI_MAX_PARMS]; -static int num_slave_addrs; +static int num_slave_addrs = 0; #define IPMI_IO_ADDR_SPACE 0 #define IPMI_MEM_ADDR_SPACE 1 -static char *addr_space_to_str[] = { "i/o", "mem" }; +static char *addr_space_to_str[] = { "I/O", "mem" }; static int hotmod_handler(const char *val, struct kernel_param *kp); @@ -1397,7 +1397,20 @@ static struct hotmod_vals hotmod_as[] = { { "i/o", IPMI_IO_ADDR_SPACE }, { NULL } }; - +static int ipmi_strcasecmp(const char *s1, const char *s2) +{ + while (*s1 || *s2) { + if (!*s1) + return -1; + if (!*s2) + return 1; + if (*s1 != *s2) + return *s1 - *s2; + s1++; + s2++; + } + return 0; +} static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) { char *s; @@ -1411,7 +1424,7 @@ static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) *s = '\0'; s++; for (i = 0; hotmod_ops[i].name; i++) { - if (strcmp(*curr, v[i].name) == 0) { + if (ipmi_strcasecmp(*curr, v[i].name) == 0) { *val = v[i].val; *curr = s; return 0; @@ -1422,34 +1435,10 @@ static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) return -EINVAL; } -static int check_hotmod_int_op(const char *curr, const char *option, - const char *name, int *val) -{ - char *n; - - if (strcmp(curr, name) == 0) { - if (!option) { - printk(KERN_WARNING PFX - "No option given for '%s'\n", - curr); - return -EINVAL; - } - *val = simple_strtoul(option, &n, 0); - if ((*n != '\0') || (*option == '\0')) { - printk(KERN_WARNING PFX - "Bad option given for '%s'\n", - curr); - return -EINVAL; - } - return 1; - } - return 0; -} - static int hotmod_handler(const char *val, struct kernel_param *kp) { char *str = kstrdup(val, GFP_KERNEL); - int rv; + int rv = -EINVAL; char *next, *curr, *s, *n, *o; enum hotmod_op op; enum si_type si_type; @@ -1461,15 +1450,13 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) int irq; int ipmb; int ival; - int len; struct smi_info *info; if (!str) return -ENOMEM; /* Kill any trailing spaces, as we can get a "\n" from echo. */ - len = strlen(str); - ival = len - 1; + ival = strlen(str) - 1; while ((ival >= 0) && isspace(str[ival])) { str[ival] = '\0'; ival--; @@ -1526,37 +1513,35 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) *o = '\0'; o++; } - rv = check_hotmod_int_op(curr, o, "rsp", ®spacing); - if (rv < 0) - goto out; - else if (rv) - continue; - rv = check_hotmod_int_op(curr, o, "rsi", ®size); - if (rv < 0) - goto out; - else if (rv) - continue; - rv = check_hotmod_int_op(curr, o, "rsh", ®shift); - if (rv < 0) - goto out; - else if (rv) - continue; - rv = check_hotmod_int_op(curr, o, "irq", &irq); - if (rv < 0) - goto out; - else if (rv) - continue; - rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb); - if (rv < 0) - goto out; - else if (rv) - continue; +#define HOTMOD_INT_OPT(name, val) \ + if (ipmi_strcasecmp(curr, name) == 0) { \ + if (!o) { \ + printk(KERN_WARNING PFX \ + "No option given for '%s'\n", \ + curr); \ + goto out; \ + } \ + val = simple_strtoul(o, &n, 0); \ + if ((*n != '\0') || (*o == '\0')) { \ + printk(KERN_WARNING PFX \ + "Bad option given for '%s'\n", \ + curr); \ + goto out; \ + } \ + } - rv = -EINVAL; - printk(KERN_WARNING PFX - "Invalid hotmod option '%s'\n", - curr); - goto out; + HOTMOD_INT_OPT("rsp", regspacing) + else HOTMOD_INT_OPT("rsi", regsize) + else HOTMOD_INT_OPT("rsh", regshift) + else HOTMOD_INT_OPT("irq", irq) + else HOTMOD_INT_OPT("ipmb", ipmb) + else { + printk(KERN_WARNING PFX + "Invalid hotmod option '%s'\n", + curr); + goto out; + } +#undef HOTMOD_INT_OPT } if (op == HM_ADD) { @@ -1605,7 +1590,6 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) mutex_unlock(&smi_infos_lock); } } - rv = len; out: kfree(str); return rv; @@ -1626,11 +1610,11 @@ static __devinit void hardcode_find_bmc(void) info->addr_source = "hardcoded"; - if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { + if (!si_type[i] || ipmi_strcasecmp(si_type[i], "kcs") == 0) { info->si_type = SI_KCS; - } else if (strcmp(si_type[i], "smic") == 0) { + } else if (ipmi_strcasecmp(si_type[i], "smic") == 0) { info->si_type = SI_SMIC; - } else if (strcmp(si_type[i], "bt") == 0) { + } else if (ipmi_strcasecmp(si_type[i], "bt") == 0) { info->si_type = SI_BT; } else { printk(KERN_WARNING @@ -1684,7 +1668,7 @@ static __devinit void hardcode_find_bmc(void) /* Once we get an ACPI failure, we don't try any more, because we go through the tables sequentially. Once we don't find a table, there are no more. */ -static int acpi_failure; +static int acpi_failure = 0; /* For GPE-type interrupts. */ static u32 ipmi_acpi_gpe(void *context) @@ -1795,6 +1779,7 @@ struct SPMITable { static __devinit int try_init_acpi(struct SPMITable *spmi) { struct smi_info *info; + char *io_type; u8 addr_space; if (spmi->IPMIlegacy != 1) { @@ -1858,9 +1843,11 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) info->io.regshift = spmi->addr.register_bit_offset; if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + io_type = "memory"; info->io_setup = mem_setup; info->io.addr_type = IPMI_IO_ADDR_SPACE; } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { + io_type = "I/O"; info->io_setup = port_setup; info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else { @@ -2786,7 +2773,8 @@ static __devinit int init_ipmi_si(void) #endif #ifdef CONFIG_ACPI - acpi_find_bmc(); + if (si_trydefaults) + acpi_find_bmc(); #endif #ifdef CONFIG_PCI diff --git a/trunk/drivers/char/ipmi/ipmi_watchdog.c b/trunk/drivers/char/ipmi/ipmi_watchdog.c index 78280380a905..90fb2a541916 100644 --- a/trunk/drivers/char/ipmi/ipmi_watchdog.c +++ b/trunk/drivers/char/ipmi/ipmi_watchdog.c @@ -134,14 +134,14 @@ static int nowayout = WATCHDOG_NOWAYOUT; -static ipmi_user_t watchdog_user; +static ipmi_user_t watchdog_user = NULL; static int watchdog_ifnum; /* Default the timeout to 10 seconds. */ static int timeout = 10; /* The pre-timeout is disabled by default. */ -static int pretimeout; +static int pretimeout = 0; /* Default action is to reset the board on a timeout. */ static unsigned char action_val = WDOG_TIMEOUT_RESET; @@ -156,10 +156,10 @@ static unsigned char preop_val = WDOG_PREOP_NONE; static char preop[16] = "preop_none"; static DEFINE_SPINLOCK(ipmi_read_lock); -static char data_to_read; +static char data_to_read = 0; static DECLARE_WAIT_QUEUE_HEAD(read_q); -static struct fasync_struct *fasync_q; -static char pretimeout_since_last_heartbeat; +static struct fasync_struct *fasync_q = NULL; +static char pretimeout_since_last_heartbeat = 0; static char expect_close; static int ifnum_to_use = -1; @@ -177,7 +177,7 @@ static void ipmi_unregister_watchdog(int ipmi_intf); /* If true, the driver will start running as soon as it is configured and ready. */ -static int start_now; +static int start_now = 0; static int set_param_int(const char *val, struct kernel_param *kp) { @@ -300,16 +300,16 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE; /* If shutting down via IPMI, we ignore the heartbeat. */ -static int ipmi_ignore_heartbeat; +static int ipmi_ignore_heartbeat = 0; /* Is someone using the watchdog? Only one user is allowed. */ -static unsigned long ipmi_wdog_open; +static unsigned long ipmi_wdog_open = 0; /* If set to 1, the heartbeat command will set the state to reset and start the timer. The timer doesn't normally run when the driver is first opened until the heartbeat is set the first time, this variable is used to accomplish this. */ -static int ipmi_start_timer_on_heartbeat; +static int ipmi_start_timer_on_heartbeat = 0; /* IPMI version of the BMC. */ static unsigned char ipmi_version_major; diff --git a/trunk/drivers/char/lcd.c b/trunk/drivers/char/lcd.c index d649abbf0857..da601fd6c07a 100644 --- a/trunk/drivers/char/lcd.c +++ b/trunk/drivers/char/lcd.c @@ -459,7 +459,7 @@ static int lcd_ioctl(struct inode *inode, struct file *file, (&display, (struct lcd_display *) arg, sizeof(struct lcd_display))) return -EFAULT; - rom = kmalloc((128), GFP_ATOMIC); + rom = (unsigned char *) kmalloc((128), GFP_ATOMIC); if (rom == NULL) { printk(KERN_ERR LCD "kmalloc() failed in %s\n", __FUNCTION__); diff --git a/trunk/drivers/char/lp.c b/trunk/drivers/char/lp.c index b51d08be0bcf..b70b5388b5a8 100644 --- a/trunk/drivers/char/lp.c +++ b/trunk/drivers/char/lp.c @@ -525,7 +525,7 @@ static int lp_open(struct inode * inode, struct file * file) return -EIO; } } - lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); + lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); if (!lp_table[minor].lp_buffer) { LP_F(minor) &= ~LP_BUSY; return -ENOMEM; diff --git a/trunk/drivers/char/mem.c b/trunk/drivers/char/mem.c index 4f1813e04754..089020e0ee5a 100644 --- a/trunk/drivers/char/mem.c +++ b/trunk/drivers/char/mem.c @@ -646,8 +646,7 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size) count = size; zap_page_range(vma, addr, count, NULL); - if (zeromap_page_range(vma, addr, count, PAGE_COPY)) - break; + zeromap_page_range(vma, addr, count, PAGE_COPY); size -= count; buf += count; @@ -714,14 +713,11 @@ static ssize_t read_zero(struct file * file, char __user * buf, static int mmap_zero(struct file * file, struct vm_area_struct * vma) { - int err; - if (vma->vm_flags & VM_SHARED) return shmem_zero_setup(vma); - err = zeromap_page_range(vma, vma->vm_start, - vma->vm_end - vma->vm_start, vma->vm_page_prot); - BUG_ON(err == -EEXIST); - return err; + if (zeromap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + return 0; } #else /* CONFIG_MMU */ static ssize_t read_zero(struct file * file, char * buf, diff --git a/trunk/drivers/char/mxser_new.c b/trunk/drivers/char/mxser_new.c index cd989dce7c53..efa8076c33e0 100644 --- a/trunk/drivers/char/mxser_new.c +++ b/trunk/drivers/char/mxser_new.c @@ -315,7 +315,6 @@ static struct mxser_mon_ext mon_data_ext; static int mxser_set_baud_method[MXSER_PORTS + 1]; static spinlock_t gm_lock; -#ifdef CONFIG_PCI static int CheckIsMoxaMust(int io) { u8 oldmcr, hwid; @@ -338,7 +337,6 @@ static int CheckIsMoxaMust(int io) } return MOXA_OTHER_UART; } -#endif static void process_txrx_fifo(struct mxser_port *info) { @@ -2382,11 +2380,9 @@ static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, if (irq) free_irq(brd->irq, brd); if (pdev != NULL) { /* PCI */ -#ifdef CONFIG_PCI pci_release_region(pdev, 2); pci_release_region(pdev, 3); pci_dev_put(pdev); -#endif } else { release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); release_region(brd->vector, 1); @@ -2550,7 +2546,6 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) static int __devinit mxser_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { -#ifdef CONFIG_PCI struct mxser_board *brd; unsigned int i, j; unsigned long ioaddress; @@ -2649,9 +2644,6 @@ static int __devinit mxser_probe(struct pci_dev *pdev, brd->info = NULL; err: return retval; -#else - return -ENODEV; -#endif } static void __devexit mxser_remove(struct pci_dev *pdev) diff --git a/trunk/drivers/char/n_r3964.c b/trunk/drivers/char/n_r3964.c index dc6d41841457..103d338f21e2 100644 --- a/trunk/drivers/char/n_r3964.c +++ b/trunk/drivers/char/n_r3964.c @@ -125,8 +125,8 @@ static void transmit_block(struct r3964_info *pInfo); static void receive_char(struct r3964_info *pInfo, const unsigned char c); static void receive_error(struct r3964_info *pInfo, const char flag); static void on_timeout(unsigned long priv); -static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg); -static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf); +static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg); +static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char __user *buf); static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, int error_code, struct r3964_block_header *pBlock); static struct r3964_message* remove_msg(struct r3964_info *pInfo, @@ -829,7 +829,7 @@ static void on_timeout(unsigned long priv) } static struct r3964_client_info *findClient( - struct r3964_info *pInfo, struct pid *pid) + struct r3964_info *pInfo, pid_t pid) { struct r3964_client_info *pClient; @@ -843,7 +843,7 @@ static struct r3964_client_info *findClient( return NULL; } -static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) +static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg) { struct r3964_client_info *pClient; struct r3964_client_info **ppClient; @@ -858,7 +858,7 @@ static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) if(pClient->pid == pid) { - TRACE_PS("removing client %d from client list", pid_nr(pid)); + TRACE_PS("removing client %d from client list", pid); *ppClient = pClient->next; while(pClient->msg_count) { @@ -869,7 +869,6 @@ static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) TRACE_M("enable_signals - msg kfree %p",pMsg); } } - put_pid(pClient->pid); kfree(pClient); TRACE_M("enable_signals - kfree %p",pClient); return 0; @@ -893,10 +892,10 @@ static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) if(pClient==NULL) return -ENOMEM; - TRACE_PS("add client %d to client list", pid_nr(pid)); + TRACE_PS("add client %d to client list", pid); spin_lock_init(&pClient->lock); pClient->sig_flags=arg; - pClient->pid = get_pid(pid); + pClient->pid = pid; pClient->next=pInfo->firstClient; pClient->first_msg = NULL; pClient->last_msg = NULL; @@ -909,7 +908,7 @@ static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) return 0; } -static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf) +static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char __user *buf) { struct r3964_client_info *pClient; struct r3964_block_header *block; @@ -1006,7 +1005,7 @@ static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, /* Send SIGIO signal to client process: */ if(pClient->sig_flags & R3964_USE_SIGIO) { - kill_pid(pClient->pid, SIGIO, 1); + kill_proc(pClient->pid, SIGIO, 1); } } @@ -1043,7 +1042,7 @@ static void remove_client_block(struct r3964_info *pInfo, { struct r3964_block_header *block; - TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); + TRACE_PS("remove_client_block PID %d", pClient->pid); block=pClient->next_block_to_read; if(block) @@ -1158,7 +1157,6 @@ static void r3964_close(struct tty_struct *tty) TRACE_M("r3964_close - msg kfree %p",pMsg); } } - put_pid(pClient->pid); kfree(pClient); TRACE_M("r3964_close - client kfree %p",pClient); pClient=pNext; @@ -1195,11 +1193,12 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, struct r3964_client_message theMsg; DECLARE_WAITQUEUE (wait, current); + int pid = current->pid; int count; TRACE_L("read()"); - pClient=findClient(pInfo, task_pid(current)); + pClient=findClient(pInfo, pid); if(pClient) { pMsg = remove_msg(pInfo, pClient); @@ -1253,6 +1252,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, struct r3964_block_header *pHeader; struct r3964_client_info *pClient; unsigned char *new_data; + int pid; TRACE_L("write request, %d characters", count); /* @@ -1295,7 +1295,9 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, pHeader->locks = 0; pHeader->owner = NULL; - pClient=findClient(pInfo, task_pid(current)); + pid=current->pid; + + pClient=findClient(pInfo, pid); if(pClient) { pHeader->owner = pClient; @@ -1326,7 +1328,7 @@ static int r3964_ioctl(struct tty_struct * tty, struct file * file, switch(cmd) { case R3964_ENABLE_SIGNALS: - return enable_signals(pInfo, task_pid(current), arg); + return enable_signals(pInfo, current->pid, arg); case R3964_SETPRIORITY: if(argR3964_SLAVE) return -EINVAL; @@ -1339,7 +1341,7 @@ static int r3964_ioctl(struct tty_struct * tty, struct file * file, pInfo->flags &= ~R3964_BCC; return 0; case R3964_READ_TELEGRAM: - return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg); + return read_telegram(pInfo, current->pid, (unsigned char __user *)arg); default: return -ENOIOCTLCMD; } @@ -1355,6 +1357,7 @@ static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, struct poll_table_struct *wait) { struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; + int pid=current->pid; struct r3964_client_info *pClient; struct r3964_message *pMsg=NULL; unsigned long flags; @@ -1362,7 +1365,7 @@ static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, TRACE_L("POLL"); - pClient=findClient(pInfo, task_pid(current)); + pClient=findClient(pInfo,pid); if(pClient) { poll_wait(file, &pInfo->read_wait, wait); diff --git a/trunk/drivers/char/n_tty.c b/trunk/drivers/char/n_tty.c index 2bdb0144a22e..e96a00fe1389 100644 --- a/trunk/drivers/char/n_tty.c +++ b/trunk/drivers/char/n_tty.c @@ -1151,6 +1151,7 @@ static int copy_from_read_buf(struct tty_struct *tty, n = min(*nr, n); spin_unlock_irqrestore(&tty->read_lock, flags); if (n) { + mb(); retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n); n -= retval; spin_lock_irqsave(&tty->read_lock, flags); diff --git a/trunk/drivers/char/pcmcia/synclink_cs.c b/trunk/drivers/char/pcmcia/synclink_cs.c index f108c136800a..5152cedd8878 100644 --- a/trunk/drivers/char/pcmcia/synclink_cs.c +++ b/trunk/drivers/char/pcmcia/synclink_cs.c @@ -541,7 +541,7 @@ static int mgslpc_probe(struct pcmcia_device *link) if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_attach\n"); - info = kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); + info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); if (!info) { printk("Error can't allocate device instance data\n"); return -ENOMEM; diff --git a/trunk/drivers/char/random.c b/trunk/drivers/char/random.c index 13d0b1350a62..092a01cc02da 100644 --- a/trunk/drivers/char/random.c +++ b/trunk/drivers/char/random.c @@ -1203,7 +1203,7 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp, static int uuid_strategy(ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, - void __user *newval, size_t newlen) + void __user *newval, size_t newlen, void **context) { unsigned char tmp_uuid[16], *uuid; unsigned int len; diff --git a/trunk/drivers/char/rio/riocmd.c b/trunk/drivers/char/rio/riocmd.c index 245f03195b7c..167ebc84e8d7 100644 --- a/trunk/drivers/char/rio/riocmd.c +++ b/trunk/drivers/char/rio/riocmd.c @@ -556,7 +556,7 @@ struct CmdBlk *RIOGetCmdBlk(void) { struct CmdBlk *CmdBlkP; - CmdBlkP = kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC); + CmdBlkP = (struct CmdBlk *)kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC); if (CmdBlkP) memset(CmdBlkP, 0, sizeof(struct CmdBlk)); return CmdBlkP; diff --git a/trunk/drivers/char/rtc.c b/trunk/drivers/char/rtc.c index e1d70e8b6268..66a7385bc34a 100644 --- a/trunk/drivers/char/rtc.c +++ b/trunk/drivers/char/rtc.c @@ -113,7 +113,7 @@ static int rtc_has_irq = 1; #define hpet_set_rtc_irq_bit(arg) 0 #define hpet_rtc_timer_init() do { } while (0) #define hpet_rtc_dropped_irq() 0 -static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;} +static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;} #else extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); #endif @@ -165,9 +165,7 @@ static void mask_rtc_irq_bit(unsigned char bit) } #endif -#ifdef CONFIG_PROC_FS static int rtc_proc_open(struct inode *inode, struct file *file); -#endif /* * Bits in rtc_status. (6 bits of room for future expansion) @@ -908,7 +906,6 @@ static struct miscdevice rtc_dev = { .fops = &rtc_fops, }; -#ifdef CONFIG_PROC_FS static const struct file_operations rtc_proc_fops = { .owner = THIS_MODULE, .open = rtc_proc_open, @@ -916,13 +913,14 @@ static const struct file_operations rtc_proc_fops = { .llseek = seq_lseek, .release = single_release, }; + +#if defined(RTC_IRQ) && !defined(__sparc__) +static irq_handler_t rtc_int_handler_ptr; #endif static int __init rtc_init(void) { -#ifdef CONFIG_PROC_FS struct proc_dir_entry *ent; -#endif #if defined(__alpha__) || defined(__mips__) unsigned int year, ctrl; char *guess = NULL; @@ -934,11 +932,9 @@ static int __init rtc_init(void) struct sparc_isa_bridge *isa_br; struct sparc_isa_device *isa_dev; #endif -#else - void *r; -#ifdef RTC_IRQ - irq_handler_t rtc_int_handler_ptr; #endif +#ifndef __sparc__ + void *r; #endif #ifdef __sparc__ @@ -962,7 +958,6 @@ static int __init rtc_init(void) } } #endif - rtc_has_irq = 0; printk(KERN_ERR "rtc_init: no PC rtc found\n"); return -EIO; @@ -977,7 +972,6 @@ static int __init rtc_init(void) * PCI Slot 2 INTA# (and some INTx# in Slot 1). */ if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) { - rtc_has_irq = 0; printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq); return -EIO; } @@ -988,9 +982,6 @@ static int __init rtc_init(void) else r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); if (!r) { -#ifdef RTC_IRQ - rtc_has_irq = 0; -#endif printk(KERN_ERR "rtc: I/O resource %lx is not free.\n", (long)(RTC_PORT(0))); return -EIO; @@ -1005,7 +996,6 @@ static int __init rtc_init(void) if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ - rtc_has_irq = 0; printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); if (RTC_IOMAPPED) release_region(RTC_PORT(0), RTC_IO_EXTENT); @@ -1022,19 +1012,21 @@ static int __init rtc_init(void) if (misc_register(&rtc_dev)) { #ifdef RTC_IRQ free_irq(RTC_IRQ, NULL); - rtc_has_irq = 0; #endif release_region(RTC_PORT(0), RTC_IO_EXTENT); return -ENODEV; } -#ifdef CONFIG_PROC_FS ent = create_proc_entry("driver/rtc", 0, NULL); - if (ent) - ent->proc_fops = &rtc_proc_fops; - else - printk(KERN_WARNING "rtc: Failed to register with procfs.\n"); + if (!ent) { +#ifdef RTC_IRQ + free_irq(RTC_IRQ, NULL); #endif + release_region(RTC_PORT(0), RTC_IO_EXTENT); + misc_deregister(&rtc_dev); + return -ENOMEM; + } + ent->proc_fops = &rtc_proc_fops; #if defined(__alpha__) || defined(__mips__) rtc_freq = HZ; @@ -1167,7 +1159,6 @@ static void rtc_dropped_irq(unsigned long data) } #endif -#ifdef CONFIG_PROC_FS /* * Info exported via "/proc/driver/rtc". */ @@ -1252,7 +1243,6 @@ static int rtc_proc_open(struct inode *inode, struct file *file) { return single_open(file, rtc_proc_show, NULL); } -#endif void rtc_get_rtc_time(struct rtc_time *rtc_tm) { diff --git a/trunk/drivers/char/sx.c b/trunk/drivers/char/sx.c index 1da92a689ae4..a3008ce13015 100644 --- a/trunk/drivers/char/sx.c +++ b/trunk/drivers/char/sx.c @@ -2498,10 +2498,8 @@ static void __devexit sx_remove_card(struct sx_board *board, /* It is safe/allowed to del_timer a non-active timer */ del_timer(&board->timer); if (pdev) { -#ifdef CONFIG_PCI pci_iounmap(pdev, board->base); pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2); -#endif } else { iounmap(board->base); release_region(board->hw_base, board->hw_len); @@ -2603,7 +2601,6 @@ static struct eisa_driver sx_eisadriver = { #endif -#ifdef CONFIG_PCI /******************************************************** * Setting bit 17 in the CNTRL register of the PLX 9050 * * chip forces a retry on writes while a read is pending.* @@ -2635,12 +2632,10 @@ static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board) } iounmap(rebase); } -#endif static int __devinit sx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { -#ifdef CONFIG_PCI struct sx_board *board; unsigned int i, reg; int retval = -EIO; @@ -2705,9 +2700,6 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev, board->flags &= ~SX_BOARD_PRESENT; err: return retval; -#else - return -ENODEV; -#endif } static void __devexit sx_pci_remove(struct pci_dev *pdev) diff --git a/trunk/drivers/char/synclink.c b/trunk/drivers/char/synclink.c index 3fa625db9e4b..acc6fab601cc 100644 --- a/trunk/drivers/char/synclink.c +++ b/trunk/drivers/char/synclink.c @@ -4332,7 +4332,7 @@ static struct mgsl_struct* mgsl_allocate_device(void) { struct mgsl_struct *info; - info = kmalloc(sizeof(struct mgsl_struct), + info = (struct mgsl_struct *)kmalloc(sizeof(struct mgsl_struct), GFP_KERNEL); if (!info) { diff --git a/trunk/drivers/char/synclinkmp.c b/trunk/drivers/char/synclinkmp.c index 8f4d67afe5bf..53e8ccf94fe3 100644 --- a/trunk/drivers/char/synclinkmp.c +++ b/trunk/drivers/char/synclinkmp.c @@ -2730,7 +2730,7 @@ static int startup(SLMP_INFO * info) return 0; if (!info->tx_buf) { - info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); + info->tx_buf = (unsigned char *)kmalloc(info->max_frame_size, GFP_KERNEL); if (!info->tx_buf) { printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n", __FILE__,__LINE__,info->device_name); @@ -3798,7 +3798,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) { SLMP_INFO *info; - info = kmalloc(sizeof(SLMP_INFO), + info = (SLMP_INFO *)kmalloc(sizeof(SLMP_INFO), GFP_KERNEL); if (!info) { diff --git a/trunk/drivers/char/sysrq.c b/trunk/drivers/char/sysrq.c index 13935235e066..05810c8d20bc 100644 --- a/trunk/drivers/char/sysrq.c +++ b/trunk/drivers/char/sysrq.c @@ -41,34 +41,7 @@ #include /* Whether we react on sysrq keys or just ignore them */ -int __read_mostly __sysrq_enabled = 1; - -static int __read_mostly sysrq_always_enabled; - -int sysrq_on(void) -{ - return __sysrq_enabled || sysrq_always_enabled; -} - -/* - * A value of 1 means 'all', other nonzero values are an op mask: - */ -static inline int sysrq_on_mask(int mask) -{ - return sysrq_always_enabled || __sysrq_enabled == 1 || - (__sysrq_enabled & mask); -} - -static int __init sysrq_always_enabled_setup(char *str) -{ - sysrq_always_enabled = 1; - printk(KERN_INFO "debug: sysrq always enabled.\n"); - - return 1; -} - -__setup("sysrq_always_enabled", sysrq_always_enabled_setup); - +int sysrq_enabled = 1; static void sysrq_handle_loglevel(int key, struct tty_struct *tty) { @@ -406,7 +379,8 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) * Should we check for enabled operations (/proc/sysrq-trigger * should not) and is the invoked operation enabled? */ - if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { + if (!check_mask || sysrq_enabled == 1 || + (sysrq_enabled & op_p->enable_mask)) { printk("%s\n", op_p->action_msg); console_loglevel = orig_log_level; op_p->handler(key, tty); @@ -440,8 +414,9 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) */ void handle_sysrq(int key, struct tty_struct *tty) { - if (sysrq_on()) - __handle_sysrq(key, tty, 1); + if (!sysrq_enabled) + return; + __handle_sysrq(key, tty, 1); } EXPORT_SYMBOL(handle_sysrq); diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/char/tty_io.c index 47a6eacb10bc..4044c864fdd4 100644 --- a/trunk/drivers/char/tty_io.c +++ b/trunk/drivers/char/tty_io.c @@ -3335,13 +3335,18 @@ static void __do_SAK(struct work_struct *work) int session; int i; struct file *filp; + struct tty_ldisc *disc; struct fdtable *fdt; if (!tty) return; session = tty->session; - tty_ldisc_flush(tty); + /* We don't want an ldisc switch during this */ + disc = tty_ldisc_ref(tty); + if (disc && disc->flush_buffer) + disc->flush_buffer(tty); + tty_ldisc_deref(disc); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); @@ -3816,7 +3821,6 @@ struct tty_struct *get_current_tty(void) barrier(); return tty; } -EXPORT_SYMBOL_GPL(get_current_tty); /* * Initialize the console device. This is called *early*, so diff --git a/trunk/drivers/char/viocons.c b/trunk/drivers/char/viocons.c index 0e0da443cbd5..6d2e314860df 100644 --- a/trunk/drivers/char/viocons.c +++ b/trunk/drivers/char/viocons.c @@ -61,7 +61,10 @@ static DEFINE_SPINLOCK(consolelock); static DEFINE_SPINLOCK(consoleloglock); +#ifdef CONFIG_MAGIC_SYSRQ static int vio_sysrq_pressed; +extern int sysrq_enabled; +#endif #define VIOCHAR_NUM_BUF 16 @@ -933,10 +936,8 @@ static void vioHandleData(struct HvLpEvent *event) */ num_pushed = 0; for (index = 0; index < cevent->len; index++) { - /* - * Will be optimized away if !CONFIG_MAGIC_SYSRQ: - */ - if (sysrq_on()) { +#ifdef CONFIG_MAGIC_SYSRQ + if (sysrq_enabled) { /* 0x0f is the ascii character for ^O */ if (cevent->data[index] == '\x0f') { vio_sysrq_pressed = 1; @@ -955,6 +956,7 @@ static void vioHandleData(struct HvLpEvent *event) continue; } } +#endif /* * The sysrq sequence isn't included in this check if * sysrq is enabled and compiled into the kernel because diff --git a/trunk/drivers/char/vt.c b/trunk/drivers/char/vt.c index 06c32a3e3ca4..a8239dac994f 100644 --- a/trunk/drivers/char/vt.c +++ b/trunk/drivers/char/vt.c @@ -784,7 +784,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) return 0; - newscreen = kmalloc(new_screen_size, GFP_USER); + newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER); if (!newscreen) return -ENOMEM; diff --git a/trunk/drivers/char/vt_ioctl.c b/trunk/drivers/char/vt_ioctl.c index dc8368ebb1ac..ac5d60edbafa 100644 --- a/trunk/drivers/char/vt_ioctl.c +++ b/trunk/drivers/char/vt_ioctl.c @@ -129,7 +129,7 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str !capable(CAP_SYS_RESOURCE)) return -EPERM; - key_map = kmalloc(sizeof(plain_map), + key_map = (ushort *) kmalloc(sizeof(plain_map), GFP_KERNEL); if (!key_map) return -ENOMEM; @@ -259,7 +259,7 @@ do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) sz = 256; while (sz < funcbufsize - funcbufleft + delta) sz <<= 1; - fnw = kmalloc(sz, GFP_KERNEL); + fnw = (char *) kmalloc(sz, GFP_KERNEL); if(!fnw) { ret = -ENOMEM; goto reterr; @@ -1087,7 +1087,7 @@ static void complete_change_console(struct vc_data *vc) switch_screen(vc); /* - * This can't appear below a successful kill_pid(). If it did, + * This can't appear below a successful kill_proc(). If it did, * then the *blank_screen operation could occur while X, having * received acqsig, is waking up on another processor. This * condition can lead to overlapping accesses to the VGA range @@ -1110,7 +1110,7 @@ static void complete_change_console(struct vc_data *vc) */ if (vc->vt_mode.mode == VT_PROCESS) { /* - * Send the signal as privileged - kill_pid() will + * Send the signal as privileged - kill_proc() will * tell us if the process has gone or something else * is awry */ @@ -1170,7 +1170,7 @@ void change_console(struct vc_data *new_vc) vc = vc_cons[fg_console].d; if (vc->vt_mode.mode == VT_PROCESS) { /* - * Send the signal as privileged - kill_pid() will + * Send the signal as privileged - kill_proc() will * tell us if the process has gone or something else * is awry */ diff --git a/trunk/drivers/char/watchdog/at91rm9200_wdt.c b/trunk/drivers/char/watchdog/at91rm9200_wdt.c index 38bd37372599..cb86967e2c5f 100644 --- a/trunk/drivers/char/watchdog/at91rm9200_wdt.c +++ b/trunk/drivers/char/watchdog/at91rm9200_wdt.c @@ -203,9 +203,9 @@ static int __init at91wdt_probe(struct platform_device *pdev) { int res; - if (at91wdt_miscdev.parent) + if (at91wdt_miscdev.dev) return -EBUSY; - at91wdt_miscdev.parent = &pdev->dev; + at91wdt_miscdev.dev = &pdev->dev; res = misc_register(&at91wdt_miscdev); if (res) @@ -221,7 +221,7 @@ static int __exit at91wdt_remove(struct platform_device *pdev) res = misc_deregister(&at91wdt_miscdev); if (!res) - at91wdt_miscdev.parent = NULL; + at91wdt_miscdev.dev = NULL; return res; } diff --git a/trunk/drivers/char/watchdog/mpcore_wdt.c b/trunk/drivers/char/watchdog/mpcore_wdt.c index e88947f8fe53..3404a9c67f08 100644 --- a/trunk/drivers/char/watchdog/mpcore_wdt.c +++ b/trunk/drivers/char/watchdog/mpcore_wdt.c @@ -347,7 +347,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) goto err_free; } - mpcore_wdt_miscdev.parent = &dev->dev; + mpcore_wdt_miscdev.dev = &dev->dev; ret = misc_register(&mpcore_wdt_miscdev); if (ret) { dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n", diff --git a/trunk/drivers/char/watchdog/omap_wdt.c b/trunk/drivers/char/watchdog/omap_wdt.c index 6c6f97332dbb..5dbd7dc2936f 100644 --- a/trunk/drivers/char/watchdog/omap_wdt.c +++ b/trunk/drivers/char/watchdog/omap_wdt.c @@ -290,7 +290,7 @@ static int __init omap_wdt_probe(struct platform_device *pdev) omap_wdt_disable(); omap_wdt_adjust_timeout(timer_margin); - omap_wdt_miscdev.parent = &pdev->dev; + omap_wdt_miscdev.dev = &pdev->dev; ret = misc_register(&omap_wdt_miscdev); if (ret) goto fail; diff --git a/trunk/drivers/char/watchdog/pcwd_usb.c b/trunk/drivers/char/watchdog/pcwd_usb.c index 2da5ac99687c..61138726b501 100644 --- a/trunk/drivers/char/watchdog/pcwd_usb.c +++ b/trunk/drivers/char/watchdog/pcwd_usb.c @@ -42,7 +42,6 @@ #include #include #include -#include /* For HID_REQ_SET_REPORT & HID_DT_REPORT */ #ifdef CONFIG_USB_DEBUG @@ -110,6 +109,10 @@ MODULE_DEVICE_TABLE (usb, usb_pcwd_table); #define CMD_ENABLE_WATCHDOG 0x30 /* Enable / Disable Watchdog */ #define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG +/* Some defines that I like to be somewhere else like include/linux/usb_hid.h */ +#define HID_REQ_SET_REPORT 0x09 +#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02) + /* We can only use 1 card due to the /dev/watchdog restriction */ static int cards_found; diff --git a/trunk/drivers/char/watchdog/rm9k_wdt.c b/trunk/drivers/char/watchdog/rm9k_wdt.c index 7576a13e86bc..ec3909371c21 100644 --- a/trunk/drivers/char/watchdog/rm9k_wdt.c +++ b/trunk/drivers/char/watchdog/rm9k_wdt.c @@ -47,7 +47,7 @@ /* Function prototypes */ -static irqreturn_t wdt_gpi_irqhdl(int, void *); +static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); static void wdt_gpi_start(void); static void wdt_gpi_stop(void); static void wdt_gpi_set_timeout(unsigned int); @@ -94,28 +94,8 @@ module_param(nowayout, bool, 0444); MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); -/* Kernel interfaces */ -static struct file_operations fops = { - .owner = THIS_MODULE, - .open = wdt_gpi_open, - .release = wdt_gpi_release, - .write = wdt_gpi_write, - .unlocked_ioctl = wdt_gpi_ioctl, -}; - -static struct miscdevice miscdev = { - .minor = WATCHDOG_MINOR, - .name = wdt_gpi_name, - .fops = &fops, -}; - -static struct notifier_block wdt_gpi_shutdown = { - .notifier_call = wdt_gpi_notify, -}; - - /* Interrupt handler */ -static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt) +static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) { if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1)) return IRQ_NONE; @@ -332,6 +312,26 @@ wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) } +/* Kernel interfaces */ +static struct file_operations fops = { + .owner = THIS_MODULE, + .open = wdt_gpi_open, + .release = wdt_gpi_release, + .write = wdt_gpi_write, + .unlocked_ioctl = wdt_gpi_ioctl, +}; + +static struct miscdevice miscdev = { + .minor = WATCHDOG_MINOR, + .name = wdt_gpi_name, + .fops = &fops, +}; + +static struct notifier_block wdt_gpi_shutdown = { + .notifier_call = wdt_gpi_notify, +}; + + /* Init & exit procedures */ static const struct resource * wdt_gpi_get_resource(struct platform_device *pdv, const char *name, diff --git a/trunk/drivers/clocksource/acpi_pm.c b/trunk/drivers/clocksource/acpi_pm.c index b6bcdbbf57b3..8ab61ef97b4c 100644 --- a/trunk/drivers/clocksource/acpi_pm.c +++ b/trunk/drivers/clocksource/acpi_pm.c @@ -77,11 +77,11 @@ static struct clocksource clocksource_acpi_pm = { #ifdef CONFIG_PCI -static int __devinitdata acpi_pm_good; +static int acpi_pm_good; static int __init acpi_pm_good_setup(char *__str) { - acpi_pm_good = 1; - return 1; + acpi_pm_good = 1; + return 1; } __setup("acpi_pm_good", acpi_pm_good_setup); diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index 9fb2edf36611..47ab42db122a 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -29,8 +29,7 @@ #include #include -#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \ - "cpufreq-core", msg) +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) /** * The "cpufreq driver" - the arch- or hardware-dependent low @@ -152,8 +151,7 @@ static void cpufreq_debug_disable_ratelimit(void) spin_unlock_irqrestore(&disable_ratelimit_lock, flags); } -void cpufreq_debug_printk(unsigned int type, const char *prefix, - const char *fmt, ...) +void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt, ...) { char s[256]; va_list args; @@ -163,8 +161,7 @@ void cpufreq_debug_printk(unsigned int type, const char *prefix, WARN_ON(!prefix); if (type & debug) { spin_lock_irqsave(&disable_ratelimit_lock, flags); - if (!disable_ratelimit && debug_ratelimit - && !printk_ratelimit()) { + if (!disable_ratelimit && debug_ratelimit && !printk_ratelimit()) { spin_unlock_irqrestore(&disable_ratelimit_lock, flags); return; } @@ -185,12 +182,10 @@ EXPORT_SYMBOL(cpufreq_debug_printk); module_param(debug, uint, 0644); -MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core," - " 2 to debug drivers, and 4 to debug governors."); +MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core, 2 to debug drivers, and 4 to debug governors."); module_param(debug_ratelimit, uint, 0644); -MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging:" - " set to 0 to disable ratelimiting."); +MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging: set to 0 to disable ratelimiting."); #else /* !CONFIG_CPU_FREQ_DEBUG */ @@ -224,23 +219,17 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) if (!l_p_j_ref_freq) { l_p_j_ref = loops_per_jiffy; l_p_j_ref_freq = ci->old; - dprintk("saving %lu as reference value for loops_per_jiffy;" - "freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq); + dprintk("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq); } if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) || (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) { - loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, - ci->new); - dprintk("scaling loops_per_jiffy to %lu" - "for frequency %u kHz\n", loops_per_jiffy, ci->new); + loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); + dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new); } } #else -static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) -{ - return; -} +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; } #endif @@ -327,8 +316,7 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_PERFORMANCE; err = 0; - } else if (!strnicmp(str_governor, "powersave", - CPUFREQ_NAME_LEN)) { + } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_POWERSAVE; err = 0; } @@ -340,8 +328,7 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, t = __find_governor(str_governor); if (t == NULL) { - char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", - str_governor); + char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor); if (name) { int ret; @@ -374,8 +361,7 @@ extern struct sysdev_class cpu_sysdev_class; /** - * cpufreq_per_cpu_attr_read() / show_##file_name() - - * print out cpufreq information + * cpufreq_per_cpu_attr_read() / show_##file_name() - print out cpufreq information * * Write out information from cpufreq_driver->policy[cpu]; object must be * "unsigned int". @@ -394,8 +380,7 @@ show_one(scaling_min_freq, min); show_one(scaling_max_freq, max); show_one(scaling_cur_freq, cur); -static int __cpufreq_set_policy(struct cpufreq_policy *data, - struct cpufreq_policy *policy); +static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy); /** * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access @@ -431,8 +416,7 @@ store_one(scaling_max_freq,max); /** * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware */ -static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, - char *buf) +static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, char *buf) { unsigned int cur_freq = cpufreq_get(policy->cpu); if (!cur_freq) @@ -444,8 +428,7 @@ static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, /** * show_scaling_governor - show the current policy for the specified CPU */ -static ssize_t show_scaling_governor (struct cpufreq_policy * policy, - char *buf) +static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) { if(policy->policy == CPUFREQ_POLICY_POWERSAVE) return sprintf(buf, "powersave\n"); @@ -475,8 +458,7 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy, if (ret != 1) return -EINVAL; - if (cpufreq_parse_governor(str_governor, &new_policy.policy, - &new_policy.governor)) + if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor)) return -EINVAL; lock_cpu_hotplug(); @@ -492,10 +474,7 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy, unlock_cpu_hotplug(); - if (ret) - return ret; - else - return count; + return ret ? ret : count; } /** @@ -509,7 +488,7 @@ static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf) /** * show_scaling_available_governors - show the available CPUfreq governors */ -static ssize_t show_scaling_available_governors (struct cpufreq_policy *policy, +static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, char *buf) { ssize_t i = 0; @@ -595,11 +574,7 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf) policy = cpufreq_cpu_get(policy->cpu); if (!policy) return -EINVAL; - if (fattr->show) - ret = fattr->show(policy, buf); - else - ret = -EIO; - + ret = fattr->show ? fattr->show(policy,buf) : -EIO; cpufreq_cpu_put(policy); return ret; } @@ -613,11 +588,7 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr, policy = cpufreq_cpu_get(policy->cpu); if (!policy) return -EINVAL; - if (fattr->store) - ret = fattr->store(policy, buf, count); - else - ret = -EIO; - + ret = fattr->store ? fattr->store(policy,buf,count) : -EIO; cpufreq_cpu_put(policy); return ret; } @@ -942,8 +913,7 @@ static void handle_update(struct work_struct *work) * We adjust to current frequency first, and need to clean up later. So either call * to cpufreq_update_policy() or schedule handle_update()). */ -static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, - unsigned int new_freq) +static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int new_freq) { struct cpufreq_freqs freqs; @@ -968,16 +938,16 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int cpufreq_quick_get(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - unsigned int ret_freq = 0; + unsigned int ret = 0; if (policy) { mutex_lock(&policy->lock); - ret_freq = policy->cur; + ret = policy->cur; mutex_unlock(&policy->lock); cpufreq_cpu_put(policy); } - return (ret_freq); + return (ret); } EXPORT_SYMBOL(cpufreq_quick_get); @@ -991,7 +961,7 @@ EXPORT_SYMBOL(cpufreq_quick_get); unsigned int cpufreq_get(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - unsigned int ret_freq = 0; + unsigned int ret = 0; if (!policy) return 0; @@ -1001,14 +971,12 @@ unsigned int cpufreq_get(unsigned int cpu) mutex_lock(&policy->lock); - ret_freq = cpufreq_driver->get(cpu); + ret = cpufreq_driver->get(cpu); - if (ret_freq && policy->cur && - !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { - /* verify no discrepancy between actual and - saved value exists */ - if (unlikely(ret_freq != policy->cur)) { - cpufreq_out_of_sync(cpu, policy->cur, ret_freq); + if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { + /* verify no discrepancy between actual and saved value exists */ + if (unlikely(ret != policy->cur)) { + cpufreq_out_of_sync(cpu, policy->cur, ret); schedule_work(&policy->update); } } @@ -1018,7 +986,7 @@ unsigned int cpufreq_get(unsigned int cpu) out: cpufreq_cpu_put(policy); - return (ret_freq); + return (ret); } EXPORT_SYMBOL(cpufreq_get); @@ -1030,7 +998,7 @@ EXPORT_SYMBOL(cpufreq_get); static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) { int cpu = sysdev->id; - int ret = 0; + unsigned int ret = 0; unsigned int cur_freq = 0; struct cpufreq_policy *cpu_policy; @@ -1112,7 +1080,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) static int cpufreq_resume(struct sys_device * sysdev) { int cpu = sysdev->id; - int ret = 0; + unsigned int ret = 0; struct cpufreq_policy *cpu_policy; dprintk("resuming cpu %u\n", cpu); @@ -1308,45 +1276,22 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, } EXPORT_SYMBOL_GPL(cpufreq_driver_target); -int cpufreq_driver_getavg(struct cpufreq_policy *policy) -{ - int ret = 0; - - policy = cpufreq_cpu_get(policy->cpu); - if (!policy) - return -EINVAL; - - mutex_lock(&policy->lock); - - if (cpu_online(policy->cpu) && cpufreq_driver->getavg) - ret = cpufreq_driver->getavg(policy->cpu); - - mutex_unlock(&policy->lock); - - cpufreq_cpu_put(policy); - return ret; -} -EXPORT_SYMBOL_GPL(cpufreq_driver_getavg); - /* * Locking: Must be called with the lock_cpu_hotplug() lock held * when "event" is CPUFREQ_GOV_LIMITS */ -static int __cpufreq_governor(struct cpufreq_policy *policy, - unsigned int event) +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) { int ret; if (!try_module_get(policy->governor->owner)) return -EINVAL; - dprintk("__cpufreq_governor for CPU %u, event %u\n", - policy->cpu, event); + dprintk("__cpufreq_governor for CPU %u, event %u\n", policy->cpu, event); ret = policy->governor->governor(policy, event); - /* we keep one module reference alive for - each CPU governed by this CPU */ + /* we keep one module reference alive for each CPU governed by this CPU */ if ((event != CPUFREQ_GOV_START) || ret) module_put(policy->governor->owner); if ((event == CPUFREQ_GOV_STOP) && !ret) @@ -1422,12 +1367,9 @@ EXPORT_SYMBOL(cpufreq_get_policy); /* - * data : current policy. - * policy : policy to be set. * Locking: Must be called with the lock_cpu_hotplug() lock held */ -static int __cpufreq_set_policy(struct cpufreq_policy *data, - struct cpufreq_policy *policy) +static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy) { int ret = 0; @@ -1435,8 +1377,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, policy->min, policy->max); - memcpy(&policy->cpuinfo, &data->cpuinfo, - sizeof(struct cpufreq_cpuinfo)); + memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); if (policy->min > data->min && policy->min > policy->max) { ret = -EINVAL; @@ -1469,8 +1410,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, data->min = policy->min; data->max = policy->max; - dprintk("new min and max freqs are %u - %u kHz\n", - data->min, data->max); + dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max); if (cpufreq_driver->setpolicy) { data->policy = policy->policy; @@ -1491,12 +1431,10 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, data->governor = policy->governor; if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { /* new governor failed, so re-start old one */ - dprintk("starting governor %s failed\n", - data->governor->name); + dprintk("starting governor %s failed\n", data->governor->name); if (old_gov) { data->governor = old_gov; - __cpufreq_governor(data, - CPUFREQ_GOV_START); + __cpufreq_governor(data, CPUFREQ_GOV_START); } ret = -EINVAL; goto error_out; @@ -1586,8 +1524,7 @@ int cpufreq_update_policy(unsigned int cpu) data->cur = policy.cur; } else { if (data->cur != policy.cur) - cpufreq_out_of_sync(cpu, data->cur, - policy.cur); + cpufreq_out_of_sync(cpu, data->cur, policy.cur); } } @@ -1689,10 +1626,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) /* if all ->init() calls failed, unregister */ if (ret) { - dprintk("no CPU initialized for driver %s\n", - driver_data->name); - sysdev_driver_unregister(&cpu_sysdev_class, - &cpufreq_sysdev_driver); + dprintk("no CPU initialized for driver %s\n", driver_data->name); + sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); spin_lock_irqsave(&cpufreq_driver_lock, flags); cpufreq_driver = NULL; diff --git a/trunk/drivers/cpufreq/cpufreq_conservative.c b/trunk/drivers/cpufreq/cpufreq_conservative.c index eef0270c6f3d..5ef5ede5b884 100644 --- a/trunk/drivers/cpufreq/cpufreq_conservative.c +++ b/trunk/drivers/cpufreq/cpufreq_conservative.c @@ -44,17 +44,15 @@ * latency of the processor. The governor will work on any processor with * transition latency <= 10mS, using appropriate sampling * rate. - * For CPUs with transition latency > 10mS (mostly drivers - * with CPUFREQ_ETERNAL), this governor will not work. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. * All times here are in uS. */ static unsigned int def_sampling_rate; #define MIN_SAMPLING_RATE_RATIO (2) /* for correct statistics, we need at least 10 ticks between each measure */ -#define MIN_STAT_SAMPLING_RATE \ - (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) -#define MIN_SAMPLING_RATE \ - (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) +#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) +#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) #define MAX_SAMPLING_RATE (500 * def_sampling_rate) #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) #define DEF_SAMPLING_DOWN_FACTOR (1) @@ -105,16 +103,11 @@ static struct dbs_tuners dbs_tuners_ins = { static inline unsigned int get_cpu_idle_time(unsigned int cpu) { - unsigned int add_nice = 0, ret; - - if (dbs_tuners_ins.ignore_nice) - add_nice = kstat_cpu(cpu).cpustat.nice; - - ret = kstat_cpu(cpu).cpustat.idle + + return kstat_cpu(cpu).cpustat.idle + kstat_cpu(cpu).cpustat.iowait + - add_nice; - - return ret; + ( dbs_tuners_ins.ignore_nice ? + kstat_cpu(cpu).cpustat.nice : + 0); } /************************** sysfs interface ************************/ @@ -459,7 +452,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; struct cpu_dbs_info_s *this_dbs_info; unsigned int j; - int rc; this_dbs_info = &per_cpu(cpu_dbs_info, cpu); @@ -476,13 +468,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, break; mutex_lock(&dbs_mutex); - - rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); - if (rc) { - mutex_unlock(&dbs_mutex); - return rc; - } - for_each_cpu_mask(j, policy->cpus) { struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); @@ -495,7 +480,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, this_dbs_info->enable = 1; this_dbs_info->down_skip = 0; this_dbs_info->requested_freq = policy->cur; - + sysfs_create_group(&policy->kobj, &dbs_attr_group); dbs_enable++; /* * Start the timerschedule work, when this governor diff --git a/trunk/drivers/cpufreq/cpufreq_ondemand.c b/trunk/drivers/cpufreq/cpufreq_ondemand.c index f697449327c6..e1cc5113c2ae 100644 --- a/trunk/drivers/cpufreq/cpufreq_ondemand.c +++ b/trunk/drivers/cpufreq/cpufreq_ondemand.c @@ -41,10 +41,8 @@ static unsigned int def_sampling_rate; #define MIN_SAMPLING_RATE_RATIO (2) /* for correct statistics, we need at least 10 ticks between each measure */ -#define MIN_STAT_SAMPLING_RATE \ - (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) -#define MIN_SAMPLING_RATE \ - (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) +#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) +#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) #define MAX_SAMPLING_RATE (500 * def_sampling_rate) #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) #define TRANSITION_LATENCY_LIMIT (10 * 1000) @@ -208,8 +206,7 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, ret = sscanf(buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > MAX_SAMPLING_RATE - || input < MIN_SAMPLING_RATE) { + if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) { mutex_unlock(&dbs_mutex); return -EINVAL; } @@ -400,15 +397,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) * policy. To be safe, we focus 10 points under the threshold. */ if (load < (dbs_tuners_ins.up_threshold - 10)) { - unsigned int freq_next, freq_cur; - - freq_cur = cpufreq_driver_getavg(policy); - if (!freq_cur) - freq_cur = policy->cur; - - freq_next = (freq_cur * load) / + unsigned int freq_next = (policy->cur * load) / (dbs_tuners_ins.up_threshold - 10); - if (!dbs_tuners_ins.powersave_bias) { __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); @@ -482,7 +472,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; struct cpu_dbs_info_s *this_dbs_info; unsigned int j; - int rc; this_dbs_info = &per_cpu(cpu_dbs_info, cpu); @@ -505,23 +494,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (dbs_enable == 1) { kondemand_wq = create_workqueue("kondemand"); if (!kondemand_wq) { - printk(KERN_ERR - "Creation of kondemand failed\n"); + printk(KERN_ERR "Creation of kondemand failed\n"); dbs_enable--; mutex_unlock(&dbs_mutex); return -ENOSPC; } } - - rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); - if (rc) { - if (dbs_enable == 1) - destroy_workqueue(kondemand_wq); - dbs_enable--; - mutex_unlock(&dbs_mutex); - return rc; - } - for_each_cpu_mask(j, policy->cpus) { struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); @@ -531,6 +509,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, j_dbs_info->prev_cpu_wall = get_jiffies_64(); } this_dbs_info->enable = 1; + sysfs_create_group(&policy->kobj, &dbs_attr_group); /* * Start the timerschedule work, when this governor * is used for first time diff --git a/trunk/drivers/cpufreq/cpufreq_performance.c b/trunk/drivers/cpufreq/cpufreq_performance.c index e8e1451ef1c1..de91e3371ef8 100644 --- a/trunk/drivers/cpufreq/cpufreq_performance.c +++ b/trunk/drivers/cpufreq/cpufreq_performance.c @@ -15,8 +15,7 @@ #include #include -#define dprintk(msg...) \ - cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "performance", msg) +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "performance", msg) static int cpufreq_governor_performance(struct cpufreq_policy *policy, @@ -25,10 +24,8 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy, switch (event) { case CPUFREQ_GOV_START: case CPUFREQ_GOV_LIMITS: - dprintk("setting to %u kHz because of event %u\n", - policy->max, event); - __cpufreq_driver_target(policy, policy->max, - CPUFREQ_RELATION_H); + dprintk("setting to %u kHz because of event %u\n", policy->max, event); + __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); break; default: break; diff --git a/trunk/drivers/cpufreq/cpufreq_powersave.c b/trunk/drivers/cpufreq/cpufreq_powersave.c index 13fe06b94b0a..0a2596044e65 100644 --- a/trunk/drivers/cpufreq/cpufreq_powersave.c +++ b/trunk/drivers/cpufreq/cpufreq_powersave.c @@ -15,8 +15,7 @@ #include #include -#define dprintk(msg...) \ - cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "powersave", msg) +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "powersave", msg) static int cpufreq_governor_powersave(struct cpufreq_policy *policy, unsigned int event) @@ -24,10 +23,8 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy, switch (event) { case CPUFREQ_GOV_START: case CPUFREQ_GOV_LIMITS: - dprintk("setting to %u kHz because of event %u\n", - policy->min, event); - __cpufreq_driver_target(policy, policy->min, - CPUFREQ_RELATION_L); + dprintk("setting to %u kHz because of event %u\n", policy->min, event); + __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); break; default: break; diff --git a/trunk/drivers/cpufreq/cpufreq_stats.c b/trunk/drivers/cpufreq/cpufreq_stats.c index 6742b1adf2c8..c2ecc599dc5f 100644 --- a/trunk/drivers/cpufreq/cpufreq_stats.c +++ b/trunk/drivers/cpufreq/cpufreq_stats.c @@ -351,8 +351,8 @@ __init cpufreq_stats_init(void) register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); for_each_online_cpu(cpu) { - cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, - CPU_ONLINE, (void *)(long)cpu); + cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, + (void *)(long)cpu); } return 0; } @@ -368,15 +368,14 @@ __exit cpufreq_stats_exit(void) unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); lock_cpu_hotplug(); for_each_online_cpu(cpu) { - cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, - CPU_DEAD, (void *)(long)cpu); + cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD, + (void *)(long)cpu); } unlock_cpu_hotplug(); } MODULE_AUTHOR ("Zou Nan hai "); -MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats" - "through sysfs filesystem"); +MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats through sysfs filesystem"); MODULE_LICENSE ("GPL"); module_init(cpufreq_stats_init); diff --git a/trunk/drivers/cpufreq/cpufreq_userspace.c b/trunk/drivers/cpufreq/cpufreq_userspace.c index 2a4eb0bfaf30..a06c204589cd 100644 --- a/trunk/drivers/cpufreq/cpufreq_userspace.c +++ b/trunk/drivers/cpufreq/cpufreq_userspace.c @@ -131,26 +131,19 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int event) { unsigned int cpu = policy->cpu; - int rc = 0; - switch (event) { case CPUFREQ_GOV_START: if (!cpu_online(cpu)) return -EINVAL; BUG_ON(!policy->cur); mutex_lock(&userspace_mutex); - rc = sysfs_create_file (&policy->kobj, - &freq_attr_scaling_setspeed.attr); - if (rc) - goto start_out; - cpu_is_managed[cpu] = 1; cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max; cpu_cur_freq[cpu] = policy->cur; cpu_set_freq[cpu] = policy->cur; + sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]); -start_out: mutex_unlock(&userspace_mutex); break; case CPUFREQ_GOV_STOP: @@ -187,7 +180,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, mutex_unlock(&userspace_mutex); break; } - return rc; + return 0; } diff --git a/trunk/drivers/cpufreq/freq_table.c b/trunk/drivers/cpufreq/freq_table.c index e7490925fdcf..551f4ccf87fd 100644 --- a/trunk/drivers/cpufreq/freq_table.c +++ b/trunk/drivers/cpufreq/freq_table.c @@ -9,8 +9,7 @@ #include #include -#define dprintk(msg...) \ - cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg) +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg) /********************************************************************* * FREQUENCY TABLE HELPERS * @@ -30,8 +29,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, continue; } - dprintk("table entry %u: %u kHz, %u index\n", - i, freq, table[i].index); + dprintk("table entry %u: %u kHz, %u index\n", i, freq, table[i].index); if (freq < min_freq) min_freq = freq; if (freq > max_freq) @@ -56,14 +54,13 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, unsigned int i; unsigned int count = 0; - dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n", - policy->min, policy->max, policy->cpu); + dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); if (!cpu_online(policy->cpu)) return -EINVAL; - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { unsigned int freq = table[i].frequency; @@ -78,11 +75,10 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, if (!count) policy->max = next_larger; - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - dprintk("verification lead to (%u - %u kHz) for cpu %u\n", - policy->min, policy->max, policy->cpu); + dprintk("verification lead to (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); return 0; } @@ -105,8 +101,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, }; unsigned int i; - dprintk("request for target %u kHz (relation: %u) for cpu %u\n", - target_freq, relation, policy->cpu); + dprintk("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu); switch (relation) { case CPUFREQ_RELATION_H: @@ -197,10 +192,7 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) } struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { - .attr = { .name = "scaling_available_frequencies", - .mode = 0444, - .owner=THIS_MODULE - }, + .attr = { .name = "scaling_available_frequencies", .mode = 0444, .owner=THIS_MODULE }, .show = show_available_freqs, }; EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); diff --git a/trunk/drivers/crypto/Kconfig b/trunk/drivers/crypto/Kconfig index 879250d3d069..e816535ab305 100644 --- a/trunk/drivers/crypto/Kconfig +++ b/trunk/drivers/crypto/Kconfig @@ -53,7 +53,7 @@ config CRYPTO_DEV_PADLOCK_SHA config CRYPTO_DEV_GEODE tristate "Support for the Geode LX AES engine" - depends on CRYPTO && X86_32 && PCI + depends on CRYPTO && X86_32 select CRYPTO_ALGAPI select CRYPTO_BLKCIPHER default m diff --git a/trunk/drivers/fc4/fc.c b/trunk/drivers/fc4/fc.c index 22b62b3cd14e..ca4e67a022d0 100644 --- a/trunk/drivers/fc4/fc.c +++ b/trunk/drivers/fc4/fc.c @@ -266,7 +266,7 @@ static void fcp_report_map_done(fc_channel *fc, int i, int status) printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic); fc->state = FC_STATE_OFFLINE; } else { - fc->posmap = kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL); + fc->posmap = (fcp_posmap *)kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL); if (!fc->posmap) { printk("FC: Not enough memory, offlining channel\n"); fc->state = FC_STATE_OFFLINE; @@ -355,7 +355,7 @@ void fcp_register(fc_channel *fc, u8 type, int unregister) for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++) set_bit (i, fc->scsi_bitmap); fc->scsi_free = fc->can_queue; - fc->cmd_slots = kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL); + fc->cmd_slots = (fcp_cmnd **)kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL); fc->abort_count = 0; } else { fc->scsi_name[0] = 0; @@ -933,7 +933,7 @@ int fcp_scsi_dev_reset(struct scsi_cmnd *SCpnt) DECLARE_MUTEX_LOCKED(sem); if (!fc->rst_pkt) { - fc->rst_pkt = kmalloc(sizeof(SCpnt), GFP_KERNEL); + fc->rst_pkt = (struct scsi_cmnd *) kmalloc(sizeof(SCpnt), GFP_KERNEL); if (!fc->rst_pkt) return FAILED; fcmd = FCP_CMND(fc->rst_pkt); @@ -1107,7 +1107,7 @@ int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport) logi *l; int status; - l = kzalloc(2 * sizeof(logi), GFP_KERNEL); + l = (logi *)kzalloc(2 * sizeof(logi), GFP_KERNEL); if (!l) return -ENOMEM; l->code = LS_PLOGI; memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn)); @@ -1141,7 +1141,7 @@ int fc_do_prli(fc_channel *fc, unsigned char alpa) prli *p; int status; - p = kzalloc(2 * sizeof(prli), GFP_KERNEL); + p = (prli *)kzalloc(2 * sizeof(prli), GFP_KERNEL); if (!p) return -ENOMEM; p->code = LS_PRLI; p->params[0] = 0x08002000; diff --git a/trunk/drivers/hwmon/f71805f.c b/trunk/drivers/hwmon/f71805f.c index de17a72149d9..dfca856854c3 100644 --- a/trunk/drivers/hwmon/f71805f.c +++ b/trunk/drivers/hwmon/f71805f.c @@ -122,6 +122,9 @@ superio_exit(int base) /* status nr from 0 to 2 */ #define F71805F_REG_STATUS(nr) (0x36 + (nr)) +/* individual register bits */ +#define FAN_CTRL_SKIP 0x80 + /* * Data structures and manipulation thereof */ @@ -143,7 +146,7 @@ struct f71805f_data { u8 in_low[9]; u16 fan[3]; u16 fan_low[3]; - u8 fan_enabled; /* Read once at init time */ + u8 fan_ctrl[3]; u8 temp[3]; u8 temp_high[3]; u8 temp_hyst[3]; @@ -281,9 +284,10 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) F71805F_REG_IN_LOW(nr)); } for (nr = 0; nr < 3; nr++) { - if (data->fan_enabled & (1 << nr)) - data->fan_low[nr] = f71805f_read16(data, - F71805F_REG_FAN_LOW(nr)); + if (data->fan_ctrl[nr] & FAN_CTRL_SKIP) + continue; + data->fan_low[nr] = f71805f_read16(data, + F71805F_REG_FAN_LOW(nr)); } for (nr = 0; nr < 3; nr++) { data->temp_high[nr] = f71805f_read8(data, @@ -304,9 +308,10 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) F71805F_REG_IN(nr)); } for (nr = 0; nr < 3; nr++) { - if (data->fan_enabled & (1 << nr)) - data->fan[nr] = f71805f_read16(data, - F71805F_REG_FAN(nr)); + if (data->fan_ctrl[nr] & FAN_CTRL_SKIP) + continue; + data->fan[nr] = f71805f_read16(data, + F71805F_REG_FAN(nr)); } for (nr = 0; nr < 3; nr++) { data->temp[nr] = f71805f_read8(data, @@ -798,9 +803,8 @@ static void __devinit f71805f_init_device(struct f71805f_data *data) /* Fan monitoring can be disabled. If it is, we won't be polling the register values, and won't create the related sysfs files. */ for (i = 0; i < 3; i++) { - reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i)); - if (!(reg & 0x80)) - data->fan_enabled |= (1 << i); + data->fan_ctrl[i] = f71805f_read8(data, + F71805F_REG_FAN_CTRL(i)); } } @@ -831,7 +835,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev) if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group))) goto exit_free; for (i = 0; i < 3; i++) { - if (!(data->fan_enabled & (1 << i))) + if (data->fan_ctrl[i] & FAN_CTRL_SKIP) continue; if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group_fan[i]))) diff --git a/trunk/drivers/i2c/algos/Kconfig b/trunk/drivers/i2c/algos/Kconfig index af0203409dd1..c034820615bb 100644 --- a/trunk/drivers/i2c/algos/Kconfig +++ b/trunk/drivers/i2c/algos/Kconfig @@ -38,6 +38,17 @@ config I2C_ALGOPCA This support is also available as a module. If so, the module will be called i2c-algo-pca. +config I2C_ALGOITE + tristate "ITE I2C Algorithm" + depends on MIPS_ITE8172 && I2C + help + This supports the use of the ITE8172 I2C interface found on some MIPS + systems. Say Y if you have one of these. You should also say Y for + the ITE I2C peripheral driver support below. + + This support is also available as a module. If so, the module + will be called i2c-algo-ite. + config I2C_ALGO8XX tristate "MPC8xx CPM I2C interface" depends on 8xx && I2C diff --git a/trunk/drivers/i2c/algos/Makefile b/trunk/drivers/i2c/algos/Makefile index cac1051bd4f1..208be04a3dbd 100644 --- a/trunk/drivers/i2c/algos/Makefile +++ b/trunk/drivers/i2c/algos/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o +obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o ifeq ($(CONFIG_I2C_DEBUG_ALGO),y) diff --git a/trunk/drivers/i2c/algos/i2c-algo-bit.c b/trunk/drivers/i2c/algos/i2c-algo-bit.c index 95aa5395a5be..21c36bfb5e6b 100644 --- a/trunk/drivers/i2c/algos/i2c-algo-bit.c +++ b/trunk/drivers/i2c/algos/i2c-algo-bit.c @@ -540,7 +540,15 @@ int i2c_bit_add_bus(struct i2c_adapter *adap) return i2c_add_adapter(adap); } + + +int i2c_bit_del_bus(struct i2c_adapter *adap) +{ + return i2c_del_adapter(adap); +} + EXPORT_SYMBOL(i2c_bit_add_bus); +EXPORT_SYMBOL(i2c_bit_del_bus); MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); diff --git a/trunk/drivers/i2c/algos/i2c-algo-ite.c b/trunk/drivers/i2c/algos/i2c-algo-ite.c new file mode 100644 index 000000000000..70d8eefb5efc --- /dev/null +++ b/trunk/drivers/i2c/algos/i2c-algo-ite.c @@ -0,0 +1,806 @@ +/* + ------------------------------------------------------------------------- + i2c-algo-ite.c i2c driver algorithms for ITE adapters + + Hai-Pao Fan, MontaVista Software, Inc. + hpfan@mvista.com or source@mvista.com + + Copyright 2000 MontaVista Software Inc. + + --------------------------------------------------------------------------- + This file was highly leveraged from i2c-algo-pcf.c, which was created + by Simon G. Vogl and Hans Berglund: + + + Copyright (C) 1995-1997 Simon G. Vogl + 1998-2000 Hans Berglund + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and + Frodo Looijaard ,and also from Martin Bailey + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "i2c-algo-ite.h" + +#define PM_DSR IT8172_PCI_IO_BASE + IT_PM_DSR +#define PM_IBSR IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04 +#define GPIO_CCR IT8172_PCI_IO_BASE + IT_GPCCR + +#define DEB2(x) if (i2c_debug>=2) x +#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/ +#define DEF_TIMEOUT 16 + + +/* module parameters: + */ +static int i2c_debug; +static int iic_test; /* see if the line-setting functions work */ + +/* --- setting states on the bus with the right timing: --------------- */ + +#define get_clock(adap) adap->getclock(adap->data) +#define iic_outw(adap, reg, val) adap->setiic(adap->data, reg, val) +#define iic_inw(adap, reg) adap->getiic(adap->data, reg) + + +/* --- other auxiliary functions -------------------------------------- */ + +static void iic_start(struct i2c_algo_iic_data *adap) +{ + iic_outw(adap,ITE_I2CHCR,ITE_CMD); +} + +static void iic_stop(struct i2c_algo_iic_data *adap) +{ + iic_outw(adap,ITE_I2CHCR,0); + iic_outw(adap,ITE_I2CHSR,ITE_I2CHSR_TDI); +} + +static void iic_reset(struct i2c_algo_iic_data *adap) +{ + iic_outw(adap, PM_IBSR, iic_inw(adap, PM_IBSR) | 0x80); +} + + +static int wait_for_bb(struct i2c_algo_iic_data *adap) +{ + int timeout = DEF_TIMEOUT; + short status; + + status = iic_inw(adap, ITE_I2CHSR); +#ifndef STUB_I2C + while (timeout-- && (status & ITE_I2CHSR_HB)) { + udelay(1000); /* How much is this? */ + status = iic_inw(adap, ITE_I2CHSR); + } +#endif + if (timeout<=0) { + printk(KERN_ERR "Timeout, host is busy\n"); + iic_reset(adap); + } + return(timeout<=0); +} + +/* After we issue a transaction on the IIC bus, this function + * is called. It puts this process to sleep until we get an interrupt from + * from the controller telling us that the transaction we requested in complete. + */ +static int wait_for_pin(struct i2c_algo_iic_data *adap, short *status) { + + int timeout = DEF_TIMEOUT; + + timeout = wait_for_bb(adap); + if (timeout) { + DEB2(printk("Timeout waiting for host not busy\n");) + return -EIO; + } + timeout = DEF_TIMEOUT; + + *status = iic_inw(adap, ITE_I2CHSR); +#ifndef STUB_I2C + while (timeout-- && !(*status & ITE_I2CHSR_TDI)) { + adap->waitforpin(); + *status = iic_inw(adap, ITE_I2CHSR); + } +#endif + if (timeout <= 0) + return(-1); + else + return(0); +} + +static int wait_for_fe(struct i2c_algo_iic_data *adap, short *status) +{ + int timeout = DEF_TIMEOUT; + + *status = iic_inw(adap, ITE_I2CFSR); +#ifndef STUB_I2C + while (timeout-- && (*status & ITE_I2CFSR_FE)) { + udelay(1000); + iic_inw(adap, ITE_I2CFSR); + } +#endif + if (timeout <= 0) + return(-1); + else + return(0); +} + +static int iic_init (struct i2c_algo_iic_data *adap) +{ + short i; + + /* Clear bit 7 to set I2C to normal operation mode */ + i=iic_inw(adap, PM_DSR)& 0xff7f; + iic_outw(adap, PM_DSR, i); + + /* set IT_GPCCR port C bit 2&3 as function 2 */ + i = iic_inw(adap, GPIO_CCR) & 0xfc0f; + iic_outw(adap,GPIO_CCR,i); + + /* Clear slave address/sub-address */ + iic_outw(adap,ITE_I2CSAR, 0); + iic_outw(adap,ITE_I2CSSAR, 0); + + /* Set clock counter register */ + iic_outw(adap,ITE_I2CCKCNT, get_clock(adap)); + + /* Set START/reSTART/STOP time registers */ + iic_outw(adap,ITE_I2CSHDR, 0x0a); + iic_outw(adap,ITE_I2CRSUR, 0x0a); + iic_outw(adap,ITE_I2CPSUR, 0x0a); + + /* Enable interrupts on completing the current transaction */ + iic_outw(adap,ITE_I2CHCR, ITE_I2CHCR_IE | ITE_I2CHCR_HCE); + + /* Clear transfer count */ + iic_outw(adap,ITE_I2CFBCR, 0x0); + + DEB2(printk("iic_init: Initialized IIC on ITE 0x%x\n", + iic_inw(adap, ITE_I2CHSR))); + return 0; +} + + +/* + * Sanity check for the adapter hardware - check the reaction of + * the bus lines only if it seems to be idle. + */ +static int test_bus(struct i2c_algo_iic_data *adap, char *name) { +#if 0 + int scl,sda; + sda=getsda(adap); + if (adap->getscl==NULL) { + printk("test_bus: Warning: Adapter can't read from clock line - skipping test.\n"); + return 0; + } + scl=getscl(adap); + printk("test_bus: Adapter: %s scl: %d sda: %d -- testing...\n", + name,getscl(adap),getsda(adap)); + if (!scl || !sda ) { + printk("test_bus: %s seems to be busy.\n",adap->name); + goto bailout; + } + sdalo(adap); + printk("test_bus:1 scl: %d sda: %d\n", getscl(adap), + getsda(adap)); + if ( 0 != getsda(adap) ) { + printk("test_bus: %s SDA stuck high!\n",name); + sdahi(adap); + goto bailout; + } + if ( 0 == getscl(adap) ) { + printk("test_bus: %s SCL unexpected low while pulling SDA low!\n", + name); + goto bailout; + } + sdahi(adap); + printk("test_bus:2 scl: %d sda: %d\n", getscl(adap), + getsda(adap)); + if ( 0 == getsda(adap) ) { + printk("test_bus: %s SDA stuck low!\n",name); + sdahi(adap); + goto bailout; + } + if ( 0 == getscl(adap) ) { + printk("test_bus: %s SCL unexpected low while SDA high!\n", + adap->name); + goto bailout; + } + scllo(adap); + printk("test_bus:3 scl: %d sda: %d\n", getscl(adap), + getsda(adap)); + if ( 0 != getscl(adap) ) { + + sclhi(adap); + goto bailout; + } + if ( 0 == getsda(adap) ) { + printk("test_bus: %s SDA unexpected low while pulling SCL low!\n", + name); + goto bailout; + } + sclhi(adap); + printk("test_bus:4 scl: %d sda: %d\n", getscl(adap), + getsda(adap)); + if ( 0 == getscl(adap) ) { + printk("test_bus: %s SCL stuck low!\n",name); + sclhi(adap); + goto bailout; + } + if ( 0 == getsda(adap) ) { + printk("test_bus: %s SDA unexpected low while SCL high!\n", + name); + goto bailout; + } + printk("test_bus: %s passed test.\n",name); + return 0; +bailout: + sdahi(adap); + sclhi(adap); + return -ENODEV; +#endif + return (0); +} + +/* ----- Utility functions + */ + + +/* Verify the device we want to talk to on the IIC bus really exists. */ +static inline int try_address(struct i2c_algo_iic_data *adap, + unsigned int addr, int retries) +{ + int i, ret = -1; + short status; + + for (i=0;iudelay); + } + DEB2(if (i) printk("try_address: needed %d retries for 0x%x\n",i, + addr)); + return ret; +} + + +static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf, + int count) +{ + struct i2c_algo_iic_data *adap = i2c_adap->algo_data; + int wrcount=0, timeout; + short status; + int loops, remainder, i, j; + union { + char byte[2]; + unsigned short word; + } tmp; + + iic_outw(adap, ITE_I2CSSAR, (unsigned short)buf[wrcount++]); + count--; + if (count == 0) + return -EIO; + + loops = count / 32; /* 32-byte FIFO */ + remainder = count % 32; + + if(loops) { + for(i=0; iname); + return -EREMOTEIO; /* got a better one ?? */ + } + if (status & ITE_I2CHSR_DB) { + iic_stop(adap); + printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name); + return -EREMOTEIO; /* got a better one ?? */ + } + } + } + if(remainder) { + iic_outw(adap, ITE_I2CFBCR, remainder); + for(i=0; iname); + return -EREMOTEIO; /* got a better one ?? */ + } +#ifndef STUB_I2C + if (status & ITE_I2CHSR_DB) { + iic_stop(adap); + printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name); + return -EREMOTEIO; /* got a better one ?? */ + } +#endif + } + iic_stop(adap); + return wrcount; +} + + +static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count, + int sread) +{ + int rdcount=0, i, timeout; + short status; + struct i2c_algo_iic_data *adap = i2c_adap->algo_data; + int loops, remainder, j; + union { + char byte[2]; + unsigned short word; + } tmp; + + loops = count / 32; /* 32-byte FIFO */ + remainder = count % 32; + + if(loops) { + for(i=0; iname); + return (-1); + } +#ifndef STUB_I2C + if (status & ITE_I2CHSR_DB) { + iic_stop(adap); + printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name); + return (-1); + } +#endif + + timeout = wait_for_fe(adap, &status); + if(timeout) { + iic_stop(adap); + printk("iic_readbytes: %s FIFO is empty\n", i2c_adap->name); + return (-1); + } + + for(j=0; j<32/2; j++) { + tmp.word = iic_inw(adap, ITE_I2CFDR); + buf[rdcount++] = tmp.byte[1]; + buf[rdcount++] = tmp.byte[0]; + } + + /* status FIFO underrun */ + iic_inw(adap, ITE_I2CFSR); + + } + } + + + if(remainder) { + remainder=(remainder+1)/2 * 2; + iic_outw(adap, ITE_I2CFBCR, remainder); + if (sread) + iic_outw(adap, ITE_I2CHCR, ITE_SREAD); + else + iic_outw(adap, ITE_I2CHCR, ITE_READ); /* Issue READ command */ + + timeout = wait_for_pin(adap, &status); + if(timeout) { + iic_stop(adap); + printk("iic_readbytes: %s read timeout.\n", i2c_adap->name); + return (-1); + } +#ifndef STUB_I2C + if (status & ITE_I2CHSR_DB) { + iic_stop(adap); + printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name); + return (-1); + } +#endif + timeout = wait_for_fe(adap, &status); + if(timeout) { + iic_stop(adap); + printk("iic_readbytes: %s FIFO is empty\n", i2c_adap->name); + return (-1); + } + + for(i=0; i<(remainder+1)/2; i++) { + tmp.word = iic_inw(adap, ITE_I2CFDR); + buf[rdcount++] = tmp.byte[1]; + buf[rdcount++] = tmp.byte[0]; + } + + /* status FIFO underrun */ + iic_inw(adap, ITE_I2CFSR); + + } + + iic_stop(adap); + return rdcount; +} + + +/* This function implements combined transactions. Combined + * transactions consist of combinations of reading and writing blocks of data. + * Each transfer (i.e. a read or a write) is separated by a repeated start + * condition. + */ +#if 0 +static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) +{ + int i; + struct i2c_msg *pmsg; + int ret; + + DEB2(printk("Beginning combined transaction\n")); + + for(i=0; i<(num-1); i++) { + pmsg = &msgs[i]; + if(pmsg->flags & I2C_M_RD) { + DEB2(printk(" This one is a read\n")); + ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER); + } + else if(!(pmsg->flags & I2C_M_RD)) { + DEB2(printk("This one is a write\n")); + ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER); + } + } + /* Last read or write segment needs to be terminated with a stop */ + pmsg = &msgs[i]; + + if(pmsg->flags & I2C_M_RD) { + DEB2(printk("Doing the last read\n")); + ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER); + } + else if(!(pmsg->flags & I2C_M_RD)) { + DEB2(printk("Doing the last write\n")); + ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER); + } + + return ret; +} +#endif + + +/* Whenever we initiate a transaction, the first byte clocked + * onto the bus after the start condition is the address (7 bit) of the + * device we want to talk to. This function manipulates the address specified + * so that it makes sense to the hardware when written to the IIC peripheral. + * + * Note: 10 bit addresses are not supported in this driver, although they are + * supported by the hardware. This functionality needs to be implemented. + */ +static inline int iic_doAddress(struct i2c_algo_iic_data *adap, + struct i2c_msg *msg, int retries) +{ + unsigned short flags = msg->flags; + unsigned int addr; + int ret; + +/* Ten bit addresses not supported right now */ + if ( (flags & I2C_M_TEN) ) { +#if 0 + addr = 0xf0 | (( msg->addr >> 7) & 0x03); + DEB2(printk("addr0: %d\n",addr)); + ret = try_address(adap, addr, retries); + if (ret!=1) { + printk("iic_doAddress: died at extended address code.\n"); + return -EREMOTEIO; + } + iic_outw(adap,msg->addr & 0x7f); + if (ret != 1) { + printk("iic_doAddress: died at 2nd address code.\n"); + return -EREMOTEIO; + } + if ( flags & I2C_M_RD ) { + i2c_repstart(adap); + addr |= 0x01; + ret = try_address(adap, addr, retries); + if (ret!=1) { + printk("iic_doAddress: died at extended address code.\n"); + return -EREMOTEIO; + } + } +#endif + } else { + + addr = ( msg->addr << 1 ); + +#if 0 + if (flags & I2C_M_RD ) + addr |= 1; + if (flags & I2C_M_REV_DIR_ADDR ) + addr ^= 1; +#endif + + if (iic_inw(adap, ITE_I2CSAR) != addr) { + iic_outw(adap, ITE_I2CSAR, addr); + ret = try_address(adap, addr, retries); + if (ret!=1) { + printk("iic_doAddress: died at address code.\n"); + return -EREMOTEIO; + } + } + + } + + return 0; +} + + +/* Description: Prepares the controller for a transaction (clearing status + * registers, data buffers, etc), and then calls either iic_readbytes or + * iic_sendbytes to do the actual transaction. + * + * still to be done: Before we issue a transaction, we should + * verify that the bus is not busy or in some unknown state. + */ +static int iic_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, + int num) +{ + struct i2c_algo_iic_data *adap = i2c_adap->algo_data; + struct i2c_msg *pmsg; + int i = 0; + int ret, timeout; + + pmsg = &msgs[i]; + + if(!pmsg->len) { + DEB2(printk("iic_xfer: read/write length is 0\n");) + return -EIO; + } + if(!(pmsg->flags & I2C_M_RD) && (!(pmsg->len)%2) ) { + DEB2(printk("iic_xfer: write buffer length is not odd\n");) + return -EIO; + } + + /* Wait for any pending transfers to complete */ + timeout = wait_for_bb(adap); + if (timeout) { + DEB2(printk("iic_xfer: Timeout waiting for host not busy\n");) + return -EIO; + } + + /* Flush FIFO */ + iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH); + + /* Load address */ + ret = iic_doAddress(adap, pmsg, i2c_adap->retries); + if (ret) + return -EIO; + +#if 0 + /* Combined transaction (read and write) */ + if(num > 1) { + DEB2(printk("iic_xfer: Call combined transaction\n")); + ret = iic_combined_transaction(i2c_adap, msgs, num); + } +#endif + + DEB3(printk("iic_xfer: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", + i, msgs[i].addr, msgs[i].flags, msgs[i].len);) + + if(pmsg->flags & I2C_M_RD) /* Read */ + ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, 0); + else { /* Write */ + udelay(1000); + ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len); + } + + if (ret != pmsg->len) + DEB3(printk("iic_xfer: error or fail on read/write %d bytes.\n",ret)); + else + DEB3(printk("iic_xfer: read/write %d bytes.\n",ret)); + + return ret; +} + + +/* Implements device specific ioctls. Higher level ioctls can + * be found in i2c-core.c and are typical of any i2c controller (specifying + * slave address, timeouts, etc). These ioctls take advantage of any hardware + * features built into the controller for which this algorithm-adapter set + * was written. These ioctls allow you to take control of the data and clock + * lines and set the either high or low, + * similar to a GPIO pin. + */ +static int algo_control(struct i2c_adapter *adapter, + unsigned int cmd, unsigned long arg) +{ + + struct i2c_algo_iic_data *adap = adapter->algo_data; + struct i2c_iic_msg s_msg; + char *buf; + int ret; + + if (cmd == I2C_SREAD) { + if(copy_from_user(&s_msg, (struct i2c_iic_msg *)arg, + sizeof(struct i2c_iic_msg))) + return -EFAULT; + buf = kmalloc(s_msg.len, GFP_KERNEL); + if (buf== NULL) + return -ENOMEM; + + /* Flush FIFO */ + iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH); + + /* Load address */ + iic_outw(adap, ITE_I2CSAR,s_msg.addr<<1); + iic_outw(adap, ITE_I2CSSAR,s_msg.waddr & 0xff); + + ret = iic_readbytes(adapter, buf, s_msg.len, 1); + if (ret>=0) { + if(copy_to_user( s_msg.buf, buf, s_msg.len) ) + ret = -EFAULT; + } + kfree(buf); + } + return 0; +} + + +static u32 iic_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_PROTOCOL_MANGLING; +} + +/* -----exported algorithm data: ------------------------------------- */ + +static struct i2c_algorithm iic_algo = { + .master_xfer = iic_xfer, + .algo_control = algo_control, /* ioctl */ + .functionality = iic_func, +}; + + +/* + * registering functions to load algorithms at runtime + */ +int i2c_iic_add_bus(struct i2c_adapter *adap) +{ + struct i2c_algo_iic_data *iic_adap = adap->algo_data; + + if (iic_test) { + int ret = test_bus(iic_adap, adap->name); + if (ret<0) + return -ENODEV; + } + + DEB2(printk("i2c-algo-ite: hw routines for %s registered.\n", + adap->name)); + + /* register new adapter to i2c module... */ + adap->algo = &iic_algo; + + adap->timeout = 100; /* default values, should */ + adap->retries = 3; /* be replaced by defines */ + adap->flags = 0; + + iic_init(iic_adap); + return i2c_add_adapter(adap); +} + + +int i2c_iic_del_bus(struct i2c_adapter *adap) +{ + int res; + if ((res = i2c_del_adapter(adap)) < 0) + return res; + DEB2(printk("i2c-algo-ite: adapter unregistered: %s\n",adap->name)); + + return 0; +} + + +int __init i2c_algo_iic_init (void) +{ + printk(KERN_INFO "ITE iic (i2c) algorithm module\n"); + return 0; +} + + +void i2c_algo_iic_exit(void) +{ + return; +} + + +EXPORT_SYMBOL(i2c_iic_add_bus); +EXPORT_SYMBOL(i2c_iic_del_bus); + +/* The MODULE_* macros resolve to nothing if MODULES is not defined + * when this file is compiled. + */ +MODULE_AUTHOR("MontaVista Software "); +MODULE_DESCRIPTION("ITE iic algorithm"); +MODULE_LICENSE("GPL"); + +module_param(iic_test, bool, 0); +module_param(i2c_debug, int, S_IRUGO | S_IWUSR); + +MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available"); +MODULE_PARM_DESC(i2c_debug, + "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); + + +/* This function resolves to init_module (the function invoked when a module + * is loaded via insmod) when this file is compiled with MODULES defined. + * Otherwise (i.e. if you want this driver statically linked to the kernel), + * a pointer to this function is stored in a table and called + * during the initialization of the kernel (in do_basic_setup in /init/main.c) + * + * All this functionality is complements of the macros defined in linux/init.h + */ +module_init(i2c_algo_iic_init); + + +/* If MODULES is defined when this file is compiled, then this function will + * resolved to cleanup_module. + */ +module_exit(i2c_algo_iic_exit); diff --git a/trunk/drivers/i2c/algos/i2c-algo-ite.h b/trunk/drivers/i2c/algos/i2c-algo-ite.h new file mode 100644 index 000000000000..a8ca3c9b546a --- /dev/null +++ b/trunk/drivers/i2c/algos/i2c-algo-ite.h @@ -0,0 +1,117 @@ +/* + -------------------------------------------------------------------- + i2c-ite.h: Global defines for the I2C controller on board the + ITE MIPS processor. + -------------------------------------------------------------------- + Hai-Pao Fan, MontaVista Software, Inc. + hpfan@mvista.com or source@mvista.com + + Copyright 2001 MontaVista Software Inc. + + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#ifndef I2C_ITE_H +#define I2C_ITE_H 1 + +#include + +/* I2C Registers */ +#define ITE_I2CHCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x30 +#define ITE_I2CHSR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x34 +#define ITE_I2CSAR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x38 +#define ITE_I2CSSAR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x3c +#define ITE_I2CCKCNT IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x48 +#define ITE_I2CSHDR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x4c +#define ITE_I2CRSUR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x50 +#define ITE_I2CPSUR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x54 + +#define ITE_I2CFDR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x70 +#define ITE_I2CFBCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x74 +#define ITE_I2CFCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x78 +#define ITE_I2CFSR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x7c + + +/* Host Control Register ITE_I2CHCR */ +#define ITE_I2CHCR_HCE 0x01 /* Enable I2C Host Controller */ +#define ITE_I2CHCR_IE 0x02 /* Enable the interrupt after completing + the current transaction */ +#define ITE_I2CHCR_CP_W 0x00 /* bit2-4 000 - Write */ +#define ITE_I2CHCR_CP_R 0x08 /* 010 - Current address read */ +#define ITE_I2CHCR_CP_S 0x10 /* 100 - Sequential read */ +#define ITE_I2CHCR_ST 0x20 /* Initiates the I2C host controller to execute + the command and send the data programmed in + all required registers to I2C bus */ +#define ITE_CMD ITE_I2CHCR_HCE | ITE_I2CHCR_IE | ITE_I2CHCR_ST +#define ITE_WRITE ITE_CMD | ITE_I2CHCR_CP_W +#define ITE_READ ITE_CMD | ITE_I2CHCR_CP_R +#define ITE_SREAD ITE_CMD | ITE_I2CHCR_CP_S + +/* Host Status Register ITE_I2CHSR */ +#define ITE_I2CHSR_DB 0x01 /* Device is busy, receives NACK response except + in the first and last bytes */ +#define ITE_I2CHSR_DNE 0x02 /* Target address on I2C bus does not exist */ +#define ITE_I2CHSR_TDI 0x04 /* R/W Transaction on I2C bus was completed */ +#define ITE_I2CHSR_HB 0x08 /* Host controller is processing transactions */ +#define ITE_I2CHSR_FER 0x10 /* Error occurs in the FIFO */ + +/* Slave Address Register ITE_I2CSAR */ +#define ITE_I2CSAR_SA_MASK 0xfe /* Target I2C device address */ +#define ITE_I2CSAR_ASO 0x0100 /* Output 1/0 to I2CAS port when the + next slave address is addressed */ + +/* Slave Sub-address Register ITE_I2CSSAR */ +#define ITE_I2CSSAR_SUBA_MASK 0xff /* Target I2C device sub-address */ + +/* Clock Counter Register ITE_I2CCKCNT */ +#define ITE_I2CCKCNT_STOP 0x00 /* stop I2C clock */ +#define ITE_I2CCKCNT_HPCC_MASK 0x7f /* SCL high period counter */ +#define ITE_I2CCKCNT_LPCC_MASK 0x7f00 /* SCL low period counter */ + +/* START Hold Time Register ITE_I2CSHDR */ +/* value is counted based on 16 MHz internal clock */ +#define ITE_I2CSHDR_FM 0x0a /* START condition at fast mode */ +#define ITE_I2CSHDR_SM 0x47 /* START contition at standard mode */ + +/* (Repeated) START Setup Time Register ITE_I2CRSUR */ +/* value is counted based on 16 MHz internal clock */ +#define ITE_I2CRSUR_FM 0x0a /* repeated START condition at fast mode */ +#define ITE_I2CRSUR_SM 0x50 /* repeated START condition at standard mode */ + +/* STOP setup Time Register ITE_I2CPSUR */ + +/* FIFO Data Register ITE_I2CFDR */ +#define ITE_I2CFDR_MASK 0xff + +/* FIFO Byte Count Register ITE_I2CFBCR */ +#define ITE_I2CFBCR_MASK 0x3f + +/* FIFO Control Register ITE_I2CFCR */ +#define ITE_I2CFCR_FLUSH 0x01 /* Flush FIFO and reset the FIFO point + and I2CFSR */ +/* FIFO Status Register ITE_I2CFSR */ +#define ITE_I2CFSR_FO 0x01 /* FIFO is overrun when write */ +#define ITE_I2CFSR_FU 0x02 /* FIFO is underrun when read */ +#define ITE_I2CFSR_FF 0x04 /* FIFO is full when write */ +#define ITE_I2CFSR_FE 0x08 /* FIFO is empty when read */ + +#endif /* I2C_ITE_H */ diff --git a/trunk/drivers/i2c/algos/i2c-algo-pca.c b/trunk/drivers/i2c/algos/i2c-algo-pca.c index 36fdf971f080..9081c9fbcd29 100644 --- a/trunk/drivers/i2c/algos/i2c-algo-pca.c +++ b/trunk/drivers/i2c/algos/i2c-algo-pca.c @@ -381,7 +381,14 @@ int i2c_pca_add_bus(struct i2c_adapter *adap) return rval; } + +int i2c_pca_del_bus(struct i2c_adapter *adap) +{ + return i2c_del_adapter(adap); +} + EXPORT_SYMBOL(i2c_pca_add_bus); +EXPORT_SYMBOL(i2c_pca_del_bus); MODULE_AUTHOR("Ian Campbell "); MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm"); diff --git a/trunk/drivers/i2c/algos/i2c-algo-pcf.c b/trunk/drivers/i2c/algos/i2c-algo-pcf.c index ecb2c2d7d540..3b2003398966 100644 --- a/trunk/drivers/i2c/algos/i2c-algo-pcf.c +++ b/trunk/drivers/i2c/algos/i2c-algo-pcf.c @@ -486,7 +486,15 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap) return rval; } + + +int i2c_pcf_del_bus(struct i2c_adapter *adap) +{ + return i2c_del_adapter(adap); +} + EXPORT_SYMBOL(i2c_pcf_add_bus); +EXPORT_SYMBOL(i2c_pcf_del_bus); MODULE_AUTHOR("Hans Berglund "); MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm"); diff --git a/trunk/drivers/i2c/algos/i2c-algo-sgi.c b/trunk/drivers/i2c/algos/i2c-algo-sgi.c index ac2d5053078a..490d99997fd0 100644 --- a/trunk/drivers/i2c/algos/i2c-algo-sgi.c +++ b/trunk/drivers/i2c/algos/i2c-algo-sgi.c @@ -171,7 +171,15 @@ int i2c_sgi_add_bus(struct i2c_adapter *adap) return i2c_add_adapter(adap); } + + +int i2c_sgi_del_bus(struct i2c_adapter *adap) +{ + return i2c_del_adapter(adap); +} + EXPORT_SYMBOL(i2c_sgi_add_bus); +EXPORT_SYMBOL(i2c_sgi_del_bus); MODULE_AUTHOR("Ladislav Michl "); MODULE_DESCRIPTION("I2C-Bus SGI algorithm"); diff --git a/trunk/drivers/i2c/busses/Kconfig b/trunk/drivers/i2c/busses/Kconfig index e1989f3a2684..90f91d039ee2 100644 --- a/trunk/drivers/i2c/busses/Kconfig +++ b/trunk/drivers/i2c/busses/Kconfig @@ -74,13 +74,6 @@ config I2C_AMD8111 This driver can also be built as a module. If so, the module will be called i2c-amd8111. -config I2C_AT91 - tristate "Atmel AT91 I2C Two-Wire interface (TWI)" - depends on I2C && ARCH_AT91 && EXPERIMENTAL - help - This supports the use of the I2C interface on Atmel AT91 - processors. - config I2C_AU1550 tristate "Au1550/Au1200 SMBus interface" depends on I2C && (SOC_AU1550 || SOC_AU1200) @@ -216,6 +209,18 @@ config I2C_ISA tristate depends on I2C +config I2C_ITE + tristate "ITE I2C Adapter" + depends on I2C && MIPS_ITE8172 + select I2C_ALGOITE + help + This supports the ITE8172 I2C peripheral found on some MIPS + systems. Say Y if you have one of these. You should also say Y for + the ITE I2C driver algorithm support above. + + This support is also available as a module. If so, the module + will be called i2c-ite. + config I2C_IXP4XX tristate "IXP4xx GPIO-Based I2C Interface" depends on I2C && ARCH_IXP4XX @@ -476,17 +481,6 @@ config I2C_STUB If you don't know what to do here, definitely say N. -config I2C_VERSATILE - tristate "ARM Versatile/Realview I2C bus support" - depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW) - select I2C_ALGOBIT - help - Say yes if you want to support the I2C serial bus on ARMs Versatile - range of platforms. - - This driver can also be built as a module. If so, the module - will be called i2c-versatile. - config I2C_VIA tristate "VIA 82C586B" depends on I2C && PCI && EXPERIMENTAL @@ -554,23 +548,4 @@ config I2C_MV64XXX This driver can also be built as a module. If so, the module will be called i2c-mv64xxx. -config I2C_PNX - tristate "I2C bus support for Philips PNX targets" - depends on ARCH_PNX4008 && I2C - help - This driver supports the Philips IP3204 I2C IP block master and/or - slave controller - - This driver can also be built as a module. If so, the module - will be called i2c-pnx. - -config I2C_PNX_EARLY - bool "Early initialization for I2C on PNXxxxx" - depends on I2C_PNX=y - help - Under certain circumstances one may need to make sure I2C on PNXxxxx - is initialized earlier than some other driver that depends on it - (for instance, that might be USB in case of PNX4008). With this - option turned on you can guarantee that. - endmenu diff --git a/trunk/drivers/i2c/busses/Makefile b/trunk/drivers/i2c/busses/Makefile index 37196c1d0794..493c87289b62 100644 --- a/trunk/drivers/i2c/busses/Makefile +++ b/trunk/drivers/i2c/busses/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o -obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o @@ -17,6 +16,7 @@ obj-$(CONFIG_I2C_I810) += i2c-i810.o obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_ISA) += i2c-isa.o +obj-$(CONFIG_I2C_ITE) += i2c-ite.o obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o @@ -29,7 +29,6 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o -obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o @@ -40,7 +39,6 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_STUB) += i2c-stub.o -obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o diff --git a/trunk/drivers/i2c/busses/i2c-at91.c b/trunk/drivers/i2c/busses/i2c-at91.c deleted file mode 100644 index 67f91bdda089..000000000000 --- a/trunk/drivers/i2c/busses/i2c-at91.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - i2c Support for Atmel's AT91 Two-Wire Interface (TWI) - - Copyright (C) 2004 Rick Bronson - Converted to 2.6 by Andrew Victor - - Borrowed heavily from original work by: - Copyright (C) 2000 Philip Edelbrock - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define TWI_CLOCK 100000 /* Hz. max 400 Kbits/sec */ - - -static struct clk *twi_clk; -static void __iomem *twi_base; - -#define at91_twi_read(reg) __raw_readl(twi_base + (reg)) -#define at91_twi_write(reg, val) __raw_writel((val), twi_base + (reg)) - - -/* - * Initialize the TWI hardware registers. - */ -static void __devinit at91_twi_hwinit(void) -{ - unsigned long cdiv, ckdiv; - - at91_twi_write(AT91_TWI_IDR, 0xffffffff); /* Disable all interrupts */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST); /* Reset peripheral */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN); /* Set Master mode */ - - /* Calcuate clock dividers */ - cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3; - cdiv = cdiv + 1; /* round up */ - ckdiv = 0; - while (cdiv > 255) { - ckdiv++; - cdiv = cdiv >> 1; - } - - if (cpu_is_at91rm9200()) { /* AT91RM9200 Errata #22 */ - if (ckdiv > 5) { - printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n"); - ckdiv = 5; - } - } - - at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv); -} - -/* - * Poll the i2c status register until the specified bit is set. - * Returns 0 if timed out (100 msec). - */ -static short at91_poll_status(unsigned long bit) -{ - int loop_cntr = 10000; - - do { - udelay(10); - } while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0)); - - return (loop_cntr > 0); -} - -static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - /* Send Start */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_START); - - /* Read data */ - while (length--) { - if (!length) /* need to send Stop before reading last byte */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP); - if (!at91_poll_status(AT91_TWI_RXRDY)) { - dev_dbg(&adap->dev, "RXRDY timeout\n"); - return -ETIMEDOUT; - } - *buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff); - } - - return 0; -} - -static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - /* Load first byte into transmitter */ - at91_twi_write(AT91_TWI_THR, *buf++); - - /* Send Start */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_START); - - do { - if (!at91_poll_status(AT91_TWI_TXRDY)) { - dev_dbg(&adap->dev, "TXRDY timeout\n"); - return -ETIMEDOUT; - } - - length--; /* byte was transmitted */ - - if (length > 0) /* more data to send? */ - at91_twi_write(AT91_TWI_THR, *buf++); - } while (length); - - /* Send Stop */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP); - - return 0; -} - -/* - * Generic i2c master transfer entrypoint. - * - * Note: We do not use Atmel's feature of storing the "internal device address". - * Instead the "internal device address" has to be written using a seperate - * i2c message. - * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html - */ -static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num) -{ - int i, ret; - - dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); - - for (i = 0; i < num; i++) { - dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i, - pmsg->flags & I2C_M_RD ? "read" : "writ", - pmsg->len, pmsg->len > 1 ? "s" : "", - pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); - - at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16) - | ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0)); - - if (pmsg->len && pmsg->buf) { /* sanity check */ - if (pmsg->flags & I2C_M_RD) - ret = xfer_read(adap, pmsg->buf, pmsg->len); - else - ret = xfer_write(adap, pmsg->buf, pmsg->len); - - if (ret) - return ret; - - /* Wait until transfer is finished */ - if (!at91_poll_status(AT91_TWI_TXCOMP)) { - dev_dbg(&adap->dev, "TXCOMP timeout\n"); - return -ETIMEDOUT; - } - } - dev_dbg(&adap->dev, "transfer complete\n"); - pmsg++; /* next message */ - } - return i; -} - -/* - * Return list of supported functionality. - */ -static u32 at91_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm at91_algorithm = { - .master_xfer = at91_xfer, - .functionality = at91_func, -}; - -/* - * Main initialization routine. - */ -static int __devinit at91_i2c_probe(struct platform_device *pdev) -{ - struct i2c_adapter *adapter; - struct resource *res; - int rc; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - if (!request_mem_region(res->start, res->end - res->start + 1, "at91_i2c")) - return -EBUSY; - - twi_base = ioremap(res->start, res->end - res->start + 1); - if (!twi_base) { - rc = -ENOMEM; - goto fail0; - } - - twi_clk = clk_get(NULL, "twi_clk"); - if (IS_ERR(twi_clk)) { - dev_err(&pdev->dev, "no clock defined\n"); - rc = -ENODEV; - goto fail1; - } - - adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (adapter == NULL) { - dev_err(&pdev->dev, "can't allocate inteface!\n"); - rc = -ENOMEM; - goto fail2; - } - sprintf(adapter->name, "AT91"); - adapter->algo = &at91_algorithm; - adapter->class = I2C_CLASS_HWMON; - adapter->dev.parent = &pdev->dev; - - platform_set_drvdata(pdev, adapter); - - clk_enable(twi_clk); /* enable peripheral clock */ - at91_twi_hwinit(); /* initialize TWI controller */ - - rc = i2c_add_adapter(adapter); - if (rc) { - dev_err(&pdev->dev, "Adapter %s registration failed\n", - adapter->name); - goto fail3; - } - - dev_info(&pdev->dev, "AT91 i2c bus driver.\n"); - return 0; - -fail3: - platform_set_drvdata(pdev, NULL); - kfree(adapter); - clk_disable(twi_clk); -fail2: - clk_put(twi_clk); -fail1: - iounmap(twi_base); -fail0: - release_mem_region(res->start, res->end - res->start + 1); - - return rc; -} - -static int __devexit at91_i2c_remove(struct platform_device *pdev) -{ - struct i2c_adapter *adapter = platform_get_drvdata(pdev); - struct resource *res; - int rc; - - rc = i2c_del_adapter(adapter); - platform_set_drvdata(pdev, NULL); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iounmap(twi_base); - release_mem_region(res->start, res->end - res->start + 1); - - clk_disable(twi_clk); /* disable peripheral clock */ - clk_put(twi_clk); - - return rc; -} - -#ifdef CONFIG_PM - -/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */ - -static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - clk_disable(twi_clk); - return 0; -} - -static int at91_i2c_resume(struct platform_device *pdev) -{ - return clk_enable(twi_clk); -} - -#else -#define at91_i2c_suspend NULL -#define at91_i2c_resume NULL -#endif - -static struct platform_driver at91_i2c_driver = { - .probe = at91_i2c_probe, - .remove = __devexit_p(at91_i2c_remove), - .suspend = at91_i2c_suspend, - .resume = at91_i2c_resume, - .driver = { - .name = "at91_i2c", - .owner = THIS_MODULE, - }, -}; - -static int __init at91_i2c_init(void) -{ - return platform_driver_register(&at91_i2c_driver); -} - -static void __exit at91_i2c_exit(void) -{ - platform_driver_unregister(&at91_i2c_driver); -} - -module_init(at91_i2c_init); -module_exit(at91_i2c_exit); - -MODULE_AUTHOR("Rick Bronson"); -MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/i2c/busses/i2c-elektor.c b/trunk/drivers/i2c/busses/i2c-elektor.c index 834967464814..a591fe685f06 100644 --- a/trunk/drivers/i2c/busses/i2c-elektor.c +++ b/trunk/drivers/i2c/busses/i2c-elektor.c @@ -293,7 +293,7 @@ static int __init i2c_pcfisa_init(void) static void i2c_pcfisa_exit(void) { - i2c_del_adapter(&pcf_isa_ops); + i2c_pcf_del_bus(&pcf_isa_ops); if (irq > 0) { disable_irq(irq); diff --git a/trunk/drivers/i2c/busses/i2c-hydra.c b/trunk/drivers/i2c/busses/i2c-hydra.c index 9832f773651d..457d48a0ab9d 100644 --- a/trunk/drivers/i2c/busses/i2c-hydra.c +++ b/trunk/drivers/i2c/busses/i2c-hydra.c @@ -146,7 +146,7 @@ static int __devinit hydra_probe(struct pci_dev *dev, static void __devexit hydra_remove(struct pci_dev *dev) { pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ - i2c_del_adapter(&hydra_adap); + i2c_bit_del_bus(&hydra_adap); iounmap(hydra_bit_data.data); release_mem_region(pci_resource_start(dev, 0)+ offsetof(struct Hydra, CachePD), 4); diff --git a/trunk/drivers/i2c/busses/i2c-i801.c b/trunk/drivers/i2c/busses/i2c-i801.c index ae625b854470..c7be2fdbd86b 100644 --- a/trunk/drivers/i2c/busses/i2c-i801.c +++ b/trunk/drivers/i2c/busses/i2c-i801.c @@ -470,20 +470,12 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id int err; I801_dev = dev; - switch (dev->device) { - case PCI_DEVICE_ID_INTEL_82801DB_3: - case PCI_DEVICE_ID_INTEL_82801EB_3: - case PCI_DEVICE_ID_INTEL_ESB_4: - case PCI_DEVICE_ID_INTEL_ICH6_16: - case PCI_DEVICE_ID_INTEL_ICH7_17: - case PCI_DEVICE_ID_INTEL_ESB2_17: - case PCI_DEVICE_ID_INTEL_ICH8_5: - case PCI_DEVICE_ID_INTEL_ICH9_6: + if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || + (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || + (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) isich4 = 1; - break; - default: + else isich4 = 0; - } err = pci_enable_device(dev); if (err) { diff --git a/trunk/drivers/i2c/busses/i2c-i810.c b/trunk/drivers/i2c/busses/i2c-i810.c index 10c98bc88aa6..b66fb6bb1870 100644 --- a/trunk/drivers/i2c/busses/i2c-i810.c +++ b/trunk/drivers/i2c/busses/i2c-i810.c @@ -219,14 +219,14 @@ static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id return retval; retval = i2c_bit_add_bus(&i810_ddc_adapter); if (retval) - i2c_del_adapter(&i810_i2c_adapter); + i2c_bit_del_bus(&i810_i2c_adapter); return retval; } static void __devexit i810_remove(struct pci_dev *dev) { - i2c_del_adapter(&i810_ddc_adapter); - i2c_del_adapter(&i810_i2c_adapter); + i2c_bit_del_bus(&i810_ddc_adapter); + i2c_bit_del_bus(&i810_i2c_adapter); iounmap(ioaddr); } diff --git a/trunk/drivers/i2c/busses/i2c-ibm_iic.c b/trunk/drivers/i2c/busses/i2c-ibm_iic.c index 1898e9987021..781a99c1647a 100644 --- a/trunk/drivers/i2c/busses/i2c-ibm_iic.c +++ b/trunk/drivers/i2c/busses/i2c-ibm_iic.c @@ -680,12 +680,6 @@ static int __devinit iic_probe(struct ocp_device *ocp){ dev->idx = ocp->def->index; ocp_set_drvdata(ocp, dev); - if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs), - "ibm_iic")) { - ret = -EBUSY; - goto fail1; - } - if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){ printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n", dev->idx); @@ -756,8 +750,6 @@ static int __devinit iic_probe(struct ocp_device *ocp){ iounmap(dev->vaddr); fail2: - release_mem_region(ocp->def->paddr, sizeof(struct iic_regs)); -fail1: ocp_set_drvdata(ocp, NULL); kfree(dev); return ret; @@ -785,7 +777,6 @@ static void __devexit iic_remove(struct ocp_device *ocp) free_irq(dev->irq, dev); } iounmap(dev->vaddr); - release_mem_region(ocp->def->paddr, sizeof(struct iic_regs)); kfree(dev); } } diff --git a/trunk/drivers/i2c/busses/i2c-ite.c b/trunk/drivers/i2c/busses/i2c-ite.c new file mode 100644 index 000000000000..f7d71869b3b9 --- /dev/null +++ b/trunk/drivers/i2c/busses/i2c-ite.c @@ -0,0 +1,278 @@ +/* + ------------------------------------------------------------------------- + i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system + ------------------------------------------------------------------------- + Hai-Pao Fan, MontaVista Software, Inc. + hpfan@mvista.com or source@mvista.com + + Copyright 2001 MontaVista Software Inc. + + ---------------------------------------------------------------------------- + This file was highly leveraged from i2c-elektor.c, which was created + by Simon G. Vogl and Hans Berglund: + + + Copyright (C) 1995-97 Simon G. Vogl + 1998-99 Hans Berglund + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and even + Frodo Looijaard */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "../i2c-ite.h" + +#define DEFAULT_BASE 0x14014030 +#define ITE_IIC_IO_SIZE 0x40 +#define DEFAULT_IRQ 0 +#define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */ +#define DEFAULT_OWN 0x55 + +static int base; +static int irq; +static int clock; +static int own; + +static struct iic_ite gpi; +static wait_queue_head_t iic_wait; +static int iic_pending; +static spinlock_t lock; + +/* ----- local functions ---------------------------------------------- */ + +static void iic_ite_setiic(void *data, int ctl, short val) +{ + unsigned long j = jiffies + 10; + + pr_debug(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff); +#ifdef DEBUG + while (time_before(jiffies, j)) + schedule(); +#endif + outw(val,ctl); +} + +static short iic_ite_getiic(void *data, int ctl) +{ + short val; + + val = inw(ctl); + pr_debug("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff); + return (val); +} + +/* Return our slave address. This is the address + * put on the I2C bus when another master on the bus wants to address us + * as a slave + */ +static int iic_ite_getown(void *data) +{ + return (gpi.iic_own); +} + + +static int iic_ite_getclock(void *data) +{ + return (gpi.iic_clock); +} + + +/* Put this process to sleep. We will wake up when the + * IIC controller interrupts. + */ +static void iic_ite_waitforpin(void) { + DEFINE_WAIT(wait); + int timeout = 2; + unsigned long flags; + + /* If interrupts are enabled (which they are), then put the process to + * sleep. This process will be awakened by two events -- either the + * the IIC peripheral interrupts or the timeout expires. + * If interrupts are not enabled then delay for a reasonable amount + * of time and return. + */ + if (gpi.iic_irq > 0) { + spin_lock_irqsave(&lock, flags); + if (iic_pending == 0) { + spin_unlock_irqrestore(&lock, flags); + prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE); + if (schedule_timeout(timeout*HZ)) { + spin_lock_irqsave(&lock, flags); + if (iic_pending == 1) { + iic_pending = 0; + } + spin_unlock_irqrestore(&lock, flags); + } + finish_wait(&iic_wait, &wait); + } else { + iic_pending = 0; + spin_unlock_irqrestore(&lock, flags); + } + } else { + udelay(100); + } +} + + +static irqreturn_t iic_ite_handler(int this_irq, void *dev_id) +{ + spin_lock(&lock); + iic_pending = 1; + spin_unlock(&lock); + + wake_up_interruptible(&iic_wait); + + return IRQ_HANDLED; +} + + +/* Lock the region of memory where I/O registers exist. Request our + * interrupt line and register its associated handler. + */ +static int iic_hw_resrc_init(void) +{ + if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c")) + return -ENODEV; + + if (gpi.iic_irq <= 0) + return 0; + + if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0) + gpi.iic_irq = 0; + else + enable_irq(gpi.iic_irq); + + return 0; +} + + +static void iic_ite_release(void) +{ + if (gpi.iic_irq > 0) { + disable_irq(gpi.iic_irq); + free_irq(gpi.iic_irq, 0); + } + release_region(gpi.iic_base , 2); +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_iic_data iic_ite_data = { + NULL, + iic_ite_setiic, + iic_ite_getiic, + iic_ite_getown, + iic_ite_getclock, + iic_ite_waitforpin, + 80, 80, 100, /* waits, timeout */ +}; + +static struct i2c_adapter iic_ite_ops = { + .owner = THIS_MODULE, + .id = I2C_HW_I_IIC, + .algo_data = &iic_ite_data, + .name = "ITE IIC adapter", +}; + +/* Called when the module is loaded. This function starts the + * cascade of calls up through the hierarchy of i2c modules (i.e. up to the + * algorithm layer and into to the core layer) + */ +static int __init iic_ite_init(void) +{ + + struct iic_ite *piic = &gpi; + + printk(KERN_INFO "Initialize ITE IIC adapter module\n"); + if (base == 0) + piic->iic_base = DEFAULT_BASE; + else + piic->iic_base = base; + + if (irq == 0) + piic->iic_irq = DEFAULT_IRQ; + else + piic->iic_irq = irq; + + if (clock == 0) + piic->iic_clock = DEFAULT_CLOCK; + else + piic->iic_clock = clock; + + if (own == 0) + piic->iic_own = DEFAULT_OWN; + else + piic->iic_own = own; + + iic_ite_data.data = (void *)piic; + init_waitqueue_head(&iic_wait); + spin_lock_init(&lock); + if (iic_hw_resrc_init() == 0) { + if (i2c_iic_add_bus(&iic_ite_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + printk(KERN_INFO " found device at %#x irq %d.\n", + piic->iic_base, piic->iic_irq); + return 0; +} + + +static void iic_ite_exit(void) +{ + i2c_iic_del_bus(&iic_ite_ops); + iic_ite_release(); +} + +/* If modules is NOT defined when this file is compiled, then the MODULE_* + * macros will resolve to nothing + */ +MODULE_AUTHOR("MontaVista Software "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter"); +MODULE_LICENSE("GPL"); + +module_param(base, int, 0); +module_param(irq, int, 0); +module_param(clock, int, 0); +module_param(own, int, 0); + + +/* Called when module is loaded or when kernel is initialized. + * If MODULES is defined when this file is compiled, then this function will + * resolve to init_module (the function called when insmod is invoked for a + * module). Otherwise, this function is called early in the boot, when the + * kernel is intialized. Check out /include/init.h to see how this works. + */ +module_init(iic_ite_init); + +/* Resolves to module_cleanup when MODULES is defined. */ +module_exit(iic_ite_exit); diff --git a/trunk/drivers/i2c/busses/i2c-ixp2000.c b/trunk/drivers/i2c/busses/i2c-ixp2000.c index efa3ecc5522a..dd3f4cd3aa68 100644 --- a/trunk/drivers/i2c/busses/i2c-ixp2000.c +++ b/trunk/drivers/i2c/busses/i2c-ixp2000.c @@ -90,7 +90,7 @@ static int ixp2000_i2c_remove(struct platform_device *plat_dev) platform_set_drvdata(plat_dev, NULL); - i2c_del_adapter(&drv_data->adapter); + i2c_bit_del_bus(&drv_data->adapter); kfree(drv_data); diff --git a/trunk/drivers/i2c/busses/i2c-ixp4xx.c b/trunk/drivers/i2c/busses/i2c-ixp4xx.c index 08e89b83984a..68fe863f9d54 100644 --- a/trunk/drivers/i2c/busses/i2c-ixp4xx.c +++ b/trunk/drivers/i2c/busses/i2c-ixp4xx.c @@ -91,7 +91,7 @@ static int ixp4xx_i2c_remove(struct platform_device *plat_dev) platform_set_drvdata(plat_dev, NULL); - i2c_del_adapter(&drv_data->adapter); + i2c_bit_del_bus(&drv_data->adapter); kfree(drv_data); diff --git a/trunk/drivers/i2c/busses/i2c-nforce2.c b/trunk/drivers/i2c/busses/i2c-nforce2.c index ad37c10e7fec..e0292e414ab2 100644 --- a/trunk/drivers/i2c/busses/i2c-nforce2.c +++ b/trunk/drivers/i2c/busses/i2c-nforce2.c @@ -35,7 +35,7 @@ nForce4 MCP55 0368 This driver supports the 2 SMBuses that are included in the MCP of the - nForce2/3/4/5xx chipsets. + nForce2/3/4 chipsets. */ /* Note: we assume there can only be one nForce2, with two SMBus interfaces */ @@ -52,8 +52,8 @@ #include MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Hans-Frieder Vogt "); -MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver"); +MODULE_AUTHOR ("Hans-Frieder Vogt "); +MODULE_DESCRIPTION("nForce2 SMBus driver"); struct nforce2_smbus { @@ -80,6 +80,9 @@ struct nforce2_smbus { #define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */ #define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */ #define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */ +#define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data bytes */ +#define NVIDIA_SMB_ALRM_A (smbus->base + 0x25) /* alarm address */ +#define NVIDIA_SMB_ALRM_D (smbus->base + 0x26) /* 2 bytes alarm data */ #define NVIDIA_SMB_STS_DONE 0x80 #define NVIDIA_SMB_STS_ALRM 0x40 @@ -92,17 +95,40 @@ struct nforce2_smbus { #define NVIDIA_SMB_PRTCL_BYTE 0x04 #define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06 #define NVIDIA_SMB_PRTCL_WORD_DATA 0x08 +#define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a +#define NVIDIA_SMB_PRTCL_PROC_CALL 0x0c +#define NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL 0x0d +#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA 0x4a #define NVIDIA_SMB_PRTCL_PEC 0x80 static struct pci_driver nforce2_driver; -/* Return -1 on error */ +static s32 nforce2_access(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data); +static u32 nforce2_func(struct i2c_adapter *adapter); + + +static const struct i2c_algorithm smbus_algorithm = { + .smbus_xfer = nforce2_access, + .functionality = nforce2_func, +}; + +static struct i2c_adapter nforce2_adapter = { + .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON, + .algo = &smbus_algorithm, +}; + +/* Return -1 on error. See smbus.h for more information */ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { struct nforce2_smbus *smbus = adap->algo_data; unsigned char protocol, pec, temp; + unsigned char len = 0; /* to keep the compiler quiet */ + int i; protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : NVIDIA_SMB_PRTCL_WRITE; @@ -137,6 +163,35 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec; break; + case I2C_SMBUS_BLOCK_DATA: + outb_p(command, NVIDIA_SMB_CMD); + if (read_write == I2C_SMBUS_WRITE) { + len = min_t(u8, data->block[0], 32); + outb_p(len, NVIDIA_SMB_BCNT); + for (i = 0; i < len; i++) + outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i); + } + protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec; + break; + + case I2C_SMBUS_I2C_BLOCK_DATA: + len = min_t(u8, data->block[0], 32); + outb_p(command, NVIDIA_SMB_CMD); + outb_p(len, NVIDIA_SMB_BCNT); + if (read_write == I2C_SMBUS_WRITE) + for (i = 0; i < len; i++) + outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i); + protocol |= NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA; + break; + + case I2C_SMBUS_PROC_CALL: + dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); + return -1; + + case I2C_SMBUS_BLOCK_PROC_CALL: + dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n"); + return -1; + default: dev_err(&adap->dev, "Unsupported transaction %d\n", size); return -1; @@ -172,8 +227,19 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, break; case I2C_SMBUS_WORD_DATA: + /* case I2C_SMBUS_PROC_CALL: not supported */ data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8); break; + + case I2C_SMBUS_BLOCK_DATA: + /* case I2C_SMBUS_BLOCK_PROC_CALL: not supported */ + len = inb_p(NVIDIA_SMB_BCNT); + len = min_t(u8, len, 32); + case I2C_SMBUS_I2C_BLOCK_DATA: + for (i = 0; i < len; i++) + data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); + data->block[0] = len; + break; } return 0; @@ -184,14 +250,10 @@ static u32 nforce2_func(struct i2c_adapter *adapter) { /* other functionality might be possible, but is not tested */ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA; + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA /* | + I2C_FUNC_SMBUS_BLOCK_DATA */; } -static struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = nforce2_access, - .functionality = nforce2_func, -}; - static struct pci_device_id nforce2_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) }, @@ -205,6 +267,7 @@ static struct pci_device_id nforce2_ids[] = { { 0 } }; + MODULE_DEVICE_TABLE (pci, nforce2_ids); @@ -228,7 +291,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, } smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; - smbus->size = 64; + smbus->size = 8; } smbus->dev = dev; @@ -237,9 +300,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, smbus->base, smbus->base+smbus->size-1, name); return -1; } - smbus->adapter.owner = THIS_MODULE; - smbus->adapter.class = I2C_CLASS_HWMON; - smbus->adapter.algo = &smbus_algorithm; + smbus->adapter = nforce2_adapter; smbus->adapter.algo_data = smbus; smbus->adapter.dev.parent = &dev->dev; snprintf(smbus->adapter.name, I2C_NAME_SIZE, diff --git a/trunk/drivers/i2c/busses/i2c-omap.c b/trunk/drivers/i2c/busses/i2c-omap.c index bcd8367cede1..dec04da0455c 100644 --- a/trunk/drivers/i2c/busses/i2c-omap.c +++ b/trunk/drivers/i2c/busses/i2c-omap.c @@ -231,8 +231,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) * 13 2 1 * 19.2 2 1 */ - if (fclk_rate > 12000000) - psc = fclk_rate / 12000000; + if (fclk_rate > 16000000) + psc = (fclk_rate + 8000000) / 12000000; } /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ diff --git a/trunk/drivers/i2c/busses/i2c-parport-light.c b/trunk/drivers/i2c/busses/i2c-parport-light.c index 4bc42810b9aa..5eb2bd294fd9 100644 --- a/trunk/drivers/i2c/busses/i2c-parport-light.c +++ b/trunk/drivers/i2c/busses/i2c-parport-light.c @@ -163,7 +163,7 @@ static void __exit i2c_parport_exit(void) if (adapter_parm[type].init.val) line_set(0, &adapter_parm[type].init); - i2c_del_adapter(&parport_adapter); + i2c_bit_del_bus(&parport_adapter); release_region(base, 3); } diff --git a/trunk/drivers/i2c/busses/i2c-parport.c b/trunk/drivers/i2c/busses/i2c-parport.c index 66696a40c7b5..48a829431c7b 100644 --- a/trunk/drivers/i2c/busses/i2c-parport.c +++ b/trunk/drivers/i2c/busses/i2c-parport.c @@ -218,7 +218,7 @@ static void i2c_parport_detach (struct parport *port) if (adapter_parm[type].init.val) line_set(port, 0, &adapter_parm[type].init); - i2c_del_adapter(&adapter->adapter); + i2c_bit_del_bus(&adapter->adapter); parport_unregister_device(adapter->pdev); if (prev) prev->next = adapter->next; diff --git a/trunk/drivers/i2c/busses/i2c-pca-isa.c b/trunk/drivers/i2c/busses/i2c-pca-isa.c index cc6536a19eca..407840b6a260 100644 --- a/trunk/drivers/i2c/busses/i2c-pca-isa.c +++ b/trunk/drivers/i2c/busses/i2c-pca-isa.c @@ -156,7 +156,7 @@ static int __init pca_isa_init(void) static void pca_isa_exit(void) { - i2c_del_adapter(&pca_isa_ops); + i2c_pca_del_bus(&pca_isa_ops); if (irq > 0) { disable_irq(irq); diff --git a/trunk/drivers/i2c/busses/i2c-pnx.c b/trunk/drivers/i2c/busses/i2c-pnx.c deleted file mode 100644 index de0bca77e926..000000000000 --- a/trunk/drivers/i2c/busses/i2c-pnx.c +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Provides I2C support for Philips PNX010x/PNX4008 boards. - * - * Authors: Dennis Kovalev - * Vitaly Wool - * - * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define I2C_PNX_TIMEOUT 10 /* msec */ -#define I2C_PNX_SPEED_KHZ 100 -#define I2C_PNX_REGION_SIZE 0x100 -#define PNX_DEFAULT_FREQ 13 /* MHz */ - -static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data) -{ - while (timeout > 0 && - (ioread32(I2C_REG_STS(data)) & mstatus_active)) { - mdelay(1); - timeout--; - } - return (timeout <= 0); -} - -static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data) -{ - while (timeout > 0 && - (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) { - mdelay(1); - timeout--; - } - return (timeout <= 0); -} - -static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap) -{ - struct i2c_pnx_algo_data *data = adap->algo_data; - struct timer_list *timer = &data->mif.timer; - int expires = I2C_PNX_TIMEOUT / (1000 / HZ); - - del_timer_sync(timer); - - dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n", - jiffies, expires); - - timer->expires = jiffies + expires; - timer->data = (unsigned long)adap; - - add_timer(timer); -} - -/** - * i2c_pnx_start - start a device - * @slave_addr: slave address - * @adap: pointer to adapter structure - * - * Generate a START signal in the desired mode. - */ -static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) -{ - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - - dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __FUNCTION__, - slave_addr, alg_data->mif.mode); - - /* Check for 7 bit slave addresses only */ - if (slave_addr & ~0x7f) { - dev_err(&adap->dev, "%s: Invalid slave address %x. " - "Only 7-bit addresses are supported\n", - adap->name, slave_addr); - return -EINVAL; - } - - /* First, make sure bus is idle */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) { - /* Somebody else is monopolizing the bus */ - dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, " - "cntrl = %x, stat = %x\n", - adap->name, slave_addr, - ioread32(I2C_REG_CTL(alg_data)), - ioread32(I2C_REG_STS(alg_data))); - return -EBUSY; - } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) { - /* Sorry, we lost the bus */ - dev_err(&adap->dev, "%s: Arbitration failure. " - "Slave addr = %02x\n", adap->name, slave_addr); - return -EIO; - } - - /* - * OK, I2C is enabled and we have the bus. - * Clear the current TDI and AFI status flags. - */ - iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi, - I2C_REG_STS(alg_data)); - - dev_dbg(&adap->dev, "%s(): sending %#x\n", __FUNCTION__, - (slave_addr << 1) | start_bit | alg_data->mif.mode); - - /* Write the slave address, START bit and R/W bit */ - iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode, - I2C_REG_TX(alg_data)); - - dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__); - - return 0; -} - -/** - * i2c_pnx_stop - stop a device - * @adap: pointer to I2C adapter structure - * - * Generate a STOP signal to terminate the master transaction. - */ -static void i2c_pnx_stop(struct i2c_adapter *adap) -{ - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - /* Only 1 msec max timeout due to interrupt context */ - long timeout = 1000; - - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", - __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); - - /* Write a STOP bit to TX FIFO */ - iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data)); - - /* Wait until the STOP is seen. */ - while (timeout > 0 && - (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) { - /* may be called from interrupt context */ - udelay(1); - timeout--; - } - - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", - __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); -} - -/** - * i2c_pnx_master_xmit - transmit data to slave - * @adap: pointer to I2C adapter structure - * - * Sends one byte of data to the slave - */ -static int i2c_pnx_master_xmit(struct i2c_adapter *adap) -{ - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - u32 val; - - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", - __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); - - if (alg_data->mif.len > 0) { - /* We still have something to talk about... */ - val = *alg_data->mif.buf++; - - if (alg_data->mif.len == 1) { - val |= stop_bit; - if (!alg_data->last) - val |= start_bit; - } - - alg_data->mif.len--; - iowrite32(val, I2C_REG_TX(alg_data)); - - dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __FUNCTION__, - val, alg_data->mif.len + 1); - - if (alg_data->mif.len == 0) { - if (alg_data->last) { - /* Wait until the STOP is seen. */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) - dev_err(&adap->dev, "The bus is still " - "active after timeout\n"); - } - /* Disable master interrupts */ - iowrite32(ioread32(I2C_REG_CTL(alg_data)) & - ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie), - I2C_REG_CTL(alg_data)); - - del_timer_sync(&alg_data->mif.timer); - - dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n", - __FUNCTION__); - - complete(&alg_data->mif.complete); - } - } else if (alg_data->mif.len == 0) { - /* zero-sized transfer */ - i2c_pnx_stop(adap); - - /* Disable master interrupts. */ - iowrite32(ioread32(I2C_REG_CTL(alg_data)) & - ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie), - I2C_REG_CTL(alg_data)); - - /* Stop timer. */ - del_timer_sync(&alg_data->mif.timer); - dev_dbg(&adap->dev, "%s(): Waking up xfer routine after " - "zero-xfer.\n", __FUNCTION__); - - complete(&alg_data->mif.complete); - } - - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", - __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); - - return 0; -} - -/** - * i2c_pnx_master_rcv - receive data from slave - * @adap: pointer to I2C adapter structure - * - * Reads one byte data from the slave - */ -static int i2c_pnx_master_rcv(struct i2c_adapter *adap) -{ - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - unsigned int val = 0; - u32 ctl = 0; - - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", - __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); - - /* Check, whether there is already data, - * or we didn't 'ask' for it yet. - */ - if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { - dev_dbg(&adap->dev, "%s(): Write dummy data to fill " - "Rx-fifo...\n", __FUNCTION__); - - if (alg_data->mif.len == 1) { - /* Last byte, do not acknowledge next rcv. */ - val |= stop_bit; - if (!alg_data->last) - val |= start_bit; - - /* - * Enable interrupt RFDAIE (data in Rx fifo), - * and disable DRMIE (need data for Tx) - */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl |= mcntrl_rffie | mcntrl_daie; - ctl &= ~mcntrl_drmie; - iowrite32(ctl, I2C_REG_CTL(alg_data)); - } - - /* - * Now we'll 'ask' for data: - * For each byte we want to receive, we must - * write a (dummy) byte to the Tx-FIFO. - */ - iowrite32(val, I2C_REG_TX(alg_data)); - - return 0; - } - - /* Handle data. */ - if (alg_data->mif.len > 0) { - val = ioread32(I2C_REG_RX(alg_data)); - *alg_data->mif.buf++ = (u8) (val & 0xff); - dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __FUNCTION__, val, - alg_data->mif.len); - - alg_data->mif.len--; - if (alg_data->mif.len == 0) { - if (alg_data->last) - /* Wait until the STOP is seen. */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) - dev_err(&adap->dev, "The bus is still " - "active after timeout\n"); - - /* Disable master interrupts */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | - mcntrl_drmie | mcntrl_daie); - iowrite32(ctl, I2C_REG_CTL(alg_data)); - - /* Kill timer. */ - del_timer_sync(&alg_data->mif.timer); - complete(&alg_data->mif.complete); - } - } - - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", - __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); - - return 0; -} - -static irqreturn_t -i2c_pnx_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - u32 stat, ctl; - struct i2c_adapter *adap = dev_id; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - - dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n", - __FUNCTION__, - ioread32(I2C_REG_STS(alg_data)), - ioread32(I2C_REG_CTL(alg_data)), - alg_data->mif.mode); - stat = ioread32(I2C_REG_STS(alg_data)); - - /* let's see what kind of event this is */ - if (stat & mstatus_afi) { - /* We lost arbitration in the midst of a transfer */ - alg_data->mif.ret = -EIO; - - /* Disable master interrupts. */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | - mcntrl_drmie); - iowrite32(ctl, I2C_REG_CTL(alg_data)); - - /* Stop timer, to prevent timeout. */ - del_timer_sync(&alg_data->mif.timer); - complete(&alg_data->mif.complete); - } else if (stat & mstatus_nai) { - /* Slave did not acknowledge, generate a STOP */ - dev_dbg(&adap->dev, "%s(): " - "Slave did not acknowledge, generating a STOP.\n", - __FUNCTION__); - i2c_pnx_stop(adap); - - /* Disable master interrupts. */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | - mcntrl_drmie); - iowrite32(ctl, I2C_REG_CTL(alg_data)); - - /* Our return value. */ - alg_data->mif.ret = -EIO; - - /* Stop timer, to prevent timeout. */ - del_timer_sync(&alg_data->mif.timer); - complete(&alg_data->mif.complete); - } else { - /* - * Two options: - * - Master Tx needs data. - * - There is data in the Rx-fifo - * The latter is only the case if we have requested for data, - * via a dummy write. (See 'i2c_pnx_master_rcv'.) - * We therefore check, as a sanity check, whether that interrupt - * has been enabled. - */ - if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) { - if (alg_data->mif.mode == I2C_SMBUS_WRITE) { - i2c_pnx_master_xmit(adap); - } else if (alg_data->mif.mode == I2C_SMBUS_READ) { - i2c_pnx_master_rcv(adap); - } - } - } - - /* Clear TDI and AFI bits */ - stat = ioread32(I2C_REG_STS(alg_data)); - iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data)); - - dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n", - __FUNCTION__, ioread32(I2C_REG_STS(alg_data)), - ioread32(I2C_REG_CTL(alg_data))); - - return IRQ_HANDLED; -} - -static void i2c_pnx_timeout(unsigned long data) -{ - struct i2c_adapter *adap = (struct i2c_adapter *)data; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - u32 ctl; - - dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. " - "Resetting master...\n", - ioread32(I2C_REG_STS(alg_data)), - ioread32(I2C_REG_CTL(alg_data))); - - /* Reset master and disable interrupts */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie); - iowrite32(ctl, I2C_REG_CTL(alg_data)); - - ctl |= mcntrl_reset; - iowrite32(ctl, I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); - alg_data->mif.ret = -EIO; - complete(&alg_data->mif.complete); -} - -static inline void bus_reset_if_active(struct i2c_adapter *adap) -{ - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - u32 stat; - - if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) { - dev_err(&adap->dev, - "%s: Bus is still active after xfer. Reset it...\n", - adap->name); - iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, - I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); - } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) { - /* If there is data in the fifo's after transfer, - * flush fifo's by reset. - */ - iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, - I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); - } else if (stat & mstatus_nai) { - iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, - I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); - } -} - -/** - * i2c_pnx_xfer - generic transfer entry point - * @adap: pointer to I2C adapter structure - * @msgs: array of messages - * @num: number of messages - * - * Initiates the transfer - */ -static int -i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct i2c_msg *pmsg; - int rc = 0, completed = 0, i; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - u32 stat = ioread32(I2C_REG_STS(alg_data)); - - dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n", - __FUNCTION__, num, ioread32(I2C_REG_STS(alg_data))); - - bus_reset_if_active(adap); - - /* Process transactions in a loop. */ - for (i = 0; rc >= 0 && i < num; i++) { - u8 addr; - - pmsg = &msgs[i]; - addr = pmsg->addr; - - if (pmsg->flags & I2C_M_TEN) { - dev_err(&adap->dev, - "%s: 10 bits addr not supported!\n", - adap->name); - rc = -EINVAL; - break; - } - - alg_data->mif.buf = pmsg->buf; - alg_data->mif.len = pmsg->len; - alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ? - I2C_SMBUS_READ : I2C_SMBUS_WRITE; - alg_data->mif.ret = 0; - alg_data->last = (i == num - 1); - - dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __FUNCTION__, - alg_data->mif.mode, - alg_data->mif.len); - - i2c_pnx_arm_timer(adap); - - /* initialize the completion var */ - init_completion(&alg_data->mif.complete); - - /* Enable master interrupt */ - iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie | - mcntrl_naie | mcntrl_drmie, - I2C_REG_CTL(alg_data)); - - /* Put start-code and slave-address on the bus. */ - rc = i2c_pnx_start(addr, adap); - if (rc < 0) - break; - - /* Wait for completion */ - wait_for_completion(&alg_data->mif.complete); - - if (!(rc = alg_data->mif.ret)) - completed++; - dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n", - __FUNCTION__, rc); - - /* Clear TDI and AFI bits in case they are set. */ - if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) { - dev_dbg(&adap->dev, - "%s: TDI still set... clearing now.\n", - adap->name); - iowrite32(stat, I2C_REG_STS(alg_data)); - } - if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) { - dev_dbg(&adap->dev, - "%s: AFI still set... clearing now.\n", - adap->name); - iowrite32(stat, I2C_REG_STS(alg_data)); - } - } - - bus_reset_if_active(adap); - - /* Cleanup to be sure... */ - alg_data->mif.buf = NULL; - alg_data->mif.len = 0; - - dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n", - __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); - - if (completed != num) - return ((rc < 0) ? rc : -EREMOTEIO); - - return num; -} - -static u32 i2c_pnx_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm pnx_algorithm = { - .master_xfer = i2c_pnx_xfer, - .functionality = i2c_pnx_func, -}; - -static int i2c_pnx_controller_suspend(struct platform_device *pdev, - pm_message_t state) -{ - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - return i2c_pnx->suspend(pdev, state); -} - -static int i2c_pnx_controller_resume(struct platform_device *pdev) -{ - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - return i2c_pnx->resume(pdev); -} - -static int __devinit i2c_pnx_probe(struct platform_device *pdev) -{ - unsigned long tmp; - int ret = 0; - struct i2c_pnx_algo_data *alg_data; - int freq_mhz; - struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data; - - if (!i2c_pnx || !i2c_pnx->adapter) { - dev_err(&pdev->dev, "%s: no platform data supplied\n", - __FUNCTION__); - ret = -EINVAL; - goto out; - } - - platform_set_drvdata(pdev, i2c_pnx); - - if (i2c_pnx->calculate_input_freq) - freq_mhz = i2c_pnx->calculate_input_freq(pdev); - else { - freq_mhz = PNX_DEFAULT_FREQ; - dev_info(&pdev->dev, "Setting bus frequency to default value: " - "%d MHz", freq_mhz); - } - - i2c_pnx->adapter->algo = &pnx_algorithm; - - alg_data = i2c_pnx->adapter->algo_data; - init_timer(&alg_data->mif.timer); - alg_data->mif.timer.function = i2c_pnx_timeout; - alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter; - - /* Register I/O resource */ - if (!request_region(alg_data->base, I2C_PNX_REGION_SIZE, pdev->name)) { - dev_err(&pdev->dev, - "I/O region 0x%08x for I2C already in use.\n", - alg_data->base); - ret = -ENODEV; - goto out_drvdata; - } - - if (!(alg_data->ioaddr = - (u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) { - dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n"); - ret = -ENOMEM; - goto out_release; - } - - i2c_pnx->set_clock_run(pdev); - - /* - * Clock Divisor High This value is the number of system clocks - * the serial clock (SCL) will be high. - * For example, if the system clock period is 50 ns and the maximum - * desired serial period is 10000 ns (100 kHz), then CLKHI would be - * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value - * programmed into CLKHI will vary from this slightly due to - * variations in the output pad's rise and fall times as well as - * the deglitching filter length. - */ - - tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; - iowrite32(tmp, I2C_REG_CKH(alg_data)); - iowrite32(tmp, I2C_REG_CKL(alg_data)); - - iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data)); - if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) { - ret = -ENODEV; - goto out_unmap; - } - init_completion(&alg_data->mif.complete); - - ret = request_irq(alg_data->irq, i2c_pnx_interrupt, - 0, pdev->name, i2c_pnx->adapter); - if (ret) - goto out_clock; - - /* Register this adapter with the I2C subsystem */ - i2c_pnx->adapter->dev.parent = &pdev->dev; - ret = i2c_add_adapter(i2c_pnx->adapter); - if (ret < 0) { - dev_err(&pdev->dev, "I2C: Failed to add bus\n"); - goto out_irq; - } - - dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", - i2c_pnx->adapter->name, alg_data->base, alg_data->irq); - - return 0; - -out_irq: - free_irq(alg_data->irq, alg_data); -out_clock: - i2c_pnx->set_clock_stop(pdev); -out_unmap: - iounmap((void *)alg_data->ioaddr); -out_release: - release_region(alg_data->base, I2C_PNX_REGION_SIZE); -out_drvdata: - platform_set_drvdata(pdev, NULL); -out: - return ret; -} - -static int __devexit i2c_pnx_remove(struct platform_device *pdev) -{ - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - struct i2c_adapter *adap = i2c_pnx->adapter; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - - free_irq(alg_data->irq, alg_data); - i2c_del_adapter(adap); - i2c_pnx->set_clock_stop(pdev); - iounmap((void *)alg_data->ioaddr); - release_region(alg_data->base, I2C_PNX_REGION_SIZE); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver i2c_pnx_driver = { - .driver = { - .name = "pnx-i2c", - .owner = THIS_MODULE, - }, - .probe = i2c_pnx_probe, - .remove = __devexit_p(i2c_pnx_remove), - .suspend = i2c_pnx_controller_suspend, - .resume = i2c_pnx_controller_resume, -}; - -static int __init i2c_adap_pnx_init(void) -{ - return platform_driver_register(&i2c_pnx_driver); -} - -static void __exit i2c_adap_pnx_exit(void) -{ - platform_driver_unregister(&i2c_pnx_driver); -} - -MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev "); -MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses"); -MODULE_LICENSE("GPL"); - -#ifdef CONFIG_I2C_PNX_EARLY -/* We need to make sure I2C is initialized before USB */ -subsys_initcall(i2c_adap_pnx_init); -#else -mudule_init(i2c_adap_pnx_init); -#endif -module_exit(i2c_adap_pnx_exit); diff --git a/trunk/drivers/i2c/busses/i2c-prosavage.c b/trunk/drivers/i2c/busses/i2c-prosavage.c index 07c1f1e27df1..7745e21874a8 100644 --- a/trunk/drivers/i2c/busses/i2c-prosavage.c +++ b/trunk/drivers/i2c/busses/i2c-prosavage.c @@ -212,7 +212,7 @@ static void prosavage_remove(struct pci_dev *dev) if (chip->i2c_bus[i].adap_ok == 0) continue; - ret = i2c_del_adapter(&chip->i2c_bus[i].adap); + ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap); if (ret) { dev_err(&dev->dev, "%s not removed\n", chip->i2c_bus[i].adap.name); diff --git a/trunk/drivers/i2c/busses/i2c-savage4.c b/trunk/drivers/i2c/busses/i2c-savage4.c index 844b4ff90893..209f47ea1750 100644 --- a/trunk/drivers/i2c/busses/i2c-savage4.c +++ b/trunk/drivers/i2c/busses/i2c-savage4.c @@ -173,7 +173,7 @@ static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_ static void __devexit savage4_remove(struct pci_dev *dev) { - i2c_del_adapter(&savage4_i2c_adapter); + i2c_bit_del_bus(&savage4_i2c_adapter); iounmap(ioaddr); } diff --git a/trunk/drivers/i2c/busses/i2c-versatile.c b/trunk/drivers/i2c/busses/i2c-versatile.c deleted file mode 100644 index 081d9578ce10..000000000000 --- a/trunk/drivers/i2c/busses/i2c-versatile.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * i2c-versatile.c - * - * Copyright (C) 2006 ARM Ltd. - * written by Russell King, Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include - -#include - -#define I2C_CONTROL 0x00 -#define I2C_CONTROLS 0x00 -#define I2C_CONTROLC 0x04 -#define SCL (1 << 0) -#define SDA (1 << 1) - -struct i2c_versatile { - struct i2c_adapter adap; - struct i2c_algo_bit_data algo; - void __iomem *base; -}; - -static void i2c_versatile_setsda(void *data, int state) -{ - struct i2c_versatile *i2c = data; - - writel(SDA, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC)); -} - -static void i2c_versatile_setscl(void *data, int state) -{ - struct i2c_versatile *i2c = data; - - writel(SCL, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC)); -} - -static int i2c_versatile_getsda(void *data) -{ - struct i2c_versatile *i2c = data; - return !!(readl(i2c->base + I2C_CONTROL) & SDA); -} - -static int i2c_versatile_getscl(void *data) -{ - struct i2c_versatile *i2c = data; - return !!(readl(i2c->base + I2C_CONTROL) & SCL); -} - -static struct i2c_algo_bit_data i2c_versatile_algo = { - .setsda = i2c_versatile_setsda, - .setscl = i2c_versatile_setscl, - .getsda = i2c_versatile_getsda, - .getscl = i2c_versatile_getscl, - .udelay = 30, - .timeout = HZ, -}; - -static int i2c_versatile_probe(struct platform_device *dev) -{ - struct i2c_versatile *i2c; - struct resource *r; - int ret; - - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!r) { - ret = -EINVAL; - goto err_out; - } - - if (!request_mem_region(r->start, r->end - r->start + 1, "versatile-i2c")) { - ret = -EBUSY; - goto err_out; - } - - i2c = kzalloc(sizeof(struct i2c_versatile), GFP_KERNEL); - if (!i2c) { - ret = -ENOMEM; - goto err_release; - } - - i2c->base = ioremap(r->start, r->end - r->start + 1); - if (!i2c->base) { - ret = -ENOMEM; - goto err_free; - } - - writel(SCL | SDA, i2c->base + I2C_CONTROLS); - - i2c->adap.owner = THIS_MODULE; - strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name)); - i2c->adap.algo_data = &i2c->algo; - i2c->adap.dev.parent = &dev->dev; - i2c->algo = i2c_versatile_algo; - i2c->algo.data = i2c; - - ret = i2c_bit_add_bus(&i2c->adap); - if (ret >= 0) { - platform_set_drvdata(dev, i2c); - return 0; - } - - iounmap(i2c->base); - err_free: - kfree(i2c); - err_release: - release_mem_region(r->start, r->end - r->start + 1); - err_out: - return ret; -} - -static int i2c_versatile_remove(struct platform_device *dev) -{ - struct i2c_versatile *i2c = platform_get_drvdata(dev); - - platform_set_drvdata(dev, NULL); - - i2c_del_adapter(&i2c->adap); - return 0; -} - -static struct platform_driver i2c_versatile_driver = { - .probe = i2c_versatile_probe, - .remove = i2c_versatile_remove, - .driver = { - .name = "versatile-i2c", - .owner = THIS_MODULE, - }, -}; - -static int __init i2c_versatile_init(void) -{ - return platform_driver_register(&i2c_versatile_driver); -} - -static void __exit i2c_versatile_exit(void) -{ - platform_driver_unregister(&i2c_versatile_driver); -} - -module_init(i2c_versatile_init); -module_exit(i2c_versatile_exit); - -MODULE_DESCRIPTION("ARM Versatile I2C bus driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/i2c/busses/i2c-via.c b/trunk/drivers/i2c/busses/i2c-via.c index 15d7e00e47e6..910e200ad500 100644 --- a/trunk/drivers/i2c/busses/i2c-via.c +++ b/trunk/drivers/i2c/busses/i2c-via.c @@ -151,7 +151,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i static void __devexit vt586b_remove(struct pci_dev *dev) { - i2c_del_adapter(&vt586b_adapter); + i2c_bit_del_bus(&vt586b_adapter); release_region(I2C_DIR, IOSPACE); pm_io_base = 0; } diff --git a/trunk/drivers/i2c/busses/i2c-voodoo3.c b/trunk/drivers/i2c/busses/i2c-voodoo3.c index b0377b81744b..6c8d25183382 100644 --- a/trunk/drivers/i2c/busses/i2c-voodoo3.c +++ b/trunk/drivers/i2c/busses/i2c-voodoo3.c @@ -211,14 +211,14 @@ static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_ return retval; retval = i2c_bit_add_bus(&voodoo3_ddc_adapter); if (retval) - i2c_del_adapter(&voodoo3_i2c_adapter); + i2c_bit_del_bus(&voodoo3_i2c_adapter); return retval; } static void __devexit voodoo3_remove(struct pci_dev *dev) { - i2c_del_adapter(&voodoo3_i2c_adapter); - i2c_del_adapter(&voodoo3_ddc_adapter); + i2c_bit_del_bus(&voodoo3_i2c_adapter); + i2c_bit_del_bus(&voodoo3_ddc_adapter); iounmap(ioaddr); } diff --git a/trunk/drivers/i2c/busses/scx200_i2c.c b/trunk/drivers/i2c/busses/scx200_i2c.c index 6cd96e43aa72..8ddbae4fafe6 100644 --- a/trunk/drivers/i2c/busses/scx200_i2c.c +++ b/trunk/drivers/i2c/busses/scx200_i2c.c @@ -116,7 +116,7 @@ static int scx200_i2c_init(void) static void scx200_i2c_cleanup(void) { - i2c_del_adapter(&scx200_i2c_ops); + i2c_bit_del_bus(&scx200_i2c_ops); } module_init(scx200_i2c_init); diff --git a/trunk/drivers/i2c/chips/ds1337.c b/trunk/drivers/i2c/chips/ds1337.c index ec17d6b684a2..93d483b8b770 100644 --- a/trunk/drivers/i2c/chips/ds1337.c +++ b/trunk/drivers/i2c/chips/ds1337.c @@ -347,19 +347,13 @@ static void ds1337_init_client(struct i2c_client *client) if ((status & 0x80) || (control & 0x80)) { /* RTC not running */ - u8 buf[1+16]; /* First byte is interpreted as address */ + u8 buf[16]; struct i2c_msg msg[1]; dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__); /* Initialize all, including STATUS and CONTROL to zero */ memset(buf, 0, sizeof(buf)); - - /* Write valid values in the date/time registers */ - buf[1+DS1337_REG_DAY] = 1; - buf[1+DS1337_REG_DATE] = 1; - buf[1+DS1337_REG_MONTH] = 1; - msg[0].addr = client->addr; msg[0].flags = 0; msg[0].len = sizeof(buf); diff --git a/trunk/drivers/i2c/chips/tps65010.c b/trunk/drivers/i2c/chips/tps65010.c index 4ee56def61f2..60bef94cd25f 100644 --- a/trunk/drivers/i2c/chips/tps65010.c +++ b/trunk/drivers/i2c/chips/tps65010.c @@ -82,7 +82,7 @@ struct tps65010 { struct i2c_client client; struct mutex lock; int irq; - struct delayed_work work; + struct work_struct work; struct dentry *file; unsigned charging:1; unsigned por:1; @@ -328,7 +328,7 @@ static void tps65010_interrupt(struct tps65010 *tps) { u8 tmp = 0, mask, poll; - /* IRQs won't trigger for certain events, but we can get + /* IRQs won't trigger irqs for certain events, but we can get * others by polling (normally, with external power applied). */ poll = 0; @@ -411,11 +411,10 @@ static void tps65010_interrupt(struct tps65010 *tps) } /* handle IRQs and polling using keventd for now */ -static void tps65010_work(struct work_struct *work) +static void tps65010_work(void *_tps) { - struct tps65010 *tps; + struct tps65010 *tps = _tps; - tps = container_of(work, struct tps65010, work.work); mutex_lock(&tps->lock); tps65010_interrupt(tps); @@ -453,7 +452,7 @@ static irqreturn_t tps65010_irq(int irq, void *_tps) disable_irq_nosync(irq); set_bit(FLAG_IRQ_ENABLE, &tps->flags); - (void) schedule_work(&tps->work.work); + (void) schedule_work(&tps->work); return IRQ_HANDLED; } @@ -466,15 +465,13 @@ static int __exit tps65010_detach_client(struct i2c_client *client) struct tps65010 *tps; tps = container_of(client, struct tps65010, client); - free_irq(tps->irq, tps); #ifdef CONFIG_ARM if (machine_is_omap_h2()) omap_free_gpio(58); if (machine_is_omap_osk()) omap_free_gpio(OMAP_MPUIO(1)); #endif - cancel_delayed_work(&tps->work); - flush_scheduled_work(); + free_irq(tps->irq, tps); debugfs_remove(tps->file); if (i2c_detach_client(client) == 0) kfree(tps); @@ -508,7 +505,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) return 0; mutex_init(&tps->lock); - INIT_DELAYED_WORK(&tps->work, tps65010_work); + INIT_WORK(&tps->work, tps65010_work, tps); tps->irq = -1; tps->client.addr = address; tps->client.adapter = bus; @@ -623,7 +620,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) (void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK3, 0x0f | i2c_smbus_read_byte_data(&tps->client, TPS_MASK3)); - tps65010_work(&tps->work.work); + tps65010_work(tps); tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL, tps, DEBUG_FOPS); @@ -675,7 +672,7 @@ int tps65010_set_vbus_draw(unsigned mA) && test_and_set_bit( FLAG_VBUS_CHANGED, &the_tps->flags)) { /* gadget drivers call this in_irq() */ - (void) schedule_work(&the_tps->work.work); + (void) schedule_work(&the_tps->work); } local_irq_restore(flags); diff --git a/trunk/drivers/i2c/i2c-core.c b/trunk/drivers/i2c/i2c-core.c index 3e31f1d265c9..7ca81f42d14b 100644 --- a/trunk/drivers/i2c/i2c-core.c +++ b/trunk/drivers/i2c/i2c-core.c @@ -127,17 +127,20 @@ static ssize_t show_client_name(struct device *dev, struct device_attribute *att return sprintf(buf, "%s\n", client->name); } -/* - * We can't use the DEVICE_ATTR() macro here, as we used the same name for - * an i2c adapter attribute (above). +/* + * We can't use the DEVICE_ATTR() macro here as we want the same filename for a + * different type of a device. So beware if the DEVICE_ATTR() macro ever + * changes, this definition will also have to change. */ -static struct device_attribute dev_attr_client_name = - __ATTR(name, S_IRUGO, &show_client_name, NULL); +static struct device_attribute dev_attr_client_name = { + .attr = {.name = "name", .mode = S_IRUGO, .owner = THIS_MODULE }, + .show = &show_client_name, +}; /* --------------------------------------------------- - * registering functions - * --------------------------------------------------- + * registering functions + * --------------------------------------------------- */ /* ----- @@ -311,7 +314,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) res = driver_register(&driver->driver); if (res) return res; - + mutex_lock(&core_lists); list_add_tail(&driver->list,&drivers); @@ -335,13 +338,13 @@ int i2c_del_driver(struct i2c_driver *driver) struct list_head *item1, *item2, *_n; struct i2c_client *client; struct i2c_adapter *adap; - + int res = 0; mutex_lock(&core_lists); /* Have a look at each adapter, if clients of this driver are still - * attached. If so, detach them to be able to kill the driver + * attached. If so, detach them to be able to kill the driver * afterwards. */ list_for_each(item1,&adapters) { @@ -416,14 +419,14 @@ int i2c_attach_client(struct i2c_client *client) goto out_unlock; } list_add_tail(&client->list,&adapter->clients); - + client->usage_count = 0; client->dev.parent = &client->adapter->dev; client->dev.driver = &client->driver->driver; client->dev.bus = &i2c_bus_type; client->dev.release = &i2c_client_release; - + snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), "%d-%04x", i2c_adapter_id(adapter), client->addr); dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", @@ -464,7 +467,7 @@ int i2c_detach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; int res = 0; - + if (client->usage_count > 0) { dev_warn(&client->dev, "Client [%s] still busy, " "can't detach\n", client->name); @@ -532,10 +535,10 @@ int i2c_release_client(struct i2c_client *client) __FUNCTION__); return -EPERM; } - + client->usage_count--; i2c_dec_use_client(client); - + return 0; } @@ -600,7 +603,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) } #endif - mutex_lock_nested(&adap->bus_lock, adap->level); + mutex_lock(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); mutex_unlock(&adap->bus_lock); @@ -621,7 +624,7 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count) msg.flags = client->flags & I2C_M_TEN; msg.len = count; msg.buf = (char *)buf; - + ret = i2c_transfer(adap, &msg, 1); /* If everything went ok (i.e. 1 msg transmitted), return #bytes @@ -754,7 +757,7 @@ int i2c_probe(struct i2c_adapter *adapter, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { if (address_data->probe[0] == I2C_CLIENT_END && address_data->normal_i2c[0] == I2C_CLIENT_END) - return 0; + return 0; dev_warn(&adapter->dev, "SMBus Quick command not supported, " "can't probe for chips\n"); @@ -814,7 +817,7 @@ int i2c_probe(struct i2c_adapter *adapter, struct i2c_adapter* i2c_get_adapter(int id) { struct i2c_adapter *adapter; - + mutex_lock(&core_lists); adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); if (adapter && !try_module_get(adapter->owner)) @@ -831,14 +834,14 @@ void i2c_put_adapter(struct i2c_adapter *adap) /* The SMBus parts */ -#define POLY (0x1070U << 3) +#define POLY (0x1070U << 3) static u8 crc8(u16 data) { int i; - + for(i = 0; i < 8; i++) { - if (data & 0x8000) + if (data & 0x8000) data = data ^ POLY; data = data << 1; } @@ -888,13 +891,13 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) rpec, cpec); return -1; } - return 0; + return 0; } s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value) { return i2c_smbus_xfer(client->adapter,client->addr,client->flags, - value,0,I2C_SMBUS_QUICK,NULL); + value,0,I2C_SMBUS_QUICK,NULL); } s32 i2c_smbus_read_byte(struct i2c_client *client) @@ -993,11 +996,11 @@ s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, I2C_SMBUS_I2C_BLOCK_DATA, &data); } -/* Simulate a SMBus command using the i2c protocol +/* Simulate a SMBus command using the i2c protocol No checking of parameters is done! */ -static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, +static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, unsigned short flags, - char read_write, u8 command, int size, + char read_write, u8 command, int size, union i2c_smbus_data * data) { /* So we need to generate a series of msgs. In the case of writing, we @@ -1007,7 +1010,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; int num = read_write == I2C_SMBUS_READ?2:1; - struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, + struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, { addr, flags | I2C_M_RD, 0, msgbuf1 } }; int i; @@ -1100,14 +1103,14 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, if (i) { /* Compute PEC if first message is a write */ if (!(msg[0].flags & I2C_M_RD)) { - if (num == 1) /* Write only */ + if (num == 1) /* Write only */ i2c_smbus_add_pec(&msg[0]); else /* Write followed by read */ partial_pec = i2c_smbus_msg_pec(0, &msg[0]); } /* Ask for PEC if last message is a read */ if (msg[num-1].flags & I2C_M_RD) - msg[num-1].len++; + msg[num-1].len++; } if (i2c_transfer(adapter, msg, num) < 0) @@ -1127,7 +1130,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, case I2C_SMBUS_BYTE_DATA: data->byte = msgbuf1[0]; break; - case I2C_SMBUS_WORD_DATA: + case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_PROC_CALL: data->word = msgbuf1[0] | (msgbuf1[1] << 8); break; @@ -1143,7 +1146,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, - char read_write, u8 command, int size, + char read_write, u8 command, int size, union i2c_smbus_data * data) { s32 res; diff --git a/trunk/drivers/i2c/i2c-dev.c b/trunk/drivers/i2c/i2c-dev.c index ac5bd2a7ca99..2e22a2ffa606 100644 --- a/trunk/drivers/i2c/i2c-dev.c +++ b/trunk/drivers/i2c/i2c-dev.c @@ -1,5 +1,5 @@ /* - i2c-dev.c - i2c-bus driver, char device interface + i2c-dev.c - i2c-bus driver, char device interface Copyright (C) 1995-97 Simon G. Vogl Copyright (C) 1998-99 Frodo Looijaard @@ -90,7 +90,6 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) spin_lock(&i2c_dev_list_lock); list_del(&i2c_dev->list); spin_unlock(&i2c_dev_list_lock); - kfree(i2c_dev); } static ssize_t show_adapter_name(struct device *dev, @@ -173,7 +172,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, switch ( cmd ) { case I2C_SLAVE: case I2C_SLAVE_FORCE: - if ((arg > 0x3ff) || + if ((arg > 0x3ff) || (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) return -EINVAL; if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg)) @@ -194,11 +193,12 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, return 0; case I2C_FUNCS: funcs = i2c_get_functionality(client->adapter); - return put_user(funcs, (unsigned long __user *)arg); + return (copy_to_user((unsigned long __user *)arg, &funcs, + sizeof(unsigned long)))?-EFAULT:0; case I2C_RDWR: - if (copy_from_user(&rdwr_arg, - (struct i2c_rdwr_ioctl_data __user *)arg, + if (copy_from_user(&rdwr_arg, + (struct i2c_rdwr_ioctl_data __user *)arg, sizeof(rdwr_arg))) return -EFAULT; @@ -206,9 +206,9 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, * be sent at once */ if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) return -EINVAL; - + rdwr_pa = (struct i2c_msg *) - kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), + kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL); if (rdwr_pa == NULL) return -ENOMEM; @@ -278,9 +278,9 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, (struct i2c_smbus_ioctl_data __user *) arg, sizeof(struct i2c_smbus_ioctl_data))) return -EFAULT; - if ((data_arg.size != I2C_SMBUS_BYTE) && + if ((data_arg.size != I2C_SMBUS_BYTE) && (data_arg.size != I2C_SMBUS_QUICK) && - (data_arg.size != I2C_SMBUS_BYTE_DATA) && + (data_arg.size != I2C_SMBUS_BYTE_DATA) && (data_arg.size != I2C_SMBUS_WORD_DATA) && (data_arg.size != I2C_SMBUS_PROC_CALL) && (data_arg.size != I2C_SMBUS_BLOCK_DATA) && @@ -291,11 +291,11 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, data_arg.size); return -EINVAL; } - /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, + /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, so the check is valid if size==I2C_SMBUS_QUICK too. */ - if ((data_arg.read_write != I2C_SMBUS_READ) && + if ((data_arg.read_write != I2C_SMBUS_READ) && (data_arg.read_write != I2C_SMBUS_WRITE)) { - dev_dbg(&client->adapter->dev, + dev_dbg(&client->adapter->dev, "read_write out of range (%x) in ioctl I2C_SMBUS.\n", data_arg.read_write); return -EINVAL; @@ -304,7 +304,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, /* Note that command values are always valid! */ if ((data_arg.size == I2C_SMBUS_QUICK) || - ((data_arg.size == I2C_SMBUS_BYTE) && + ((data_arg.size == I2C_SMBUS_BYTE) && (data_arg.read_write == I2C_SMBUS_WRITE))) /* These are special: we do not use data */ return i2c_smbus_xfer(client->adapter, client->addr, @@ -322,14 +322,14 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || (data_arg.size == I2C_SMBUS_BYTE)) datasize = sizeof(data_arg.data->byte); - else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || + else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || (data_arg.size == I2C_SMBUS_PROC_CALL)) datasize = sizeof(data_arg.data->word); else /* size == smbus block, i2c block, or block proc. call */ datasize = sizeof(data_arg.data->block); - if ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || + if ((data_arg.size == I2C_SMBUS_PROC_CALL) || + (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || (data_arg.read_write == I2C_SMBUS_WRITE)) { if (copy_from_user(&temp, data_arg.data, datasize)) return -EFAULT; @@ -337,8 +337,8 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, res = i2c_smbus_xfer(client->adapter,client->addr,client->flags, data_arg.read_write, data_arg.command,data_arg.size,&temp); - if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || + if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || + (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || (data_arg.read_write == I2C_SMBUS_READ))) { if (copy_to_user(data_arg.data, &temp, datasize)) return -EFAULT; @@ -417,8 +417,8 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, MKDEV(I2C_MAJOR, adap->nr), "i2c-%d", adap->nr); - if (IS_ERR(i2c_dev->dev)) { - res = PTR_ERR(i2c_dev->dev); + if (!i2c_dev->dev) { + res = -ENODEV; goto error; } res = device_create_file(i2c_dev->dev, &dev_attr_name); @@ -432,6 +432,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); error: return_i2c_dev(i2c_dev); + kfree(i2c_dev); return res; } @@ -446,6 +447,7 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) device_remove_file(i2c_dev->dev, &dev_attr_name); return_i2c_dev(i2c_dev); device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); + kfree(i2c_dev); pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); return 0; diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index 3f828052f8d2..e23bc0d62159 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -796,7 +796,7 @@ endchoice config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ int "Maximum transfer size (KB) per request (up to 128)" default "128" - depends on BLK_DEV_IDE_AU1XXX + depends BLK_DEV_IDE_AU1XXX config IDE_ARM def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c index 5969cec58dc1..88214943d00a 100644 --- a/trunk/drivers/ide/ide-cd.c +++ b/trunk/drivers/ide/ide-cd.c @@ -687,15 +687,8 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) { struct request *rq = HWGROUP(drive)->rq; - ide_hwif_t *hwif = HWIF(drive); int stat, err, sense_key; - /* We may have bogus DMA interrupts in PIO state here */ - if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) { - stat = hwif->INB(hwif->dma_status); - /* Should we force the bit as well ? */ - hwif->OUTB(stat, hwif->dma_status); - } /* Check for errors. */ stat = HWIF(drive)->INB(IDE_STATUS_REG); if (stat_ret) diff --git a/trunk/drivers/ide/ide-floppy.c b/trunk/drivers/ide/ide-floppy.c index d33717c8afd4..e3a267622bb6 100644 --- a/trunk/drivers/ide/ide-floppy.c +++ b/trunk/drivers/ide/ide-floppy.c @@ -2147,7 +2147,7 @@ static int ide_floppy_probe(ide_drive_t *drive) printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name); goto failed; } - if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { + if ((floppy = (idefloppy_floppy_t *) kzalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); goto failed; } diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 5a5c565a32a8..dad9c47ebb69 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -1000,6 +1000,10 @@ static int ide_init_queue(ide_drive_t *drive) /* needs drive->queue to be set */ ide_toggle_bounce(drive, 1); + /* enable led activity for disk drives only */ + if (drive->media == ide_disk && hwif->led_act) + blk_queue_activity_fn(q, hwif->led_act, drive); + return 0; } diff --git a/trunk/drivers/ide/ide-tape.c b/trunk/drivers/ide/ide-tape.c index b3bcd1d7315e..e2f4bb549063 100644 --- a/trunk/drivers/ide/ide-tape.c +++ b/trunk/drivers/ide/ide-tape.c @@ -2573,11 +2573,11 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, int pages = tape->pages_per_stage; char *b_data = NULL; - if ((stage = kmalloc(sizeof (idetape_stage_t),GFP_KERNEL)) == NULL) + if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL) return NULL; stage->next = NULL; - bh = stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); + bh = stage->bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); if (bh == NULL) goto abort; bh->b_reqnext = NULL; @@ -2607,7 +2607,7 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, continue; } prev_bh = bh; - if ((bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) { + if ((bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) { free_page((unsigned long) b_data); goto abort; } @@ -4860,7 +4860,7 @@ static int ide_tape_probe(ide_drive_t *drive) printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name); printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n"); } - tape = kzalloc(sizeof (idetape_tape_t), GFP_KERNEL); + tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL); if (tape == NULL) { printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); goto failed; diff --git a/trunk/drivers/ide/pci/hpt366.c b/trunk/drivers/ide/pci/hpt366.c index 08119da06d54..e993a51f250e 100644 --- a/trunk/drivers/ide/pci/hpt366.c +++ b/trunk/drivers/ide/pci/hpt366.c @@ -4,7 +4,6 @@ * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc - * Portions Copyright (C) 2005-2006 MontaVista Software, Inc. * * Thanks to HighPoint Technologies for their assistance, and hardware. * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his @@ -12,11 +11,9 @@ * development and support. * * - * HighPoint has its own drivers (open source except for the RAID part) - * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/. - * This may be useful to anyone wanting to work on this driver, however do not - * trust them too much since the code tends to become less and less meaningful - * as the time passes... :-/ + * Highpoint have their own driver (source except for the raid part) + * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz + * This may be useful to anyone wanting to work on the mainstream hpt IDE. * * Note that final HPT370 support was done by force extraction of GPL. * @@ -55,29 +52,6 @@ * keeping me sane. * Alan Cox * - * - fix the clock turnaround code: it was writing to the wrong ports when - * called for the secondary channel, caching the current clock mode per- - * channel caused the cached register value to get out of sync with the - * actual one, the channels weren't serialized, the turnaround shouldn't - * be done on 66 MHz PCI bus - * - avoid calibrating PLL twice as the second time results in a wrong PCI - * frequency and thus in the wrong timings for the secondary channel - * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not - * allow for this speed anyway) - * - add support for HPT302N and HPT371N clocking (the same as for HPT372N) - * - HPT371/N are single channel chips, so avoid touching the primary channel - * which exists only virtually (there's no pins for it) - * - fix/remove bad/unused timing tables and use one set of tables for the whole - * HPT37x chip family; save space by introducing the separate transfer mode - * table in which the mode lookup is done - * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives - * the wrong PCI frequency since DPLL has already been calibrated by BIOS - * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, - * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead - * - pass to init_chipset() handlers a copy of the IDE PCI device structure as - * they tamper with its fields - * - * */ @@ -102,8 +76,8 @@ /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE -#undef HPT_DELAY_INTERRUPT -#define HPT_SERIALIZE_IO 0 +#undef HPT_DELAY_INTERRUPT +#undef HPT_SERIALIZE_IO static const char *quirk_drives[] = { "QUANTUM FIREBALLlct08 08", @@ -167,175 +141,305 @@ static const char *bad_ata33[] = { NULL }; -static u8 xfer_speeds[] = { - XFER_UDMA_6, - XFER_UDMA_5, - XFER_UDMA_4, - XFER_UDMA_3, - XFER_UDMA_2, - XFER_UDMA_1, - XFER_UDMA_0, - - XFER_MW_DMA_2, - XFER_MW_DMA_1, - XFER_MW_DMA_0, - - XFER_PIO_4, - XFER_PIO_3, - XFER_PIO_2, - XFER_PIO_1, - XFER_PIO_0 +struct chipset_bus_clock_list_entry { + u8 xfer_speed; + unsigned int chipset_settings; }; -/* Key for bus clock timings - * 36x 37x - * bits bits - * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA. - * cycles = value + 1 - * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA. - * cycles = value + 1 - * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file - * register access. - * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file - * register access. - * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer. - * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock. - * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and - * MW DMA xfer. - * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for - * task file register access. - * 28 28 UDMA enable. - * 29 29 DMA enable. - * 30 30 PIO MST enable. If set, the chip is in bus master mode during - * PIO xfer. - * 31 31 FIFO enable. +/* key for bus clock timings + * bit + * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW + * DMA. cycles = value + 1 + * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW + * DMA. cycles = value + 1 + * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file + * register access. + * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file + * register access. + * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. + * during task file register access. + * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA + * xfer. + * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task + * register access. + * 28 UDMA enable + * 29 DMA enable + * 30 PIO_MST enable. if set, the chip is in bus master mode during + * PIO. + * 31 FIFO enable. */ +static struct chipset_bus_clock_list_entry forty_base_hpt366[] = { + { XFER_UDMA_4, 0x900fd943 }, + { XFER_UDMA_3, 0x900ad943 }, + { XFER_UDMA_2, 0x900bd943 }, + { XFER_UDMA_1, 0x9008d943 }, + { XFER_UDMA_0, 0x9008d943 }, + + { XFER_MW_DMA_2, 0xa008d943 }, + { XFER_MW_DMA_1, 0xa010d955 }, + { XFER_MW_DMA_0, 0xa010d9fc }, + + { XFER_PIO_4, 0xc008d963 }, + { XFER_PIO_3, 0xc010d974 }, + { XFER_PIO_2, 0xc010d997 }, + { XFER_PIO_1, 0xc010d9c7 }, + { XFER_PIO_0, 0xc018d9d9 }, + { 0, 0x0120d9d9 } +}; + +static struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { + { XFER_UDMA_4, 0x90c9a731 }, + { XFER_UDMA_3, 0x90cfa731 }, + { XFER_UDMA_2, 0x90caa731 }, + { XFER_UDMA_1, 0x90cba731 }, + { XFER_UDMA_0, 0x90c8a731 }, + + { XFER_MW_DMA_2, 0xa0c8a731 }, + { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */ + { XFER_MW_DMA_0, 0xa0c8a797 }, + + { XFER_PIO_4, 0xc0c8a731 }, + { XFER_PIO_3, 0xc0c8a742 }, + { XFER_PIO_2, 0xc0d0a753 }, + { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */ + { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */ + { 0, 0x0120a7a7 } +}; + +static struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { + { XFER_UDMA_4, 0x90c98521 }, + { XFER_UDMA_3, 0x90cf8521 }, + { XFER_UDMA_2, 0x90cf8521 }, + { XFER_UDMA_1, 0x90cb8521 }, + { XFER_UDMA_0, 0x90cb8521 }, + + { XFER_MW_DMA_2, 0xa0ca8521 }, + { XFER_MW_DMA_1, 0xa0ca8532 }, + { XFER_MW_DMA_0, 0xa0ca8575 }, + + { XFER_PIO_4, 0xc0ca8521 }, + { XFER_PIO_3, 0xc0ca8532 }, + { XFER_PIO_2, 0xc0ca8542 }, + { XFER_PIO_1, 0xc0d08572 }, + { XFER_PIO_0, 0xc0d08585 }, + { 0, 0x01208585 } +}; + +/* from highpoint documentation. these are old values */ +static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { +/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ + { XFER_UDMA_5, 0x16454e31 }, + { XFER_UDMA_4, 0x16454e31 }, + { XFER_UDMA_3, 0x166d4e31 }, + { XFER_UDMA_2, 0x16494e31 }, + { XFER_UDMA_1, 0x164d4e31 }, + { XFER_UDMA_0, 0x16514e31 }, + + { XFER_MW_DMA_2, 0x26514e21 }, + { XFER_MW_DMA_1, 0x26514e33 }, + { XFER_MW_DMA_0, 0x26514e97 }, + + { XFER_PIO_4, 0x06514e21 }, + { XFER_PIO_3, 0x06514e22 }, + { XFER_PIO_2, 0x06514e33 }, + { XFER_PIO_1, 0x06914e43 }, + { XFER_PIO_0, 0x06914e57 }, + { 0, 0x06514e57 } +}; + +static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { + { XFER_UDMA_5, 0x14846231 }, + { XFER_UDMA_4, 0x14886231 }, + { XFER_UDMA_3, 0x148c6231 }, + { XFER_UDMA_2, 0x148c6231 }, + { XFER_UDMA_1, 0x14906231 }, + { XFER_UDMA_0, 0x14986231 }, + + { XFER_MW_DMA_2, 0x26514e21 }, + { XFER_MW_DMA_1, 0x26514e33 }, + { XFER_MW_DMA_0, 0x26514e97 }, + + { XFER_PIO_4, 0x06514e21 }, + { XFER_PIO_3, 0x06514e22 }, + { XFER_PIO_2, 0x06514e33 }, + { XFER_PIO_1, 0x06914e43 }, + { XFER_PIO_0, 0x06914e57 }, + { 0, 0x06514e57 } +}; + +/* these are the current (4 sep 2001) timings from highpoint */ +static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { + { XFER_UDMA_5, 0x12446231 }, + { XFER_UDMA_4, 0x12446231 }, + { XFER_UDMA_3, 0x126c6231 }, + { XFER_UDMA_2, 0x12486231 }, + { XFER_UDMA_1, 0x124c6233 }, + { XFER_UDMA_0, 0x12506297 }, + + { XFER_MW_DMA_2, 0x22406c31 }, + { XFER_MW_DMA_1, 0x22406c33 }, + { XFER_MW_DMA_0, 0x22406c97 }, + + { XFER_PIO_4, 0x06414e31 }, + { XFER_PIO_3, 0x06414e42 }, + { XFER_PIO_2, 0x06414e53 }, + { XFER_PIO_1, 0x06814e93 }, + { XFER_PIO_0, 0x06814ea7 }, + { 0, 0x06814ea7 } +}; + +/* 2x 33MHz timings */ +static struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { + { XFER_UDMA_5, 0x1488e673 }, + { XFER_UDMA_4, 0x1488e673 }, + { XFER_UDMA_3, 0x1498e673 }, + { XFER_UDMA_2, 0x1490e673 }, + { XFER_UDMA_1, 0x1498e677 }, + { XFER_UDMA_0, 0x14a0e73f }, + + { XFER_MW_DMA_2, 0x2480fa73 }, + { XFER_MW_DMA_1, 0x2480fa77 }, + { XFER_MW_DMA_0, 0x2480fb3f }, + + { XFER_PIO_4, 0x0c82be73 }, + { XFER_PIO_3, 0x0c82be95 }, + { XFER_PIO_2, 0x0c82beb7 }, + { XFER_PIO_1, 0x0d02bf37 }, + { XFER_PIO_0, 0x0d02bf5f }, + { 0, 0x0d02bf5f } +}; -static u32 forty_base_hpt36x[] = { - /* XFER_UDMA_6 */ 0x900fd943, - /* XFER_UDMA_5 */ 0x900fd943, - /* XFER_UDMA_4 */ 0x900fd943, - /* XFER_UDMA_3 */ 0x900ad943, - /* XFER_UDMA_2 */ 0x900bd943, - /* XFER_UDMA_1 */ 0x9008d943, - /* XFER_UDMA_0 */ 0x9008d943, - - /* XFER_MW_DMA_2 */ 0xa008d943, - /* XFER_MW_DMA_1 */ 0xa010d955, - /* XFER_MW_DMA_0 */ 0xa010d9fc, - - /* XFER_PIO_4 */ 0xc008d963, - /* XFER_PIO_3 */ 0xc010d974, - /* XFER_PIO_2 */ 0xc010d997, - /* XFER_PIO_1 */ 0xc010d9c7, - /* XFER_PIO_0 */ 0xc018d9d9 +static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x0ac1f48a } }; -static u32 thirty_three_base_hpt36x[] = { - /* XFER_UDMA_6 */ 0x90c9a731, - /* XFER_UDMA_5 */ 0x90c9a731, - /* XFER_UDMA_4 */ 0x90c9a731, - /* XFER_UDMA_3 */ 0x90cfa731, - /* XFER_UDMA_2 */ 0x90caa731, - /* XFER_UDMA_1 */ 0x90cba731, - /* XFER_UDMA_0 */ 0x90c8a731, - - /* XFER_MW_DMA_2 */ 0xa0c8a731, - /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */ - /* XFER_MW_DMA_0 */ 0xa0c8a797, - - /* XFER_PIO_4 */ 0xc0c8a731, - /* XFER_PIO_3 */ 0xc0c8a742, - /* XFER_PIO_2 */ 0xc0d0a753, - /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */ - /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */ +static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { + { XFER_UDMA_6, 0x1c81dc62 }, + { XFER_UDMA_5, 0x1c6ddc62 }, + { XFER_UDMA_4, 0x1c8ddc62 }, + { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ + { XFER_UDMA_2, 0x1c91dc62 }, + { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ + { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ + + { XFER_MW_DMA_2, 0x2c829262 }, + { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ + { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ + + { XFER_PIO_4, 0x0c829c62 }, + { XFER_PIO_3, 0x0c829c84 }, + { XFER_PIO_2, 0x0c829ca6 }, + { XFER_PIO_1, 0x0d029d26 }, + { XFER_PIO_0, 0x0d029d5e }, + { 0, 0x0d029d5e } }; -static u32 twenty_five_base_hpt36x[] = { - /* XFER_UDMA_6 */ 0x90c98521, - /* XFER_UDMA_5 */ 0x90c98521, - /* XFER_UDMA_4 */ 0x90c98521, - /* XFER_UDMA_3 */ 0x90cf8521, - /* XFER_UDMA_2 */ 0x90cf8521, - /* XFER_UDMA_1 */ 0x90cb8521, - /* XFER_UDMA_0 */ 0x90cb8521, - - /* XFER_MW_DMA_2 */ 0xa0ca8521, - /* XFER_MW_DMA_1 */ 0xa0ca8532, - /* XFER_MW_DMA_0 */ 0xa0ca8575, - - /* XFER_PIO_4 */ 0xc0ca8521, - /* XFER_PIO_3 */ 0xc0ca8532, - /* XFER_PIO_2 */ 0xc0ca8542, - /* XFER_PIO_1 */ 0xc0d08572, - /* XFER_PIO_0 */ 0xc0d08585 +static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x0a81f443 } }; -static u32 thirty_three_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */ - /* XFER_UDMA_5 */ 0x12446231, - /* XFER_UDMA_4 */ 0x12446231, - /* XFER_UDMA_3 */ 0x126c6231, - /* XFER_UDMA_2 */ 0x12486231, - /* XFER_UDMA_1 */ 0x124c6233, - /* XFER_UDMA_0 */ 0x12506297, - - /* XFER_MW_DMA_2 */ 0x22406c31, - /* XFER_MW_DMA_1 */ 0x22406c33, - /* XFER_MW_DMA_0 */ 0x22406c97, - - /* XFER_PIO_4 */ 0x06414e31, - /* XFER_PIO_3 */ 0x06414e42, - /* XFER_PIO_2 */ 0x06414e53, - /* XFER_PIO_1 */ 0x06814e93, - /* XFER_PIO_0 */ 0x06814ea7 +static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { + { XFER_UDMA_6, 0x1c869c62 }, + { XFER_UDMA_5, 0x1cae9c62 }, + { XFER_UDMA_4, 0x1c8a9c62 }, + { XFER_UDMA_3, 0x1c8e9c62 }, + { XFER_UDMA_2, 0x1c929c62 }, + { XFER_UDMA_1, 0x1c9a9c62 }, + { XFER_UDMA_0, 0x1c829c62 }, + + { XFER_MW_DMA_2, 0x2c829c62 }, + { XFER_MW_DMA_1, 0x2c829c66 }, + { XFER_MW_DMA_0, 0x2c829d2e }, + + { XFER_PIO_4, 0x0c829c62 }, + { XFER_PIO_3, 0x0c829c84 }, + { XFER_PIO_2, 0x0c829ca6 }, + { XFER_PIO_1, 0x0d029d26 }, + { XFER_PIO_0, 0x0d029d5e }, + { 0, 0x0d029d26 } }; -static u32 fifty_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x12848242, - /* XFER_UDMA_5 */ 0x12848242, - /* XFER_UDMA_4 */ 0x12ac8242, - /* XFER_UDMA_3 */ 0x128c8242, - /* XFER_UDMA_2 */ 0x120c8242, - /* XFER_UDMA_1 */ 0x12148254, - /* XFER_UDMA_0 */ 0x121882ea, - - /* XFER_MW_DMA_2 */ 0x22808242, - /* XFER_MW_DMA_1 */ 0x22808254, - /* XFER_MW_DMA_0 */ 0x228082ea, - - /* XFER_PIO_4 */ 0x0a81f442, - /* XFER_PIO_3 */ 0x0a81f443, - /* XFER_PIO_2 */ 0x0a81f454, - /* XFER_PIO_1 */ 0x0ac1f465, - /* XFER_PIO_0 */ 0x0ac1f48a +static struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { + { XFER_UDMA_6, 0x12808242 }, + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x06814e93 } }; -static u32 sixty_six_base_hpt37x[] = { - /* XFER_UDMA_6 */ 0x1c869c62, - /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */ - /* XFER_UDMA_4 */ 0x1c8a9c62, - /* XFER_UDMA_3 */ 0x1c8e9c62, - /* XFER_UDMA_2 */ 0x1c929c62, - /* XFER_UDMA_1 */ 0x1c9a9c62, - /* XFER_UDMA_0 */ 0x1c829c62, - - /* XFER_MW_DMA_2 */ 0x2c829c62, - /* XFER_MW_DMA_1 */ 0x2c829c66, - /* XFER_MW_DMA_0 */ 0x2c829d2e, - - /* XFER_PIO_4 */ 0x0c829c62, - /* XFER_PIO_3 */ 0x0c829c84, - /* XFER_PIO_2 */ 0x0c829ca6, - /* XFER_PIO_1 */ 0x0d029d26, - /* XFER_PIO_0 */ 0x0d029d5e +/* FIXME: 50MHz timings for HPT374 */ + +#if 0 +static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { + { XFER_UDMA_6, 0x12406231 }, /* checkme */ + { XFER_UDMA_5, 0x12446231 }, /* 0x14846231 */ + { XFER_UDMA_4, 0x16814ea7 }, /* 0x14886231 */ + { XFER_UDMA_3, 0x16814ea7 }, /* 0x148c6231 */ + { XFER_UDMA_2, 0x16814ea7 }, /* 0x148c6231 */ + { XFER_UDMA_1, 0x16814ea7 }, /* 0x14906231 */ + { XFER_UDMA_0, 0x16814ea7 }, /* 0x14986231 */ + { XFER_MW_DMA_2, 0x16814ea7 }, /* 0x26514e21 */ + { XFER_MW_DMA_1, 0x16814ea7 }, /* 0x26514e97 */ + { XFER_MW_DMA_0, 0x16814ea7 }, /* 0x26514e97 */ + { XFER_PIO_4, 0x06814ea7 }, /* 0x06514e21 */ + { XFER_PIO_3, 0x06814ea7 }, /* 0x06514e22 */ + { XFER_PIO_2, 0x06814ea7 }, /* 0x06514e33 */ + { XFER_PIO_1, 0x06814ea7 }, /* 0x06914e43 */ + { XFER_PIO_0, 0x06814ea7 }, /* 0x06914e57 */ + { 0, 0x06814ea7 } }; +#endif #define HPT366_DEBUG_DRIVE_INFO 0 #define HPT374_ALLOW_ATA133_6 0 #define HPT371_ALLOW_ATA133_6 0 #define HPT302_ALLOW_ATA133_6 0 -#define HPT372_ALLOW_ATA133_6 0 +#define HPT372_ALLOW_ATA133_6 1 #define HPT370_ALLOW_ATA100_5 1 #define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 @@ -357,10 +461,9 @@ struct hpt_info int revision; /* Chipset revision */ int flags; /* Chipset properties */ #define PLL_MODE 1 -#define IS_3xxN 2 -#define PCI_66MHZ 4 +#define IS_372N 2 /* Speed table */ - u32 *speed; + struct chipset_bus_clock_list_entry *speed; }; /* @@ -497,20 +600,12 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) return 0; } -static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) +static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table) { - int i; - - /* - * Lookup the transfer mode table to get the index into - * the timing table. - * - * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used. - */ - for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) - if (xfer_speeds[i] == speed) - break; - return chipset_table[i]; + for ( ; chipset_table->xfer_speed ; chipset_table++) + if (chipset_table->xfer_speed == speed) + return chipset_table->chipset_settings; + return chipset_table->chipset_settings; } static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) @@ -861,127 +956,156 @@ static int hpt374_ide_dma_end (ide_drive_t *drive) } /** - * hpt3xxn_set_clock - perform clock switching dance - * @hwif: hwif to switch - * @mode: clocking mode (0x21 for write, 0x23 otherwise) + * hpt372n_set_clock - perform clock switching dance + * @drive: Drive to switch + * @mode: Switching mode (0x21 for write, 0x23 otherwise) * - * Switch the DPLL clock on the HPT3xxN devices. This is a right mess. - * NOTE: avoid touching the disabled primary channel on HPT371N -- it - * doesn't physically exist anyway... + * Switch the DPLL clock on the HPT372N devices. This is a + * right mess. */ - -static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) + +static void hpt372n_set_clock(ide_drive_t *drive, int mode) { - u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b); - - if ((scr2 & 0x7f) == mode) - return; - - /* MISC. control register 1 has the channel enable bit... */ - mcr1 = hwif->INB(hwif->dma_master + 0x70); - + ide_hwif_t *hwif = HWIF(drive); + + /* FIXME: should we check for DMA active and BUG() */ /* Tristate the bus */ - if (mcr1 & 0x04) - hwif->OUTB(0x80, hwif->dma_master + 0x73); - hwif->OUTB(0x80, hwif->dma_master + 0x77); - + outb(0x80, hwif->dma_base+0x73); + outb(0x80, hwif->dma_base+0x77); + /* Switch clock and reset channels */ - hwif->OUTB(mode, hwif->dma_master + 0x7b); - hwif->OUTB(0xc0, hwif->dma_master + 0x79); - + outb(mode, hwif->dma_base+0x7B); + outb(0xC0, hwif->dma_base+0x79); + /* Reset state machines */ - if (mcr1 & 0x04) - hwif->OUTB(0x37, hwif->dma_master + 0x70); - hwif->OUTB(0x37, hwif->dma_master + 0x74); - + outb(0x37, hwif->dma_base+0x70); + outb(0x37, hwif->dma_base+0x74); + /* Complete reset */ - hwif->OUTB(0x00, hwif->dma_master + 0x79); - + outb(0x00, hwif->dma_base+0x79); + /* Reconnect channels to bus */ - if (mcr1 & 0x04) - hwif->OUTB(0x00, hwif->dma_master + 0x73); - hwif->OUTB(0x00, hwif->dma_master + 0x77); + outb(0x00, hwif->dma_base+0x73); + outb(0x00, hwif->dma_base+0x77); } /** - * hpt3xxn_rw_disk - prepare for I/O + * hpt372n_rw_disk - prepare for I/O * @drive: drive for command * @rq: block request structure * - * This is called when a disk I/O is issued to HPT3xxN. + * This is called when a disk I/O is issued to the 372N. * We need it because of the clock switching. */ -static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) +static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = drive->hwif; + int wantclock; + + wantclock = rq_data_dir(rq) ? 0x23 : 0x21; + + if (hwif->config_data != wantclock) { + hpt372n_set_clock(drive, wantclock); + hwif->config_data = wantclock; + } +} + +/* + * Since SUN Cobalt is attempting to do this operation, I should disclose + * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date + * HOTSWAP ATA Infrastructure. + */ + +static void hpt3xx_reset (ide_drive_t *drive) +{ +} + +static int hpt3xx_tristate (ide_drive_t * drive, int state) { ide_hwif_t *hwif = HWIF(drive); - u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21; + struct pci_dev *dev = hwif->pci_dev; + u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40; + u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53; + + pci_read_config_byte(dev, 0x59, ®59h); + pci_read_config_byte(dev, state_reg, ®XXh); - hpt3xxn_set_clock(hwif, wantclock); + if (state) { + (void) ide_do_reset(drive); + pci_write_config_byte(dev, state_reg, regXXh|0x80); + pci_write_config_byte(dev, 0x59, reg59h|reset); + } else { + pci_write_config_byte(dev, 0x59, reg59h & ~(reset)); + pci_write_config_byte(dev, state_reg, regXXh & ~(0x80)); + (void) ide_do_reset(drive); + } + return 0; } /* - * Set/get power state for a drive. + * set/get power state for a drive. + * turning the power off does the following things: + * 1) soft-reset the drive + * 2) tri-states the ide bus * - * When we turn the power back on, we need to re-initialize things. + * when we turn things back on, we need to re-initialize things. */ #define TRISTATE_BIT 0x8000 - -static int hpt3xx_busproc(ide_drive_t *drive, int state) +static int hpt370_busproc(ide_drive_t * drive, int state) { ide_hwif_t *hwif = drive->hwif; struct pci_dev *dev = hwif->pci_dev; - u8 tristate, resetmask, bus_reg = 0; - u16 tri_reg = 0; + u8 tristate = 0, resetmask = 0, bus_reg = 0; + u16 tri_reg; hwif->bus_state = state; if (hwif->channel) { /* secondary channel */ - tristate = 0x56; - resetmask = 0x80; + tristate = 0x56; + resetmask = 0x80; } else { /* primary channel */ - tristate = 0x52; + tristate = 0x52; resetmask = 0x40; } - /* Grab the status. */ + /* grab status */ pci_read_config_word(dev, tristate, &tri_reg); pci_read_config_byte(dev, 0x59, &bus_reg); - /* - * Set the state. We don't set it if we don't need to do so. - * Make sure that the drive knows that it has failed if it's off. - */ + /* set the state. we don't set it if we don't need to do so. + * make sure that the drive knows that it has failed if it's off */ switch (state) { case BUSSTATE_ON: - if (!(bus_reg & resetmask)) + hwif->drives[0].failures = 0; + hwif->drives[1].failures = 0; + if ((bus_reg & resetmask) == 0) return 0; - hwif->drives[0].failures = hwif->drives[1].failures = 0; - - pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask); - pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT); - return 0; + tri_reg &= ~TRISTATE_BIT; + bus_reg &= ~resetmask; + break; case BUSSTATE_OFF: - if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT)) + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask)) return 0; tri_reg &= ~TRISTATE_BIT; + bus_reg |= resetmask; break; case BUSSTATE_TRISTATE: - if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT)) + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask)) return 0; tri_reg |= TRISTATE_BIT; + bus_reg |= resetmask; break; - default: - return -EINVAL; } - - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - + pci_write_config_byte(dev, 0x59, bus_reg); pci_write_config_word(dev, tristate, tri_reg); - pci_write_config_byte(dev, 0x59, bus_reg | resetmask); + return 0; } @@ -995,14 +1119,14 @@ static void __devinit hpt366_clocking(ide_hwif_t *hwif) /* detect bus speed by looking at control reg timing: */ switch((reg1 >> 8) & 7) { case 5: - info->speed = forty_base_hpt36x; + info->speed = forty_base_hpt366; break; case 9: - info->speed = twenty_five_base_hpt36x; + info->speed = twenty_five_base_hpt366; break; case 7: default: - info->speed = thirty_three_base_hpt36x; + info->speed = thirty_three_base_hpt366; break; } } @@ -1012,9 +1136,9 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) struct hpt_info *info = ide_get_hwifdata(hwif); struct pci_dev *dev = hwif->pci_dev; int adjust, i; - u16 freq = 0; - u32 pll, temp = 0; - u8 reg5bh = 0, mcr1 = 0; + u16 freq; + u32 pll; + u8 reg5bh; /* * default to pci clock. make sure MA15/16 are set to output @@ -1027,40 +1151,27 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pci_write_config_byte(dev, 0x5b, 0x23); /* - * We'll have to read f_CNT value in order to determine - * the PCI clock frequency according to the following ratio: - * - * f_CNT = Fpci * 192 / Fdpll - * - * First try reading the register in which the HighPoint BIOS - * saves f_CNT value before reprogramming the DPLL from its - * default setting (which differs for the various chips). - * NOTE: This register is only accessible via I/O space. + * set up the PLL. we need to adjust it so that it's stable. + * freq = Tpll * 192 / Tpci * - * In case the signature check fails, we'll have to resort to - * reading the f_CNT register itself in hopes that nobody has - * touched the DPLL yet... + * Todo. For non x86 should probably check the dword is + * set to 0xABCDExxx indicating the BIOS saved f_CNT */ - temp = inl(pci_resource_start(dev, 4) + 0x90); - if ((temp & 0xFFFFF000) != 0xABCDE000) { - printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n"); - - /* Calculate the average value of f_CNT */ - for (temp = i = 0; i < 128; i++) { - pci_read_config_word(dev, 0x78, &freq); - temp += freq & 0x1ff; - mdelay(1); - } - freq = temp / 128; - } else - freq = temp & 0x1ff; - + pci_read_config_word(dev, 0x78, &freq); + freq &= 0x1FF; + /* - * HPT3xxN chips use different PCI clock information. - * Currently we always set up the PLL for them. + * The 372N uses different PCI clock information and has + * some other complications + * On PCI33 timing we must clock switch + * On PCI66 timing we must NOT use the PCI clock + * + * Currently we always set up the PLL for the 372N */ - - if (info->flags & IS_3xxN) { + + if(info->flags & IS_372N) + { + printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n"); if(freq < 0x55) pll = F_LOW_PCI_33; else if(freq < 0x70) @@ -1069,8 +1180,10 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pll = F_LOW_PCI_50; else pll = F_LOW_PCI_66; - - printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll); + + printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll); + + /* We always use the pll not the PCI clock on 372N */ } else { @@ -1084,22 +1197,41 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pll = F_LOW_PCI_66; if (pll == F_LOW_PCI_33) { - info->speed = thirty_three_base_hpt37x; + if (info->revision >= 8) + info->speed = thirty_three_base_hpt374; + else if (info->revision >= 5) + info->speed = thirty_three_base_hpt372; + else if (info->revision >= 4) + info->speed = thirty_three_base_hpt370a; + else + info->speed = thirty_three_base_hpt370; printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n"); } else if (pll == F_LOW_PCI_40) { /* Unsupported */ } else if (pll == F_LOW_PCI_50) { - info->speed = fifty_base_hpt37x; + if (info->revision >= 8) + info->speed = fifty_base_hpt370a; + else if (info->revision >= 5) + info->speed = fifty_base_hpt372; + else if (info->revision >= 4) + info->speed = fifty_base_hpt370a; + else + info->speed = fifty_base_hpt370a; printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); } else { - info->speed = sixty_six_base_hpt37x; + if (info->revision >= 8) { + printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n"); + } + else if (info->revision >= 5) + info->speed = sixty_six_base_hpt372; + else if (info->revision >= 4) + info->speed = sixty_six_base_hpt370a; + else + info->speed = sixty_six_base_hpt370; printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); } } - - if (pll == F_LOW_PCI_66) - info->flags |= PCI_66MHZ; - + /* * only try the pll if we don't have a table for the clock * speed that we're running at. NOTE: the internal PLL will @@ -1116,8 +1248,11 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) info->flags |= PLL_MODE; /* - * Adjust the PLL based upon the PCI clock, enable it, and - * wait for stabilization... + * FIXME: make this work correctly, esp with 372N as per + * reference driver code. + * + * adjust PLL based upon PCI clock, enable it, and wait for + * stabilization. */ adjust = 0; freq = (pll < F_LOW_PCI_50) ? 2 : 4; @@ -1140,12 +1275,22 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pci_write_config_dword(dev, 0x5c, pll & ~0x100); pci_write_config_byte(dev, 0x5b, 0x21); - - info->speed = fifty_base_hpt37x; + if (info->revision >= 8) + info->speed = fifty_base_hpt370a; + else if (info->revision >= 5) + info->speed = fifty_base_hpt372; + else if (info->revision >= 4) + info->speed = fifty_base_hpt370a; + else + info->speed = fifty_base_hpt370a; printk("HPT37X: using 50MHz internal PLL\n"); goto init_hpt37X_done; } } + if (!pci_get_drvdata(dev)) { + printk("No Clock Stabilization!!!\n"); + return; + } pll_recal: if (adjust & 1) pll -= (adjust >> 1); @@ -1155,16 +1300,11 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) init_hpt37X_done: if (!info->speed) - printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n", - (info->flags & IS_3xxN) ? "N" : "", pll, freq); - /* - * Reset the state engines. - * NOTE: avoid accidentally enabling the primary channel on HPT371N. - */ - pci_read_config_byte(dev, 0x50, &mcr1); - if (mcr1 & 0x04) - pci_write_config_byte(dev, 0x50, 0x37); - pci_write_config_byte(dev, 0x54, 0x37); + printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n", + (info->flags & IS_372N)?"N":"", pll, freq); + /* reset state engine */ + pci_write_config_byte(dev, 0x50, 0x37); + pci_write_config_byte(dev, 0x54, 0x37); udelay(100); } @@ -1227,7 +1367,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = ide_get_hwifdata(hwif); u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; - int serialize = HPT_SERIALIZE_IO; hwif->tuneproc = &hpt3xx_tune_drive; hwif->speedproc = &hpt3xx_tune_chipset; @@ -1235,20 +1374,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; - /* - * HPT3xxN chips have some complications: - * - * - on 33 MHz PCI we must clock switch - * - on 66 MHz PCI we must NOT use the PCI clock - */ - if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) { - /* - * Clock is shared between the channels, - * so we'll have to serialize them... :-( - */ - serialize = 1; - hwif->rw_disk = &hpt3xxn_rw_disk; - } + if(info->flags & IS_372N) + hwif->rw_disk = &hpt372n_rw_disk; /* * The HPT37x uses the CBLID pins as outputs for MA15/MA16 @@ -1291,15 +1418,29 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) PCI_FUNC(hwif->pci_dev->devfn)); #endif /* DEBUG */ - /* Serialize access to this device */ - if (serialize && hwif->mate) +#ifdef HPT_SERIALIZE_IO + /* serialize access to this device */ + if (hwif->mate) hwif->serialized = hwif->mate->serialized = 1; +#endif - /* - * Set up ioctl for power status. - * NOTE: power affects both drives on each channel. - */ - hwif->busproc = &hpt3xx_busproc; + if (info->revision >= 3) { + u8 reg5ah = 0; + pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); + /* + * set up ioctl for power status. + * note: power affects both + * drives on each channel + */ + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt370_busproc; + } else if (info->revision >= 2) { + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt3xx_tristate; + } else { + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt3xx_tristate; + } if (!hwif->dma_base) { hwif->drives[0].autotune = 1; @@ -1349,7 +1490,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) return; if(info->speed == NULL) { - printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n"); + printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n"); return; } @@ -1378,10 +1519,9 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) static void __devinit init_iops_hpt366(ide_hwif_t *hwif) { - struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); - struct pci_dev *dev = hwif->pci_dev; - u16 did = dev->device; - u8 rid = 0; + struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); + unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4); + u8 did, rid; if(info == NULL) { printk(KERN_WARNING "hpt366: out of memory.\n"); @@ -1389,22 +1529,15 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif) } ide_set_hwifdata(hwif, info); - /* Avoid doing the same thing twice. */ - if (hwif->channel && hwif->mate) { - memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info)); - return; - } + if(dmabase) { + did = inb(dmabase + 0x22); + rid = inb(dmabase + 0x28); - pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid); - - if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) || - ((did == PCI_DEVICE_ID_TTI_HPT372 || - did == PCI_DEVICE_ID_TTI_HPT302 || - did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) || - did == PCI_DEVICE_ID_TTI_HPT372N) - info->flags |= IS_3xxN; + if((did == 4 && rid == 6) || (did == 5 && rid > 1)) + info->flags |= IS_372N; + } - info->revision = hpt_revision(dev); + info->revision = hpt_revision(hwif->pci_dev); if (info->revision >= 3) hpt37x_clocking(hwif); @@ -1441,23 +1574,6 @@ static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d) return ide_setup_pci_device(dev, d); } -static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) -{ - u8 mcr1 = 0; - - /* - * HPT371 chips physically have only one channel, the secondary one, - * but the primary channel registers do exist! Go figure... - * So, we manually disable the non-existing channel here - * (if the BIOS hasn't done this already). - */ - pci_read_config_byte(dev, 0x50, &mcr1); - if (mcr1 & 0x04) - pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04)); - - return ide_setup_pci_device(dev, d); -} - static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *findev = NULL; @@ -1545,14 +1661,13 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .bootable = OFF_BOARD, },{ /* 3 */ .name = "HPT371", - .init_setup = init_setup_hpt371, + .init_setup = init_setup_hpt37x, .init_chipset = init_chipset_hpt366, .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, },{ /* 4 */ .name = "HPT374", @@ -1584,16 +1699,13 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { * * Called when the PCI registration layer (or the IDE initialization) * finds a device matching our IDE device tables. - * - * NOTE: since we'll have to modify some fields of the ide_pci_device_t - * structure depending on the chip's revision, we'd better pass a local - * copy down the call chain... */ + static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t d = hpt366_chipsets[id->driver_data]; + ide_pci_device_t *d = &hpt366_chipsets[id->driver_data]; - return d.init_setup(dev, &d); + return d->init_setup(dev, d); } static struct pci_device_id hpt366_pci_tbl[] = { diff --git a/trunk/drivers/ide/pci/pdc202xx_new.c b/trunk/drivers/ide/pci/pdc202xx_new.c index 7cb48576e479..3ca581063f72 100644 --- a/trunk/drivers/ide/pci/pdc202xx_new.c +++ b/trunk/drivers/ide/pci/pdc202xx_new.c @@ -39,14 +39,6 @@ #define PDC202_DEBUG_CABLE 0 -#undef DEBUG - -#ifdef DEBUG -#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args) -#else -#define DBG(fmt, args...) -#endif - static const char *pdc_quirk_drives[] = { "QUANTUM FIREBALLlct08 08", "QUANTUM FIREBALLP KA6.4", @@ -59,11 +51,37 @@ static const char *pdc_quirk_drives[] = { NULL }; -static u8 max_dma_rate(struct pci_dev *pdev) +#define set_2regs(a, b) \ + do { \ + hwif->OUTB((a + adj), indexreg); \ + hwif->OUTB(b, datareg); \ + } while(0) + +#define set_ultra(a, b, c) \ + do { \ + set_2regs(0x10,(a)); \ + set_2regs(0x11,(b)); \ + set_2regs(0x12,(c)); \ + } while(0) + +#define set_ata2(a, b) \ + do { \ + set_2regs(0x0e,(a)); \ + set_2regs(0x0f,(b)); \ + } while(0) + +#define set_pio(a, b, c) \ + do { \ + set_2regs(0x0c,(a)); \ + set_2regs(0x0d,(b)); \ + set_2regs(0x13,(c)); \ + } while(0) + +static u8 pdcnew_ratemask (ide_drive_t *drive) { u8 mode; - switch(pdev->device) { + switch(HWIF(drive)->pci_dev->device) { case PCI_DEVICE_ID_PROMISE_20277: case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: @@ -78,21 +96,12 @@ static u8 max_dma_rate(struct pci_dev *pdev) default: return 0; } - - return mode; -} - -static u8 pdcnew_ratemask(ide_drive_t *drive) -{ - u8 mode = max_dma_rate(HWIF(drive)->pci_dev); - if (!eighty_ninty_three(drive)) - mode = min_t(u8, mode, 1); - - return mode; + mode = min(mode, (u8)1); + return mode; } -static int check_in_drive_lists(ide_drive_t *drive, const char **list) +static int check_in_drive_lists (ide_drive_t *drive, const char **list) { struct hd_driveid *id = drive->id; @@ -112,141 +121,43 @@ static int check_in_drive_lists(ide_drive_t *drive, const char **list) return 0; } -/** - * get_indexed_reg - Get indexed register - * @hwif: for the port address - * @index: index of the indexed register - */ -static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) -{ - u8 value; - - hwif->OUTB(index, hwif->dma_vendor1); - value = hwif->INB(hwif->dma_vendor3); - - DBG("index[%02X] value[%02X]\n", index, value); - return value; -} - -/** - * set_indexed_reg - Set indexed register - * @hwif: for the port address - * @index: index of the indexed register - */ -static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value) -{ - hwif->OUTB(index, hwif->dma_vendor1); - hwif->OUTB(value, hwif->dma_vendor3); - DBG("index[%02X] value[%02X]\n", index, value); -} - -/* - * ATA Timing Tables based on 133 MHz PLL output clock. - * - * If the PLL outputs 100 MHz clock, the ASIC hardware will set - * the timing registers automatically when "set features" command is - * issued to the device. However, if the PLL output clock is 133 MHz, - * the following tables must be used. - */ -static struct pio_timing { - u8 reg0c, reg0d, reg13; -} pio_timings [] = { - { 0xfb, 0x2b, 0xac }, /* PIO mode 0, IORDY off, Prefetch off */ - { 0x46, 0x29, 0xa4 }, /* PIO mode 1, IORDY off, Prefetch off */ - { 0x23, 0x26, 0x64 }, /* PIO mode 2, IORDY off, Prefetch off */ - { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ - { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ -}; - -static struct mwdma_timing { - u8 reg0e, reg0f; -} mwdma_timings [] = { - { 0xdf, 0x5f }, /* MWDMA mode 0 */ - { 0x6b, 0x27 }, /* MWDMA mode 1 */ - { 0x69, 0x25 }, /* MWDMA mode 2 */ -}; - -static struct udma_timing { - u8 reg10, reg11, reg12; -} udma_timings [] = { - { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ - { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ - { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ - { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ - { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ - { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ - { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ -}; - -static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) +static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); - u8 adj = (drive->dn & 1) ? 0x08 : 0x00; - int err; - - speed = ide_rate_filter(pdcnew_ratemask(drive), speed); - - /* - * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will - * automatically set the timing registers based on 100 MHz PLL output. - */ - err = ide_config_drive_speed(drive, speed); - - /* - * As we set up the PLL to output 133 MHz for UltraDMA/133 capable - * chips, we must override the default register settings... - */ - if (max_dma_rate(hwif->pci_dev) == 4) { - u8 mode = speed & 0x07; - - switch (speed) { - case XFER_UDMA_6: - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - set_indexed_reg(hwif, 0x10 + adj, - udma_timings[mode].reg10); - set_indexed_reg(hwif, 0x11 + adj, - udma_timings[mode].reg11); - set_indexed_reg(hwif, 0x12 + adj, - udma_timings[mode].reg12); - break; - - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - set_indexed_reg(hwif, 0x0e + adj, - mwdma_timings[mode].reg0e); - set_indexed_reg(hwif, 0x0f + adj, - mwdma_timings[mode].reg0f); - break; - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - set_indexed_reg(hwif, 0x0c + adj, - pio_timings[mode].reg0c); - set_indexed_reg(hwif, 0x0d + adj, - pio_timings[mode].reg0d); - set_indexed_reg(hwif, 0x13 + adj, - pio_timings[mode].reg13); - break; - default: - printk(KERN_ERR "pdc202xx_new: " - "Unknown speed %d ignored\n", speed); - } - } else if (speed == XFER_UDMA_2) { - /* Set tHOLD bit to 0 if using UDMA mode 2 */ - u8 tmp = get_indexed_reg(hwif, 0x10 + adj); + unsigned long indexreg = hwif->dma_vendor1; + unsigned long datareg = hwif->dma_vendor3; + u8 thold = 0x10; + u8 adj = (drive->dn%2) ? 0x08 : 0x00; + u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); + + if (speed == XFER_UDMA_2) { + hwif->OUTB((thold + adj), indexreg); + hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg); + } - set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f); - } + switch (speed) { + case XFER_UDMA_7: + speed = XFER_UDMA_6; + case XFER_UDMA_6: set_ultra(0x1a, 0x01, 0xcb); break; + case XFER_UDMA_5: set_ultra(0x1a, 0x02, 0xcb); break; + case XFER_UDMA_4: set_ultra(0x1a, 0x03, 0xcd); break; + case XFER_UDMA_3: set_ultra(0x1a, 0x05, 0xcd); break; + case XFER_UDMA_2: set_ultra(0x2a, 0x07, 0xcd); break; + case XFER_UDMA_1: set_ultra(0x3a, 0x0a, 0xd0); break; + case XFER_UDMA_0: set_ultra(0x4a, 0x0f, 0xd5); break; + case XFER_MW_DMA_2: set_ata2(0x69, 0x25); break; + case XFER_MW_DMA_1: set_ata2(0x6b, 0x27); break; + case XFER_MW_DMA_0: set_ata2(0xdf, 0x5f); break; + case XFER_PIO_4: set_pio(0x23, 0x09, 0x25); break; + case XFER_PIO_3: set_pio(0x27, 0x0d, 0x35); break; + case XFER_PIO_2: set_pio(0x23, 0x26, 0x64); break; + case XFER_PIO_1: set_pio(0x46, 0x29, 0xa4); break; + case XFER_PIO_0: set_pio(0xfb, 0x2b, 0xac); break; + default: + ; + } - return err; + return (ide_config_drive_speed(drive, speed)); } /* 0 1 2 3 4 5 6 7 8 @@ -259,42 +170,36 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - (void)pdcnew_tune_chipset(drive, XFER_PIO_0 + pio); + (void)pdcnew_new_tune_chipset(drive, XFER_PIO_0 + pio); } -static u8 pdcnew_cable_detect(ide_hwif_t *hwif) +static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) { - return get_indexed_reg(hwif, 0x0b) & 0x04; + hwif->OUTB(0x0b, hwif->dma_vendor1); + return ((u8)((hwif->INB(hwif->dma_vendor3) & 0x04))); } - -static int config_chipset_for_dma(ide_drive_t *drive) +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); - u8 ultra_66 = (id->dma_ultra & 0x0078) ? 1 : 0; - u8 cable = pdcnew_cable_detect(hwif); - u8 speed; + u8 speed = -1; + u8 cable; + + u8 ultra_66 = ((id->dma_ultra & 0x0010) || + (id->dma_ultra & 0x0008)) ? 1 : 0; + + cable = pdcnew_new_cable_detect(hwif); if (ultra_66 && cable) { - printk(KERN_WARNING "Warning: %s channel " - "requires an 80-pin cable for operation.\n", - hwif->channel ? "Secondary" : "Primary"); + printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); } if (drive->media != ide_disk) return 0; - - if (id->capability & 4) { - /* - * Set IORDY_EN & PREFETCH_EN (this seems to have - * NO real effect since this register is reloaded - * by hardware when the transfer mode is selected) - */ - u8 tmp, adj = (drive->dn & 1) ? 0x08 : 0x00; - - tmp = get_indexed_reg(hwif, 0x13 + adj); - set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03); + if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */ + hwif->OUTB((0x13 + ((drive->dn%2) ? 0x08 : 0x00)), hwif->dma_vendor1); + hwif->OUTB((hwif->INB(hwif->dma_vendor3)|0x03), hwif->dma_vendor3); } speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); @@ -306,7 +211,7 @@ static int config_chipset_for_dma(ide_drive_t *drive) return ide_dma_enable(drive); } -static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) +static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; @@ -331,9 +236,9 @@ static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) return 0; } -static int pdcnew_quirkproc(ide_drive_t *drive) +static int pdcnew_quirkproc (ide_drive_t *drive) { - return check_in_drive_lists(drive, pdc_quirk_drives); + return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); } static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) @@ -350,100 +255,21 @@ static int pdcnew_ide_dma_timeout(ide_drive_t *drive) return __ide_dma_timeout(drive); } -static void pdcnew_reset(ide_drive_t *drive) +static void pdcnew_new_reset (ide_drive_t *drive) { /* * Deleted this because it is redundant from the caller. */ - printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n", + printk(KERN_WARNING "PDC202XX: %s channel reset.\n", HWIF(drive)->channel ? "Secondary" : "Primary"); } -/** - * read_counter - Read the byte count registers - * @dma_base: for the port address - */ -static long __devinit read_counter(u32 dma_base) -{ - u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08; - u8 cnt0, cnt1, cnt2, cnt3; - long count = 0, last; - int retry = 3; - - do { - last = count; - - /* Read the current count */ - outb(0x20, pri_dma_base + 0x01); - cnt0 = inb(pri_dma_base + 0x03); - outb(0x21, pri_dma_base + 0x01); - cnt1 = inb(pri_dma_base + 0x03); - outb(0x20, sec_dma_base + 0x01); - cnt2 = inb(sec_dma_base + 0x03); - outb(0x21, sec_dma_base + 0x01); - cnt3 = inb(sec_dma_base + 0x03); - - count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0; - - /* - * The 30-bit decrementing counter is read in 4 pieces. - * Incorrect value may be read when the most significant bytes - * are changing... - */ - } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count)); - - DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n", - cnt0, cnt1, cnt2, cnt3); - - return count; -} - -/** - * detect_pll_input_clock - Detect the PLL input clock in Hz. - * @dma_base: for the port address - * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock. - */ -static long __devinit detect_pll_input_clock(unsigned long dma_base) -{ - long start_count, end_count; - long pll_input; - u8 scr1; - - start_count = read_counter(dma_base); - - /* Start the test mode */ - outb(0x01, dma_base + 0x01); - scr1 = inb(dma_base + 0x03); - DBG("scr1[%02X]\n", scr1); - outb(scr1 | 0x40, dma_base + 0x03); - - /* Let the counter run for 10 ms. */ - mdelay(10); - - end_count = read_counter(dma_base); - - /* Stop the test mode */ - outb(0x01, dma_base + 0x01); - scr1 = inb(dma_base + 0x03); - DBG("scr1[%02X]\n", scr1); - outb(scr1 & ~0x40, dma_base + 0x03); - - /* - * Calculate the input clock in Hz - * (the clock counter is 30 bit wide and counts down) - */ - pll_input = ((start_count - end_count) & 0x3ffffff) * 100; - - DBG("start[%ld] end[%ld]\n", start_count, end_count); - - return pll_input; -} - #ifdef CONFIG_PPC_PMAC static void __devinit apple_kiwi_init(struct pci_dev *pdev) { struct device_node *np = pci_device_to_OF_node(pdev); unsigned int class_rev = 0; + void __iomem *mmio; u8 conf; if (np == NULL || !device_is_compatible(np, "kiwi-root")) @@ -454,20 +280,30 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev) if (class_rev >= 0x03) { /* Setup chip magic config stuff (from darwin) */ - pci_read_config_byte (pdev, 0x40, &conf); - pci_write_config_byte(pdev, 0x40, (conf | 0x01)); + pci_read_config_byte(pdev, 0x40, &conf); + pci_write_config_byte(pdev, 0x40, conf | 0x01); + } + mmio = ioremap(pci_resource_start(pdev, 5), + pci_resource_len(pdev, 5)); + + /* Setup some PLL stuffs */ + switch (pdev->device) { + case PCI_DEVICE_ID_PROMISE_20270: + writew(0x0d2b, mmio + 0x1202); + mdelay(30); + break; + case PCI_DEVICE_ID_PROMISE_20271: + writew(0x0826, mmio + 0x1202); + mdelay(30); + break; } + + iounmap(mmio); } #endif /* CONFIG_PPC_PMAC */ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name) { - unsigned long dma_base = pci_resource_start(dev, 4); - unsigned long sec_dma_base = dma_base + 0x08; - long pll_input, pll_output, ratio; - int f, r; - u8 pll_ctl0, pll_ctl1; - if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); @@ -479,106 +315,6 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha apple_kiwi_init(dev); #endif - /* Calculate the required PLL output frequency */ - switch(max_dma_rate(dev)) { - case 4: /* it's 133 MHz for Ultra133 chips */ - pll_output = 133333333; - break; - case 3: /* and 100 MHz for Ultra100 chips */ - default: - pll_output = 100000000; - break; - } - - /* - * Detect PLL input clock. - * On some systems, where PCI bus is running at non-standard clock rate - * (e.g. 25 or 40 MHz), we have to adjust the cycle time. - * PDC20268 and newer chips employ PLL circuit to help correct timing - * registers setting. - */ - pll_input = detect_pll_input_clock(dma_base); - printk("%s: PLL input clock is %ld kHz\n", name, pll_input / 1000); - - /* Sanity check */ - if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) { - printk(KERN_ERR "%s: Bad PLL input clock %ld Hz, giving up!\n", - name, pll_input); - goto out; - } - -#ifdef DEBUG - DBG("pll_output is %ld Hz\n", pll_output); - - /* Show the current clock value of PLL control register - * (maybe already configured by the BIOS) - */ - outb(0x02, sec_dma_base + 0x01); - pll_ctl0 = inb(sec_dma_base + 0x03); - outb(0x03, sec_dma_base + 0x01); - pll_ctl1 = inb(sec_dma_base + 0x03); - - DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); -#endif - - /* - * Calculate the ratio of F, R and NO - * POUT = (F + 2) / (( R + 2) * NO) - */ - ratio = pll_output / (pll_input / 1000); - if (ratio < 8600L) { /* 8.6x */ - /* Using NO = 0x01, R = 0x0d */ - r = 0x0d; - } else if (ratio < 12900L) { /* 12.9x */ - /* Using NO = 0x01, R = 0x08 */ - r = 0x08; - } else if (ratio < 16100L) { /* 16.1x */ - /* Using NO = 0x01, R = 0x06 */ - r = 0x06; - } else if (ratio < 64000L) { /* 64x */ - r = 0x00; - } else { - /* Invalid ratio */ - printk(KERN_ERR "%s: Bad ratio %ld, giving up!\n", name, ratio); - goto out; - } - - f = (ratio * (r + 2)) / 1000 - 2; - - DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio); - - if (unlikely(f < 0 || f > 127)) { - /* Invalid F */ - printk(KERN_ERR "%s: F[%d] invalid!\n", name, f); - goto out; - } - - pll_ctl0 = (u8) f; - pll_ctl1 = (u8) r; - - DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); - - outb(0x02, sec_dma_base + 0x01); - outb(pll_ctl0, sec_dma_base + 0x03); - outb(0x03, sec_dma_base + 0x01); - outb(pll_ctl1, sec_dma_base + 0x03); - - /* Wait the PLL circuit to be stable */ - mdelay(30); - -#ifdef DEBUG - /* - * Show the current clock value of PLL control register - */ - outb(0x02, sec_dma_base + 0x01); - pll_ctl0 = inb(sec_dma_base + 0x03); - outb(0x03, sec_dma_base + 0x01); - pll_ctl1 = inb(sec_dma_base + 0x03); - - DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); -#endif - - out: return dev->irq; } @@ -588,8 +324,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->tuneproc = &pdcnew_tune_drive; hwif->quirkproc = &pdcnew_quirkproc; - hwif->speedproc = &pdcnew_tune_chipset; - hwif->resetproc = &pdcnew_reset; + hwif->speedproc = &pdcnew_new_tune_chipset; + hwif->resetproc = &pdcnew_new_reset; hwif->drives[0].autotune = hwif->drives[1].autotune = 1; @@ -601,14 +337,11 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; - - if (!hwif->udma_four) - hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1; - + if (!(hwif->udma_four)) + hwif->udma_four = (pdcnew_new_cable_detect(hwif)) ? 0 : 1; if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; - #if PDC202_DEBUG_CABLE printk(KERN_DEBUG "%s: %s-pin cable\n", hwif->name, hwif->udma_four ? "80" : "40"); diff --git a/trunk/drivers/ide/pci/piix.c b/trunk/drivers/ide/pci/piix.c index b1e9a8eba6b6..cdc3aab9ebcb 100644 --- a/trunk/drivers/ide/pci/piix.c +++ b/trunk/drivers/ide/pci/piix.c @@ -505,10 +505,6 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) /* This is a painful system best to let it self tune for now */ return; } - /* ESB2 appears to generate spurious DMA interrupts in PIO mode - when in native mode */ - if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18) - hwif->atapi_irq_bogon = 1; hwif->autodma = 0; hwif->tuneproc = &piix_tune_drive; diff --git a/trunk/drivers/ide/setup-pci.c b/trunk/drivers/ide/setup-pci.c index 695e23904d30..0719b6484824 100644 --- a/trunk/drivers/ide/setup-pci.c +++ b/trunk/drivers/ide/setup-pci.c @@ -844,11 +844,11 @@ void __init ide_scan_pcibus (int scan_direction) pre_init = 0; if (!scan_direction) { - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { ide_scan_pcidev(dev); } } else { - while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_find_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { ide_scan_pcidev(dev); } } diff --git a/trunk/drivers/ieee1394/pcilynx.c b/trunk/drivers/ieee1394/pcilynx.c index fbb7f14ec509..13a617917bf2 100644 --- a/trunk/drivers/ieee1394/pcilynx.c +++ b/trunk/drivers/ieee1394/pcilynx.c @@ -1485,7 +1485,7 @@ static int __devinit add_card(struct pci_dev *dev, } - i2c_del_adapter(i2c_ad); + i2c_bit_del_bus(i2c_ad); kfree(i2c_ad); } } diff --git a/trunk/drivers/infiniband/core/Makefile b/trunk/drivers/infiniband/core/Makefile index 50fb1cd447b7..163d991eb8c9 100644 --- a/trunk/drivers/infiniband/core/Makefile +++ b/trunk/drivers/infiniband/core/Makefile @@ -1,11 +1,9 @@ infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS) := ib_addr.o rdma_cm.o -user_access-$(CONFIG_INFINIBAND_ADDR_TRANS) := rdma_ucm.o obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \ ib_cm.o iw_cm.o $(infiniband-y) obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o -obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \ - $(user_access-y) +obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ device.o fmr_pool.o cache.o @@ -20,8 +18,6 @@ iw_cm-y := iwcm.o rdma_cm-y := cma.o -rdma_ucm-y := ucma.o - ib_addr-y := addr.o ib_umad-y := user_mad.o diff --git a/trunk/drivers/infiniband/core/cm.c b/trunk/drivers/infiniband/core/cm.c index d446998b12a4..79c937bf6962 100644 --- a/trunk/drivers/infiniband/core/cm.c +++ b/trunk/drivers/infiniband/core/cm.c @@ -3289,10 +3289,6 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv, spin_lock_irqsave(&cm_id_priv->lock, flags); switch (cm_id_priv->id.state) { - /* Allow transition to RTS before sending REP */ - case IB_CM_REQ_RCVD: - case IB_CM_MRA_REQ_SENT: - case IB_CM_REP_RCVD: case IB_CM_MRA_REP_SENT: case IB_CM_REP_SENT: diff --git a/trunk/drivers/infiniband/core/cma.c b/trunk/drivers/infiniband/core/cma.c index 533193d4e5df..985a6b564d8f 100644 --- a/trunk/drivers/infiniband/core/cma.c +++ b/trunk/drivers/infiniband/core/cma.c @@ -70,7 +70,6 @@ static DEFINE_MUTEX(lock); static struct workqueue_struct *cma_wq; static DEFINE_IDR(sdp_ps); static DEFINE_IDR(tcp_ps); -static DEFINE_IDR(udp_ps); struct cma_device { struct list_head list; @@ -134,6 +133,7 @@ struct rdma_id_private { u32 seq_num; u32 qp_num; + enum ib_qp_type qp_type; u8 srq; }; @@ -392,6 +392,7 @@ int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd, id->qp = qp; id_priv->qp_num = qp->qp_num; + id_priv->qp_type = qp->qp_type; id_priv->srq = (qp->srq != NULL); return 0; err: @@ -509,17 +510,9 @@ static inline int cma_any_addr(struct sockaddr *addr) return cma_zero_addr(addr) || cma_loopback_addr(addr); } -static inline __be16 cma_port(struct sockaddr *addr) -{ - if (addr->sa_family == AF_INET) - return ((struct sockaddr_in *) addr)->sin_port; - else - return ((struct sockaddr_in6 *) addr)->sin6_port; -} - static inline int cma_any_port(struct sockaddr *addr) { - return !cma_port(addr); + return !((struct sockaddr_in *) addr)->sin_port; } static int cma_get_net_info(void *hdr, enum rdma_port_space ps, @@ -601,6 +594,20 @@ static inline int cma_user_data_offset(enum rdma_port_space ps) } } +static int cma_notify_user(struct rdma_id_private *id_priv, + enum rdma_cm_event_type type, int status, + void *data, u8 data_len) +{ + struct rdma_cm_event event; + + event.event = type; + event.status = status; + event.private_data = data; + event.private_data_len = data_len; + + return id_priv->id.event_handler(&id_priv->id, &event); +} + static void cma_cancel_route(struct rdma_id_private *id_priv) { switch (rdma_node_get_transport(id_priv->id.device->node_type)) { @@ -769,61 +776,63 @@ static int cma_verify_rep(struct rdma_id_private *id_priv, void *data) return 0; } -static void cma_set_rep_event_data(struct rdma_cm_event *event, - struct ib_cm_rep_event_param *rep_data, - void *private_data) +static int cma_rtu_recv(struct rdma_id_private *id_priv) { - event->param.conn.private_data = private_data; - event->param.conn.private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE; - event->param.conn.responder_resources = rep_data->responder_resources; - event->param.conn.initiator_depth = rep_data->initiator_depth; - event->param.conn.flow_control = rep_data->flow_control; - event->param.conn.rnr_retry_count = rep_data->rnr_retry_count; - event->param.conn.srq = rep_data->srq; - event->param.conn.qp_num = rep_data->remote_qpn; + int ret; + + ret = cma_modify_qp_rts(&id_priv->id); + if (ret) + goto reject; + + return 0; +reject: + cma_modify_qp_err(&id_priv->id); + ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED, + NULL, 0, NULL, 0); + return ret; } static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) { struct rdma_id_private *id_priv = cm_id->context; - struct rdma_cm_event event; - int ret = 0; + enum rdma_cm_event_type event; + u8 private_data_len = 0; + int ret = 0, status = 0; atomic_inc(&id_priv->dev_remove); if (!cma_comp(id_priv, CMA_CONNECT)) goto out; - memset(&event, 0, sizeof event); switch (ib_event->event) { case IB_CM_REQ_ERROR: case IB_CM_REP_ERROR: - event.event = RDMA_CM_EVENT_UNREACHABLE; - event.status = -ETIMEDOUT; + event = RDMA_CM_EVENT_UNREACHABLE; + status = -ETIMEDOUT; break; case IB_CM_REP_RECEIVED: - event.status = cma_verify_rep(id_priv, ib_event->private_data); - if (event.status) - event.event = RDMA_CM_EVENT_CONNECT_ERROR; + status = cma_verify_rep(id_priv, ib_event->private_data); + if (status) + event = RDMA_CM_EVENT_CONNECT_ERROR; else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) { - event.status = cma_rep_recv(id_priv); - event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR : - RDMA_CM_EVENT_ESTABLISHED; + status = cma_rep_recv(id_priv); + event = status ? RDMA_CM_EVENT_CONNECT_ERROR : + RDMA_CM_EVENT_ESTABLISHED; } else - event.event = RDMA_CM_EVENT_CONNECT_RESPONSE; - cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd, - ib_event->private_data); + event = RDMA_CM_EVENT_CONNECT_RESPONSE; + private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE; break; case IB_CM_RTU_RECEIVED: - case IB_CM_USER_ESTABLISHED: - event.event = RDMA_CM_EVENT_ESTABLISHED; + status = cma_rtu_recv(id_priv); + event = status ? RDMA_CM_EVENT_CONNECT_ERROR : + RDMA_CM_EVENT_ESTABLISHED; break; case IB_CM_DREQ_ERROR: - event.status = -ETIMEDOUT; /* fall through */ + status = -ETIMEDOUT; /* fall through */ case IB_CM_DREQ_RECEIVED: case IB_CM_DREP_RECEIVED: if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT)) goto out; - event.event = RDMA_CM_EVENT_DISCONNECTED; + event = RDMA_CM_EVENT_DISCONNECTED; break; case IB_CM_TIMEWAIT_EXIT: case IB_CM_MRA_RECEIVED: @@ -831,10 +840,9 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) goto out; case IB_CM_REJ_RECEIVED: cma_modify_qp_err(&id_priv->id); - event.status = ib_event->param.rej_rcvd.reason; - event.event = RDMA_CM_EVENT_REJECTED; - event.param.conn.private_data = ib_event->private_data; - event.param.conn.private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; + status = ib_event->param.rej_rcvd.reason; + event = RDMA_CM_EVENT_REJECTED; + private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; break; default: printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", @@ -842,7 +850,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) goto out; } - ret = id_priv->id.event_handler(&id_priv->id, &event); + ret = cma_notify_user(id_priv, event, status, ib_event->private_data, + private_data_len); if (ret) { /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.ib = NULL; @@ -856,8 +865,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) return ret; } -static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, - struct ib_cm_event *ib_event) +static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id, + struct ib_cm_event *ib_event) { struct rdma_id_private *id_priv; struct rdma_cm_id *id; @@ -904,61 +913,9 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, return NULL; } -static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, - struct ib_cm_event *ib_event) -{ - struct rdma_id_private *id_priv; - struct rdma_cm_id *id; - union cma_ip_addr *src, *dst; - __u16 port; - u8 ip_ver; - int ret; - - id = rdma_create_id(listen_id->event_handler, listen_id->context, - listen_id->ps); - if (IS_ERR(id)) - return NULL; - - - if (cma_get_net_info(ib_event->private_data, listen_id->ps, - &ip_ver, &port, &src, &dst)) - goto err; - - cma_save_net_info(&id->route.addr, &listen_id->route.addr, - ip_ver, port, src, dst); - - ret = rdma_translate_ip(&id->route.addr.src_addr, - &id->route.addr.dev_addr); - if (ret) - goto err; - - id_priv = container_of(id, struct rdma_id_private, id); - id_priv->state = CMA_CONNECT; - return id_priv; -err: - rdma_destroy_id(id); - return NULL; -} - -static void cma_set_req_event_data(struct rdma_cm_event *event, - struct ib_cm_req_event_param *req_data, - void *private_data, int offset) -{ - event->param.conn.private_data = private_data + offset; - event->param.conn.private_data_len = IB_CM_REQ_PRIVATE_DATA_SIZE - offset; - event->param.conn.responder_resources = req_data->responder_resources; - event->param.conn.initiator_depth = req_data->initiator_depth; - event->param.conn.flow_control = req_data->flow_control; - event->param.conn.retry_count = req_data->retry_count; - event->param.conn.rnr_retry_count = req_data->rnr_retry_count; - event->param.conn.srq = req_data->srq; - event->param.conn.qp_num = req_data->remote_qpn; -} - static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) { struct rdma_id_private *listen_id, *conn_id; - struct rdma_cm_event event; int offset, ret; listen_id = cm_id->context; @@ -968,19 +925,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) goto out; } - memset(&event, 0, sizeof event); - offset = cma_user_data_offset(listen_id->id.ps); - event.event = RDMA_CM_EVENT_CONNECT_REQUEST; - if (listen_id->id.ps == RDMA_PS_UDP) { - conn_id = cma_new_udp_id(&listen_id->id, ib_event); - event.param.ud.private_data = ib_event->private_data + offset; - event.param.ud.private_data_len = - IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE - offset; - } else { - conn_id = cma_new_conn_id(&listen_id->id, ib_event); - cma_set_req_event_data(&event, &ib_event->param.req_rcvd, - ib_event->private_data, offset); - } + conn_id = cma_new_id(&listen_id->id, ib_event); if (!conn_id) { ret = -ENOMEM; goto out; @@ -997,7 +942,10 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) cm_id->context = conn_id; cm_id->cm_handler = cma_ib_handler; - ret = conn_id->id.event_handler(&conn_id->id, &event); + offset = cma_user_data_offset(listen_id->id.ps); + ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0, + ib_event->private_data + offset, + IB_CM_REQ_PRIVATE_DATA_SIZE - offset); if (!ret) goto out; @@ -1016,7 +964,8 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr) { - return cpu_to_be64(((u64)ps << 16) + be16_to_cpu(cma_port(addr))); + return cpu_to_be64(((u64)ps << 16) + + be16_to_cpu(((struct sockaddr_in *) addr)->sin_port)); } static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, @@ -1072,16 +1021,15 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) { struct rdma_id_private *id_priv = iw_id->context; - struct rdma_cm_event event; + enum rdma_cm_event_type event = 0; struct sockaddr_in *sin; int ret = 0; - memset(&event, 0, sizeof event); atomic_inc(&id_priv->dev_remove); switch (iw_event->event) { case IW_CM_EVENT_CLOSE: - event.event = RDMA_CM_EVENT_DISCONNECTED; + event = RDMA_CM_EVENT_DISCONNECTED; break; case IW_CM_EVENT_CONNECT_REPLY: sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; @@ -1089,21 +1037,20 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) sin = (struct sockaddr_in *) &id_priv->id.route.addr.dst_addr; *sin = iw_event->remote_addr; if (iw_event->status) - event.event = RDMA_CM_EVENT_REJECTED; + event = RDMA_CM_EVENT_REJECTED; else - event.event = RDMA_CM_EVENT_ESTABLISHED; + event = RDMA_CM_EVENT_ESTABLISHED; break; case IW_CM_EVENT_ESTABLISHED: - event.event = RDMA_CM_EVENT_ESTABLISHED; + event = RDMA_CM_EVENT_ESTABLISHED; break; default: BUG_ON(1); } - event.status = iw_event->status; - event.param.conn.private_data = iw_event->private_data; - event.param.conn.private_data_len = iw_event->private_data_len; - ret = id_priv->id.event_handler(&id_priv->id, &event); + ret = cma_notify_user(id_priv, event, iw_event->status, + iw_event->private_data, + iw_event->private_data_len); if (ret) { /* Destroy the CM ID by returning a non-zero value. */ id_priv->cm_id.iw = NULL; @@ -1124,7 +1071,6 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, struct rdma_id_private *listen_id, *conn_id; struct sockaddr_in *sin; struct net_device *dev = NULL; - struct rdma_cm_event event; int ret; listen_id = cm_id->context; @@ -1178,11 +1124,9 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr; *sin = iw_event->remote_addr; - memset(&event, 0, sizeof event); - event.event = RDMA_CM_EVENT_CONNECT_REQUEST; - event.param.conn.private_data = iw_event->private_data; - event.param.conn.private_data_len = iw_event->private_data_len; - ret = conn_id->id.event_handler(&conn_id->id, &event); + ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0, + iw_event->private_data, + iw_event->private_data_len); if (ret) { /* User wants to destroy the CM ID */ conn_id->cm_id.iw = NULL; @@ -1571,9 +1515,8 @@ static void addr_handler(int status, struct sockaddr *src_addr, struct rdma_dev_addr *dev_addr, void *context) { struct rdma_id_private *id_priv = context; - struct rdma_cm_event event; + enum rdma_cm_event_type event; - memset(&event, 0, sizeof event); atomic_inc(&id_priv->dev_remove); /* @@ -1593,15 +1536,14 @@ static void addr_handler(int status, struct sockaddr *src_addr, if (status) { if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND)) goto out; - event.event = RDMA_CM_EVENT_ADDR_ERROR; - event.status = status; + event = RDMA_CM_EVENT_ADDR_ERROR; } else { memcpy(&id_priv->id.route.addr.src_addr, src_addr, ip_addr_size(src_addr)); - event.event = RDMA_CM_EVENT_ADDR_RESOLVED; + event = RDMA_CM_EVENT_ADDR_RESOLVED; } - if (id_priv->id.event_handler(&id_priv->id, &event)) { + if (cma_notify_user(id_priv, event, status, NULL, 0)) { cma_exch(id_priv, CMA_DESTROYING); cma_release_remove(id_priv); cma_deref_id(id_priv); @@ -1791,9 +1733,6 @@ static int cma_get_port(struct rdma_id_private *id_priv) case RDMA_PS_TCP: ps = &tcp_ps; break; - case RDMA_PS_UDP: - ps = &udp_ps; - break; default: return -EPROTONOSUPPORT; } @@ -1882,110 +1821,6 @@ static int cma_format_hdr(void *hdr, enum rdma_port_space ps, return 0; } -static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, - struct ib_cm_event *ib_event) -{ - struct rdma_id_private *id_priv = cm_id->context; - struct rdma_cm_event event; - struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd; - int ret = 0; - - memset(&event, 0, sizeof event); - atomic_inc(&id_priv->dev_remove); - if (!cma_comp(id_priv, CMA_CONNECT)) - goto out; - - switch (ib_event->event) { - case IB_CM_SIDR_REQ_ERROR: - event.event = RDMA_CM_EVENT_UNREACHABLE; - event.status = -ETIMEDOUT; - break; - case IB_CM_SIDR_REP_RECEIVED: - event.param.ud.private_data = ib_event->private_data; - event.param.ud.private_data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE; - if (rep->status != IB_SIDR_SUCCESS) { - event.event = RDMA_CM_EVENT_UNREACHABLE; - event.status = ib_event->param.sidr_rep_rcvd.status; - break; - } - if (rep->qkey != RDMA_UD_QKEY) { - event.event = RDMA_CM_EVENT_UNREACHABLE; - event.status = -EINVAL; - break; - } - ib_init_ah_from_path(id_priv->id.device, id_priv->id.port_num, - id_priv->id.route.path_rec, - &event.param.ud.ah_attr); - event.param.ud.qp_num = rep->qpn; - event.param.ud.qkey = rep->qkey; - event.event = RDMA_CM_EVENT_ESTABLISHED; - event.status = 0; - break; - default: - printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", - ib_event->event); - goto out; - } - - ret = id_priv->id.event_handler(&id_priv->id, &event); - if (ret) { - /* Destroy the CM ID by returning a non-zero value. */ - id_priv->cm_id.ib = NULL; - cma_exch(id_priv, CMA_DESTROYING); - cma_release_remove(id_priv); - rdma_destroy_id(&id_priv->id); - return ret; - } -out: - cma_release_remove(id_priv); - return ret; -} - -static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, - struct rdma_conn_param *conn_param) -{ - struct ib_cm_sidr_req_param req; - struct rdma_route *route; - int ret; - - req.private_data_len = sizeof(struct cma_hdr) + - conn_param->private_data_len; - req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC); - if (!req.private_data) - return -ENOMEM; - - if (conn_param->private_data && conn_param->private_data_len) - memcpy((void *) req.private_data + sizeof(struct cma_hdr), - conn_param->private_data, conn_param->private_data_len); - - route = &id_priv->id.route; - ret = cma_format_hdr((void *) req.private_data, id_priv->id.ps, route); - if (ret) - goto out; - - id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, - cma_sidr_rep_handler, id_priv); - if (IS_ERR(id_priv->cm_id.ib)) { - ret = PTR_ERR(id_priv->cm_id.ib); - goto out; - } - - req.path = route->path_rec; - req.service_id = cma_get_service_id(id_priv->id.ps, - &route->addr.dst_addr); - req.timeout_ms = 1 << (CMA_CM_RESPONSE_TIMEOUT - 8); - req.max_cm_retries = CMA_MAX_CM_RETRIES; - - ret = ib_send_cm_sidr_req(id_priv->cm_id.ib, &req); - if (ret) { - ib_destroy_cm_id(id_priv->cm_id.ib); - id_priv->cm_id.ib = NULL; - } -out: - kfree(req.private_data); - return ret; -} - static int cma_connect_ib(struct rdma_id_private *id_priv, struct rdma_conn_param *conn_param) { @@ -2025,7 +1860,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, req.service_id = cma_get_service_id(id_priv->id.ps, &route->addr.dst_addr); req.qp_num = id_priv->qp_num; - req.qp_type = IB_QPT_RC; + req.qp_type = id_priv->qp_type; req.starting_psn = id_priv->seq_num; req.responder_resources = conn_param->responder_resources; req.initiator_depth = conn_param->initiator_depth; @@ -2102,15 +1937,13 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) if (!id->qp) { id_priv->qp_num = conn_param->qp_num; + id_priv->qp_type = conn_param->qp_type; id_priv->srq = conn_param->srq; } switch (rdma_node_get_transport(id->device->node_type)) { case RDMA_TRANSPORT_IB: - if (id->ps == RDMA_PS_UDP) - ret = cma_resolve_ib_udp(id_priv, conn_param); - else - ret = cma_connect_ib(id_priv, conn_param); + ret = cma_connect_ib(id_priv, conn_param); break; case RDMA_TRANSPORT_IWARP: ret = cma_connect_iw(id_priv, conn_param); @@ -2133,25 +1966,11 @@ static int cma_accept_ib(struct rdma_id_private *id_priv, struct rdma_conn_param *conn_param) { struct ib_cm_rep_param rep; - struct ib_qp_attr qp_attr; - int qp_attr_mask, ret; - - if (id_priv->id.qp) { - ret = cma_modify_qp_rtr(&id_priv->id); - if (ret) - goto out; - - qp_attr.qp_state = IB_QPS_RTS; - ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr, - &qp_attr_mask); - if (ret) - goto out; + int ret; - qp_attr.max_rd_atomic = conn_param->initiator_depth; - ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask); - if (ret) - goto out; - } + ret = cma_modify_qp_rtr(&id_priv->id); + if (ret) + return ret; memset(&rep, 0, sizeof rep); rep.qp_num = id_priv->qp_num; @@ -2166,9 +1985,7 @@ static int cma_accept_ib(struct rdma_id_private *id_priv, rep.rnr_retry_count = conn_param->rnr_retry_count; rep.srq = id_priv->srq ? 1 : 0; - ret = ib_send_cm_rep(id_priv->cm_id.ib, &rep); -out: - return ret; + return ib_send_cm_rep(id_priv->cm_id.ib, &rep); } static int cma_accept_iw(struct rdma_id_private *id_priv, @@ -2193,24 +2010,6 @@ static int cma_accept_iw(struct rdma_id_private *id_priv, return iw_cm_accept(id_priv->cm_id.iw, &iw_param); } -static int cma_send_sidr_rep(struct rdma_id_private *id_priv, - enum ib_cm_sidr_status status, - const void *private_data, int private_data_len) -{ - struct ib_cm_sidr_rep_param rep; - - memset(&rep, 0, sizeof rep); - rep.status = status; - if (status == IB_SIDR_SUCCESS) { - rep.qp_num = id_priv->qp_num; - rep.qkey = RDMA_UD_QKEY; - } - rep.private_data = private_data; - rep.private_data_len = private_data_len; - - return ib_send_cm_sidr_rep(id_priv->cm_id.ib, &rep); -} - int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) { struct rdma_id_private *id_priv; @@ -2222,16 +2021,13 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) if (!id->qp && conn_param) { id_priv->qp_num = conn_param->qp_num; + id_priv->qp_type = conn_param->qp_type; id_priv->srq = conn_param->srq; } switch (rdma_node_get_transport(id->device->node_type)) { case RDMA_TRANSPORT_IB: - if (id->ps == RDMA_PS_UDP) - ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS, - conn_param->private_data, - conn_param->private_data_len); - else if (conn_param) + if (conn_param) ret = cma_accept_ib(id_priv, conn_param); else ret = cma_rep_recv(id_priv); @@ -2255,27 +2051,6 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) } EXPORT_SYMBOL(rdma_accept); -int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event) -{ - struct rdma_id_private *id_priv; - int ret; - - id_priv = container_of(id, struct rdma_id_private, id); - if (!cma_comp(id_priv, CMA_CONNECT)) - return -EINVAL; - - switch (id->device->node_type) { - case RDMA_NODE_IB_CA: - ret = ib_cm_notify(id_priv->cm_id.ib, event); - break; - default: - ret = 0; - break; - } - return ret; -} -EXPORT_SYMBOL(rdma_notify); - int rdma_reject(struct rdma_cm_id *id, const void *private_data, u8 private_data_len) { @@ -2288,13 +2063,9 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data, switch (rdma_node_get_transport(id->device->node_type)) { case RDMA_TRANSPORT_IB: - if (id->ps == RDMA_PS_UDP) - ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, - private_data, private_data_len); - else - ret = ib_send_cm_rej(id_priv->cm_id.ib, - IB_CM_REJ_CONSUMER_DEFINED, NULL, - 0, private_data, private_data_len); + ret = ib_send_cm_rej(id_priv->cm_id.ib, + IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, + private_data, private_data_len); break; case RDMA_TRANSPORT_IWARP: ret = iw_cm_reject(id_priv->cm_id.iw, @@ -2365,7 +2136,6 @@ static void cma_add_one(struct ib_device *device) static int cma_remove_id_dev(struct rdma_id_private *id_priv) { - struct rdma_cm_event event; enum cma_state state; /* Record that we want to remove the device */ @@ -2380,9 +2150,8 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv) if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL)) return 0; - memset(&event, 0, sizeof event); - event.event = RDMA_CM_EVENT_DEVICE_REMOVAL; - return id_priv->id.event_handler(&id_priv->id, &event); + return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL, + 0, NULL, 0); } static void cma_process_remove(struct cma_device *cma_dev) @@ -2464,7 +2233,6 @@ static void cma_cleanup(void) destroy_workqueue(cma_wq); idr_destroy(&sdp_ps); idr_destroy(&tcp_ps); - idr_destroy(&udp_ps); } module_init(cma_init); diff --git a/trunk/drivers/infiniband/core/fmr_pool.c b/trunk/drivers/infiniband/core/fmr_pool.c index 8926a2bd4a87..86a3b2d401db 100644 --- a/trunk/drivers/infiniband/core/fmr_pool.c +++ b/trunk/drivers/infiniband/core/fmr_pool.c @@ -394,12 +394,20 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool); */ int ib_flush_fmr_pool(struct ib_fmr_pool *pool) { - int serial = atomic_inc_return(&pool->req_ser); + int serial; + + atomic_inc(&pool->req_ser); + /* + * It's OK if someone else bumps req_ser again here -- we'll + * just wait a little longer. + */ + serial = atomic_read(&pool->req_ser); wake_up_process(pool->thread); if (wait_event_interruptible(pool->force_wait, - atomic_read(&pool->flush_ser) - serial >= 0)) + atomic_read(&pool->flush_ser) - + atomic_read(&pool->req_ser) >= 0)) return -EINTR; return 0; diff --git a/trunk/drivers/infiniband/core/mad.c b/trunk/drivers/infiniband/core/mad.c index 5ed141ebd1c8..15f38d94b3a8 100644 --- a/trunk/drivers/infiniband/core/mad.c +++ b/trunk/drivers/infiniband/core/mad.c @@ -998,17 +998,17 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr) mad_agent = mad_send_wr->send_buf.mad_agent; sge = mad_send_wr->sg_list; - sge[0].addr = ib_dma_map_single(mad_agent->device, - mad_send_wr->send_buf.mad, - sge[0].length, - DMA_TO_DEVICE); - mad_send_wr->header_mapping = sge[0].addr; - - sge[1].addr = ib_dma_map_single(mad_agent->device, - ib_get_payload(mad_send_wr), - sge[1].length, - DMA_TO_DEVICE); - mad_send_wr->payload_mapping = sge[1].addr; + sge[0].addr = dma_map_single(mad_agent->device->dma_device, + mad_send_wr->send_buf.mad, + sge[0].length, + DMA_TO_DEVICE); + pci_unmap_addr_set(mad_send_wr, header_mapping, sge[0].addr); + + sge[1].addr = dma_map_single(mad_agent->device->dma_device, + ib_get_payload(mad_send_wr), + sge[1].length, + DMA_TO_DEVICE); + pci_unmap_addr_set(mad_send_wr, payload_mapping, sge[1].addr); spin_lock_irqsave(&qp_info->send_queue.lock, flags); if (qp_info->send_queue.count < qp_info->send_queue.max_active) { @@ -1026,12 +1026,12 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr) } spin_unlock_irqrestore(&qp_info->send_queue.lock, flags); if (ret) { - ib_dma_unmap_single(mad_agent->device, - mad_send_wr->header_mapping, - sge[0].length, DMA_TO_DEVICE); - ib_dma_unmap_single(mad_agent->device, - mad_send_wr->payload_mapping, - sge[1].length, DMA_TO_DEVICE); + dma_unmap_single(mad_agent->device->dma_device, + pci_unmap_addr(mad_send_wr, header_mapping), + sge[0].length, DMA_TO_DEVICE); + dma_unmap_single(mad_agent->device->dma_device, + pci_unmap_addr(mad_send_wr, payload_mapping), + sge[1].length, DMA_TO_DEVICE); } return ret; } @@ -1850,11 +1850,11 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv, mad_priv_hdr = container_of(mad_list, struct ib_mad_private_header, mad_list); recv = container_of(mad_priv_hdr, struct ib_mad_private, header); - ib_dma_unmap_single(port_priv->device, - recv->header.mapping, - sizeof(struct ib_mad_private) - - sizeof(struct ib_mad_private_header), - DMA_FROM_DEVICE); + dma_unmap_single(port_priv->device->dma_device, + pci_unmap_addr(&recv->header, mapping), + sizeof(struct ib_mad_private) - + sizeof(struct ib_mad_private_header), + DMA_FROM_DEVICE); /* Setup MAD receive work completion from "normal" work completion */ recv->header.wc = *wc; @@ -2080,12 +2080,12 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv, qp_info = send_queue->qp_info; retry: - ib_dma_unmap_single(mad_send_wr->send_buf.mad_agent->device, - mad_send_wr->header_mapping, - mad_send_wr->sg_list[0].length, DMA_TO_DEVICE); - ib_dma_unmap_single(mad_send_wr->send_buf.mad_agent->device, - mad_send_wr->payload_mapping, - mad_send_wr->sg_list[1].length, DMA_TO_DEVICE); + dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device, + pci_unmap_addr(mad_send_wr, header_mapping), + mad_send_wr->sg_list[0].length, DMA_TO_DEVICE); + dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device, + pci_unmap_addr(mad_send_wr, payload_mapping), + mad_send_wr->sg_list[1].length, DMA_TO_DEVICE); queued_send_wr = NULL; spin_lock_irqsave(&send_queue->lock, flags); list_del(&mad_list->list); @@ -2528,12 +2528,13 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, break; } } - sg_list.addr = ib_dma_map_single(qp_info->port_priv->device, - &mad_priv->grh, - sizeof *mad_priv - - sizeof mad_priv->header, - DMA_FROM_DEVICE); - mad_priv->header.mapping = sg_list.addr; + sg_list.addr = dma_map_single(qp_info->port_priv-> + device->dma_device, + &mad_priv->grh, + sizeof *mad_priv - + sizeof mad_priv->header, + DMA_FROM_DEVICE); + pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr); recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list; mad_priv->header.mad_list.mad_queue = recv_queue; @@ -2548,11 +2549,12 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, list_del(&mad_priv->header.mad_list.list); recv_queue->count--; spin_unlock_irqrestore(&recv_queue->lock, flags); - ib_dma_unmap_single(qp_info->port_priv->device, - mad_priv->header.mapping, - sizeof *mad_priv - - sizeof mad_priv->header, - DMA_FROM_DEVICE); + dma_unmap_single(qp_info->port_priv->device->dma_device, + pci_unmap_addr(&mad_priv->header, + mapping), + sizeof *mad_priv - + sizeof mad_priv->header, + DMA_FROM_DEVICE); kmem_cache_free(ib_mad_cache, mad_priv); printk(KERN_ERR PFX "ib_post_recv failed: %d\n", ret); break; @@ -2584,11 +2586,11 @@ static void cleanup_recv_queue(struct ib_mad_qp_info *qp_info) /* Remove from posted receive MAD list */ list_del(&mad_list->list); - ib_dma_unmap_single(qp_info->port_priv->device, - recv->header.mapping, - sizeof(struct ib_mad_private) - - sizeof(struct ib_mad_private_header), - DMA_FROM_DEVICE); + dma_unmap_single(qp_info->port_priv->device->dma_device, + pci_unmap_addr(&recv->header, mapping), + sizeof(struct ib_mad_private) - + sizeof(struct ib_mad_private_header), + DMA_FROM_DEVICE); kmem_cache_free(ib_mad_cache, recv); } diff --git a/trunk/drivers/infiniband/core/mad_priv.h b/trunk/drivers/infiniband/core/mad_priv.h index de89717f49fe..d5548e73e068 100644 --- a/trunk/drivers/infiniband/core/mad_priv.h +++ b/trunk/drivers/infiniband/core/mad_priv.h @@ -73,7 +73,7 @@ struct ib_mad_private_header { struct ib_mad_list_head mad_list; struct ib_mad_recv_wc recv_wc; struct ib_wc wc; - u64 mapping; + DECLARE_PCI_UNMAP_ADDR(mapping) } __attribute__ ((packed)); struct ib_mad_private { @@ -126,8 +126,8 @@ struct ib_mad_send_wr_private { struct list_head agent_list; struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_buf send_buf; - u64 header_mapping; - u64 payload_mapping; + DECLARE_PCI_UNMAP_ADDR(header_mapping) + DECLARE_PCI_UNMAP_ADDR(payload_mapping) struct ib_send_wr send_wr; struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG]; __be64 tid; diff --git a/trunk/drivers/infiniband/core/ucma.c b/trunk/drivers/infiniband/core/ucma.c deleted file mode 100644 index 81a5cdc5733a..000000000000 --- a/trunk/drivers/infiniband/core/ucma.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Sean Hefty"); -MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access"); -MODULE_LICENSE("Dual BSD/GPL"); - -enum { - UCMA_MAX_BACKLOG = 128 -}; - -struct ucma_file { - struct mutex mut; - struct file *filp; - struct list_head ctx_list; - struct list_head event_list; - wait_queue_head_t poll_wait; -}; - -struct ucma_context { - int id; - struct completion comp; - atomic_t ref; - int events_reported; - int backlog; - - struct ucma_file *file; - struct rdma_cm_id *cm_id; - u64 uid; - - struct list_head list; -}; - -struct ucma_event { - struct ucma_context *ctx; - struct list_head list; - struct rdma_cm_id *cm_id; - struct rdma_ucm_event_resp resp; -}; - -static DEFINE_MUTEX(mut); -static DEFINE_IDR(ctx_idr); - -static inline struct ucma_context *_ucma_find_context(int id, - struct ucma_file *file) -{ - struct ucma_context *ctx; - - ctx = idr_find(&ctx_idr, id); - if (!ctx) - ctx = ERR_PTR(-ENOENT); - else if (ctx->file != file) - ctx = ERR_PTR(-EINVAL); - return ctx; -} - -static struct ucma_context *ucma_get_ctx(struct ucma_file *file, int id) -{ - struct ucma_context *ctx; - - mutex_lock(&mut); - ctx = _ucma_find_context(id, file); - if (!IS_ERR(ctx)) - atomic_inc(&ctx->ref); - mutex_unlock(&mut); - return ctx; -} - -static void ucma_put_ctx(struct ucma_context *ctx) -{ - if (atomic_dec_and_test(&ctx->ref)) - complete(&ctx->comp); -} - -static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file) -{ - struct ucma_context *ctx; - int ret; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return NULL; - - atomic_set(&ctx->ref, 1); - init_completion(&ctx->comp); - ctx->file = file; - - do { - ret = idr_pre_get(&ctx_idr, GFP_KERNEL); - if (!ret) - goto error; - - mutex_lock(&mut); - ret = idr_get_new(&ctx_idr, ctx, &ctx->id); - mutex_unlock(&mut); - } while (ret == -EAGAIN); - - if (ret) - goto error; - - list_add_tail(&ctx->list, &file->ctx_list); - return ctx; - -error: - kfree(ctx); - return NULL; -} - -static void ucma_copy_conn_event(struct rdma_ucm_conn_param *dst, - struct rdma_conn_param *src) -{ - if (src->private_data_len) - memcpy(dst->private_data, src->private_data, - src->private_data_len); - dst->private_data_len = src->private_data_len; - dst->responder_resources =src->responder_resources; - dst->initiator_depth = src->initiator_depth; - dst->flow_control = src->flow_control; - dst->retry_count = src->retry_count; - dst->rnr_retry_count = src->rnr_retry_count; - dst->srq = src->srq; - dst->qp_num = src->qp_num; -} - -static void ucma_copy_ud_event(struct rdma_ucm_ud_param *dst, - struct rdma_ud_param *src) -{ - if (src->private_data_len) - memcpy(dst->private_data, src->private_data, - src->private_data_len); - dst->private_data_len = src->private_data_len; - ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr); - dst->qp_num = src->qp_num; - dst->qkey = src->qkey; -} - -static void ucma_set_event_context(struct ucma_context *ctx, - struct rdma_cm_event *event, - struct ucma_event *uevent) -{ - uevent->ctx = ctx; - uevent->resp.uid = ctx->uid; - uevent->resp.id = ctx->id; -} - -static int ucma_event_handler(struct rdma_cm_id *cm_id, - struct rdma_cm_event *event) -{ - struct ucma_event *uevent; - struct ucma_context *ctx = cm_id->context; - int ret = 0; - - uevent = kzalloc(sizeof(*uevent), GFP_KERNEL); - if (!uevent) - return event->event == RDMA_CM_EVENT_CONNECT_REQUEST; - - uevent->cm_id = cm_id; - ucma_set_event_context(ctx, event, uevent); - uevent->resp.event = event->event; - uevent->resp.status = event->status; - if (cm_id->ps == RDMA_PS_UDP) - ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud); - else - ucma_copy_conn_event(&uevent->resp.param.conn, - &event->param.conn); - - mutex_lock(&ctx->file->mut); - if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) { - if (!ctx->backlog) { - ret = -EDQUOT; - goto out; - } - ctx->backlog--; - } - list_add_tail(&uevent->list, &ctx->file->event_list); - wake_up_interruptible(&ctx->file->poll_wait); -out: - mutex_unlock(&ctx->file->mut); - return ret; -} - -static ssize_t ucma_get_event(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct ucma_context *ctx; - struct rdma_ucm_get_event cmd; - struct ucma_event *uevent; - int ret = 0; - DEFINE_WAIT(wait); - - if (out_len < sizeof uevent->resp) - return -ENOSPC; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - mutex_lock(&file->mut); - while (list_empty(&file->event_list)) { - if (file->filp->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - prepare_to_wait(&file->poll_wait, &wait, TASK_INTERRUPTIBLE); - mutex_unlock(&file->mut); - schedule(); - mutex_lock(&file->mut); - finish_wait(&file->poll_wait, &wait); - } - - if (ret) - goto done; - - uevent = list_entry(file->event_list.next, struct ucma_event, list); - - if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST) { - ctx = ucma_alloc_ctx(file); - if (!ctx) { - ret = -ENOMEM; - goto done; - } - uevent->ctx->backlog++; - ctx->cm_id = uevent->cm_id; - ctx->cm_id->context = ctx; - uevent->resp.id = ctx->id; - } - - if (copy_to_user((void __user *)(unsigned long)cmd.response, - &uevent->resp, sizeof uevent->resp)) { - ret = -EFAULT; - goto done; - } - - list_del(&uevent->list); - uevent->ctx->events_reported++; - kfree(uevent); -done: - mutex_unlock(&file->mut); - return ret; -} - -static ssize_t ucma_create_id(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_create_id cmd; - struct rdma_ucm_create_id_resp resp; - struct ucma_context *ctx; - int ret; - - if (out_len < sizeof(resp)) - return -ENOSPC; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - mutex_lock(&file->mut); - ctx = ucma_alloc_ctx(file); - mutex_unlock(&file->mut); - if (!ctx) - return -ENOMEM; - - ctx->uid = cmd.uid; - ctx->cm_id = rdma_create_id(ucma_event_handler, ctx, cmd.ps); - if (IS_ERR(ctx->cm_id)) { - ret = PTR_ERR(ctx->cm_id); - goto err1; - } - - resp.id = ctx->id; - if (copy_to_user((void __user *)(unsigned long)cmd.response, - &resp, sizeof(resp))) { - ret = -EFAULT; - goto err2; - } - return 0; - -err2: - rdma_destroy_id(ctx->cm_id); -err1: - mutex_lock(&mut); - idr_remove(&ctx_idr, ctx->id); - mutex_unlock(&mut); - kfree(ctx); - return ret; -} - -static void ucma_cleanup_events(struct ucma_context *ctx) -{ - struct ucma_event *uevent, *tmp; - - list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list) { - if (uevent->ctx != ctx) - continue; - - list_del(&uevent->list); - - /* clear incoming connections. */ - if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST) - rdma_destroy_id(uevent->cm_id); - - kfree(uevent); - } -} - -static int ucma_free_ctx(struct ucma_context *ctx) -{ - int events_reported; - - /* No new events will be generated after destroying the id. */ - rdma_destroy_id(ctx->cm_id); - - /* Cleanup events not yet reported to the user. */ - mutex_lock(&ctx->file->mut); - ucma_cleanup_events(ctx); - list_del(&ctx->list); - mutex_unlock(&ctx->file->mut); - - events_reported = ctx->events_reported; - kfree(ctx); - return events_reported; -} - -static ssize_t ucma_destroy_id(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_destroy_id cmd; - struct rdma_ucm_destroy_id_resp resp; - struct ucma_context *ctx; - int ret = 0; - - if (out_len < sizeof(resp)) - return -ENOSPC; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - mutex_lock(&mut); - ctx = _ucma_find_context(cmd.id, file); - if (!IS_ERR(ctx)) - idr_remove(&ctx_idr, ctx->id); - mutex_unlock(&mut); - - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ucma_put_ctx(ctx); - wait_for_completion(&ctx->comp); - resp.events_reported = ucma_free_ctx(ctx); - - if (copy_to_user((void __user *)(unsigned long)cmd.response, - &resp, sizeof(resp))) - ret = -EFAULT; - - return ret; -} - -static ssize_t ucma_bind_addr(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_bind_addr cmd; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr); - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t ucma_resolve_addr(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_resolve_addr cmd; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr, - (struct sockaddr *) &cmd.dst_addr, - cmd.timeout_ms); - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t ucma_resolve_route(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_resolve_route cmd; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ret = rdma_resolve_route(ctx->cm_id, cmd.timeout_ms); - ucma_put_ctx(ctx); - return ret; -} - -static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp, - struct rdma_route *route) -{ - struct rdma_dev_addr *dev_addr; - - resp->num_paths = route->num_paths; - switch (route->num_paths) { - case 0: - dev_addr = &route->addr.dev_addr; - ib_addr_get_dgid(dev_addr, - (union ib_gid *) &resp->ib_route[0].dgid); - ib_addr_get_sgid(dev_addr, - (union ib_gid *) &resp->ib_route[0].sgid); - resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); - break; - case 2: - ib_copy_path_rec_to_user(&resp->ib_route[1], - &route->path_rec[1]); - /* fall through */ - case 1: - ib_copy_path_rec_to_user(&resp->ib_route[0], - &route->path_rec[0]); - break; - default: - break; - } -} - -static ssize_t ucma_query_route(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_query_route cmd; - struct rdma_ucm_query_route_resp resp; - struct ucma_context *ctx; - struct sockaddr *addr; - int ret = 0; - - if (out_len < sizeof(resp)) - return -ENOSPC; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - memset(&resp, 0, sizeof resp); - addr = &ctx->cm_id->route.addr.src_addr; - memcpy(&resp.src_addr, addr, addr->sa_family == AF_INET ? - sizeof(struct sockaddr_in) : - sizeof(struct sockaddr_in6)); - addr = &ctx->cm_id->route.addr.dst_addr; - memcpy(&resp.dst_addr, addr, addr->sa_family == AF_INET ? - sizeof(struct sockaddr_in) : - sizeof(struct sockaddr_in6)); - if (!ctx->cm_id->device) - goto out; - - resp.node_guid = ctx->cm_id->device->node_guid; - resp.port_num = ctx->cm_id->port_num; - switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) { - case RDMA_TRANSPORT_IB: - ucma_copy_ib_route(&resp, &ctx->cm_id->route); - break; - default: - break; - } - -out: - if (copy_to_user((void __user *)(unsigned long)cmd.response, - &resp, sizeof(resp))) - ret = -EFAULT; - - ucma_put_ctx(ctx); - return ret; -} - -static void ucma_copy_conn_param(struct rdma_conn_param *dst, - struct rdma_ucm_conn_param *src) -{ - dst->private_data = src->private_data; - dst->private_data_len = src->private_data_len; - dst->responder_resources =src->responder_resources; - dst->initiator_depth = src->initiator_depth; - dst->flow_control = src->flow_control; - dst->retry_count = src->retry_count; - dst->rnr_retry_count = src->rnr_retry_count; - dst->srq = src->srq; - dst->qp_num = src->qp_num; -} - -static ssize_t ucma_connect(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_connect cmd; - struct rdma_conn_param conn_param; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - if (!cmd.conn_param.valid) - return -EINVAL; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ucma_copy_conn_param(&conn_param, &cmd.conn_param); - ret = rdma_connect(ctx->cm_id, &conn_param); - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t ucma_listen(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_listen cmd; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ctx->backlog = cmd.backlog > 0 && cmd.backlog < UCMA_MAX_BACKLOG ? - cmd.backlog : UCMA_MAX_BACKLOG; - ret = rdma_listen(ctx->cm_id, ctx->backlog); - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_accept cmd; - struct rdma_conn_param conn_param; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - if (cmd.conn_param.valid) { - ctx->uid = cmd.uid; - ucma_copy_conn_param(&conn_param, &cmd.conn_param); - ret = rdma_accept(ctx->cm_id, &conn_param); - } else - ret = rdma_accept(ctx->cm_id, NULL); - - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t ucma_reject(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_reject cmd; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ret = rdma_reject(ctx->cm_id, cmd.private_data, cmd.private_data_len); - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t ucma_disconnect(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_disconnect cmd; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ret = rdma_disconnect(ctx->cm_id); - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t ucma_init_qp_attr(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_init_qp_attr cmd; - struct ib_uverbs_qp_attr resp; - struct ucma_context *ctx; - struct ib_qp_attr qp_attr; - int ret; - - if (out_len < sizeof(resp)) - return -ENOSPC; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - resp.qp_attr_mask = 0; - memset(&qp_attr, 0, sizeof qp_attr); - qp_attr.qp_state = cmd.qp_state; - ret = rdma_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask); - if (ret) - goto out; - - ib_copy_qp_attr_to_user(&resp, &qp_attr); - if (copy_to_user((void __user *)(unsigned long)cmd.response, - &resp, sizeof(resp))) - ret = -EFAULT; - -out: - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf, - int in_len, int out_len) -{ - struct rdma_ucm_notify cmd; - struct ucma_context *ctx; - int ret; - - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; - - ctx = ucma_get_ctx(file, cmd.id); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - ret = rdma_notify(ctx->cm_id, (enum ib_event_type) cmd.event); - ucma_put_ctx(ctx); - return ret; -} - -static ssize_t (*ucma_cmd_table[])(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) = { - [RDMA_USER_CM_CMD_CREATE_ID] = ucma_create_id, - [RDMA_USER_CM_CMD_DESTROY_ID] = ucma_destroy_id, - [RDMA_USER_CM_CMD_BIND_ADDR] = ucma_bind_addr, - [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr, - [RDMA_USER_CM_CMD_RESOLVE_ROUTE]= ucma_resolve_route, - [RDMA_USER_CM_CMD_QUERY_ROUTE] = ucma_query_route, - [RDMA_USER_CM_CMD_CONNECT] = ucma_connect, - [RDMA_USER_CM_CMD_LISTEN] = ucma_listen, - [RDMA_USER_CM_CMD_ACCEPT] = ucma_accept, - [RDMA_USER_CM_CMD_REJECT] = ucma_reject, - [RDMA_USER_CM_CMD_DISCONNECT] = ucma_disconnect, - [RDMA_USER_CM_CMD_INIT_QP_ATTR] = ucma_init_qp_attr, - [RDMA_USER_CM_CMD_GET_EVENT] = ucma_get_event, - [RDMA_USER_CM_CMD_GET_OPTION] = NULL, - [RDMA_USER_CM_CMD_SET_OPTION] = NULL, - [RDMA_USER_CM_CMD_NOTIFY] = ucma_notify, -}; - -static ssize_t ucma_write(struct file *filp, const char __user *buf, - size_t len, loff_t *pos) -{ - struct ucma_file *file = filp->private_data; - struct rdma_ucm_cmd_hdr hdr; - ssize_t ret; - - if (len < sizeof(hdr)) - return -EINVAL; - - if (copy_from_user(&hdr, buf, sizeof(hdr))) - return -EFAULT; - - if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucma_cmd_table)) - return -EINVAL; - - if (hdr.in + sizeof(hdr) > len) - return -EINVAL; - - if (!ucma_cmd_table[hdr.cmd]) - return -ENOSYS; - - ret = ucma_cmd_table[hdr.cmd](file, buf + sizeof(hdr), hdr.in, hdr.out); - if (!ret) - ret = len; - - return ret; -} - -static unsigned int ucma_poll(struct file *filp, struct poll_table_struct *wait) -{ - struct ucma_file *file = filp->private_data; - unsigned int mask = 0; - - poll_wait(filp, &file->poll_wait, wait); - - if (!list_empty(&file->event_list)) - mask = POLLIN | POLLRDNORM; - - return mask; -} - -static int ucma_open(struct inode *inode, struct file *filp) -{ - struct ucma_file *file; - - file = kmalloc(sizeof *file, GFP_KERNEL); - if (!file) - return -ENOMEM; - - INIT_LIST_HEAD(&file->event_list); - INIT_LIST_HEAD(&file->ctx_list); - init_waitqueue_head(&file->poll_wait); - mutex_init(&file->mut); - - filp->private_data = file; - file->filp = filp; - return 0; -} - -static int ucma_close(struct inode *inode, struct file *filp) -{ - struct ucma_file *file = filp->private_data; - struct ucma_context *ctx, *tmp; - - mutex_lock(&file->mut); - list_for_each_entry_safe(ctx, tmp, &file->ctx_list, list) { - mutex_unlock(&file->mut); - - mutex_lock(&mut); - idr_remove(&ctx_idr, ctx->id); - mutex_unlock(&mut); - - ucma_free_ctx(ctx); - mutex_lock(&file->mut); - } - mutex_unlock(&file->mut); - kfree(file); - return 0; -} - -static struct file_operations ucma_fops = { - .owner = THIS_MODULE, - .open = ucma_open, - .release = ucma_close, - .write = ucma_write, - .poll = ucma_poll, -}; - -static struct miscdevice ucma_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = "rdma_cm", - .fops = &ucma_fops, -}; - -static ssize_t show_abi_version(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", RDMA_USER_CM_ABI_VERSION); -} -static DEVICE_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); - -static int __init ucma_init(void) -{ - int ret; - - ret = misc_register(&ucma_misc); - if (ret) - return ret; - - ret = device_create_file(ucma_misc.this_device, &dev_attr_abi_version); - if (ret) { - printk(KERN_ERR "rdma_ucm: couldn't create abi_version attr\n"); - goto err; - } - return 0; -err: - misc_deregister(&ucma_misc); - return ret; -} - -static void __exit ucma_cleanup(void) -{ - device_remove_file(ucma_misc.this_device, &dev_attr_abi_version); - misc_deregister(&ucma_misc); - idr_destroy(&ctx_idr); -} - -module_init(ucma_init); -module_exit(ucma_cleanup); diff --git a/trunk/drivers/infiniband/core/uverbs_marshall.c b/trunk/drivers/infiniband/core/uverbs_marshall.c index 5440da0e59b4..ce46b13ae02b 100644 --- a/trunk/drivers/infiniband/core/uverbs_marshall.c +++ b/trunk/drivers/infiniband/core/uverbs_marshall.c @@ -32,8 +32,8 @@ #include -void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst, - struct ib_ah_attr *src) +static void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst, + struct ib_ah_attr *src) { memcpy(dst->grh.dgid, src->grh.dgid.raw, sizeof src->grh.dgid); dst->grh.flow_label = src->grh.flow_label; @@ -47,7 +47,6 @@ void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst, dst->is_global = src->ah_flags & IB_AH_GRH ? 1 : 0; dst->port_num = src->port_num; } -EXPORT_SYMBOL(ib_copy_ah_attr_to_user); void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst, struct ib_qp_attr *src) diff --git a/trunk/drivers/infiniband/core/uverbs_mem.c b/trunk/drivers/infiniband/core/uverbs_mem.c index c95fe952abd5..db12cc0841df 100644 --- a/trunk/drivers/infiniband/core/uverbs_mem.c +++ b/trunk/drivers/infiniband/core/uverbs_mem.c @@ -52,8 +52,8 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d int i; list_for_each_entry_safe(chunk, tmp, &umem->chunk_list, list) { - ib_dma_unmap_sg(dev, chunk->page_list, - chunk->nents, DMA_BIDIRECTIONAL); + dma_unmap_sg(dev->dma_device, chunk->page_list, + chunk->nents, DMA_BIDIRECTIONAL); for (i = 0; i < chunk->nents; ++i) { if (umem->writable && dirty) set_page_dirty_lock(chunk->page_list[i].page); @@ -136,10 +136,10 @@ int ib_umem_get(struct ib_device *dev, struct ib_umem *mem, chunk->page_list[i].length = PAGE_SIZE; } - chunk->nmap = ib_dma_map_sg(dev, - &chunk->page_list[0], - chunk->nents, - DMA_BIDIRECTIONAL); + chunk->nmap = dma_map_sg(dev->dma_device, + &chunk->page_list[0], + chunk->nents, + DMA_BIDIRECTIONAL); if (chunk->nmap <= 0) { for (i = 0; i < chunk->nents; ++i) put_page(chunk->page_list[i].page); diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_qp.c b/trunk/drivers/infiniband/hw/amso1100/c2_qp.c index 420c1380f5c3..179d005ed4a5 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_qp.c +++ b/trunk/drivers/infiniband/hw/amso1100/c2_qp.c @@ -161,10 +161,8 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp, if (attr_mask & IB_QP_STATE) { /* Ensure the state is valid */ - if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) { - err = -EINVAL; - goto bail0; - } + if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) + return -EINVAL; wr.next_qp_state = cpu_to_be32(to_c2_state(attr->qp_state)); @@ -186,10 +184,9 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp, if (attr->cur_qp_state != IB_QPS_RTR && attr->cur_qp_state != IB_QPS_RTS && attr->cur_qp_state != IB_QPS_SQD && - attr->cur_qp_state != IB_QPS_SQE) { - err = -EINVAL; - goto bail0; - } else + attr->cur_qp_state != IB_QPS_SQE) + return -EINVAL; + else wr.next_qp_state = cpu_to_be32(to_c2_state(attr->cur_qp_state)); diff --git a/trunk/drivers/infiniband/hw/ipath/Makefile b/trunk/drivers/infiniband/hw/ipath/Makefile index ec2e603ea241..7dc10551cf18 100644 --- a/trunk/drivers/infiniband/hw/ipath/Makefile +++ b/trunk/drivers/infiniband/hw/ipath/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o ib_ipath-y := \ ipath_cq.o \ ipath_diag.o \ - ipath_dma.o \ ipath_driver.o \ ipath_eeprom.o \ ipath_file_ops.o \ diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_dma.c b/trunk/drivers/infiniband/hw/ipath/ipath_dma.c deleted file mode 100644 index 6e0f2b8918ce..000000000000 --- a/trunk/drivers/infiniband/hw/ipath/ipath_dma.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2006 QLogic, Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "ipath_verbs.h" - -#define BAD_DMA_ADDRESS ((u64) 0) - -/* - * The following functions implement driver specific replacements - * for the ib_dma_*() functions. - * - * These functions return kernel virtual addresses instead of - * device bus addresses since the driver uses the CPU to copy - * data instead of using hardware DMA. - */ - -static int ipath_mapping_error(struct ib_device *dev, u64 dma_addr) -{ - return dma_addr == BAD_DMA_ADDRESS; -} - -static u64 ipath_dma_map_single(struct ib_device *dev, - void *cpu_addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); - return (u64) cpu_addr; -} - -static void ipath_dma_unmap_single(struct ib_device *dev, - u64 addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); -} - -static u64 ipath_dma_map_page(struct ib_device *dev, - struct page *page, - unsigned long offset, - size_t size, - enum dma_data_direction direction) -{ - u64 addr; - - BUG_ON(!valid_dma_direction(direction)); - - if (offset + size > PAGE_SIZE) { - addr = BAD_DMA_ADDRESS; - goto done; - } - - addr = (u64) page_address(page); - if (addr) - addr += offset; - /* TODO: handle highmem pages */ - -done: - return addr; -} - -static void ipath_dma_unmap_page(struct ib_device *dev, - u64 addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); -} - -int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction direction) -{ - u64 addr; - int i; - int ret = nents; - - BUG_ON(!valid_dma_direction(direction)); - - for (i = 0; i < nents; i++) { - addr = (u64) page_address(sg[i].page); - /* TODO: handle highmem pages */ - if (!addr) { - ret = 0; - break; - } - } - return ret; -} - -static void ipath_unmap_sg(struct ib_device *dev, - struct scatterlist *sg, int nents, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); -} - -static u64 ipath_sg_dma_address(struct ib_device *dev, struct scatterlist *sg) -{ - u64 addr = (u64) page_address(sg->page); - - if (addr) - addr += sg->offset; - return addr; -} - -static unsigned int ipath_sg_dma_len(struct ib_device *dev, - struct scatterlist *sg) -{ - return sg->length; -} - -static void ipath_sync_single_for_cpu(struct ib_device *dev, - u64 addr, - size_t size, - enum dma_data_direction dir) -{ -} - -static void ipath_sync_single_for_device(struct ib_device *dev, - u64 addr, - size_t size, - enum dma_data_direction dir) -{ -} - -static void *ipath_dma_alloc_coherent(struct ib_device *dev, size_t size, - u64 *dma_handle, gfp_t flag) -{ - struct page *p; - void *addr = NULL; - - p = alloc_pages(flag, get_order(size)); - if (p) - addr = page_address(p); - if (dma_handle) - *dma_handle = (u64) addr; - return addr; -} - -static void ipath_dma_free_coherent(struct ib_device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_handle) -{ - free_pages((unsigned long) cpu_addr, get_order(size)); -} - -struct ib_dma_mapping_ops ipath_dma_mapping_ops = { - ipath_mapping_error, - ipath_dma_map_single, - ipath_dma_unmap_single, - ipath_dma_map_page, - ipath_dma_unmap_page, - ipath_map_sg, - ipath_unmap_sg, - ipath_sg_dma_address, - ipath_sg_dma_len, - ipath_sync_single_for_cpu, - ipath_sync_single_for_device, - ipath_dma_alloc_coherent, - ipath_dma_free_coherent -}; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_driver.c b/trunk/drivers/infiniband/hw/ipath/ipath_driver.c index ae7f21a0cdc0..1aeddb48e355 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_driver.c @@ -1825,6 +1825,8 @@ void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno, */ void ipath_shutdown_device(struct ipath_devdata *dd) { + u64 val; + ipath_dbg("Shutting down the device\n"); dd->ipath_flags |= IPATH_LINKUNK; @@ -1847,7 +1849,7 @@ void ipath_shutdown_device(struct ipath_devdata *dd) */ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL); /* flush it */ - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); + val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); /* * enough for anything that's going to trickle out to have actually * done so. diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c b/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c index b932bcb67a5e..340f27e3ebff 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -699,6 +699,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport, int start_stop) { struct ipath_devdata *dd = pd->port_dd; + u64 tval; ipath_cdbg(PROC, "%sabling rcv for unit %u port %u:%u\n", start_stop ? "en" : "dis", dd->ipath_unit, @@ -728,7 +729,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport, ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl); /* now be sure chip saw it before we return */ - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); + tval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); if (start_stop) { /* * And try to be sure that tail reg update has happened too. @@ -737,7 +738,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport, * in memory copy, since we could overwrite an update by the * chip if we did. */ - ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port); + tval = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port); } /* always; new head should be equal to new tail; see above */ bail: diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c b/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c index 7468477ba837..e57c7a351cb5 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c @@ -1447,7 +1447,7 @@ static void ipath_ht_tidtemplate(struct ipath_devdata *dd) static int ipath_ht_early_init(struct ipath_devdata *dd) { u32 __iomem *piobuf; - u32 pioincr, val32; + u32 pioincr, val32, egrsize; int i; /* @@ -1467,6 +1467,7 @@ static int ipath_ht_early_init(struct ipath_devdata *dd) * errors interrupts if we ever see one). */ dd->ipath_rcvegrbufsize = dd->ipath_piosize2k; + egrsize = dd->ipath_rcvegrbufsize; /* * the min() check here is currently a nop, but it may not diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c b/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c index ae8bf9950c6d..6af89683f710 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c @@ -602,7 +602,7 @@ static void ipath_pe_init_hwerrors(struct ipath_devdata *dd) */ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd) { - u64 val, config1, prev_val; + u64 val, tmp, config1, prev_val; int ret = 0; ipath_dbg("Trying to bringup serdes\n"); @@ -633,7 +633,7 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd) | INFINIPATH_SERDC0_L1PWR_DN; ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); /* be sure chip saw it */ - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); + tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); udelay(5); /* need pll reset set at least for a bit */ /* * after PLL is reset, set the per-lane Resets and TxIdle and @@ -647,7 +647,7 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd) "and txidle (%llx)\n", (unsigned long long) val); ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); /* be sure chip saw it */ - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); + tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); /* need PLL reset clear for at least 11 usec before lane * resets cleared; give it a few more to be sure */ udelay(15); @@ -851,12 +851,12 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd, int pos, ret; dd->ipath_msi_lo = 0; /* used as a flag during reset processing */ + dd->ipath_irq = pdev->irq; ret = pci_enable_msi(dd->pcidev); if (ret) ipath_dev_err(dd, "pci_enable_msi failed: %d, " "interrupts may not work\n", ret); /* continue even if it fails, we may still be OK... */ - dd->ipath_irq = pdev->irq; if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) { u16 control; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c b/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c index d4f6b5239ef8..d819cca524cd 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c @@ -347,9 +347,10 @@ static int init_chip_first(struct ipath_devdata *dd, static int init_chip_reset(struct ipath_devdata *dd, struct ipath_portdata **pdp) { + struct ipath_portdata *pd; u32 rtmp; - *pdp = dd->ipath_pd[0]; + *pdp = pd = dd->ipath_pd[0]; /* ensure chip does no sends or receives while we re-initialize */ dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U; ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_intr.c b/trunk/drivers/infiniband/hw/ipath/ipath_intr.c index 72b9e279d19d..5652a550d442 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_intr.c @@ -598,9 +598,10 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) * on close */ if (errs & INFINIPATH_E_RRCVHDRFULL) { + int any; u32 hd, tl; ipath_stats.sps_hdrqfull++; - for (i = 0; i < dd->ipath_cfgports; i++) { + for (any = i = 0; i < dd->ipath_cfgports; i++) { struct ipath_portdata *pd = dd->ipath_pd[i]; if (i == 0) { hd = dd->ipath_port0head; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_keys.c b/trunk/drivers/infiniband/hw/ipath/ipath_keys.c index 851763d7d2db..9a6cbd05adcd 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_keys.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_keys.c @@ -134,7 +134,7 @@ int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge, */ if (sge->lkey == 0) { isge->mr = NULL; - isge->vaddr = (void *) sge->addr; + isge->vaddr = bus_to_virt(sge->addr); isge->length = sge->length; isge->sge_length = sge->length; ret = 1; @@ -202,12 +202,12 @@ int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss, int ret; /* - * We use RKEY == zero for kernel virtual addresses - * (see ipath_get_dma_mr and ipath_dma.c). + * We use RKEY == zero for physical addresses + * (see ipath_get_dma_mr). */ if (rkey == 0) { sge->mr = NULL; - sge->vaddr = (void *) vaddr; + sge->vaddr = phys_to_virt(vaddr); sge->length = len; sge->sge_length = len; ss->sg_list = NULL; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_mr.c b/trunk/drivers/infiniband/hw/ipath/ipath_mr.c index 8cc8598d6c69..a0673c1eef71 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_mr.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_mr.c @@ -54,8 +54,6 @@ static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr) * @acc: access flags * * Returns the memory region on success, otherwise returns an errno. - * Note that all DMA addresses should be created via the - * struct ib_dma_mapping_ops functions (see ipath_dma.c). */ struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc) { @@ -151,7 +149,8 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd, m = 0; n = 0; for (i = 0; i < num_phys_buf; i++) { - mr->mr.map[m]->segs[n].vaddr = (void *) buffer_list[i].addr; + mr->mr.map[m]->segs[n].vaddr = + phys_to_virt(buffer_list[i].addr); mr->mr.map[m]->segs[n].length = buffer_list[i].size; mr->mr.length += buffer_list[i].size; n++; @@ -348,7 +347,7 @@ int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list, n = 0; ps = 1 << fmr->page_shift; for (i = 0; i < list_len; i++) { - fmr->mr.map[m]->segs[n].vaddr = (void *) page_list[i]; + fmr->mr.map[m]->segs[n].vaddr = phys_to_virt(page_list[i]); fmr->mr.map[m]->segs[n].length = ps; if (++n == IPATH_SEGSZ) { m++; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c b/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c index ffa6318ad0cc..182de34f9f47 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c @@ -215,6 +215,7 @@ static ssize_t store_mlid(struct device *dev, size_t count) { struct ipath_devdata *dd = dev_get_drvdata(dev); + int unit; u16 mlid; int ret; @@ -222,6 +223,8 @@ static ssize_t store_mlid(struct device *dev, if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE) goto invalid; + unit = dd->ipath_unit; + dd->ipath_mlid = mlid; goto bail; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c index 2aaacdb7e52a..acdee33ee1f8 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -1599,7 +1599,6 @@ int ipath_register_ib_device(struct ipath_devdata *dd) dev->detach_mcast = ipath_multicast_detach; dev->process_mad = ipath_process_mad; dev->mmap = ipath_mmap; - dev->dma_ops = &ipath_dma_mapping_ops; snprintf(dev->node_desc, sizeof(dev->node_desc), IPATH_IDSTR " %s", init_utsname()->nodename); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h index c0c8d5b24a7d..8039f6e5f0c8 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h @@ -812,6 +812,4 @@ extern unsigned int ib_ipath_max_srq_wrs; extern const u32 ib_ipath_rnr_table[]; -extern struct ib_dma_mapping_ops ipath_dma_mapping_ops; - #endif /* IPATH_VERBS_H */ diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h index 07deee8f81ce..99547996aba2 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h @@ -105,12 +105,12 @@ struct ipoib_mcast; struct ipoib_rx_buf { struct sk_buff *skb; - u64 mapping; + dma_addr_t mapping; }; struct ipoib_tx_buf { struct sk_buff *skb; - u64 mapping; + DECLARE_PCI_UNMAP_ADDR(mapping) }; /* diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 59d9594ed6d9..f10fba5d3265 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -109,8 +109,9 @@ static int ipoib_ib_post_receive(struct net_device *dev, int id) ret = ib_post_recv(priv->qp, ¶m, &bad_wr); if (unlikely(ret)) { ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret); - ib_dma_unmap_single(priv->ca, priv->rx_ring[id].mapping, - IPOIB_BUF_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(priv->ca->dma_device, + priv->rx_ring[id].mapping, + IPOIB_BUF_SIZE, DMA_FROM_DEVICE); dev_kfree_skb_any(priv->rx_ring[id].skb); priv->rx_ring[id].skb = NULL; } @@ -122,7 +123,7 @@ static int ipoib_alloc_rx_skb(struct net_device *dev, int id) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct sk_buff *skb; - u64 addr; + dma_addr_t addr; skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4); if (!skb) @@ -135,9 +136,10 @@ static int ipoib_alloc_rx_skb(struct net_device *dev, int id) */ skb_reserve(skb, 4); - addr = ib_dma_map_single(priv->ca, skb->data, IPOIB_BUF_SIZE, - DMA_FROM_DEVICE); - if (unlikely(ib_dma_mapping_error(priv->ca, addr))) { + addr = dma_map_single(priv->ca->dma_device, + skb->data, IPOIB_BUF_SIZE, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(addr))) { dev_kfree_skb_any(skb); return -EIO; } @@ -172,7 +174,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) struct ipoib_dev_priv *priv = netdev_priv(dev); unsigned int wr_id = wc->wr_id & ~IPOIB_OP_RECV; struct sk_buff *skb; - u64 addr; + dma_addr_t addr; ipoib_dbg_data(priv, "recv completion: id %d, op %d, status: %d\n", wr_id, wc->opcode, wc->status); @@ -191,8 +193,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) ipoib_warn(priv, "failed recv event " "(status=%d, wrid=%d vend_err %x)\n", wc->status, wr_id, wc->vendor_err); - ib_dma_unmap_single(priv->ca, addr, - IPOIB_BUF_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(priv->ca->dma_device, addr, + IPOIB_BUF_SIZE, DMA_FROM_DEVICE); dev_kfree_skb_any(skb); priv->rx_ring[wr_id].skb = NULL; return; @@ -210,7 +212,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n", wc->byte_len, wc->slid); - ib_dma_unmap_single(priv->ca, addr, IPOIB_BUF_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(priv->ca->dma_device, addr, + IPOIB_BUF_SIZE, DMA_FROM_DEVICE); skb_put(skb, wc->byte_len); skb_pull(skb, IB_GRH_BYTES); @@ -258,8 +261,10 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) tx_req = &priv->tx_ring[wr_id]; - ib_dma_unmap_single(priv->ca, tx_req->mapping, - tx_req->skb->len, DMA_TO_DEVICE); + dma_unmap_single(priv->ca->dma_device, + pci_unmap_addr(tx_req, mapping), + tx_req->skb->len, + DMA_TO_DEVICE); ++priv->stats.tx_packets; priv->stats.tx_bytes += tx_req->skb->len; @@ -306,7 +311,7 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) static inline int post_send(struct ipoib_dev_priv *priv, unsigned int wr_id, struct ib_ah *address, u32 qpn, - u64 addr, int len) + dma_addr_t addr, int len) { struct ib_send_wr *bad_wr; @@ -325,7 +330,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_tx_buf *tx_req; - u64 addr; + dma_addr_t addr; if (unlikely(skb->len > dev->mtu + INFINIBAND_ALEN)) { ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", @@ -348,20 +353,21 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, */ tx_req = &priv->tx_ring[priv->tx_head & (ipoib_sendq_size - 1)]; tx_req->skb = skb; - addr = ib_dma_map_single(priv->ca, skb->data, skb->len, - DMA_TO_DEVICE); - if (unlikely(ib_dma_mapping_error(priv->ca, addr))) { + addr = dma_map_single(priv->ca->dma_device, skb->data, skb->len, + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(addr))) { ++priv->stats.tx_errors; dev_kfree_skb_any(skb); return; } - tx_req->mapping = addr; + pci_unmap_addr_set(tx_req, mapping, addr); if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), address->ah, qpn, addr, skb->len))) { ipoib_warn(priv, "post_send failed\n"); ++priv->stats.tx_errors; - ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE); + dma_unmap_single(priv->ca->dma_device, addr, skb->len, + DMA_TO_DEVICE); dev_kfree_skb_any(skb); } else { dev->trans_start = jiffies; @@ -532,27 +538,24 @@ int ipoib_ib_dev_stop(struct net_device *dev) while ((int) priv->tx_tail - (int) priv->tx_head < 0) { tx_req = &priv->tx_ring[priv->tx_tail & (ipoib_sendq_size - 1)]; - ib_dma_unmap_single(priv->ca, - tx_req->mapping, - tx_req->skb->len, - DMA_TO_DEVICE); + dma_unmap_single(priv->ca->dma_device, + pci_unmap_addr(tx_req, mapping), + tx_req->skb->len, + DMA_TO_DEVICE); dev_kfree_skb_any(tx_req->skb); ++priv->tx_tail; } - for (i = 0; i < ipoib_recvq_size; ++i) { - struct ipoib_rx_buf *rx_req; - - rx_req = &priv->rx_ring[i]; - if (!rx_req->skb) - continue; - ib_dma_unmap_single(priv->ca, - rx_req->mapping, - IPOIB_BUF_SIZE, - DMA_FROM_DEVICE); - dev_kfree_skb_any(rx_req->skb); - rx_req->skb = NULL; - } + for (i = 0; i < ipoib_recvq_size; ++i) + if (priv->rx_ring[i].skb) { + dma_unmap_single(priv->ca->dma_device, + pci_unmap_addr(&priv->rx_ring[i], + mapping), + IPOIB_BUF_SIZE, + DMA_FROM_DEVICE); + dev_kfree_skb_any(priv->rx_ring[i].skb); + priv->rx_ring[i].skb = NULL; + } goto timeout; } diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index 705eb1d0e554..c09280243726 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -497,6 +497,8 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) return; } + skb_queue_head_init(&neigh->queue); + /* * We can only be called from ipoib_start_xmit, so we're * inside tx_lock -- no need to save/restore flags. @@ -804,7 +806,6 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour) neigh->neighbour = neighbour; *to_ipoib_neigh(neighbour) = neigh; - skb_queue_head_init(&neigh->queue); return neigh; } diff --git a/trunk/drivers/infiniband/ulp/iser/iscsi_iser.h b/trunk/drivers/infiniband/ulp/iser/iscsi_iser.h index cae8c96a55f8..234e5b061a75 100644 --- a/trunk/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/trunk/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -182,7 +182,7 @@ struct iser_regd_buf { struct iser_mem_reg reg; /* memory registration info */ void *virt_addr; struct iser_device *device; /* device->device for dma_unmap */ - u64 dma_addr; /* if non zero, addr for dma_unmap */ + dma_addr_t dma_addr; /* if non zero, addr for dma_unmap */ enum dma_data_direction direction; /* direction for dma_unmap */ unsigned int data_size; atomic_t ref_count; /* refcount, freed when dec to 0 */ diff --git a/trunk/drivers/infiniband/ulp/iser/iser_initiator.c b/trunk/drivers/infiniband/ulp/iser/iser_initiator.c index e73c87b9be43..9b3d79c796c8 100644 --- a/trunk/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/trunk/drivers/infiniband/ulp/iser/iser_initiator.c @@ -487,8 +487,10 @@ int iser_send_control(struct iscsi_conn *conn, struct iscsi_iser_conn *iser_conn = conn->dd_data; struct iser_desc *mdesc = mtask->dd_data; struct iser_dto *send_dto = NULL; + unsigned int itt; unsigned long data_seg_len; int err = 0; + unsigned char opcode; struct iser_regd_buf *regd_buf; struct iser_device *device; @@ -510,6 +512,8 @@ int iser_send_control(struct iscsi_conn *conn, iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE); + itt = ntohl(mtask->hdr->itt); + opcode = mtask->hdr->opcode & ISCSI_OPCODE_MASK; data_seg_len = ntoh24(mtask->hdr->dlength); if (data_seg_len > 0) { diff --git a/trunk/drivers/infiniband/ulp/iser/iser_memory.c b/trunk/drivers/infiniband/ulp/iser/iser_memory.c index fc9f1fd0ae54..3aedd59b8a84 100644 --- a/trunk/drivers/infiniband/ulp/iser/iser_memory.c +++ b/trunk/drivers/infiniband/ulp/iser/iser_memory.c @@ -52,7 +52,7 @@ */ int iser_regd_buff_release(struct iser_regd_buf *regd_buf) { - struct ib_device *dev; + struct device *dma_device; if ((atomic_read(®d_buf->ref_count) == 0) || atomic_dec_and_test(®d_buf->ref_count)) { @@ -61,8 +61,8 @@ int iser_regd_buff_release(struct iser_regd_buf *regd_buf) iser_unreg_mem(®d_buf->reg); if (regd_buf->dma_addr) { - dev = regd_buf->device->ib_device; - ib_dma_unmap_single(dev, + dma_device = regd_buf->device->ib_device->dma_device; + dma_unmap_single(dma_device, regd_buf->dma_addr, regd_buf->data_size, regd_buf->direction); @@ -84,12 +84,12 @@ void iser_reg_single(struct iser_device *device, struct iser_regd_buf *regd_buf, enum dma_data_direction direction) { - u64 dma_addr; + dma_addr_t dma_addr; - dma_addr = ib_dma_map_single(device->ib_device, - regd_buf->virt_addr, - regd_buf->data_size, direction); - BUG_ON(ib_dma_mapping_error(device->ib_device, dma_addr)); + dma_addr = dma_map_single(device->ib_device->dma_device, + regd_buf->virt_addr, + regd_buf->data_size, direction); + BUG_ON(dma_mapping_error(dma_addr)); regd_buf->reg.lkey = device->mr->lkey; regd_buf->reg.len = regd_buf->data_size; @@ -107,7 +107,7 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, enum iser_data_dir cmd_dir) { int dma_nents; - struct ib_device *dev; + struct device *dma_device; char *mem = NULL; struct iser_data_buf *data = &iser_ctask->data[cmd_dir]; unsigned long cmd_data_len = data->data_len; @@ -147,12 +147,17 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, iser_ctask->data_copy[cmd_dir].copy_buf = mem; - dev = iser_ctask->iser_conn->ib_conn->device->ib_device; - dma_nents = ib_dma_map_sg(dev, - &iser_ctask->data_copy[cmd_dir].sg_single, - 1, - (cmd_dir == ISER_DIR_OUT) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE); + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + + if (cmd_dir == ISER_DIR_OUT) + dma_nents = dma_map_sg(dma_device, + &iser_ctask->data_copy[cmd_dir].sg_single, + 1, DMA_TO_DEVICE); + else + dma_nents = dma_map_sg(dma_device, + &iser_ctask->data_copy[cmd_dir].sg_single, + 1, DMA_FROM_DEVICE); + BUG_ON(dma_nents == 0); iser_ctask->data_copy[cmd_dir].dma_nents = dma_nents; @@ -165,16 +170,19 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, enum iser_data_dir cmd_dir) { - struct ib_device *dev; + struct device *dma_device; struct iser_data_buf *mem_copy; unsigned long cmd_data_len; - dev = iser_ctask->iser_conn->ib_conn->device->ib_device; - mem_copy = &iser_ctask->data_copy[cmd_dir]; + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + mem_copy = &iser_ctask->data_copy[cmd_dir]; - ib_dma_unmap_sg(dev, &mem_copy->sg_single, 1, - (cmd_dir == ISER_DIR_OUT) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE); + if (cmd_dir == ISER_DIR_OUT) + dma_unmap_sg(dma_device, &mem_copy->sg_single, 1, + DMA_TO_DEVICE); + else + dma_unmap_sg(dma_device, &mem_copy->sg_single, 1, + DMA_FROM_DEVICE); if (cmd_dir == ISER_DIR_IN) { char *mem; @@ -223,12 +231,11 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, * consecutive elements. Also, it handles one entry SG. */ static int iser_sg_to_page_vec(struct iser_data_buf *data, - struct iser_page_vec *page_vec, - struct ib_device *ibdev) + struct iser_page_vec *page_vec) { struct scatterlist *sg = (struct scatterlist *)data->buf; - u64 first_addr, last_addr, page; - int end_aligned; + dma_addr_t first_addr, last_addr, page; + int start_aligned, end_aligned; unsigned int cur_page = 0; unsigned long total_sz = 0; int i; @@ -237,21 +244,19 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, page_vec->offset = (u64) sg[0].offset & ~MASK_4K; for (i = 0; i < data->dma_nents; i++) { - unsigned int dma_len = ib_sg_dma_len(ibdev, &sg[i]); - - total_sz += dma_len; + total_sz += sg_dma_len(&sg[i]); - first_addr = ib_sg_dma_address(ibdev, &sg[i]); - last_addr = first_addr + dma_len; + first_addr = sg_dma_address(&sg[i]); + last_addr = first_addr + sg_dma_len(&sg[i]); + start_aligned = !(first_addr & ~MASK_4K); end_aligned = !(last_addr & ~MASK_4K); /* continue to collect page fragments till aligned or SG ends */ while (!end_aligned && (i + 1 < data->dma_nents)) { i++; - dma_len = ib_sg_dma_len(ibdev, &sg[i]); - total_sz += dma_len; - last_addr = ib_sg_dma_address(ibdev, &sg[i]) + dma_len; + total_sz += sg_dma_len(&sg[i]); + last_addr = sg_dma_address(&sg[i]) + sg_dma_len(&sg[i]); end_aligned = !(last_addr & ~MASK_4K); } @@ -283,11 +288,10 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, * the number of entries which are aligned correctly. Supports the case where * consecutive SG elements are actually fragments of the same physcial page. */ -static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, - struct ib_device *ibdev) +static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data) { struct scatterlist *sg; - u64 end_addr, next_addr; + dma_addr_t end_addr, next_addr; int i, cnt; unsigned int ret_len = 0; @@ -299,12 +303,12 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, (unsigned long)page_to_phys(sg[i].page), (unsigned long)sg[i].offset, (unsigned long)sg[i].length); */ - end_addr = ib_sg_dma_address(ibdev, &sg[i]) + - ib_sg_dma_len(ibdev, &sg[i]); + end_addr = sg_dma_address(&sg[i]) + + sg_dma_len(&sg[i]); /* iser_dbg("Checking sg iobuf end address " "0x%08lX\n", end_addr); */ if (i + 1 < data->dma_nents) { - next_addr = ib_sg_dma_address(ibdev, &sg[i+1]); + next_addr = sg_dma_address(&sg[i+1]); /* are i, i+1 fragments of the same page? */ if (end_addr == next_addr) continue; @@ -321,8 +325,7 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, return ret_len; } -static void iser_data_buf_dump(struct iser_data_buf *data, - struct ib_device *ibdev) +static void iser_data_buf_dump(struct iser_data_buf *data) { struct scatterlist *sg = (struct scatterlist *)data->buf; int i; @@ -330,9 +333,9 @@ static void iser_data_buf_dump(struct iser_data_buf *data, for (i = 0; i < data->dma_nents; i++) iser_err("sg[%d] dma_addr:0x%lX page:0x%p " "off:0x%x sz:0x%x dma_len:0x%x\n", - i, (unsigned long)ib_sg_dma_address(ibdev, &sg[i]), + i, (unsigned long)sg_dma_address(&sg[i]), sg[i].page, sg[i].offset, - sg[i].length, ib_sg_dma_len(ibdev, &sg[i])); + sg[i].length,sg_dma_len(&sg[i])); } static void iser_dump_page_vec(struct iser_page_vec *page_vec) @@ -346,8 +349,7 @@ static void iser_dump_page_vec(struct iser_page_vec *page_vec) } static void iser_page_vec_build(struct iser_data_buf *data, - struct iser_page_vec *page_vec, - struct ib_device *ibdev) + struct iser_page_vec *page_vec) { int page_vec_len = 0; @@ -355,14 +357,14 @@ static void iser_page_vec_build(struct iser_data_buf *data, page_vec->offset = 0; iser_dbg("Translating sg sz: %d\n", data->dma_nents); - page_vec_len = iser_sg_to_page_vec(data, page_vec, ibdev); + page_vec_len = iser_sg_to_page_vec(data,page_vec); iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents,page_vec_len); page_vec->length = page_vec_len; if (page_vec_len * SIZE_4K < page_vec->data_size) { iser_err("page_vec too short to hold this SG\n"); - iser_data_buf_dump(data, ibdev); + iser_data_buf_dump(data); iser_dump_page_vec(page_vec); BUG(); } @@ -373,12 +375,13 @@ int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask, enum iser_data_dir iser_dir, enum dma_data_direction dma_dir) { - struct ib_device *dev; + struct device *dma_device; iser_ctask->dir[iser_dir] = 1; - dev = iser_ctask->iser_conn->ib_conn->device->ib_device; + dma_device = + iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; - data->dma_nents = ib_dma_map_sg(dev, data->buf, data->size, dma_dir); + data->dma_nents = dma_map_sg(dma_device, data->buf, data->size, dma_dir); if (data->dma_nents == 0) { iser_err("dma_map_sg failed!!!\n"); return -EINVAL; @@ -388,19 +391,20 @@ int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask, void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask) { - struct ib_device *dev; + struct device *dma_device; struct iser_data_buf *data; - dev = iser_ctask->iser_conn->ib_conn->device->ib_device; + dma_device = + iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; if (iser_ctask->dir[ISER_DIR_IN]) { data = &iser_ctask->data[ISER_DIR_IN]; - ib_dma_unmap_sg(dev, data->buf, data->size, DMA_FROM_DEVICE); + dma_unmap_sg(dma_device, data->buf, data->size, DMA_FROM_DEVICE); } if (iser_ctask->dir[ISER_DIR_OUT]) { data = &iser_ctask->data[ISER_DIR_OUT]; - ib_dma_unmap_sg(dev, data->buf, data->size, DMA_TO_DEVICE); + dma_unmap_sg(dma_device, data->buf, data->size, DMA_TO_DEVICE); } } @@ -415,7 +419,6 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, { struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn; struct iser_device *device = ib_conn->device; - struct ib_device *ibdev = device->ib_device; struct iser_data_buf *mem = &iser_ctask->data[cmd_dir]; struct iser_regd_buf *regd_buf; int aligned_len; @@ -425,11 +428,11 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, regd_buf = &iser_ctask->rdma_regd[cmd_dir]; - aligned_len = iser_data_buf_aligned_len(mem, ibdev); + aligned_len = iser_data_buf_aligned_len(mem); if (aligned_len != mem->dma_nents) { iser_err("rdma alignment violation %d/%d aligned\n", aligned_len, mem->size); - iser_data_buf_dump(mem, ibdev); + iser_data_buf_dump(mem); /* unmap the command data before accessing it */ iser_dma_unmap_task_data(iser_ctask); @@ -447,8 +450,8 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, regd_buf->reg.lkey = device->mr->lkey; regd_buf->reg.rkey = device->mr->rkey; - regd_buf->reg.len = ib_sg_dma_len(ibdev, &sg[0]); - regd_buf->reg.va = ib_sg_dma_address(ibdev, &sg[0]); + regd_buf->reg.len = sg_dma_len(&sg[0]); + regd_buf->reg.va = sg_dma_address(&sg[0]); regd_buf->reg.is_fmr = 0; iser_dbg("PHYSICAL Mem.register: lkey: 0x%08X rkey: 0x%08X " @@ -458,10 +461,10 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, (unsigned long)regd_buf->reg.va, (unsigned long)regd_buf->reg.len); } else { /* use FMR for multiple dma entries */ - iser_page_vec_build(mem, ib_conn->page_vec, ibdev); + iser_page_vec_build(mem, ib_conn->page_vec); err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, ®d_buf->reg); if (err) { - iser_data_buf_dump(mem, ibdev); + iser_data_buf_dump(mem); iser_err("mem->dma_nents = %d (dlength = 0x%x)\n", mem->dma_nents, ntoh24(iser_ctask->desc.iscsi_header.dlength)); iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n", diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index e9b6a6f07dd7..a6289595557b 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -122,8 +122,9 @@ static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size, if (!iu->buf) goto out_free_iu; - iu->dma = ib_dma_map_single(host->dev->dev, iu->buf, size, direction); - if (ib_dma_mapping_error(host->dev->dev, iu->dma)) + iu->dma = dma_map_single(host->dev->dev->dma_device, + iu->buf, size, direction); + if (dma_mapping_error(iu->dma)) goto out_free_buf; iu->size = size; @@ -144,7 +145,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu) if (!iu) return; - ib_dma_unmap_single(host->dev->dev, iu->dma, iu->size, iu->direction); + dma_unmap_single(host->dev->dev->dma_device, + iu->dma, iu->size, iu->direction); kfree(iu->buf); kfree(iu); } @@ -480,8 +482,8 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, scat = &req->fake_sg; } - ib_dma_unmap_sg(target->srp_host->dev->dev, scat, nents, - scmnd->sc_data_direction); + dma_unmap_sg(target->srp_host->dev->dev->dma_device, scat, nents, + scmnd->sc_data_direction); } static void srp_remove_req(struct srp_target_port *target, struct srp_request *req) @@ -593,26 +595,23 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, int i, j; int ret; struct srp_device *dev = target->srp_host->dev; - struct ib_device *ibdev = dev->dev; if (!dev->fmr_pool) return -ENODEV; - if ((ib_sg_dma_address(ibdev, &scat[0]) & ~dev->fmr_page_mask) && + if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) && mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3)) return -EINVAL; len = page_cnt = 0; for (i = 0; i < sg_cnt; ++i) { - unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]); - - if (ib_sg_dma_address(ibdev, &scat[i]) & ~dev->fmr_page_mask) { + if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) { if (i > 0) return -EINVAL; else ++page_cnt; } - if ((ib_sg_dma_address(ibdev, &scat[i]) + dma_len) & + if ((sg_dma_address(&scat[i]) + sg_dma_len(&scat[i])) & ~dev->fmr_page_mask) { if (i < sg_cnt - 1) return -EINVAL; @@ -620,7 +619,7 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, ++page_cnt; } - len += dma_len; + len += sg_dma_len(&scat[i]); } page_cnt += len >> dev->fmr_page_shift; @@ -632,14 +631,10 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, return -ENOMEM; page_cnt = 0; - for (i = 0; i < sg_cnt; ++i) { - unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]); - - for (j = 0; j < dma_len; j += dev->fmr_page_size) + for (i = 0; i < sg_cnt; ++i) + for (j = 0; j < sg_dma_len(&scat[i]); j += dev->fmr_page_size) dma_pages[page_cnt++] = - (ib_sg_dma_address(ibdev, &scat[i]) & - dev->fmr_page_mask) + j; - } + (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j; req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool, dma_pages, page_cnt, io_addr); @@ -649,8 +644,7 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, goto out; } - buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, &scat[0]) & - ~dev->fmr_page_mask); + buf->va = cpu_to_be64(sg_dma_address(&scat[0]) & ~dev->fmr_page_mask); buf->key = cpu_to_be32(req->fmr->fmr->rkey); buf->len = cpu_to_be32(len); @@ -669,8 +663,6 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, struct srp_cmd *cmd = req->cmd->buf; int len, nents, count; u8 fmt = SRP_DATA_DESC_DIRECT; - struct srp_device *dev; - struct ib_device *ibdev; if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE) return sizeof (struct srp_cmd); @@ -695,10 +687,8 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen); } - dev = target->srp_host->dev; - ibdev = dev->dev; - - count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction); + count = dma_map_sg(target->srp_host->dev->dev->dma_device, + scat, nents, scmnd->sc_data_direction); fmt = SRP_DATA_DESC_DIRECT; len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf); @@ -712,9 +702,9 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, */ struct srp_direct_buf *buf = (void *) cmd->add_data; - buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, scat)); - buf->key = cpu_to_be32(dev->mr->rkey); - buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat)); + buf->va = cpu_to_be64(sg_dma_address(scat)); + buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey); + buf->len = cpu_to_be32(sg_dma_len(scat)); } else if (srp_map_fmr(target, scat, count, req, (void *) cmd->add_data)) { /* @@ -732,14 +722,13 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, count * sizeof (struct srp_direct_buf); for (i = 0; i < count; ++i) { - unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]); - buf->desc_list[i].va = - cpu_to_be64(ib_sg_dma_address(ibdev, &scat[i])); + cpu_to_be64(sg_dma_address(&scat[i])); buf->desc_list[i].key = - cpu_to_be32(dev->mr->rkey); - buf->desc_list[i].len = cpu_to_be32(dma_len); - datalen += dma_len; + cpu_to_be32(target->srp_host->dev->mr->rkey); + buf->desc_list[i].len = + cpu_to_be32(sg_dma_len(&scat[i])); + datalen += sg_dma_len(&scat[i]); } if (scmnd->sc_data_direction == DMA_TO_DEVICE) @@ -819,15 +808,13 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) { - struct ib_device *dev; struct srp_iu *iu; u8 opcode; iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV]; - dev = target->srp_host->dev->dev; - ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len, - DMA_FROM_DEVICE); + dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma, + target->max_ti_iu_len, DMA_FROM_DEVICE); opcode = *(u8 *) iu->buf; @@ -863,8 +850,8 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) break; } - ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len, - DMA_FROM_DEVICE); + dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma, + target->max_ti_iu_len, DMA_FROM_DEVICE); } static void srp_completion(struct ib_cq *cq, void *target_ptr) @@ -982,7 +969,6 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, struct srp_request *req; struct srp_iu *iu; struct srp_cmd *cmd; - struct ib_device *dev; int len; if (target->state == SRP_TARGET_CONNECTING) @@ -999,9 +985,8 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, if (!iu) goto err; - dev = target->srp_host->dev->dev; - ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len, - DMA_TO_DEVICE); + dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma, + srp_max_iu_len, DMA_TO_DEVICE); req = list_entry(target->free_reqs.next, struct srp_request, list); @@ -1033,8 +1018,8 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, goto err_unmap; } - ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len, - DMA_TO_DEVICE); + dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma, + srp_max_iu_len, DMA_TO_DEVICE); if (__srp_post_send(target, iu, len)) { printk(KERN_ERR PFX "Send failed\n"); diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.h b/trunk/drivers/infiniband/ulp/srp/ib_srp.h index 868a540ef7cd..d4e35ef51374 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.h +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.h @@ -161,7 +161,7 @@ struct srp_target_port { }; struct srp_iu { - u64 dma; + dma_addr_t dma; void *buf; size_t size; enum dma_data_direction direction; diff --git a/trunk/drivers/input/keyboard/hilkbd.c b/trunk/drivers/input/keyboard/hilkbd.c index 35461eab2faf..54bc569db4b0 100644 --- a/trunk/drivers/input/keyboard/hilkbd.c +++ b/trunk/drivers/input/keyboard/hilkbd.c @@ -23,12 +23,7 @@ #include #include #include -#include #include -#include -#ifdef CONFIG_HP300 -#include -#endif MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller"); diff --git a/trunk/drivers/input/touchscreen/Kconfig b/trunk/drivers/input/touchscreen/Kconfig index 6b46c9bf1d20..29ca0ab0acb8 100644 --- a/trunk/drivers/input/touchscreen/Kconfig +++ b/trunk/drivers/input/touchscreen/Kconfig @@ -146,7 +146,7 @@ config TOUCHSCREEN_TOUCHWIN config TOUCHSCREEN_UCB1400 tristate "Philips UCB1400 touchscreen" - select AC97_BUS + select SND_AC97_BUS help This enables support for the Philips UCB1400 touchscreen interface. The UCB1400 is an AC97 audio codec. The touchscreen interface diff --git a/trunk/drivers/isdn/act2000/act2000_isa.c b/trunk/drivers/isdn/act2000/act2000_isa.c index 09ea50dd3459..3cac23739344 100644 --- a/trunk/drivers/isdn/act2000/act2000_isa.c +++ b/trunk/drivers/isdn/act2000/act2000_isa.c @@ -408,7 +408,7 @@ act2000_isa_download(act2000_card * card, act2000_ddef __user * cb) p = cblock.buffer; if (!access_ok(VERIFY_READ, p, length)) return -EFAULT; - buf = kmalloc(1024, GFP_KERNEL); + buf = (u_char *) kmalloc(1024, GFP_KERNEL); if (!buf) return -ENOMEM; timeout = 0; diff --git a/trunk/drivers/isdn/capi/capidrv.c b/trunk/drivers/isdn/capi/capidrv.c index c4d438c17dab..097bfa7bc323 100644 --- a/trunk/drivers/isdn/capi/capidrv.c +++ b/trunk/drivers/isdn/capi/capidrv.c @@ -2013,7 +2013,7 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) strcpy(card->name, id); card->contrnr = contr; card->nbchan = profp->nbchannel; - card->bchans = kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC); + card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC); if (!card->bchans) { printk(KERN_WARNING "capidrv: (%s) Could not allocate bchan-structs.\n", id); diff --git a/trunk/drivers/isdn/divert/divert_procfs.c b/trunk/drivers/isdn/divert/divert_procfs.c index 06967da7c4a8..399b316111f7 100644 --- a/trunk/drivers/isdn/divert/divert_procfs.c +++ b/trunk/drivers/isdn/divert/divert_procfs.c @@ -45,7 +45,7 @@ put_info_buffer(char *cp) return; if (!*cp) return; - if (!(ib = kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC))) + if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC))) return; /* no memory */ strcpy(ib->info_start, cp); /* set output string */ ib->next = NULL; diff --git a/trunk/drivers/isdn/divert/isdn_divert.c b/trunk/drivers/isdn/divert/isdn_divert.c index 7d97d54588d9..03319ea5aa0c 100644 --- a/trunk/drivers/isdn/divert/isdn_divert.c +++ b/trunk/drivers/isdn/divert/isdn_divert.c @@ -153,7 +153,7 @@ int cf_command(int drvid, int mode, *ielenp = p - ielenp - 1; /* set total IE length */ /* allocate mem for information struct */ - if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) + if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) return(-ENOMEM); /* no memory */ init_timer(&cs->timer); cs->info[0] = '\0'; @@ -276,7 +276,7 @@ int insertrule(int idx, divert_rule *newrule) { struct deflect_struc *ds,*ds1=NULL; unsigned long flags; - if (!(ds = kmalloc(sizeof(struct deflect_struc), + if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc), GFP_KERNEL))) return(-ENOMEM); /* no memory */ @@ -451,7 +451,7 @@ static int isdn_divert_icall(isdn_ctrl *ic) if (dv->rule.action == DEFLECT_PROCEED) if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) return(0); /* no external deflection needed */ - if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) + if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) return(0); /* no memory */ init_timer(&cs->timer); cs->info[0] = '\0'; diff --git a/trunk/drivers/isdn/gigaset/bas-gigaset.c b/trunk/drivers/isdn/gigaset/bas-gigaset.c index b5e7f9c7d74e..63b629b1cdb2 100644 --- a/trunk/drivers/isdn/gigaset/bas-gigaset.c +++ b/trunk/drivers/isdn/gigaset/bas-gigaset.c @@ -1853,24 +1853,20 @@ static int gigaset_write_cmd(struct cardstate *cs, { struct cmdbuf_t *cb; unsigned long flags; - int rc; + int status; gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? DEBUG_TRANSCMD : DEBUG_LOCKCMD, "CMD Transmit", len, buf); - if (len <= 0) { - /* nothing to do */ - rc = 0; - goto notqueued; - } + if (len <= 0) + return 0; /* nothing to do */ if (len > IF_WRITEBUF) len = IF_WRITEBUF; if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { dev_err(cs->dev, "%s: out of memory\n", __func__); - rc = -ENOMEM; - goto notqueued; + return -ENOMEM; } memcpy(cb->buf, buf, len); @@ -1895,21 +1891,11 @@ static int gigaset_write_cmd(struct cardstate *cs, if (unlikely(!cs->connected)) { spin_unlock_irqrestore(&cs->lock, flags); gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); - /* flush command queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - while (cs->cmdbuf != NULL) - complete_cb(cs); - spin_unlock_irqrestore(&cs->cmdlock, flags); return -ENODEV; } - rc = start_cbsend(cs); + status = start_cbsend(cs); spin_unlock_irqrestore(&cs->lock, flags); - return rc < 0 ? rc : len; - -notqueued: /* request handled without queuing */ - if (wake_tasklet) - tasklet_schedule(wake_tasklet); - return rc; + return status < 0 ? status : len; } /* gigaset_write_room @@ -1978,15 +1964,20 @@ static int gigaset_freebcshw(struct bc_state *bcs) /* kill URBs and tasklets before freeing - better safe than sorry */ atomic_set(&ubc->running, 0); - gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); - for (i = 0; i < BAS_OUTURBS; ++i) { - usb_kill_urb(ubc->isoouturbs[i].urb); - usb_free_urb(ubc->isoouturbs[i].urb); - } - for (i = 0; i < BAS_INURBS; ++i) { - usb_kill_urb(ubc->isoinurbs[i]); - usb_free_urb(ubc->isoinurbs[i]); - } + for (i = 0; i < BAS_OUTURBS; ++i) + if (ubc->isoouturbs[i].urb) { + gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d", + __func__, i); + usb_kill_urb(ubc->isoouturbs[i].urb); + usb_free_urb(ubc->isoouturbs[i].urb); + } + for (i = 0; i < BAS_INURBS; ++i) + if (ubc->isoinurbs[i]) { + gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d", + __func__, i); + usb_kill_urb(ubc->isoinurbs[i]); + usb_free_urb(ubc->isoinurbs[i]); + } tasklet_kill(&ubc->sent_tasklet); tasklet_kill(&ubc->rcvd_tasklet); kfree(ubc->isooutbuf); @@ -2108,32 +2099,55 @@ static void freeurbs(struct cardstate *cs) struct bas_bc_state *ubc; int i, j; - gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); for (j = 0; j < 2; ++j) { ubc = cs->bcs[j].hw.bas; - for (i = 0; i < BAS_OUTURBS; ++i) { - usb_kill_urb(ubc->isoouturbs[i].urb); - usb_free_urb(ubc->isoouturbs[i].urb); - ubc->isoouturbs[i].urb = NULL; - } - for (i = 0; i < BAS_INURBS; ++i) { - usb_kill_urb(ubc->isoinurbs[i]); - usb_free_urb(ubc->isoinurbs[i]); - ubc->isoinurbs[i] = NULL; - } + for (i = 0; i < BAS_OUTURBS; ++i) + if (ubc->isoouturbs[i].urb) { + usb_kill_urb(ubc->isoouturbs[i].urb); + gig_dbg(DEBUG_INIT, + "%s: isoc output URB %d/%d unlinked", + __func__, j, i); + usb_free_urb(ubc->isoouturbs[i].urb); + ubc->isoouturbs[i].urb = NULL; + } + for (i = 0; i < BAS_INURBS; ++i) + if (ubc->isoinurbs[i]) { + usb_kill_urb(ubc->isoinurbs[i]); + gig_dbg(DEBUG_INIT, + "%s: isoc input URB %d/%d unlinked", + __func__, j, i); + usb_free_urb(ubc->isoinurbs[i]); + ubc->isoinurbs[i] = NULL; + } + } + if (ucs->urb_int_in) { + usb_kill_urb(ucs->urb_int_in); + gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", + __func__); + usb_free_urb(ucs->urb_int_in); + ucs->urb_int_in = NULL; + } + if (ucs->urb_cmd_out) { + usb_kill_urb(ucs->urb_cmd_out); + gig_dbg(DEBUG_INIT, "%s: command output URB unlinked", + __func__); + usb_free_urb(ucs->urb_cmd_out); + ucs->urb_cmd_out = NULL; + } + if (ucs->urb_cmd_in) { + usb_kill_urb(ucs->urb_cmd_in); + gig_dbg(DEBUG_INIT, "%s: command input URB unlinked", + __func__); + usb_free_urb(ucs->urb_cmd_in); + ucs->urb_cmd_in = NULL; + } + if (ucs->urb_ctrl) { + usb_kill_urb(ucs->urb_ctrl); + gig_dbg(DEBUG_INIT, "%s: control output URB unlinked", + __func__); + usb_free_urb(ucs->urb_ctrl); + ucs->urb_ctrl = NULL; } - usb_kill_urb(ucs->urb_int_in); - usb_free_urb(ucs->urb_int_in); - ucs->urb_int_in = NULL; - usb_kill_urb(ucs->urb_cmd_out); - usb_free_urb(ucs->urb_cmd_out); - ucs->urb_cmd_out = NULL; - usb_kill_urb(ucs->urb_cmd_in); - usb_free_urb(ucs->urb_cmd_in); - ucs->urb_cmd_in = NULL; - usb_kill_urb(ucs->urb_ctrl); - usb_free_urb(ucs->urb_ctrl); - ucs->urb_ctrl = NULL; } /* gigaset_probe diff --git a/trunk/drivers/isdn/hisax/Kconfig b/trunk/drivers/isdn/hisax/Kconfig index 34ab5f7dcabc..6fa12cc8e4ff 100644 --- a/trunk/drivers/isdn/hisax/Kconfig +++ b/trunk/drivers/isdn/hisax/Kconfig @@ -110,7 +110,7 @@ config HISAX_16_3 config HISAX_TELESPCI bool "Teles PCI" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) help This enables HiSax support for the Teles PCI. See on how to configure it. @@ -238,7 +238,7 @@ config HISAX_MIC config HISAX_NETJET bool "NETjet card" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) help This enables HiSax support for the NetJet from Traverse Technologies. @@ -249,7 +249,7 @@ config HISAX_NETJET config HISAX_NETJET_U bool "NETspider U card" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) help This enables HiSax support for the Netspider U interface ISDN card from Traverse Technologies. @@ -317,7 +317,7 @@ config HISAX_GAZEL config HISAX_HFC_PCI bool "HFC PCI-Bus cards" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) help This enables HiSax support for the HFC-S PCI 2BDS0 based cards. @@ -344,7 +344,7 @@ config HISAX_HFC_SX config HISAX_ENTERNOW_PCI bool "Formula-n enter:now PCI card" - depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) help This enables HiSax support for the Formula-n enter:now PCI ISDN card. diff --git a/trunk/drivers/isdn/hysdn/hysdn_procconf.c b/trunk/drivers/isdn/hysdn/hysdn_procconf.c index 94a935089119..8e2b03889f3c 100644 --- a/trunk/drivers/isdn/hysdn/hysdn_procconf.c +++ b/trunk/drivers/isdn/hysdn/hysdn_procconf.c @@ -275,7 +275,7 @@ hysdn_conf_open(struct inode *ino, struct file *filep) } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { /* read access -> output card info data */ - if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { + if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { unlock_kernel(); return (-EFAULT); /* out of memory */ } diff --git a/trunk/drivers/isdn/hysdn/hysdn_proclog.c b/trunk/drivers/isdn/hysdn/hysdn_proclog.c index 375d956884d7..f241f5e551cb 100644 --- a/trunk/drivers/isdn/hysdn/hysdn_proclog.c +++ b/trunk/drivers/isdn/hysdn/hysdn_proclog.c @@ -111,7 +111,7 @@ put_log_buffer(hysdn_card * card, char *cp) if (pd->if_used <= 0) return; /* no open file for read */ - if (!(ib = kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC))) + if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC))) return; /* no memory */ strcpy(ib->log_start, cp); /* set output string */ ib->next = NULL; diff --git a/trunk/drivers/isdn/i4l/isdn_audio.c b/trunk/drivers/isdn/i4l/isdn_audio.c index fb350c567c6b..2cc56d6a9fae 100644 --- a/trunk/drivers/isdn/i4l/isdn_audio.c +++ b/trunk/drivers/isdn/i4l/isdn_audio.c @@ -328,7 +328,7 @@ adpcm_state * isdn_audio_adpcm_init(adpcm_state * s, int nbits) { if (!s) - s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC); + s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC); if (s) { s->a = 0; s->d = 5; @@ -343,7 +343,7 @@ dtmf_state * isdn_audio_dtmf_init(dtmf_state * s) { if (!s) - s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC); + s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC); if (s) { s->idx = 0; s->last = ' '; @@ -621,7 +621,7 @@ silence_state * isdn_audio_silence_init(silence_state * s) { if (!s) - s = kmalloc(sizeof(silence_state), GFP_ATOMIC); + s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC); if (s) { s->idx = 0; s->state = 0; diff --git a/trunk/drivers/isdn/i4l/isdn_net.c b/trunk/drivers/isdn/i4l/isdn_net.c index 838b3734e2b6..c36c817578cb 100644 --- a/trunk/drivers/isdn/i4l/isdn_net.c +++ b/trunk/drivers/isdn/i4l/isdn_net.c @@ -2948,7 +2948,7 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone) isdn_net_phone *n; if (p) { - if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL))) + if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL))) return -ENOMEM; strcpy(n->num, phone->phone); n->next = p->local->phone[phone->outgoing & 1]; diff --git a/trunk/drivers/isdn/i4l/isdn_ppp.c b/trunk/drivers/isdn/i4l/isdn_ppp.c index 1726131b20be..43811795b46b 100644 --- a/trunk/drivers/isdn/i4l/isdn_ppp.c +++ b/trunk/drivers/isdn/i4l/isdn_ppp.c @@ -717,7 +717,7 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot) printk(KERN_DEBUG "ippp: device not activated.\n"); return 0; } - nbuf = kmalloc(len + 4, GFP_ATOMIC); + nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC); if (!nbuf) { printk(KERN_WARNING "ippp: Can't alloc buf\n"); return 0; diff --git a/trunk/drivers/isdn/pcbit/layer2.c b/trunk/drivers/isdn/pcbit/layer2.c index eafcce5e656a..6ff85574e941 100644 --- a/trunk/drivers/isdn/pcbit/layer2.c +++ b/trunk/drivers/isdn/pcbit/layer2.c @@ -100,7 +100,7 @@ pcbit_l2_write(struct pcbit_dev *dev, ulong msg, ushort refnum, dev_kfree_skb(skb); return -1; } - if ((frame = kmalloc(sizeof(struct frame_buf), + if ((frame = (struct frame_buf *) kmalloc(sizeof(struct frame_buf), GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "pcbit_2_write: kmalloc failed\n"); dev_kfree_skb(skb); diff --git a/trunk/drivers/kvm/Kconfig b/trunk/drivers/kvm/Kconfig deleted file mode 100644 index 703cc88d1ef9..000000000000 --- a/trunk/drivers/kvm/Kconfig +++ /dev/null @@ -1,37 +0,0 @@ -# -# KVM configuration -# -menu "Virtualization" - -config KVM - tristate "Kernel-based Virtual Machine (KVM) support" - depends on X86 && EXPERIMENTAL - ---help--- - Support hosting fully virtualized guest machines using hardware - virtualization extensions. You will need a fairly recent - processor equipped with virtualization extensions. You will also - need to select one or more of the processor modules below. - - This module provides access to the hardware capabilities through - a character device node named /dev/kvm. - - To compile this as a module, choose M here: the module - will be called kvm. - - If unsure, say N. - -config KVM_INTEL - tristate "KVM for Intel processors support" - depends on KVM - ---help--- - Provides support for KVM on Intel processors equipped with the VT - extensions. - -config KVM_AMD - tristate "KVM for AMD processors support" - depends on KVM - ---help--- - Provides support for KVM on AMD processors equipped with the AMD-V - (SVM) extensions. - -endmenu diff --git a/trunk/drivers/kvm/Makefile b/trunk/drivers/kvm/Makefile deleted file mode 100644 index c0a789fa9d65..000000000000 --- a/trunk/drivers/kvm/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for Kernel-based Virtual Machine module -# - -kvm-objs := kvm_main.o mmu.o x86_emulate.o -obj-$(CONFIG_KVM) += kvm.o -kvm-intel-objs = vmx.o -obj-$(CONFIG_KVM_INTEL) += kvm-intel.o -kvm-amd-objs = svm.o -obj-$(CONFIG_KVM_AMD) += kvm-amd.o diff --git a/trunk/drivers/kvm/kvm.h b/trunk/drivers/kvm/kvm.h deleted file mode 100644 index 930e04ce1af6..000000000000 --- a/trunk/drivers/kvm/kvm.h +++ /dev/null @@ -1,551 +0,0 @@ -#ifndef __KVM_H -#define __KVM_H - -/* - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - */ - -#include -#include -#include -#include -#include - -#include "vmx.h" -#include - -#define CR0_PE_MASK (1ULL << 0) -#define CR0_TS_MASK (1ULL << 3) -#define CR0_NE_MASK (1ULL << 5) -#define CR0_WP_MASK (1ULL << 16) -#define CR0_NW_MASK (1ULL << 29) -#define CR0_CD_MASK (1ULL << 30) -#define CR0_PG_MASK (1ULL << 31) - -#define CR3_WPT_MASK (1ULL << 3) -#define CR3_PCD_MASK (1ULL << 4) - -#define CR3_RESEVED_BITS 0x07ULL -#define CR3_L_MODE_RESEVED_BITS (~((1ULL << 40) - 1) | 0x0fe7ULL) -#define CR3_FLAGS_MASK ((1ULL << 5) - 1) - -#define CR4_VME_MASK (1ULL << 0) -#define CR4_PSE_MASK (1ULL << 4) -#define CR4_PAE_MASK (1ULL << 5) -#define CR4_PGE_MASK (1ULL << 7) -#define CR4_VMXE_MASK (1ULL << 13) - -#define KVM_GUEST_CR0_MASK \ - (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK \ - | CR0_NW_MASK | CR0_CD_MASK) -#define KVM_VM_CR0_ALWAYS_ON \ - (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK) -#define KVM_GUEST_CR4_MASK \ - (CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK) -#define KVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK) -#define KVM_RMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK | CR4_VME_MASK) - -#define INVALID_PAGE (~(hpa_t)0) -#define UNMAPPED_GVA (~(gpa_t)0) - -#define KVM_MAX_VCPUS 1 -#define KVM_MEMORY_SLOTS 4 -#define KVM_NUM_MMU_PAGES 256 - -#define FX_IMAGE_SIZE 512 -#define FX_IMAGE_ALIGN 16 -#define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN) - -#define DE_VECTOR 0 -#define DF_VECTOR 8 -#define TS_VECTOR 10 -#define NP_VECTOR 11 -#define SS_VECTOR 12 -#define GP_VECTOR 13 -#define PF_VECTOR 14 - -#define SELECTOR_TI_MASK (1 << 2) -#define SELECTOR_RPL_MASK 0x03 - -#define IOPL_SHIFT 12 - -/* - * Address types: - * - * gva - guest virtual address - * gpa - guest physical address - * gfn - guest frame number - * hva - host virtual address - * hpa - host physical address - * hfn - host frame number - */ - -typedef unsigned long gva_t; -typedef u64 gpa_t; -typedef unsigned long gfn_t; - -typedef unsigned long hva_t; -typedef u64 hpa_t; -typedef unsigned long hfn_t; - -struct kvm_mmu_page { - struct list_head link; - hpa_t page_hpa; - unsigned long slot_bitmap; /* One bit set per slot which has memory - * in this shadow page. - */ - int global; /* Set if all ptes in this page are global */ - u64 *parent_pte; -}; - -struct vmcs { - u32 revision_id; - u32 abort; - char data[0]; -}; - -#define vmx_msr_entry kvm_msr_entry - -struct kvm_vcpu; - -/* - * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level - * 32-bit). The kvm_mmu structure abstracts the details of the current mmu - * mode. - */ -struct kvm_mmu { - void (*new_cr3)(struct kvm_vcpu *vcpu); - int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err); - void (*inval_page)(struct kvm_vcpu *vcpu, gva_t gva); - void (*free)(struct kvm_vcpu *vcpu); - gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva); - hpa_t root_hpa; - int root_level; - int shadow_root_level; -}; - -struct kvm_guest_debug { - int enabled; - unsigned long bp[4]; - int singlestep; -}; - -enum { - VCPU_REGS_RAX = 0, - VCPU_REGS_RCX = 1, - VCPU_REGS_RDX = 2, - VCPU_REGS_RBX = 3, - VCPU_REGS_RSP = 4, - VCPU_REGS_RBP = 5, - VCPU_REGS_RSI = 6, - VCPU_REGS_RDI = 7, -#ifdef CONFIG_X86_64 - VCPU_REGS_R8 = 8, - VCPU_REGS_R9 = 9, - VCPU_REGS_R10 = 10, - VCPU_REGS_R11 = 11, - VCPU_REGS_R12 = 12, - VCPU_REGS_R13 = 13, - VCPU_REGS_R14 = 14, - VCPU_REGS_R15 = 15, -#endif - NR_VCPU_REGS -}; - -enum { - VCPU_SREG_CS, - VCPU_SREG_DS, - VCPU_SREG_ES, - VCPU_SREG_FS, - VCPU_SREG_GS, - VCPU_SREG_SS, - VCPU_SREG_TR, - VCPU_SREG_LDTR, -}; - -struct kvm_vcpu { - struct kvm *kvm; - union { - struct vmcs *vmcs; - struct vcpu_svm *svm; - }; - struct mutex mutex; - int cpu; - int launched; - unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */ -#define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long) - unsigned long irq_pending[NR_IRQ_WORDS]; - unsigned long regs[NR_VCPU_REGS]; /* for rsp: vcpu_load_rsp_rip() */ - unsigned long rip; /* needs vcpu_load_rsp_rip() */ - - unsigned long cr0; - unsigned long cr2; - unsigned long cr3; - unsigned long cr4; - unsigned long cr8; - u64 shadow_efer; - u64 apic_base; - int nmsrs; - struct vmx_msr_entry *guest_msrs; - struct vmx_msr_entry *host_msrs; - - struct list_head free_pages; - struct kvm_mmu_page page_header_buf[KVM_NUM_MMU_PAGES]; - struct kvm_mmu mmu; - - struct kvm_guest_debug guest_debug; - - char fx_buf[FX_BUF_SIZE]; - char *host_fx_image; - char *guest_fx_image; - - int mmio_needed; - int mmio_read_completed; - int mmio_is_write; - int mmio_size; - unsigned char mmio_data[8]; - gpa_t mmio_phys_addr; - - struct { - int active; - u8 save_iopl; - struct kvm_save_segment { - u16 selector; - unsigned long base; - u32 limit; - u32 ar; - } tr, es, ds, fs, gs; - } rmode; -}; - -struct kvm_memory_slot { - gfn_t base_gfn; - unsigned long npages; - unsigned long flags; - struct page **phys_mem; - unsigned long *dirty_bitmap; -}; - -struct kvm { - spinlock_t lock; /* protects everything except vcpus */ - int nmemslots; - struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS]; - struct list_head active_mmu_pages; - struct kvm_vcpu vcpus[KVM_MAX_VCPUS]; - int memory_config_version; - int busy; -}; - -struct kvm_stat { - u32 pf_fixed; - u32 pf_guest; - u32 tlb_flush; - u32 invlpg; - - u32 exits; - u32 io_exits; - u32 mmio_exits; - u32 signal_exits; - u32 irq_exits; -}; - -struct descriptor_table { - u16 limit; - unsigned long base; -} __attribute__((packed)); - -struct kvm_arch_ops { - int (*cpu_has_kvm_support)(void); /* __init */ - int (*disabled_by_bios)(void); /* __init */ - void (*hardware_enable)(void *dummy); /* __init */ - void (*hardware_disable)(void *dummy); - int (*hardware_setup)(void); /* __init */ - void (*hardware_unsetup)(void); /* __exit */ - - int (*vcpu_create)(struct kvm_vcpu *vcpu); - void (*vcpu_free)(struct kvm_vcpu *vcpu); - - struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu); - void (*vcpu_put)(struct kvm_vcpu *vcpu); - - int (*set_guest_debug)(struct kvm_vcpu *vcpu, - struct kvm_debug_guest *dbg); - int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata); - int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); - u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg); - void (*get_segment)(struct kvm_vcpu *vcpu, - struct kvm_segment *var, int seg); - void (*set_segment)(struct kvm_vcpu *vcpu, - struct kvm_segment *var, int seg); - int (*is_long_mode)(struct kvm_vcpu *vcpu); - void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l); - void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0); - void (*set_cr0_no_modeswitch)(struct kvm_vcpu *vcpu, - unsigned long cr0); - void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3); - void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4); - void (*set_efer)(struct kvm_vcpu *vcpu, u64 efer); - void (*get_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); - void (*set_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); - void (*get_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); - void (*set_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); - unsigned long (*get_dr)(struct kvm_vcpu *vcpu, int dr); - void (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value, - int *exception); - void (*cache_regs)(struct kvm_vcpu *vcpu); - void (*decache_regs)(struct kvm_vcpu *vcpu); - unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); - void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags); - - void (*invlpg)(struct kvm_vcpu *vcpu, gva_t addr); - void (*tlb_flush)(struct kvm_vcpu *vcpu); - void (*inject_page_fault)(struct kvm_vcpu *vcpu, - unsigned long addr, u32 err_code); - - void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code); - - int (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run); - int (*vcpu_setup)(struct kvm_vcpu *vcpu); - void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); -}; - -extern struct kvm_stat kvm_stat; -extern struct kvm_arch_ops *kvm_arch_ops; - -#define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) -#define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt) - -int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module); -void kvm_exit_arch(void); - -void kvm_mmu_destroy(struct kvm_vcpu *vcpu); -int kvm_mmu_init(struct kvm_vcpu *vcpu); - -int kvm_mmu_reset_context(struct kvm_vcpu *vcpu); -void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot); - -hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa); -#define HPA_MSB ((sizeof(hpa_t) * 8) - 1) -#define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB) -static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; } -hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva); - -void kvm_emulator_want_group7_invlpg(void); - -extern hpa_t bad_page_address; - -static inline struct page *gfn_to_page(struct kvm_memory_slot *slot, gfn_t gfn) -{ - return slot->phys_mem[gfn - slot->base_gfn]; -} - -struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); -void mark_page_dirty(struct kvm *kvm, gfn_t gfn); - -enum emulation_result { - EMULATE_DONE, /* no further processing */ - EMULATE_DO_MMIO, /* kvm_run filled with mmio request */ - EMULATE_FAIL, /* can't emulate this instruction */ -}; - -int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run, - unsigned long cr2, u16 error_code); -void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); -void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); -void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw, - unsigned long *rflags); - -unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr); -void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value, - unsigned long *rflags); - -struct x86_emulate_ctxt; - -int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address); -int emulate_clts(struct kvm_vcpu *vcpu); -int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr, - unsigned long *dest); -int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, - unsigned long value); - -void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); -void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr0); -void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr0); -void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0); -void lmsw(struct kvm_vcpu *vcpu, unsigned long msw); - -#ifdef CONFIG_X86_64 -void set_efer(struct kvm_vcpu *vcpu, u64 efer); -#endif - -void fx_init(struct kvm_vcpu *vcpu); - -void load_msrs(struct vmx_msr_entry *e, int n); -void save_msrs(struct vmx_msr_entry *e, int n); -void kvm_resched(struct kvm_vcpu *vcpu); - -int kvm_read_guest(struct kvm_vcpu *vcpu, - gva_t addr, - unsigned long size, - void *dest); - -int kvm_write_guest(struct kvm_vcpu *vcpu, - gva_t addr, - unsigned long size, - void *data); - -unsigned long segment_base(u16 selector); - -static inline struct page *_gfn_to_page(struct kvm *kvm, gfn_t gfn) -{ - struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn); - return (slot) ? slot->phys_mem[gfn - slot->base_gfn] : NULL; -} - -static inline int is_pae(struct kvm_vcpu *vcpu) -{ - return vcpu->cr4 & CR4_PAE_MASK; -} - -static inline int is_pse(struct kvm_vcpu *vcpu) -{ - return vcpu->cr4 & CR4_PSE_MASK; -} - -static inline int is_paging(struct kvm_vcpu *vcpu) -{ - return vcpu->cr0 & CR0_PG_MASK; -} - -static inline int memslot_id(struct kvm *kvm, struct kvm_memory_slot *slot) -{ - return slot - kvm->memslots; -} - -static inline struct kvm_mmu_page *page_header(hpa_t shadow_page) -{ - struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT); - - return (struct kvm_mmu_page *)page->private; -} - -static inline u16 read_fs(void) -{ - u16 seg; - asm ("mov %%fs, %0" : "=g"(seg)); - return seg; -} - -static inline u16 read_gs(void) -{ - u16 seg; - asm ("mov %%gs, %0" : "=g"(seg)); - return seg; -} - -static inline u16 read_ldt(void) -{ - u16 ldt; - asm ("sldt %0" : "=g"(ldt)); - return ldt; -} - -static inline void load_fs(u16 sel) -{ - asm ("mov %0, %%fs" : : "rm"(sel)); -} - -static inline void load_gs(u16 sel) -{ - asm ("mov %0, %%gs" : : "rm"(sel)); -} - -#ifndef load_ldt -static inline void load_ldt(u16 sel) -{ - asm ("lldt %0" : : "g"(sel)); -} -#endif - -static inline void get_idt(struct descriptor_table *table) -{ - asm ("sidt %0" : "=m"(*table)); -} - -static inline void get_gdt(struct descriptor_table *table) -{ - asm ("sgdt %0" : "=m"(*table)); -} - -static inline unsigned long read_tr_base(void) -{ - u16 tr; - asm ("str %0" : "=g"(tr)); - return segment_base(tr); -} - -#ifdef CONFIG_X86_64 -static inline unsigned long read_msr(unsigned long msr) -{ - u64 value; - - rdmsrl(msr, value); - return value; -} -#endif - -static inline void fx_save(void *image) -{ - asm ("fxsave (%0)":: "r" (image)); -} - -static inline void fx_restore(void *image) -{ - asm ("fxrstor (%0)":: "r" (image)); -} - -static inline void fpu_init(void) -{ - asm ("finit"); -} - -static inline u32 get_rdx_init_val(void) -{ - return 0x600; /* P6 family */ -} - -#define ASM_VMX_VMCLEAR_RAX ".byte 0x66, 0x0f, 0xc7, 0x30" -#define ASM_VMX_VMLAUNCH ".byte 0x0f, 0x01, 0xc2" -#define ASM_VMX_VMRESUME ".byte 0x0f, 0x01, 0xc3" -#define ASM_VMX_VMPTRLD_RAX ".byte 0x0f, 0xc7, 0x30" -#define ASM_VMX_VMREAD_RDX_RAX ".byte 0x0f, 0x78, 0xd0" -#define ASM_VMX_VMWRITE_RAX_RDX ".byte 0x0f, 0x79, 0xd0" -#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4" -#define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4" -#define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30" - -#define MSR_IA32_TIME_STAMP_COUNTER 0x010 - -#define TSS_IOPB_BASE_OFFSET 0x66 -#define TSS_BASE_SIZE 0x68 -#define TSS_IOPB_SIZE (65536 / 8) -#define TSS_REDIRECTION_SIZE (256 / 8) -#define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1) - -#ifdef CONFIG_X86_64 - -/* - * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64. Therefore - * we need to allocate shadow page tables in the first 4GB of memory, which - * happens to fit the DMA32 zone. - */ -#define GFP_KVM_MMU (GFP_KERNEL | __GFP_DMA32) - -#else - -#define GFP_KVM_MMU GFP_KERNEL - -#endif - -#endif diff --git a/trunk/drivers/kvm/kvm_main.c b/trunk/drivers/kvm/kvm_main.c deleted file mode 100644 index fd1bb870545c..000000000000 --- a/trunk/drivers/kvm/kvm_main.c +++ /dev/null @@ -1,1917 +0,0 @@ -/* - * Kernel-based Virtual Machine driver for Linux - * - * This module enables machines with Intel VT-x extensions to run virtual - * machines without emulation or binary translation. - * - * Copyright (C) 2006 Qumranet, Inc. - * - * Authors: - * Avi Kivity - * Yaniv Kamay - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#include "kvm.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "x86_emulate.h" -#include "segment_descriptor.h" - -MODULE_AUTHOR("Qumranet"); -MODULE_LICENSE("GPL"); - -struct kvm_arch_ops *kvm_arch_ops; -struct kvm_stat kvm_stat; -EXPORT_SYMBOL_GPL(kvm_stat); - -static struct kvm_stats_debugfs_item { - const char *name; - u32 *data; - struct dentry *dentry; -} debugfs_entries[] = { - { "pf_fixed", &kvm_stat.pf_fixed }, - { "pf_guest", &kvm_stat.pf_guest }, - { "tlb_flush", &kvm_stat.tlb_flush }, - { "invlpg", &kvm_stat.invlpg }, - { "exits", &kvm_stat.exits }, - { "io_exits", &kvm_stat.io_exits }, - { "mmio_exits", &kvm_stat.mmio_exits }, - { "signal_exits", &kvm_stat.signal_exits }, - { "irq_exits", &kvm_stat.irq_exits }, - { 0, 0 } -}; - -static struct dentry *debugfs_dir; - -#define MAX_IO_MSRS 256 - -#define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL -#define LMSW_GUEST_MASK 0x0eULL -#define CR4_RESEVED_BITS (~((1ULL << 11) - 1)) -#define CR8_RESEVED_BITS (~0x0fULL) -#define EFER_RESERVED_BITS 0xfffffffffffff2fe - -#ifdef CONFIG_X86_64 -// LDT or TSS descriptor in the GDT. 16 bytes. -struct segment_descriptor_64 { - struct segment_descriptor s; - u32 base_higher; - u32 pad_zero; -}; - -#endif - -unsigned long segment_base(u16 selector) -{ - struct descriptor_table gdt; - struct segment_descriptor *d; - unsigned long table_base; - typedef unsigned long ul; - unsigned long v; - - if (selector == 0) - return 0; - - asm ("sgdt %0" : "=m"(gdt)); - table_base = gdt.base; - - if (selector & 4) { /* from ldt */ - u16 ldt_selector; - - asm ("sldt %0" : "=g"(ldt_selector)); - table_base = segment_base(ldt_selector); - } - d = (struct segment_descriptor *)(table_base + (selector & ~7)); - v = d->base_low | ((ul)d->base_mid << 16) | ((ul)d->base_high << 24); -#ifdef CONFIG_X86_64 - if (d->system == 0 - && (d->type == 2 || d->type == 9 || d->type == 11)) - v |= ((ul)((struct segment_descriptor_64 *)d)->base_higher) << 32; -#endif - return v; -} -EXPORT_SYMBOL_GPL(segment_base); - -int kvm_read_guest(struct kvm_vcpu *vcpu, - gva_t addr, - unsigned long size, - void *dest) -{ - unsigned char *host_buf = dest; - unsigned long req_size = size; - - while (size) { - hpa_t paddr; - unsigned now; - unsigned offset; - hva_t guest_buf; - - paddr = gva_to_hpa(vcpu, addr); - - if (is_error_hpa(paddr)) - break; - - guest_buf = (hva_t)kmap_atomic( - pfn_to_page(paddr >> PAGE_SHIFT), - KM_USER0); - offset = addr & ~PAGE_MASK; - guest_buf |= offset; - now = min(size, PAGE_SIZE - offset); - memcpy(host_buf, (void*)guest_buf, now); - host_buf += now; - addr += now; - size -= now; - kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0); - } - return req_size - size; -} -EXPORT_SYMBOL_GPL(kvm_read_guest); - -int kvm_write_guest(struct kvm_vcpu *vcpu, - gva_t addr, - unsigned long size, - void *data) -{ - unsigned char *host_buf = data; - unsigned long req_size = size; - - while (size) { - hpa_t paddr; - unsigned now; - unsigned offset; - hva_t guest_buf; - - paddr = gva_to_hpa(vcpu, addr); - - if (is_error_hpa(paddr)) - break; - - guest_buf = (hva_t)kmap_atomic( - pfn_to_page(paddr >> PAGE_SHIFT), KM_USER0); - offset = addr & ~PAGE_MASK; - guest_buf |= offset; - now = min(size, PAGE_SIZE - offset); - memcpy((void*)guest_buf, host_buf, now); - host_buf += now; - addr += now; - size -= now; - kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0); - } - return req_size - size; -} -EXPORT_SYMBOL_GPL(kvm_write_guest); - -static int vcpu_slot(struct kvm_vcpu *vcpu) -{ - return vcpu - vcpu->kvm->vcpus; -} - -/* - * Switches to specified vcpu, until a matching vcpu_put() - */ -static struct kvm_vcpu *vcpu_load(struct kvm *kvm, int vcpu_slot) -{ - struct kvm_vcpu *vcpu = &kvm->vcpus[vcpu_slot]; - - mutex_lock(&vcpu->mutex); - if (unlikely(!vcpu->vmcs)) { - mutex_unlock(&vcpu->mutex); - return 0; - } - return kvm_arch_ops->vcpu_load(vcpu); -} - -static void vcpu_put(struct kvm_vcpu *vcpu) -{ - kvm_arch_ops->vcpu_put(vcpu); - mutex_unlock(&vcpu->mutex); -} - -static int kvm_dev_open(struct inode *inode, struct file *filp) -{ - struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); - int i; - - if (!kvm) - return -ENOMEM; - - spin_lock_init(&kvm->lock); - INIT_LIST_HEAD(&kvm->active_mmu_pages); - for (i = 0; i < KVM_MAX_VCPUS; ++i) { - struct kvm_vcpu *vcpu = &kvm->vcpus[i]; - - mutex_init(&vcpu->mutex); - vcpu->mmu.root_hpa = INVALID_PAGE; - INIT_LIST_HEAD(&vcpu->free_pages); - } - filp->private_data = kvm; - return 0; -} - -/* - * Free any memory in @free but not in @dont. - */ -static void kvm_free_physmem_slot(struct kvm_memory_slot *free, - struct kvm_memory_slot *dont) -{ - int i; - - if (!dont || free->phys_mem != dont->phys_mem) - if (free->phys_mem) { - for (i = 0; i < free->npages; ++i) - __free_page(free->phys_mem[i]); - vfree(free->phys_mem); - } - - if (!dont || free->dirty_bitmap != dont->dirty_bitmap) - vfree(free->dirty_bitmap); - - free->phys_mem = 0; - free->npages = 0; - free->dirty_bitmap = 0; -} - -static void kvm_free_physmem(struct kvm *kvm) -{ - int i; - - for (i = 0; i < kvm->nmemslots; ++i) - kvm_free_physmem_slot(&kvm->memslots[i], 0); -} - -static void kvm_free_vcpu(struct kvm_vcpu *vcpu) -{ - kvm_arch_ops->vcpu_free(vcpu); - kvm_mmu_destroy(vcpu); -} - -static void kvm_free_vcpus(struct kvm *kvm) -{ - unsigned int i; - - for (i = 0; i < KVM_MAX_VCPUS; ++i) - kvm_free_vcpu(&kvm->vcpus[i]); -} - -static int kvm_dev_release(struct inode *inode, struct file *filp) -{ - struct kvm *kvm = filp->private_data; - - kvm_free_vcpus(kvm); - kvm_free_physmem(kvm); - kfree(kvm); - return 0; -} - -static void inject_gp(struct kvm_vcpu *vcpu) -{ - kvm_arch_ops->inject_gp(vcpu, 0); -} - -static int pdptrs_have_reserved_bits_set(struct kvm_vcpu *vcpu, - unsigned long cr3) -{ - gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT; - unsigned offset = (cr3 & (PAGE_SIZE-1)) >> 5; - int i; - u64 pdpte; - u64 *pdpt; - struct kvm_memory_slot *memslot; - - spin_lock(&vcpu->kvm->lock); - memslot = gfn_to_memslot(vcpu->kvm, pdpt_gfn); - /* FIXME: !memslot - emulate? 0xff? */ - pdpt = kmap_atomic(gfn_to_page(memslot, pdpt_gfn), KM_USER0); - - for (i = 0; i < 4; ++i) { - pdpte = pdpt[offset + i]; - if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull)) - break; - } - - kunmap_atomic(pdpt, KM_USER0); - spin_unlock(&vcpu->kvm->lock); - - return i != 4; -} - -void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) -{ - if (cr0 & CR0_RESEVED_BITS) { - printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n", - cr0, vcpu->cr0); - inject_gp(vcpu); - return; - } - - if ((cr0 & CR0_NW_MASK) && !(cr0 & CR0_CD_MASK)) { - printk(KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n"); - inject_gp(vcpu); - return; - } - - if ((cr0 & CR0_PG_MASK) && !(cr0 & CR0_PE_MASK)) { - printk(KERN_DEBUG "set_cr0: #GP, set PG flag " - "and a clear PE flag\n"); - inject_gp(vcpu); - return; - } - - if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) { -#ifdef CONFIG_X86_64 - if ((vcpu->shadow_efer & EFER_LME)) { - int cs_db, cs_l; - - if (!is_pae(vcpu)) { - printk(KERN_DEBUG "set_cr0: #GP, start paging " - "in long mode while PAE is disabled\n"); - inject_gp(vcpu); - return; - } - kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); - if (cs_l) { - printk(KERN_DEBUG "set_cr0: #GP, start paging " - "in long mode while CS.L == 1\n"); - inject_gp(vcpu); - return; - - } - } else -#endif - if (is_pae(vcpu) && - pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) { - printk(KERN_DEBUG "set_cr0: #GP, pdptrs " - "reserved bits\n"); - inject_gp(vcpu); - return; - } - - } - - kvm_arch_ops->set_cr0(vcpu, cr0); - vcpu->cr0 = cr0; - - spin_lock(&vcpu->kvm->lock); - kvm_mmu_reset_context(vcpu); - spin_unlock(&vcpu->kvm->lock); - return; -} -EXPORT_SYMBOL_GPL(set_cr0); - -void lmsw(struct kvm_vcpu *vcpu, unsigned long msw) -{ - set_cr0(vcpu, (vcpu->cr0 & ~0x0ful) | (msw & 0x0f)); -} -EXPORT_SYMBOL_GPL(lmsw); - -void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) -{ - if (cr4 & CR4_RESEVED_BITS) { - printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n"); - inject_gp(vcpu); - return; - } - - if (kvm_arch_ops->is_long_mode(vcpu)) { - if (!(cr4 & CR4_PAE_MASK)) { - printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while " - "in long mode\n"); - inject_gp(vcpu); - return; - } - } else if (is_paging(vcpu) && !is_pae(vcpu) && (cr4 & CR4_PAE_MASK) - && pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) { - printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n"); - inject_gp(vcpu); - } - - if (cr4 & CR4_VMXE_MASK) { - printk(KERN_DEBUG "set_cr4: #GP, setting VMXE\n"); - inject_gp(vcpu); - return; - } - kvm_arch_ops->set_cr4(vcpu, cr4); - spin_lock(&vcpu->kvm->lock); - kvm_mmu_reset_context(vcpu); - spin_unlock(&vcpu->kvm->lock); -} -EXPORT_SYMBOL_GPL(set_cr4); - -void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) -{ - if (kvm_arch_ops->is_long_mode(vcpu)) { - if ( cr3 & CR3_L_MODE_RESEVED_BITS) { - printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); - inject_gp(vcpu); - return; - } - } else { - if (cr3 & CR3_RESEVED_BITS) { - printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); - inject_gp(vcpu); - return; - } - if (is_paging(vcpu) && is_pae(vcpu) && - pdptrs_have_reserved_bits_set(vcpu, cr3)) { - printk(KERN_DEBUG "set_cr3: #GP, pdptrs " - "reserved bits\n"); - inject_gp(vcpu); - return; - } - } - - vcpu->cr3 = cr3; - spin_lock(&vcpu->kvm->lock); - vcpu->mmu.new_cr3(vcpu); - spin_unlock(&vcpu->kvm->lock); -} -EXPORT_SYMBOL_GPL(set_cr3); - -void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) -{ - if ( cr8 & CR8_RESEVED_BITS) { - printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8); - inject_gp(vcpu); - return; - } - vcpu->cr8 = cr8; -} -EXPORT_SYMBOL_GPL(set_cr8); - -void fx_init(struct kvm_vcpu *vcpu) -{ - struct __attribute__ ((__packed__)) fx_image_s { - u16 control; //fcw - u16 status; //fsw - u16 tag; // ftw - u16 opcode; //fop - u64 ip; // fpu ip - u64 operand;// fpu dp - u32 mxcsr; - u32 mxcsr_mask; - - } *fx_image; - - fx_save(vcpu->host_fx_image); - fpu_init(); - fx_save(vcpu->guest_fx_image); - fx_restore(vcpu->host_fx_image); - - fx_image = (struct fx_image_s *)vcpu->guest_fx_image; - fx_image->mxcsr = 0x1f80; - memset(vcpu->guest_fx_image + sizeof(struct fx_image_s), - 0, FX_IMAGE_SIZE - sizeof(struct fx_image_s)); -} -EXPORT_SYMBOL_GPL(fx_init); - -/* - * Creates some virtual cpus. Good luck creating more than one. - */ -static int kvm_dev_ioctl_create_vcpu(struct kvm *kvm, int n) -{ - int r; - struct kvm_vcpu *vcpu; - - r = -EINVAL; - if (n < 0 || n >= KVM_MAX_VCPUS) - goto out; - - vcpu = &kvm->vcpus[n]; - - mutex_lock(&vcpu->mutex); - - if (vcpu->vmcs) { - mutex_unlock(&vcpu->mutex); - return -EEXIST; - } - - vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf, - FX_IMAGE_ALIGN); - vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE; - - vcpu->cpu = -1; /* First load will set up TR */ - vcpu->kvm = kvm; - r = kvm_arch_ops->vcpu_create(vcpu); - if (r < 0) - goto out_free_vcpus; - - kvm_arch_ops->vcpu_load(vcpu); - - r = kvm_arch_ops->vcpu_setup(vcpu); - if (r >= 0) - r = kvm_mmu_init(vcpu); - - vcpu_put(vcpu); - - if (r < 0) - goto out_free_vcpus; - - return 0; - -out_free_vcpus: - kvm_free_vcpu(vcpu); - mutex_unlock(&vcpu->mutex); -out: - return r; -} - -/* - * Allocate some memory and give it an address in the guest physical address - * space. - * - * Discontiguous memory is allowed, mostly for framebuffers. - */ -static int kvm_dev_ioctl_set_memory_region(struct kvm *kvm, - struct kvm_memory_region *mem) -{ - int r; - gfn_t base_gfn; - unsigned long npages; - unsigned long i; - struct kvm_memory_slot *memslot; - struct kvm_memory_slot old, new; - int memory_config_version; - - r = -EINVAL; - /* General sanity checks */ - if (mem->memory_size & (PAGE_SIZE - 1)) - goto out; - if (mem->guest_phys_addr & (PAGE_SIZE - 1)) - goto out; - if (mem->slot >= KVM_MEMORY_SLOTS) - goto out; - if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) - goto out; - - memslot = &kvm->memslots[mem->slot]; - base_gfn = mem->guest_phys_addr >> PAGE_SHIFT; - npages = mem->memory_size >> PAGE_SHIFT; - - if (!npages) - mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES; - -raced: - spin_lock(&kvm->lock); - - memory_config_version = kvm->memory_config_version; - new = old = *memslot; - - new.base_gfn = base_gfn; - new.npages = npages; - new.flags = mem->flags; - - /* Disallow changing a memory slot's size. */ - r = -EINVAL; - if (npages && old.npages && npages != old.npages) - goto out_unlock; - - /* Check for overlaps */ - r = -EEXIST; - for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { - struct kvm_memory_slot *s = &kvm->memslots[i]; - - if (s == memslot) - continue; - if (!((base_gfn + npages <= s->base_gfn) || - (base_gfn >= s->base_gfn + s->npages))) - goto out_unlock; - } - /* - * Do memory allocations outside lock. memory_config_version will - * detect any races. - */ - spin_unlock(&kvm->lock); - - /* Deallocate if slot is being removed */ - if (!npages) - new.phys_mem = 0; - - /* Free page dirty bitmap if unneeded */ - if (!(new.flags & KVM_MEM_LOG_DIRTY_PAGES)) - new.dirty_bitmap = 0; - - r = -ENOMEM; - - /* Allocate if a slot is being created */ - if (npages && !new.phys_mem) { - new.phys_mem = vmalloc(npages * sizeof(struct page *)); - - if (!new.phys_mem) - goto out_free; - - memset(new.phys_mem, 0, npages * sizeof(struct page *)); - for (i = 0; i < npages; ++i) { - new.phys_mem[i] = alloc_page(GFP_HIGHUSER - | __GFP_ZERO); - if (!new.phys_mem[i]) - goto out_free; - } - } - - /* Allocate page dirty bitmap if needed */ - if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) { - unsigned dirty_bytes = ALIGN(npages, BITS_PER_LONG) / 8; - - new.dirty_bitmap = vmalloc(dirty_bytes); - if (!new.dirty_bitmap) - goto out_free; - memset(new.dirty_bitmap, 0, dirty_bytes); - } - - spin_lock(&kvm->lock); - - if (memory_config_version != kvm->memory_config_version) { - spin_unlock(&kvm->lock); - kvm_free_physmem_slot(&new, &old); - goto raced; - } - - r = -EAGAIN; - if (kvm->busy) - goto out_unlock; - - if (mem->slot >= kvm->nmemslots) - kvm->nmemslots = mem->slot + 1; - - *memslot = new; - ++kvm->memory_config_version; - - spin_unlock(&kvm->lock); - - for (i = 0; i < KVM_MAX_VCPUS; ++i) { - struct kvm_vcpu *vcpu; - - vcpu = vcpu_load(kvm, i); - if (!vcpu) - continue; - kvm_mmu_reset_context(vcpu); - vcpu_put(vcpu); - } - - kvm_free_physmem_slot(&old, &new); - return 0; - -out_unlock: - spin_unlock(&kvm->lock); -out_free: - kvm_free_physmem_slot(&new, &old); -out: - return r; -} - -/* - * Get (and clear) the dirty memory log for a memory slot. - */ -static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm, - struct kvm_dirty_log *log) -{ - struct kvm_memory_slot *memslot; - int r, i; - int n; - unsigned long any = 0; - - spin_lock(&kvm->lock); - - /* - * Prevent changes to guest memory configuration even while the lock - * is not taken. - */ - ++kvm->busy; - spin_unlock(&kvm->lock); - r = -EINVAL; - if (log->slot >= KVM_MEMORY_SLOTS) - goto out; - - memslot = &kvm->memslots[log->slot]; - r = -ENOENT; - if (!memslot->dirty_bitmap) - goto out; - - n = ALIGN(memslot->npages, 8) / 8; - - for (i = 0; !any && i < n; ++i) - any = memslot->dirty_bitmap[i]; - - r = -EFAULT; - if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n)) - goto out; - - - if (any) { - spin_lock(&kvm->lock); - kvm_mmu_slot_remove_write_access(kvm, log->slot); - spin_unlock(&kvm->lock); - memset(memslot->dirty_bitmap, 0, n); - for (i = 0; i < KVM_MAX_VCPUS; ++i) { - struct kvm_vcpu *vcpu = vcpu_load(kvm, i); - - if (!vcpu) - continue; - kvm_arch_ops->tlb_flush(vcpu); - vcpu_put(vcpu); - } - } - - r = 0; - -out: - spin_lock(&kvm->lock); - --kvm->busy; - spin_unlock(&kvm->lock); - return r; -} - -struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn) -{ - int i; - - for (i = 0; i < kvm->nmemslots; ++i) { - struct kvm_memory_slot *memslot = &kvm->memslots[i]; - - if (gfn >= memslot->base_gfn - && gfn < memslot->base_gfn + memslot->npages) - return memslot; - } - return 0; -} -EXPORT_SYMBOL_GPL(gfn_to_memslot); - -void mark_page_dirty(struct kvm *kvm, gfn_t gfn) -{ - int i; - struct kvm_memory_slot *memslot = 0; - unsigned long rel_gfn; - - for (i = 0; i < kvm->nmemslots; ++i) { - memslot = &kvm->memslots[i]; - - if (gfn >= memslot->base_gfn - && gfn < memslot->base_gfn + memslot->npages) { - - if (!memslot || !memslot->dirty_bitmap) - return; - - rel_gfn = gfn - memslot->base_gfn; - - /* avoid RMW */ - if (!test_bit(rel_gfn, memslot->dirty_bitmap)) - set_bit(rel_gfn, memslot->dirty_bitmap); - return; - } - } -} - -static int emulator_read_std(unsigned long addr, - unsigned long *val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - struct kvm_vcpu *vcpu = ctxt->vcpu; - void *data = val; - - while (bytes) { - gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); - unsigned offset = addr & (PAGE_SIZE-1); - unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset); - unsigned long pfn; - struct kvm_memory_slot *memslot; - void *page; - - if (gpa == UNMAPPED_GVA) - return X86EMUL_PROPAGATE_FAULT; - pfn = gpa >> PAGE_SHIFT; - memslot = gfn_to_memslot(vcpu->kvm, pfn); - if (!memslot) - return X86EMUL_UNHANDLEABLE; - page = kmap_atomic(gfn_to_page(memslot, pfn), KM_USER0); - - memcpy(data, page + offset, tocopy); - - kunmap_atomic(page, KM_USER0); - - bytes -= tocopy; - data += tocopy; - addr += tocopy; - } - - return X86EMUL_CONTINUE; -} - -static int emulator_write_std(unsigned long addr, - unsigned long val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - printk(KERN_ERR "emulator_write_std: addr %lx n %d\n", - addr, bytes); - return X86EMUL_UNHANDLEABLE; -} - -static int emulator_read_emulated(unsigned long addr, - unsigned long *val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - struct kvm_vcpu *vcpu = ctxt->vcpu; - - if (vcpu->mmio_read_completed) { - memcpy(val, vcpu->mmio_data, bytes); - vcpu->mmio_read_completed = 0; - return X86EMUL_CONTINUE; - } else if (emulator_read_std(addr, val, bytes, ctxt) - == X86EMUL_CONTINUE) - return X86EMUL_CONTINUE; - else { - gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); - if (gpa == UNMAPPED_GVA) - return vcpu_printf(vcpu, "not present\n"), X86EMUL_PROPAGATE_FAULT; - vcpu->mmio_needed = 1; - vcpu->mmio_phys_addr = gpa; - vcpu->mmio_size = bytes; - vcpu->mmio_is_write = 0; - - return X86EMUL_UNHANDLEABLE; - } -} - -static int emulator_write_emulated(unsigned long addr, - unsigned long val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - struct kvm_vcpu *vcpu = ctxt->vcpu; - gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); - - if (gpa == UNMAPPED_GVA) - return X86EMUL_PROPAGATE_FAULT; - - vcpu->mmio_needed = 1; - vcpu->mmio_phys_addr = gpa; - vcpu->mmio_size = bytes; - vcpu->mmio_is_write = 1; - memcpy(vcpu->mmio_data, &val, bytes); - - return X86EMUL_CONTINUE; -} - -static int emulator_cmpxchg_emulated(unsigned long addr, - unsigned long old, - unsigned long new, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - static int reported; - - if (!reported) { - reported = 1; - printk(KERN_WARNING "kvm: emulating exchange as write\n"); - } - return emulator_write_emulated(addr, new, bytes, ctxt); -} - -static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg) -{ - return kvm_arch_ops->get_segment_base(vcpu, seg); -} - -int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address) -{ - spin_lock(&vcpu->kvm->lock); - vcpu->mmu.inval_page(vcpu, address); - spin_unlock(&vcpu->kvm->lock); - kvm_arch_ops->invlpg(vcpu, address); - return X86EMUL_CONTINUE; -} - -int emulate_clts(struct kvm_vcpu *vcpu) -{ - unsigned long cr0 = vcpu->cr0; - - cr0 &= ~CR0_TS_MASK; - kvm_arch_ops->set_cr0(vcpu, cr0); - return X86EMUL_CONTINUE; -} - -int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr, unsigned long *dest) -{ - struct kvm_vcpu *vcpu = ctxt->vcpu; - - switch (dr) { - case 0 ... 3: - *dest = kvm_arch_ops->get_dr(vcpu, dr); - return X86EMUL_CONTINUE; - default: - printk(KERN_DEBUG "%s: unexpected dr %u\n", - __FUNCTION__, dr); - return X86EMUL_UNHANDLEABLE; - } -} - -int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value) -{ - unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U; - int exception; - - kvm_arch_ops->set_dr(ctxt->vcpu, dr, value & mask, &exception); - if (exception) { - /* FIXME: better handling */ - return X86EMUL_UNHANDLEABLE; - } - return X86EMUL_CONTINUE; -} - -static void report_emulation_failure(struct x86_emulate_ctxt *ctxt) -{ - static int reported; - u8 opcodes[4]; - unsigned long rip = ctxt->vcpu->rip; - unsigned long rip_linear; - - rip_linear = rip + get_segment_base(ctxt->vcpu, VCPU_SREG_CS); - - if (reported) - return; - - emulator_read_std(rip_linear, (void *)opcodes, 4, ctxt); - - printk(KERN_ERR "emulation failed but !mmio_needed?" - " rip %lx %02x %02x %02x %02x\n", - rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]); - reported = 1; -} - -struct x86_emulate_ops emulate_ops = { - .read_std = emulator_read_std, - .write_std = emulator_write_std, - .read_emulated = emulator_read_emulated, - .write_emulated = emulator_write_emulated, - .cmpxchg_emulated = emulator_cmpxchg_emulated, -}; - -int emulate_instruction(struct kvm_vcpu *vcpu, - struct kvm_run *run, - unsigned long cr2, - u16 error_code) -{ - struct x86_emulate_ctxt emulate_ctxt; - int r; - int cs_db, cs_l; - - kvm_arch_ops->cache_regs(vcpu); - - kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); - - emulate_ctxt.vcpu = vcpu; - emulate_ctxt.eflags = kvm_arch_ops->get_rflags(vcpu); - emulate_ctxt.cr2 = cr2; - emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM) - ? X86EMUL_MODE_REAL : cs_l - ? X86EMUL_MODE_PROT64 : cs_db - ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; - - if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) { - emulate_ctxt.cs_base = 0; - emulate_ctxt.ds_base = 0; - emulate_ctxt.es_base = 0; - emulate_ctxt.ss_base = 0; - } else { - emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS); - emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS); - emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES); - emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS); - } - - emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS); - emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS); - - vcpu->mmio_is_write = 0; - r = x86_emulate_memop(&emulate_ctxt, &emulate_ops); - - if ((r || vcpu->mmio_is_write) && run) { - run->mmio.phys_addr = vcpu->mmio_phys_addr; - memcpy(run->mmio.data, vcpu->mmio_data, 8); - run->mmio.len = vcpu->mmio_size; - run->mmio.is_write = vcpu->mmio_is_write; - } - - if (r) { - if (!vcpu->mmio_needed) { - report_emulation_failure(&emulate_ctxt); - return EMULATE_FAIL; - } - return EMULATE_DO_MMIO; - } - - kvm_arch_ops->decache_regs(vcpu); - kvm_arch_ops->set_rflags(vcpu, emulate_ctxt.eflags); - - if (vcpu->mmio_is_write) - return EMULATE_DO_MMIO; - - return EMULATE_DONE; -} -EXPORT_SYMBOL_GPL(emulate_instruction); - -static u64 mk_cr_64(u64 curr_cr, u32 new_val) -{ - return (curr_cr & ~((1ULL << 32) - 1)) | new_val; -} - -void realmode_lgdt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base) -{ - struct descriptor_table dt = { limit, base }; - - kvm_arch_ops->set_gdt(vcpu, &dt); -} - -void realmode_lidt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base) -{ - struct descriptor_table dt = { limit, base }; - - kvm_arch_ops->set_idt(vcpu, &dt); -} - -void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw, - unsigned long *rflags) -{ - lmsw(vcpu, msw); - *rflags = kvm_arch_ops->get_rflags(vcpu); -} - -unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr) -{ - switch (cr) { - case 0: - return vcpu->cr0; - case 2: - return vcpu->cr2; - case 3: - return vcpu->cr3; - case 4: - return vcpu->cr4; - default: - vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr); - return 0; - } -} - -void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val, - unsigned long *rflags) -{ - switch (cr) { - case 0: - set_cr0(vcpu, mk_cr_64(vcpu->cr0, val)); - *rflags = kvm_arch_ops->get_rflags(vcpu); - break; - case 2: - vcpu->cr2 = val; - break; - case 3: - set_cr3(vcpu, val); - break; - case 4: - set_cr4(vcpu, mk_cr_64(vcpu->cr4, val)); - break; - default: - vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr); - } -} - -/* - * Reads an msr value (of 'msr_index') into 'pdata'. - * Returns 0 on success, non-0 otherwise. - * Assumes vcpu_load() was already called. - */ -static int get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) -{ - return kvm_arch_ops->get_msr(vcpu, msr_index, pdata); -} - -#ifdef CONFIG_X86_64 - -void set_efer(struct kvm_vcpu *vcpu, u64 efer) -{ - if (efer & EFER_RESERVED_BITS) { - printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n", - efer); - inject_gp(vcpu); - return; - } - - if (is_paging(vcpu) - && (vcpu->shadow_efer & EFER_LME) != (efer & EFER_LME)) { - printk(KERN_DEBUG "set_efer: #GP, change LME while paging\n"); - inject_gp(vcpu); - return; - } - - kvm_arch_ops->set_efer(vcpu, efer); - - efer &= ~EFER_LMA; - efer |= vcpu->shadow_efer & EFER_LMA; - - vcpu->shadow_efer = efer; -} -EXPORT_SYMBOL_GPL(set_efer); - -#endif - -/* - * Writes msr value into into the appropriate "register". - * Returns 0 on success, non-0 otherwise. - * Assumes vcpu_load() was already called. - */ -static int set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) -{ - return kvm_arch_ops->set_msr(vcpu, msr_index, data); -} - -void kvm_resched(struct kvm_vcpu *vcpu) -{ - vcpu_put(vcpu); - cond_resched(); - /* Cannot fail - no vcpu unplug yet. */ - vcpu_load(vcpu->kvm, vcpu_slot(vcpu)); -} -EXPORT_SYMBOL_GPL(kvm_resched); - -void load_msrs(struct vmx_msr_entry *e, int n) -{ - int i; - - for (i = 0; i < n; ++i) - wrmsrl(e[i].index, e[i].data); -} -EXPORT_SYMBOL_GPL(load_msrs); - -void save_msrs(struct vmx_msr_entry *e, int n) -{ - int i; - - for (i = 0; i < n; ++i) - rdmsrl(e[i].index, e[i].data); -} -EXPORT_SYMBOL_GPL(save_msrs); - -static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run) -{ - struct kvm_vcpu *vcpu; - int r; - - if (kvm_run->vcpu < 0 || kvm_run->vcpu >= KVM_MAX_VCPUS) - return -EINVAL; - - vcpu = vcpu_load(kvm, kvm_run->vcpu); - if (!vcpu) - return -ENOENT; - - if (kvm_run->emulated) { - kvm_arch_ops->skip_emulated_instruction(vcpu); - kvm_run->emulated = 0; - } - - if (kvm_run->mmio_completed) { - memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); - vcpu->mmio_read_completed = 1; - } - - vcpu->mmio_needed = 0; - - r = kvm_arch_ops->run(vcpu, kvm_run); - - vcpu_put(vcpu); - return r; -} - -static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs) -{ - struct kvm_vcpu *vcpu; - - if (regs->vcpu < 0 || regs->vcpu >= KVM_MAX_VCPUS) - return -EINVAL; - - vcpu = vcpu_load(kvm, regs->vcpu); - if (!vcpu) - return -ENOENT; - - kvm_arch_ops->cache_regs(vcpu); - - regs->rax = vcpu->regs[VCPU_REGS_RAX]; - regs->rbx = vcpu->regs[VCPU_REGS_RBX]; - regs->rcx = vcpu->regs[VCPU_REGS_RCX]; - regs->rdx = vcpu->regs[VCPU_REGS_RDX]; - regs->rsi = vcpu->regs[VCPU_REGS_RSI]; - regs->rdi = vcpu->regs[VCPU_REGS_RDI]; - regs->rsp = vcpu->regs[VCPU_REGS_RSP]; - regs->rbp = vcpu->regs[VCPU_REGS_RBP]; -#ifdef CONFIG_X86_64 - regs->r8 = vcpu->regs[VCPU_REGS_R8]; - regs->r9 = vcpu->regs[VCPU_REGS_R9]; - regs->r10 = vcpu->regs[VCPU_REGS_R10]; - regs->r11 = vcpu->regs[VCPU_REGS_R11]; - regs->r12 = vcpu->regs[VCPU_REGS_R12]; - regs->r13 = vcpu->regs[VCPU_REGS_R13]; - regs->r14 = vcpu->regs[VCPU_REGS_R14]; - regs->r15 = vcpu->regs[VCPU_REGS_R15]; -#endif - - regs->rip = vcpu->rip; - regs->rflags = kvm_arch_ops->get_rflags(vcpu); - - /* - * Don't leak debug flags in case they were set for guest debugging - */ - if (vcpu->guest_debug.enabled && vcpu->guest_debug.singlestep) - regs->rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); - - vcpu_put(vcpu); - - return 0; -} - -static int kvm_dev_ioctl_set_regs(struct kvm *kvm, struct kvm_regs *regs) -{ - struct kvm_vcpu *vcpu; - - if (regs->vcpu < 0 || regs->vcpu >= KVM_MAX_VCPUS) - return -EINVAL; - - vcpu = vcpu_load(kvm, regs->vcpu); - if (!vcpu) - return -ENOENT; - - vcpu->regs[VCPU_REGS_RAX] = regs->rax; - vcpu->regs[VCPU_REGS_RBX] = regs->rbx; - vcpu->regs[VCPU_REGS_RCX] = regs->rcx; - vcpu->regs[VCPU_REGS_RDX] = regs->rdx; - vcpu->regs[VCPU_REGS_RSI] = regs->rsi; - vcpu->regs[VCPU_REGS_RDI] = regs->rdi; - vcpu->regs[VCPU_REGS_RSP] = regs->rsp; - vcpu->regs[VCPU_REGS_RBP] = regs->rbp; -#ifdef CONFIG_X86_64 - vcpu->regs[VCPU_REGS_R8] = regs->r8; - vcpu->regs[VCPU_REGS_R9] = regs->r9; - vcpu->regs[VCPU_REGS_R10] = regs->r10; - vcpu->regs[VCPU_REGS_R11] = regs->r11; - vcpu->regs[VCPU_REGS_R12] = regs->r12; - vcpu->regs[VCPU_REGS_R13] = regs->r13; - vcpu->regs[VCPU_REGS_R14] = regs->r14; - vcpu->regs[VCPU_REGS_R15] = regs->r15; -#endif - - vcpu->rip = regs->rip; - kvm_arch_ops->set_rflags(vcpu, regs->rflags); - - kvm_arch_ops->decache_regs(vcpu); - - vcpu_put(vcpu); - - return 0; -} - -static void get_segment(struct kvm_vcpu *vcpu, - struct kvm_segment *var, int seg) -{ - return kvm_arch_ops->get_segment(vcpu, var, seg); -} - -static int kvm_dev_ioctl_get_sregs(struct kvm *kvm, struct kvm_sregs *sregs) -{ - struct kvm_vcpu *vcpu; - struct descriptor_table dt; - - if (sregs->vcpu < 0 || sregs->vcpu >= KVM_MAX_VCPUS) - return -EINVAL; - vcpu = vcpu_load(kvm, sregs->vcpu); - if (!vcpu) - return -ENOENT; - - get_segment(vcpu, &sregs->cs, VCPU_SREG_CS); - get_segment(vcpu, &sregs->ds, VCPU_SREG_DS); - get_segment(vcpu, &sregs->es, VCPU_SREG_ES); - get_segment(vcpu, &sregs->fs, VCPU_SREG_FS); - get_segment(vcpu, &sregs->gs, VCPU_SREG_GS); - get_segment(vcpu, &sregs->ss, VCPU_SREG_SS); - - get_segment(vcpu, &sregs->tr, VCPU_SREG_TR); - get_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); - - kvm_arch_ops->get_idt(vcpu, &dt); - sregs->idt.limit = dt.limit; - sregs->idt.base = dt.base; - kvm_arch_ops->get_gdt(vcpu, &dt); - sregs->gdt.limit = dt.limit; - sregs->gdt.base = dt.base; - - sregs->cr0 = vcpu->cr0; - sregs->cr2 = vcpu->cr2; - sregs->cr3 = vcpu->cr3; - sregs->cr4 = vcpu->cr4; - sregs->cr8 = vcpu->cr8; - sregs->efer = vcpu->shadow_efer; - sregs->apic_base = vcpu->apic_base; - - memcpy(sregs->interrupt_bitmap, vcpu->irq_pending, - sizeof sregs->interrupt_bitmap); - - vcpu_put(vcpu); - - return 0; -} - -static void set_segment(struct kvm_vcpu *vcpu, - struct kvm_segment *var, int seg) -{ - return kvm_arch_ops->set_segment(vcpu, var, seg); -} - -static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs) -{ - struct kvm_vcpu *vcpu; - int mmu_reset_needed = 0; - int i; - struct descriptor_table dt; - - if (sregs->vcpu < 0 || sregs->vcpu >= KVM_MAX_VCPUS) - return -EINVAL; - vcpu = vcpu_load(kvm, sregs->vcpu); - if (!vcpu) - return -ENOENT; - - set_segment(vcpu, &sregs->cs, VCPU_SREG_CS); - set_segment(vcpu, &sregs->ds, VCPU_SREG_DS); - set_segment(vcpu, &sregs->es, VCPU_SREG_ES); - set_segment(vcpu, &sregs->fs, VCPU_SREG_FS); - set_segment(vcpu, &sregs->gs, VCPU_SREG_GS); - set_segment(vcpu, &sregs->ss, VCPU_SREG_SS); - - set_segment(vcpu, &sregs->tr, VCPU_SREG_TR); - set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); - - dt.limit = sregs->idt.limit; - dt.base = sregs->idt.base; - kvm_arch_ops->set_idt(vcpu, &dt); - dt.limit = sregs->gdt.limit; - dt.base = sregs->gdt.base; - kvm_arch_ops->set_gdt(vcpu, &dt); - - vcpu->cr2 = sregs->cr2; - mmu_reset_needed |= vcpu->cr3 != sregs->cr3; - vcpu->cr3 = sregs->cr3; - - vcpu->cr8 = sregs->cr8; - - mmu_reset_needed |= vcpu->shadow_efer != sregs->efer; -#ifdef CONFIG_X86_64 - kvm_arch_ops->set_efer(vcpu, sregs->efer); -#endif - vcpu->apic_base = sregs->apic_base; - - mmu_reset_needed |= vcpu->cr0 != sregs->cr0; - kvm_arch_ops->set_cr0_no_modeswitch(vcpu, sregs->cr0); - - mmu_reset_needed |= vcpu->cr4 != sregs->cr4; - kvm_arch_ops->set_cr4(vcpu, sregs->cr4); - - if (mmu_reset_needed) - kvm_mmu_reset_context(vcpu); - - memcpy(vcpu->irq_pending, sregs->interrupt_bitmap, - sizeof vcpu->irq_pending); - vcpu->irq_summary = 0; - for (i = 0; i < NR_IRQ_WORDS; ++i) - if (vcpu->irq_pending[i]) - __set_bit(i, &vcpu->irq_summary); - - vcpu_put(vcpu); - - return 0; -} - -/* - * List of msr numbers which we expose to userspace through KVM_GET_MSRS - * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST. - */ -static u32 msrs_to_save[] = { - MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, - MSR_K6_STAR, -#ifdef CONFIG_X86_64 - MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, -#endif - MSR_IA32_TIME_STAMP_COUNTER, -}; - - -/* - * Adapt set_msr() to msr_io()'s calling convention - */ -static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) -{ - return set_msr(vcpu, index, *data); -} - -/* - * Read or write a bunch of msrs. All parameters are kernel addresses. - * - * @return number of msrs set successfully. - */ -static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs, - struct kvm_msr_entry *entries, - int (*do_msr)(struct kvm_vcpu *vcpu, - unsigned index, u64 *data)) -{ - struct kvm_vcpu *vcpu; - int i; - - if (msrs->vcpu < 0 || msrs->vcpu >= KVM_MAX_VCPUS) - return -EINVAL; - - vcpu = vcpu_load(kvm, msrs->vcpu); - if (!vcpu) - return -ENOENT; - - for (i = 0; i < msrs->nmsrs; ++i) - if (do_msr(vcpu, entries[i].index, &entries[i].data)) - break; - - vcpu_put(vcpu); - - return i; -} - -/* - * Read or write a bunch of msrs. Parameters are user addresses. - * - * @return number of msrs set successfully. - */ -static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs, - int (*do_msr)(struct kvm_vcpu *vcpu, - unsigned index, u64 *data), - int writeback) -{ - struct kvm_msrs msrs; - struct kvm_msr_entry *entries; - int r, n; - unsigned size; - - r = -EFAULT; - if (copy_from_user(&msrs, user_msrs, sizeof msrs)) - goto out; - - r = -E2BIG; - if (msrs.nmsrs >= MAX_IO_MSRS) - goto out; - - r = -ENOMEM; - size = sizeof(struct kvm_msr_entry) * msrs.nmsrs; - entries = vmalloc(size); - if (!entries) - goto out; - - r = -EFAULT; - if (copy_from_user(entries, user_msrs->entries, size)) - goto out_free; - - r = n = __msr_io(kvm, &msrs, entries, do_msr); - if (r < 0) - goto out_free; - - r = -EFAULT; - if (writeback && copy_to_user(user_msrs->entries, entries, size)) - goto out_free; - - r = n; - -out_free: - vfree(entries); -out: - return r; -} - -/* - * Translate a guest virtual address to a guest physical address. - */ -static int kvm_dev_ioctl_translate(struct kvm *kvm, struct kvm_translation *tr) -{ - unsigned long vaddr = tr->linear_address; - struct kvm_vcpu *vcpu; - gpa_t gpa; - - vcpu = vcpu_load(kvm, tr->vcpu); - if (!vcpu) - return -ENOENT; - spin_lock(&kvm->lock); - gpa = vcpu->mmu.gva_to_gpa(vcpu, vaddr); - tr->physical_address = gpa; - tr->valid = gpa != UNMAPPED_GVA; - tr->writeable = 1; - tr->usermode = 0; - spin_unlock(&kvm->lock); - vcpu_put(vcpu); - - return 0; -} - -static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq) -{ - struct kvm_vcpu *vcpu; - - if (irq->vcpu < 0 || irq->vcpu >= KVM_MAX_VCPUS) - return -EINVAL; - if (irq->irq < 0 || irq->irq >= 256) - return -EINVAL; - vcpu = vcpu_load(kvm, irq->vcpu); - if (!vcpu) - return -ENOENT; - - set_bit(irq->irq, vcpu->irq_pending); - set_bit(irq->irq / BITS_PER_LONG, &vcpu->irq_summary); - - vcpu_put(vcpu); - - return 0; -} - -static int kvm_dev_ioctl_debug_guest(struct kvm *kvm, - struct kvm_debug_guest *dbg) -{ - struct kvm_vcpu *vcpu; - int r; - - if (dbg->vcpu < 0 || dbg->vcpu >= KVM_MAX_VCPUS) - return -EINVAL; - vcpu = vcpu_load(kvm, dbg->vcpu); - if (!vcpu) - return -ENOENT; - - r = kvm_arch_ops->set_guest_debug(vcpu, dbg); - - vcpu_put(vcpu); - - return r; -} - -static long kvm_dev_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) -{ - struct kvm *kvm = filp->private_data; - int r = -EINVAL; - - switch (ioctl) { - case KVM_CREATE_VCPU: { - r = kvm_dev_ioctl_create_vcpu(kvm, arg); - if (r) - goto out; - break; - } - case KVM_RUN: { - struct kvm_run kvm_run; - - r = -EFAULT; - if (copy_from_user(&kvm_run, (void *)arg, sizeof kvm_run)) - goto out; - r = kvm_dev_ioctl_run(kvm, &kvm_run); - if (r < 0) - goto out; - r = -EFAULT; - if (copy_to_user((void *)arg, &kvm_run, sizeof kvm_run)) - goto out; - r = 0; - break; - } - case KVM_GET_REGS: { - struct kvm_regs kvm_regs; - - r = -EFAULT; - if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs)) - goto out; - r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs); - if (r) - goto out; - r = -EFAULT; - if (copy_to_user((void *)arg, &kvm_regs, sizeof kvm_regs)) - goto out; - r = 0; - break; - } - case KVM_SET_REGS: { - struct kvm_regs kvm_regs; - - r = -EFAULT; - if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs)) - goto out; - r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs); - if (r) - goto out; - r = 0; - break; - } - case KVM_GET_SREGS: { - struct kvm_sregs kvm_sregs; - - r = -EFAULT; - if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs)) - goto out; - r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs); - if (r) - goto out; - r = -EFAULT; - if (copy_to_user((void *)arg, &kvm_sregs, sizeof kvm_sregs)) - goto out; - r = 0; - break; - } - case KVM_SET_SREGS: { - struct kvm_sregs kvm_sregs; - - r = -EFAULT; - if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs)) - goto out; - r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs); - if (r) - goto out; - r = 0; - break; - } - case KVM_TRANSLATE: { - struct kvm_translation tr; - - r = -EFAULT; - if (copy_from_user(&tr, (void *)arg, sizeof tr)) - goto out; - r = kvm_dev_ioctl_translate(kvm, &tr); - if (r) - goto out; - r = -EFAULT; - if (copy_to_user((void *)arg, &tr, sizeof tr)) - goto out; - r = 0; - break; - } - case KVM_INTERRUPT: { - struct kvm_interrupt irq; - - r = -EFAULT; - if (copy_from_user(&irq, (void *)arg, sizeof irq)) - goto out; - r = kvm_dev_ioctl_interrupt(kvm, &irq); - if (r) - goto out; - r = 0; - break; - } - case KVM_DEBUG_GUEST: { - struct kvm_debug_guest dbg; - - r = -EFAULT; - if (copy_from_user(&dbg, (void *)arg, sizeof dbg)) - goto out; - r = kvm_dev_ioctl_debug_guest(kvm, &dbg); - if (r) - goto out; - r = 0; - break; - } - case KVM_SET_MEMORY_REGION: { - struct kvm_memory_region kvm_mem; - - r = -EFAULT; - if (copy_from_user(&kvm_mem, (void *)arg, sizeof kvm_mem)) - goto out; - r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem); - if (r) - goto out; - break; - } - case KVM_GET_DIRTY_LOG: { - struct kvm_dirty_log log; - - r = -EFAULT; - if (copy_from_user(&log, (void *)arg, sizeof log)) - goto out; - r = kvm_dev_ioctl_get_dirty_log(kvm, &log); - if (r) - goto out; - break; - } - case KVM_GET_MSRS: - r = msr_io(kvm, (void __user *)arg, get_msr, 1); - break; - case KVM_SET_MSRS: - r = msr_io(kvm, (void __user *)arg, do_set_msr, 0); - break; - case KVM_GET_MSR_INDEX_LIST: { - struct kvm_msr_list __user *user_msr_list = (void __user *)arg; - struct kvm_msr_list msr_list; - unsigned n; - - r = -EFAULT; - if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list)) - goto out; - n = msr_list.nmsrs; - msr_list.nmsrs = ARRAY_SIZE(msrs_to_save); - if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list)) - goto out; - r = -E2BIG; - if (n < ARRAY_SIZE(msrs_to_save)) - goto out; - r = -EFAULT; - if (copy_to_user(user_msr_list->indices, &msrs_to_save, - sizeof msrs_to_save)) - goto out; - r = 0; - } - default: - ; - } -out: - return r; -} - -static struct page *kvm_dev_nopage(struct vm_area_struct *vma, - unsigned long address, - int *type) -{ - struct kvm *kvm = vma->vm_file->private_data; - unsigned long pgoff; - struct kvm_memory_slot *slot; - struct page *page; - - *type = VM_FAULT_MINOR; - pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; - slot = gfn_to_memslot(kvm, pgoff); - if (!slot) - return NOPAGE_SIGBUS; - page = gfn_to_page(slot, pgoff); - if (!page) - return NOPAGE_SIGBUS; - get_page(page); - return page; -} - -static struct vm_operations_struct kvm_dev_vm_ops = { - .nopage = kvm_dev_nopage, -}; - -static int kvm_dev_mmap(struct file *file, struct vm_area_struct *vma) -{ - vma->vm_ops = &kvm_dev_vm_ops; - return 0; -} - -static struct file_operations kvm_chardev_ops = { - .open = kvm_dev_open, - .release = kvm_dev_release, - .unlocked_ioctl = kvm_dev_ioctl, - .compat_ioctl = kvm_dev_ioctl, - .mmap = kvm_dev_mmap, -}; - -static struct miscdevice kvm_dev = { - MISC_DYNAMIC_MINOR, - "kvm", - &kvm_chardev_ops, -}; - -static int kvm_reboot(struct notifier_block *notifier, unsigned long val, - void *v) -{ - if (val == SYS_RESTART) { - /* - * Some (well, at least mine) BIOSes hang on reboot if - * in vmx root mode. - */ - printk(KERN_INFO "kvm: exiting hardware virtualization\n"); - on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); - } - return NOTIFY_OK; -} - -static struct notifier_block kvm_reboot_notifier = { - .notifier_call = kvm_reboot, - .priority = 0, -}; - -static __init void kvm_init_debug(void) -{ - struct kvm_stats_debugfs_item *p; - - debugfs_dir = debugfs_create_dir("kvm", 0); - for (p = debugfs_entries; p->name; ++p) - p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir, - p->data); -} - -static void kvm_exit_debug(void) -{ - struct kvm_stats_debugfs_item *p; - - for (p = debugfs_entries; p->name; ++p) - debugfs_remove(p->dentry); - debugfs_remove(debugfs_dir); -} - -hpa_t bad_page_address; - -int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) -{ - int r; - - kvm_arch_ops = ops; - - if (!kvm_arch_ops->cpu_has_kvm_support()) { - printk(KERN_ERR "kvm: no hardware support\n"); - return -EOPNOTSUPP; - } - if (kvm_arch_ops->disabled_by_bios()) { - printk(KERN_ERR "kvm: disabled by bios\n"); - return -EOPNOTSUPP; - } - - r = kvm_arch_ops->hardware_setup(); - if (r < 0) - return r; - - on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1); - register_reboot_notifier(&kvm_reboot_notifier); - - kvm_chardev_ops.owner = module; - - r = misc_register(&kvm_dev); - if (r) { - printk (KERN_ERR "kvm: misc device register failed\n"); - goto out_free; - } - - return r; - -out_free: - unregister_reboot_notifier(&kvm_reboot_notifier); - on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); - kvm_arch_ops->hardware_unsetup(); - return r; -} - -void kvm_exit_arch(void) -{ - misc_deregister(&kvm_dev); - - unregister_reboot_notifier(&kvm_reboot_notifier); - on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); - kvm_arch_ops->hardware_unsetup(); -} - -static __init int kvm_init(void) -{ - static struct page *bad_page; - int r = 0; - - kvm_init_debug(); - - if ((bad_page = alloc_page(GFP_KERNEL)) == NULL) { - r = -ENOMEM; - goto out; - } - - bad_page_address = page_to_pfn(bad_page) << PAGE_SHIFT; - memset(__va(bad_page_address), 0, PAGE_SIZE); - - return r; - -out: - kvm_exit_debug(); - return r; -} - -static __exit void kvm_exit(void) -{ - kvm_exit_debug(); - __free_page(pfn_to_page(bad_page_address >> PAGE_SHIFT)); -} - -module_init(kvm_init) -module_exit(kvm_exit) - -EXPORT_SYMBOL_GPL(kvm_init_arch); -EXPORT_SYMBOL_GPL(kvm_exit_arch); diff --git a/trunk/drivers/kvm/kvm_svm.h b/trunk/drivers/kvm/kvm_svm.h deleted file mode 100644 index 74cc862f4935..000000000000 --- a/trunk/drivers/kvm/kvm_svm.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __KVM_SVM_H -#define __KVM_SVM_H - -#include -#include -#include - -#include "svm.h" -#include "kvm.h" - -static const u32 host_save_msrs[] = { -#ifdef CONFIG_X86_64 - MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE, - MSR_FS_BASE, MSR_GS_BASE, -#endif - MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, - MSR_IA32_DEBUGCTLMSR, /*MSR_IA32_LASTBRANCHFROMIP, - MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/ -}; - -#define NR_HOST_SAVE_MSRS (sizeof(host_save_msrs) / sizeof(*host_save_msrs)) -#define NUM_DB_REGS 4 - -struct vcpu_svm { - struct vmcb *vmcb; - unsigned long vmcb_pa; - struct svm_cpu_data *svm_data; - uint64_t asid_generation; - - unsigned long cr0; - unsigned long cr4; - unsigned long db_regs[NUM_DB_REGS]; - - u64 next_rip; - - u64 host_msrs[NR_HOST_SAVE_MSRS]; - unsigned long host_cr2; - unsigned long host_db_regs[NUM_DB_REGS]; - unsigned long host_dr6; - unsigned long host_dr7; -}; - -#endif - diff --git a/trunk/drivers/kvm/kvm_vmx.h b/trunk/drivers/kvm/kvm_vmx.h deleted file mode 100644 index d139f73fb6e1..000000000000 --- a/trunk/drivers/kvm/kvm_vmx.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __KVM_VMX_H -#define __KVM_VMX_H - -#ifdef CONFIG_X86_64 -/* - * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt - * mechanism (cpu bug AA24) - */ -#define NR_BAD_MSRS 2 -#else -#define NR_BAD_MSRS 0 -#endif - -#endif diff --git a/trunk/drivers/kvm/mmu.c b/trunk/drivers/kvm/mmu.c deleted file mode 100644 index 3d367cbfe1f9..000000000000 --- a/trunk/drivers/kvm/mmu.c +++ /dev/null @@ -1,686 +0,0 @@ -/* - * Kernel-based Virtual Machine driver for Linux - * - * This module enables machines with Intel VT-x extensions to run virtual - * machines without emulation or binary translation. - * - * MMU support - * - * Copyright (C) 2006 Qumranet, Inc. - * - * Authors: - * Yaniv Kamay - * Avi Kivity - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ -#include -#include -#include -#include -#include -#include - -#include "vmx.h" -#include "kvm.h" - -#define pgprintk(x...) do { } while (0) - -#define ASSERT(x) \ - if (!(x)) { \ - printk(KERN_WARNING "assertion failed %s:%d: %s\n", \ - __FILE__, __LINE__, #x); \ - } - -#define PT64_ENT_PER_PAGE 512 -#define PT32_ENT_PER_PAGE 1024 - -#define PT_WRITABLE_SHIFT 1 - -#define PT_PRESENT_MASK (1ULL << 0) -#define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT) -#define PT_USER_MASK (1ULL << 2) -#define PT_PWT_MASK (1ULL << 3) -#define PT_PCD_MASK (1ULL << 4) -#define PT_ACCESSED_MASK (1ULL << 5) -#define PT_DIRTY_MASK (1ULL << 6) -#define PT_PAGE_SIZE_MASK (1ULL << 7) -#define PT_PAT_MASK (1ULL << 7) -#define PT_GLOBAL_MASK (1ULL << 8) -#define PT64_NX_MASK (1ULL << 63) - -#define PT_PAT_SHIFT 7 -#define PT_DIR_PAT_SHIFT 12 -#define PT_DIR_PAT_MASK (1ULL << PT_DIR_PAT_SHIFT) - -#define PT32_DIR_PSE36_SIZE 4 -#define PT32_DIR_PSE36_SHIFT 13 -#define PT32_DIR_PSE36_MASK (((1ULL << PT32_DIR_PSE36_SIZE) - 1) << PT32_DIR_PSE36_SHIFT) - - -#define PT32_PTE_COPY_MASK \ - (PT_PRESENT_MASK | PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_GLOBAL_MASK) - -#define PT64_PTE_COPY_MASK (PT64_NX_MASK | PT32_PTE_COPY_MASK) - -#define PT_FIRST_AVAIL_BITS_SHIFT 9 -#define PT64_SECOND_AVAIL_BITS_SHIFT 52 - -#define PT_SHADOW_PS_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT) -#define PT_SHADOW_IO_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT) - -#define PT_SHADOW_WRITABLE_SHIFT (PT_FIRST_AVAIL_BITS_SHIFT + 1) -#define PT_SHADOW_WRITABLE_MASK (1ULL << PT_SHADOW_WRITABLE_SHIFT) - -#define PT_SHADOW_USER_SHIFT (PT_SHADOW_WRITABLE_SHIFT + 1) -#define PT_SHADOW_USER_MASK (1ULL << (PT_SHADOW_USER_SHIFT)) - -#define PT_SHADOW_BITS_OFFSET (PT_SHADOW_WRITABLE_SHIFT - PT_WRITABLE_SHIFT) - -#define VALID_PAGE(x) ((x) != INVALID_PAGE) - -#define PT64_LEVEL_BITS 9 - -#define PT64_LEVEL_SHIFT(level) \ - ( PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS ) - -#define PT64_LEVEL_MASK(level) \ - (((1ULL << PT64_LEVEL_BITS) - 1) << PT64_LEVEL_SHIFT(level)) - -#define PT64_INDEX(address, level)\ - (((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1)) - - -#define PT32_LEVEL_BITS 10 - -#define PT32_LEVEL_SHIFT(level) \ - ( PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS ) - -#define PT32_LEVEL_MASK(level) \ - (((1ULL << PT32_LEVEL_BITS) - 1) << PT32_LEVEL_SHIFT(level)) - -#define PT32_INDEX(address, level)\ - (((address) >> PT32_LEVEL_SHIFT(level)) & ((1 << PT32_LEVEL_BITS) - 1)) - - -#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & PAGE_MASK) -#define PT64_DIR_BASE_ADDR_MASK \ - (PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + PT64_LEVEL_BITS)) - 1)) - -#define PT32_BASE_ADDR_MASK PAGE_MASK -#define PT32_DIR_BASE_ADDR_MASK \ - (PAGE_MASK & ~((1ULL << (PAGE_SHIFT + PT32_LEVEL_BITS)) - 1)) - - -#define PFERR_PRESENT_MASK (1U << 0) -#define PFERR_WRITE_MASK (1U << 1) -#define PFERR_USER_MASK (1U << 2) - -#define PT64_ROOT_LEVEL 4 -#define PT32_ROOT_LEVEL 2 -#define PT32E_ROOT_LEVEL 3 - -#define PT_DIRECTORY_LEVEL 2 -#define PT_PAGE_TABLE_LEVEL 1 - -static int is_write_protection(struct kvm_vcpu *vcpu) -{ - return vcpu->cr0 & CR0_WP_MASK; -} - -static int is_cpuid_PSE36(void) -{ - return 1; -} - -static int is_present_pte(unsigned long pte) -{ - return pte & PT_PRESENT_MASK; -} - -static int is_writeble_pte(unsigned long pte) -{ - return pte & PT_WRITABLE_MASK; -} - -static int is_io_pte(unsigned long pte) -{ - return pte & PT_SHADOW_IO_MARK; -} - -static void kvm_mmu_free_page(struct kvm_vcpu *vcpu, hpa_t page_hpa) -{ - struct kvm_mmu_page *page_head = page_header(page_hpa); - - list_del(&page_head->link); - page_head->page_hpa = page_hpa; - list_add(&page_head->link, &vcpu->free_pages); -} - -static int is_empty_shadow_page(hpa_t page_hpa) -{ - u32 *pos; - u32 *end; - for (pos = __va(page_hpa), end = pos + PAGE_SIZE / sizeof(u32); - pos != end; pos++) - if (*pos != 0) - return 0; - return 1; -} - -static hpa_t kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, u64 *parent_pte) -{ - struct kvm_mmu_page *page; - - if (list_empty(&vcpu->free_pages)) - return INVALID_PAGE; - - page = list_entry(vcpu->free_pages.next, struct kvm_mmu_page, link); - list_del(&page->link); - list_add(&page->link, &vcpu->kvm->active_mmu_pages); - ASSERT(is_empty_shadow_page(page->page_hpa)); - page->slot_bitmap = 0; - page->global = 1; - page->parent_pte = parent_pte; - return page->page_hpa; -} - -static void page_header_update_slot(struct kvm *kvm, void *pte, gpa_t gpa) -{ - int slot = memslot_id(kvm, gfn_to_memslot(kvm, gpa >> PAGE_SHIFT)); - struct kvm_mmu_page *page_head = page_header(__pa(pte)); - - __set_bit(slot, &page_head->slot_bitmap); -} - -hpa_t safe_gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa) -{ - hpa_t hpa = gpa_to_hpa(vcpu, gpa); - - return is_error_hpa(hpa) ? bad_page_address | (gpa & ~PAGE_MASK): hpa; -} - -hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa) -{ - struct kvm_memory_slot *slot; - struct page *page; - - ASSERT((gpa & HPA_ERR_MASK) == 0); - slot = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT); - if (!slot) - return gpa | HPA_ERR_MASK; - page = gfn_to_page(slot, gpa >> PAGE_SHIFT); - return ((hpa_t)page_to_pfn(page) << PAGE_SHIFT) - | (gpa & (PAGE_SIZE-1)); -} - -hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva) -{ - gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva); - - if (gpa == UNMAPPED_GVA) - return UNMAPPED_GVA; - return gpa_to_hpa(vcpu, gpa); -} - - -static void release_pt_page_64(struct kvm_vcpu *vcpu, hpa_t page_hpa, - int level) -{ - ASSERT(vcpu); - ASSERT(VALID_PAGE(page_hpa)); - ASSERT(level <= PT64_ROOT_LEVEL && level > 0); - - if (level == 1) - memset(__va(page_hpa), 0, PAGE_SIZE); - else { - u64 *pos; - u64 *end; - - for (pos = __va(page_hpa), end = pos + PT64_ENT_PER_PAGE; - pos != end; pos++) { - u64 current_ent = *pos; - - *pos = 0; - if (is_present_pte(current_ent)) - release_pt_page_64(vcpu, - current_ent & - PT64_BASE_ADDR_MASK, - level - 1); - } - } - kvm_mmu_free_page(vcpu, page_hpa); -} - -static void nonpaging_new_cr3(struct kvm_vcpu *vcpu) -{ -} - -static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, hpa_t p) -{ - int level = PT32E_ROOT_LEVEL; - hpa_t table_addr = vcpu->mmu.root_hpa; - - for (; ; level--) { - u32 index = PT64_INDEX(v, level); - u64 *table; - - ASSERT(VALID_PAGE(table_addr)); - table = __va(table_addr); - - if (level == 1) { - mark_page_dirty(vcpu->kvm, v >> PAGE_SHIFT); - page_header_update_slot(vcpu->kvm, table, v); - table[index] = p | PT_PRESENT_MASK | PT_WRITABLE_MASK | - PT_USER_MASK; - return 0; - } - - if (table[index] == 0) { - hpa_t new_table = kvm_mmu_alloc_page(vcpu, - &table[index]); - - if (!VALID_PAGE(new_table)) { - pgprintk("nonpaging_map: ENOMEM\n"); - return -ENOMEM; - } - - if (level == PT32E_ROOT_LEVEL) - table[index] = new_table | PT_PRESENT_MASK; - else - table[index] = new_table | PT_PRESENT_MASK | - PT_WRITABLE_MASK | PT_USER_MASK; - } - table_addr = table[index] & PT64_BASE_ADDR_MASK; - } -} - -static void nonpaging_flush(struct kvm_vcpu *vcpu) -{ - hpa_t root = vcpu->mmu.root_hpa; - - ++kvm_stat.tlb_flush; - pgprintk("nonpaging_flush\n"); - ASSERT(VALID_PAGE(root)); - release_pt_page_64(vcpu, root, vcpu->mmu.shadow_root_level); - root = kvm_mmu_alloc_page(vcpu, NULL); - ASSERT(VALID_PAGE(root)); - vcpu->mmu.root_hpa = root; - if (is_paging(vcpu)) - root |= (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)); - kvm_arch_ops->set_cr3(vcpu, root); - kvm_arch_ops->tlb_flush(vcpu); -} - -static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr) -{ - return vaddr; -} - -static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva, - u32 error_code) -{ - int ret; - gpa_t addr = gva; - - ASSERT(vcpu); - ASSERT(VALID_PAGE(vcpu->mmu.root_hpa)); - - for (;;) { - hpa_t paddr; - - paddr = gpa_to_hpa(vcpu , addr & PT64_BASE_ADDR_MASK); - - if (is_error_hpa(paddr)) - return 1; - - ret = nonpaging_map(vcpu, addr & PAGE_MASK, paddr); - if (ret) { - nonpaging_flush(vcpu); - continue; - } - break; - } - return ret; -} - -static void nonpaging_inval_page(struct kvm_vcpu *vcpu, gva_t addr) -{ -} - -static void nonpaging_free(struct kvm_vcpu *vcpu) -{ - hpa_t root; - - ASSERT(vcpu); - root = vcpu->mmu.root_hpa; - if (VALID_PAGE(root)) - release_pt_page_64(vcpu, root, vcpu->mmu.shadow_root_level); - vcpu->mmu.root_hpa = INVALID_PAGE; -} - -static int nonpaging_init_context(struct kvm_vcpu *vcpu) -{ - struct kvm_mmu *context = &vcpu->mmu; - - context->new_cr3 = nonpaging_new_cr3; - context->page_fault = nonpaging_page_fault; - context->inval_page = nonpaging_inval_page; - context->gva_to_gpa = nonpaging_gva_to_gpa; - context->free = nonpaging_free; - context->root_level = PT32E_ROOT_LEVEL; - context->shadow_root_level = PT32E_ROOT_LEVEL; - context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL); - ASSERT(VALID_PAGE(context->root_hpa)); - kvm_arch_ops->set_cr3(vcpu, context->root_hpa); - return 0; -} - - -static void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu) -{ - struct kvm_mmu_page *page, *npage; - - list_for_each_entry_safe(page, npage, &vcpu->kvm->active_mmu_pages, - link) { - if (page->global) - continue; - - if (!page->parent_pte) - continue; - - *page->parent_pte = 0; - release_pt_page_64(vcpu, page->page_hpa, 1); - } - ++kvm_stat.tlb_flush; - kvm_arch_ops->tlb_flush(vcpu); -} - -static void paging_new_cr3(struct kvm_vcpu *vcpu) -{ - kvm_mmu_flush_tlb(vcpu); -} - -static void mark_pagetable_nonglobal(void *shadow_pte) -{ - page_header(__pa(shadow_pte))->global = 0; -} - -static inline void set_pte_common(struct kvm_vcpu *vcpu, - u64 *shadow_pte, - gpa_t gaddr, - int dirty, - u64 access_bits) -{ - hpa_t paddr; - - *shadow_pte |= access_bits << PT_SHADOW_BITS_OFFSET; - if (!dirty) - access_bits &= ~PT_WRITABLE_MASK; - - if (access_bits & PT_WRITABLE_MASK) - mark_page_dirty(vcpu->kvm, gaddr >> PAGE_SHIFT); - - *shadow_pte |= access_bits; - - paddr = gpa_to_hpa(vcpu, gaddr & PT64_BASE_ADDR_MASK); - - if (!(*shadow_pte & PT_GLOBAL_MASK)) - mark_pagetable_nonglobal(shadow_pte); - - if (is_error_hpa(paddr)) { - *shadow_pte |= gaddr; - *shadow_pte |= PT_SHADOW_IO_MARK; - *shadow_pte &= ~PT_PRESENT_MASK; - } else { - *shadow_pte |= paddr; - page_header_update_slot(vcpu->kvm, shadow_pte, gaddr); - } -} - -static void inject_page_fault(struct kvm_vcpu *vcpu, - u64 addr, - u32 err_code) -{ - kvm_arch_ops->inject_page_fault(vcpu, addr, err_code); -} - -static inline int fix_read_pf(u64 *shadow_ent) -{ - if ((*shadow_ent & PT_SHADOW_USER_MASK) && - !(*shadow_ent & PT_USER_MASK)) { - /* - * If supervisor write protect is disabled, we shadow kernel - * pages as user pages so we can trap the write access. - */ - *shadow_ent |= PT_USER_MASK; - *shadow_ent &= ~PT_WRITABLE_MASK; - - return 1; - - } - return 0; -} - -static int may_access(u64 pte, int write, int user) -{ - - if (user && !(pte & PT_USER_MASK)) - return 0; - if (write && !(pte & PT_WRITABLE_MASK)) - return 0; - return 1; -} - -/* - * Remove a shadow pte. - */ -static void paging_inval_page(struct kvm_vcpu *vcpu, gva_t addr) -{ - hpa_t page_addr = vcpu->mmu.root_hpa; - int level = vcpu->mmu.shadow_root_level; - - ++kvm_stat.invlpg; - - for (; ; level--) { - u32 index = PT64_INDEX(addr, level); - u64 *table = __va(page_addr); - - if (level == PT_PAGE_TABLE_LEVEL ) { - table[index] = 0; - return; - } - - if (!is_present_pte(table[index])) - return; - - page_addr = table[index] & PT64_BASE_ADDR_MASK; - - if (level == PT_DIRECTORY_LEVEL && - (table[index] & PT_SHADOW_PS_MARK)) { - table[index] = 0; - release_pt_page_64(vcpu, page_addr, PT_PAGE_TABLE_LEVEL); - - kvm_arch_ops->tlb_flush(vcpu); - return; - } - } -} - -static void paging_free(struct kvm_vcpu *vcpu) -{ - nonpaging_free(vcpu); -} - -#define PTTYPE 64 -#include "paging_tmpl.h" -#undef PTTYPE - -#define PTTYPE 32 -#include "paging_tmpl.h" -#undef PTTYPE - -static int paging64_init_context(struct kvm_vcpu *vcpu) -{ - struct kvm_mmu *context = &vcpu->mmu; - - ASSERT(is_pae(vcpu)); - context->new_cr3 = paging_new_cr3; - context->page_fault = paging64_page_fault; - context->inval_page = paging_inval_page; - context->gva_to_gpa = paging64_gva_to_gpa; - context->free = paging_free; - context->root_level = PT64_ROOT_LEVEL; - context->shadow_root_level = PT64_ROOT_LEVEL; - context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL); - ASSERT(VALID_PAGE(context->root_hpa)); - kvm_arch_ops->set_cr3(vcpu, context->root_hpa | - (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK))); - return 0; -} - -static int paging32_init_context(struct kvm_vcpu *vcpu) -{ - struct kvm_mmu *context = &vcpu->mmu; - - context->new_cr3 = paging_new_cr3; - context->page_fault = paging32_page_fault; - context->inval_page = paging_inval_page; - context->gva_to_gpa = paging32_gva_to_gpa; - context->free = paging_free; - context->root_level = PT32_ROOT_LEVEL; - context->shadow_root_level = PT32E_ROOT_LEVEL; - context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL); - ASSERT(VALID_PAGE(context->root_hpa)); - kvm_arch_ops->set_cr3(vcpu, context->root_hpa | - (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK))); - return 0; -} - -static int paging32E_init_context(struct kvm_vcpu *vcpu) -{ - int ret; - - if ((ret = paging64_init_context(vcpu))) - return ret; - - vcpu->mmu.root_level = PT32E_ROOT_LEVEL; - vcpu->mmu.shadow_root_level = PT32E_ROOT_LEVEL; - return 0; -} - -static int init_kvm_mmu(struct kvm_vcpu *vcpu) -{ - ASSERT(vcpu); - ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa)); - - if (!is_paging(vcpu)) - return nonpaging_init_context(vcpu); - else if (kvm_arch_ops->is_long_mode(vcpu)) - return paging64_init_context(vcpu); - else if (is_pae(vcpu)) - return paging32E_init_context(vcpu); - else - return paging32_init_context(vcpu); -} - -static void destroy_kvm_mmu(struct kvm_vcpu *vcpu) -{ - ASSERT(vcpu); - if (VALID_PAGE(vcpu->mmu.root_hpa)) { - vcpu->mmu.free(vcpu); - vcpu->mmu.root_hpa = INVALID_PAGE; - } -} - -int kvm_mmu_reset_context(struct kvm_vcpu *vcpu) -{ - destroy_kvm_mmu(vcpu); - return init_kvm_mmu(vcpu); -} - -static void free_mmu_pages(struct kvm_vcpu *vcpu) -{ - while (!list_empty(&vcpu->free_pages)) { - struct kvm_mmu_page *page; - - page = list_entry(vcpu->free_pages.next, - struct kvm_mmu_page, link); - list_del(&page->link); - __free_page(pfn_to_page(page->page_hpa >> PAGE_SHIFT)); - page->page_hpa = INVALID_PAGE; - } -} - -static int alloc_mmu_pages(struct kvm_vcpu *vcpu) -{ - int i; - - ASSERT(vcpu); - - for (i = 0; i < KVM_NUM_MMU_PAGES; i++) { - struct page *page; - struct kvm_mmu_page *page_header = &vcpu->page_header_buf[i]; - - INIT_LIST_HEAD(&page_header->link); - if ((page = alloc_page(GFP_KVM_MMU)) == NULL) - goto error_1; - page->private = (unsigned long)page_header; - page_header->page_hpa = (hpa_t)page_to_pfn(page) << PAGE_SHIFT; - memset(__va(page_header->page_hpa), 0, PAGE_SIZE); - list_add(&page_header->link, &vcpu->free_pages); - } - return 0; - -error_1: - free_mmu_pages(vcpu); - return -ENOMEM; -} - -int kvm_mmu_init(struct kvm_vcpu *vcpu) -{ - int r; - - ASSERT(vcpu); - ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa)); - ASSERT(list_empty(&vcpu->free_pages)); - - if ((r = alloc_mmu_pages(vcpu))) - return r; - - if ((r = init_kvm_mmu(vcpu))) { - free_mmu_pages(vcpu); - return r; - } - return 0; -} - -void kvm_mmu_destroy(struct kvm_vcpu *vcpu) -{ - ASSERT(vcpu); - - destroy_kvm_mmu(vcpu); - free_mmu_pages(vcpu); -} - -void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot) -{ - struct kvm_mmu_page *page; - - list_for_each_entry(page, &kvm->active_mmu_pages, link) { - int i; - u64 *pt; - - if (!test_bit(slot, &page->slot_bitmap)) - continue; - - pt = __va(page->page_hpa); - for (i = 0; i < PT64_ENT_PER_PAGE; ++i) - /* avoid RMW */ - if (pt[i] & PT_WRITABLE_MASK) - pt[i] &= ~PT_WRITABLE_MASK; - - } -} diff --git a/trunk/drivers/kvm/paging_tmpl.h b/trunk/drivers/kvm/paging_tmpl.h deleted file mode 100644 index a9771b4c5bb8..000000000000 --- a/trunk/drivers/kvm/paging_tmpl.h +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Kernel-based Virtual Machine driver for Linux - * - * This module enables machines with Intel VT-x extensions to run virtual - * machines without emulation or binary translation. - * - * MMU support - * - * Copyright (C) 2006 Qumranet, Inc. - * - * Authors: - * Yaniv Kamay - * Avi Kivity - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -/* - * We need the mmu code to access both 32-bit and 64-bit guest ptes, - * so the code in this file is compiled twice, once per pte size. - */ - -#if PTTYPE == 64 - #define pt_element_t u64 - #define guest_walker guest_walker64 - #define FNAME(name) paging##64_##name - #define PT_BASE_ADDR_MASK PT64_BASE_ADDR_MASK - #define PT_DIR_BASE_ADDR_MASK PT64_DIR_BASE_ADDR_MASK - #define PT_INDEX(addr, level) PT64_INDEX(addr, level) - #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level) - #define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level) - #define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK -#elif PTTYPE == 32 - #define pt_element_t u32 - #define guest_walker guest_walker32 - #define FNAME(name) paging##32_##name - #define PT_BASE_ADDR_MASK PT32_BASE_ADDR_MASK - #define PT_DIR_BASE_ADDR_MASK PT32_DIR_BASE_ADDR_MASK - #define PT_INDEX(addr, level) PT32_INDEX(addr, level) - #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level) - #define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level) - #define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK -#else - #error Invalid PTTYPE value -#endif - -/* - * The guest_walker structure emulates the behavior of the hardware page - * table walker. - */ -struct guest_walker { - int level; - pt_element_t *table; - pt_element_t inherited_ar; -}; - -static void FNAME(init_walker)(struct guest_walker *walker, - struct kvm_vcpu *vcpu) -{ - hpa_t hpa; - struct kvm_memory_slot *slot; - - walker->level = vcpu->mmu.root_level; - slot = gfn_to_memslot(vcpu->kvm, - (vcpu->cr3 & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT); - hpa = safe_gpa_to_hpa(vcpu, vcpu->cr3 & PT64_BASE_ADDR_MASK); - walker->table = kmap_atomic(pfn_to_page(hpa >> PAGE_SHIFT), KM_USER0); - - ASSERT((!kvm_arch_ops->is_long_mode(vcpu) && is_pae(vcpu)) || - (vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) == 0); - - walker->table = (pt_element_t *)( (unsigned long)walker->table | - (unsigned long)(vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) ); - walker->inherited_ar = PT_USER_MASK | PT_WRITABLE_MASK; -} - -static void FNAME(release_walker)(struct guest_walker *walker) -{ - kunmap_atomic(walker->table, KM_USER0); -} - -static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte, - u64 *shadow_pte, u64 access_bits) -{ - ASSERT(*shadow_pte == 0); - access_bits &= guest_pte; - *shadow_pte = (guest_pte & PT_PTE_COPY_MASK); - set_pte_common(vcpu, shadow_pte, guest_pte & PT_BASE_ADDR_MASK, - guest_pte & PT_DIRTY_MASK, access_bits); -} - -static void FNAME(set_pde)(struct kvm_vcpu *vcpu, u64 guest_pde, - u64 *shadow_pte, u64 access_bits, - int index) -{ - gpa_t gaddr; - - ASSERT(*shadow_pte == 0); - access_bits &= guest_pde; - gaddr = (guest_pde & PT_DIR_BASE_ADDR_MASK) + PAGE_SIZE * index; - if (PTTYPE == 32 && is_cpuid_PSE36()) - gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) << - (32 - PT32_DIR_PSE36_SHIFT); - *shadow_pte = guest_pde & PT_PTE_COPY_MASK; - set_pte_common(vcpu, shadow_pte, gaddr, - guest_pde & PT_DIRTY_MASK, access_bits); -} - -/* - * Fetch a guest pte from a specific level in the paging hierarchy. - */ -static pt_element_t *FNAME(fetch_guest)(struct kvm_vcpu *vcpu, - struct guest_walker *walker, - int level, - gva_t addr) -{ - - ASSERT(level > 0 && level <= walker->level); - - for (;;) { - int index = PT_INDEX(addr, walker->level); - hpa_t paddr; - - ASSERT(((unsigned long)walker->table & PAGE_MASK) == - ((unsigned long)&walker->table[index] & PAGE_MASK)); - if (level == walker->level || - !is_present_pte(walker->table[index]) || - (walker->level == PT_DIRECTORY_LEVEL && - (walker->table[index] & PT_PAGE_SIZE_MASK) && - (PTTYPE == 64 || is_pse(vcpu)))) - return &walker->table[index]; - if (walker->level != 3 || kvm_arch_ops->is_long_mode(vcpu)) - walker->inherited_ar &= walker->table[index]; - paddr = safe_gpa_to_hpa(vcpu, walker->table[index] & PT_BASE_ADDR_MASK); - kunmap_atomic(walker->table, KM_USER0); - walker->table = kmap_atomic(pfn_to_page(paddr >> PAGE_SHIFT), - KM_USER0); - --walker->level; - } -} - -/* - * Fetch a shadow pte for a specific level in the paging hierarchy. - */ -static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, - struct guest_walker *walker) -{ - hpa_t shadow_addr; - int level; - u64 *prev_shadow_ent = NULL; - - shadow_addr = vcpu->mmu.root_hpa; - level = vcpu->mmu.shadow_root_level; - - for (; ; level--) { - u32 index = SHADOW_PT_INDEX(addr, level); - u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index; - pt_element_t *guest_ent; - u64 shadow_pte; - - if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) { - if (level == PT_PAGE_TABLE_LEVEL) - return shadow_ent; - shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK; - prev_shadow_ent = shadow_ent; - continue; - } - - if (PTTYPE == 32 && level > PT32_ROOT_LEVEL) { - ASSERT(level == PT32E_ROOT_LEVEL); - guest_ent = FNAME(fetch_guest)(vcpu, walker, - PT32_ROOT_LEVEL, addr); - } else - guest_ent = FNAME(fetch_guest)(vcpu, walker, - level, addr); - - if (!is_present_pte(*guest_ent)) - return NULL; - - /* Don't set accessed bit on PAE PDPTRs */ - if (vcpu->mmu.root_level != 3 || walker->level != 3) - *guest_ent |= PT_ACCESSED_MASK; - - if (level == PT_PAGE_TABLE_LEVEL) { - - if (walker->level == PT_DIRECTORY_LEVEL) { - if (prev_shadow_ent) - *prev_shadow_ent |= PT_SHADOW_PS_MARK; - FNAME(set_pde)(vcpu, *guest_ent, shadow_ent, - walker->inherited_ar, - PT_INDEX(addr, PT_PAGE_TABLE_LEVEL)); - } else { - ASSERT(walker->level == PT_PAGE_TABLE_LEVEL); - FNAME(set_pte)(vcpu, *guest_ent, shadow_ent, walker->inherited_ar); - } - return shadow_ent; - } - - shadow_addr = kvm_mmu_alloc_page(vcpu, shadow_ent); - if (!VALID_PAGE(shadow_addr)) - return ERR_PTR(-ENOMEM); - shadow_pte = shadow_addr | PT_PRESENT_MASK; - if (vcpu->mmu.root_level > 3 || level != 3) - shadow_pte |= PT_ACCESSED_MASK - | PT_WRITABLE_MASK | PT_USER_MASK; - *shadow_ent = shadow_pte; - prev_shadow_ent = shadow_ent; - } -} - -/* - * The guest faulted for write. We need to - * - * - check write permissions - * - update the guest pte dirty bit - * - update our own dirty page tracking structures - */ -static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu, - u64 *shadow_ent, - struct guest_walker *walker, - gva_t addr, - int user) -{ - pt_element_t *guest_ent; - int writable_shadow; - gfn_t gfn; - - if (is_writeble_pte(*shadow_ent)) - return 0; - - writable_shadow = *shadow_ent & PT_SHADOW_WRITABLE_MASK; - if (user) { - /* - * User mode access. Fail if it's a kernel page or a read-only - * page. - */ - if (!(*shadow_ent & PT_SHADOW_USER_MASK) || !writable_shadow) - return 0; - ASSERT(*shadow_ent & PT_USER_MASK); - } else - /* - * Kernel mode access. Fail if it's a read-only page and - * supervisor write protection is enabled. - */ - if (!writable_shadow) { - if (is_write_protection(vcpu)) - return 0; - *shadow_ent &= ~PT_USER_MASK; - } - - guest_ent = FNAME(fetch_guest)(vcpu, walker, PT_PAGE_TABLE_LEVEL, addr); - - if (!is_present_pte(*guest_ent)) { - *shadow_ent = 0; - return 0; - } - - gfn = (*guest_ent & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT; - mark_page_dirty(vcpu->kvm, gfn); - *shadow_ent |= PT_WRITABLE_MASK; - *guest_ent |= PT_DIRTY_MASK; - - return 1; -} - -/* - * Page fault handler. There are several causes for a page fault: - * - there is no shadow pte for the guest pte - * - write access through a shadow pte marked read only so that we can set - * the dirty bit - * - write access to a shadow pte marked read only so we can update the page - * dirty bitmap, when userspace requests it - * - mmio access; in this case we will never install a present shadow pte - * - normal guest page fault due to the guest pte marked not present, not - * writable, or not executable - * - * Returns: 1 if we need to emulate the instruction, 0 otherwise - */ -static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, - u32 error_code) -{ - int write_fault = error_code & PFERR_WRITE_MASK; - int pte_present = error_code & PFERR_PRESENT_MASK; - int user_fault = error_code & PFERR_USER_MASK; - struct guest_walker walker; - u64 *shadow_pte; - int fixed; - - /* - * Look up the shadow pte for the faulting address. - */ - for (;;) { - FNAME(init_walker)(&walker, vcpu); - shadow_pte = FNAME(fetch)(vcpu, addr, &walker); - if (IS_ERR(shadow_pte)) { /* must be -ENOMEM */ - nonpaging_flush(vcpu); - FNAME(release_walker)(&walker); - continue; - } - break; - } - - /* - * The page is not mapped by the guest. Let the guest handle it. - */ - if (!shadow_pte) { - inject_page_fault(vcpu, addr, error_code); - FNAME(release_walker)(&walker); - return 0; - } - - /* - * Update the shadow pte. - */ - if (write_fault) - fixed = FNAME(fix_write_pf)(vcpu, shadow_pte, &walker, addr, - user_fault); - else - fixed = fix_read_pf(shadow_pte); - - FNAME(release_walker)(&walker); - - /* - * mmio: emulate if accessible, otherwise its a guest fault. - */ - if (is_io_pte(*shadow_pte)) { - if (may_access(*shadow_pte, write_fault, user_fault)) - return 1; - pgprintk("%s: io work, no access\n", __FUNCTION__); - inject_page_fault(vcpu, addr, - error_code | PFERR_PRESENT_MASK); - return 0; - } - - /* - * pte not present, guest page fault. - */ - if (pte_present && !fixed) { - inject_page_fault(vcpu, addr, error_code); - return 0; - } - - ++kvm_stat.pf_fixed; - - return 0; -} - -static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr) -{ - struct guest_walker walker; - pt_element_t guest_pte; - gpa_t gpa; - - FNAME(init_walker)(&walker, vcpu); - guest_pte = *FNAME(fetch_guest)(vcpu, &walker, PT_PAGE_TABLE_LEVEL, - vaddr); - FNAME(release_walker)(&walker); - - if (!is_present_pte(guest_pte)) - return UNMAPPED_GVA; - - if (walker.level == PT_DIRECTORY_LEVEL) { - ASSERT((guest_pte & PT_PAGE_SIZE_MASK)); - ASSERT(PTTYPE == 64 || is_pse(vcpu)); - - gpa = (guest_pte & PT_DIR_BASE_ADDR_MASK) | (vaddr & - (PT_LEVEL_MASK(PT_PAGE_TABLE_LEVEL) | ~PAGE_MASK)); - - if (PTTYPE == 32 && is_cpuid_PSE36()) - gpa |= (guest_pte & PT32_DIR_PSE36_MASK) << - (32 - PT32_DIR_PSE36_SHIFT); - } else { - gpa = (guest_pte & PT_BASE_ADDR_MASK); - gpa |= (vaddr & ~PAGE_MASK); - } - - return gpa; -} - -#undef pt_element_t -#undef guest_walker -#undef FNAME -#undef PT_BASE_ADDR_MASK -#undef PT_INDEX -#undef SHADOW_PT_INDEX -#undef PT_LEVEL_MASK -#undef PT_PTE_COPY_MASK -#undef PT_NON_PTE_COPY_MASK -#undef PT_DIR_BASE_ADDR_MASK diff --git a/trunk/drivers/kvm/segment_descriptor.h b/trunk/drivers/kvm/segment_descriptor.h deleted file mode 100644 index 71fdf458619a..000000000000 --- a/trunk/drivers/kvm/segment_descriptor.h +++ /dev/null @@ -1,17 +0,0 @@ -struct segment_descriptor { - u16 limit_low; - u16 base_low; - u8 base_mid; - u8 type : 4; - u8 system : 1; - u8 dpl : 2; - u8 present : 1; - u8 limit_high : 4; - u8 avl : 1; - u8 long_mode : 1; - u8 default_op : 1; - u8 granularity : 1; - u8 base_high; -} __attribute__((packed)); - - diff --git a/trunk/drivers/kvm/svm.c b/trunk/drivers/kvm/svm.c deleted file mode 100644 index 0e6bc8c649ce..000000000000 --- a/trunk/drivers/kvm/svm.c +++ /dev/null @@ -1,1641 +0,0 @@ -/* - * Kernel-based Virtual Machine driver for Linux - * - * AMD SVM support - * - * Copyright (C) 2006 Qumranet, Inc. - * - * Authors: - * Yaniv Kamay - * Avi Kivity - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#include -#include -#include -#include - -#include "kvm_svm.h" -#include "x86_emulate.h" - -MODULE_AUTHOR("Qumranet"); -MODULE_LICENSE("GPL"); - -#define IOPM_ALLOC_ORDER 2 -#define MSRPM_ALLOC_ORDER 1 - -#define DB_VECTOR 1 -#define UD_VECTOR 6 -#define GP_VECTOR 13 - -#define DR7_GD_MASK (1 << 13) -#define DR6_BD_MASK (1 << 13) -#define CR4_DE_MASK (1UL << 3) - -#define SEG_TYPE_LDT 2 -#define SEG_TYPE_BUSY_TSS16 3 - -#define KVM_EFER_LMA (1 << 10) -#define KVM_EFER_LME (1 << 8) - -unsigned long iopm_base; -unsigned long msrpm_base; - -struct kvm_ldttss_desc { - u16 limit0; - u16 base0; - unsigned base1 : 8, type : 5, dpl : 2, p : 1; - unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8; - u32 base3; - u32 zero1; -} __attribute__((packed)); - -struct svm_cpu_data { - int cpu; - - uint64_t asid_generation; - uint32_t max_asid; - uint32_t next_asid; - struct kvm_ldttss_desc *tss_desc; - - struct page *save_area; -}; - -static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data); - -struct svm_init_data { - int cpu; - int r; -}; - -static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000}; - -#define NUM_MSR_MAPS (sizeof(msrpm_ranges) / sizeof(*msrpm_ranges)) -#define MSRS_RANGE_SIZE 2048 -#define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2) - -#define MAX_INST_SIZE 15 - -static unsigned get_addr_size(struct kvm_vcpu *vcpu) -{ - struct vmcb_save_area *sa = &vcpu->svm->vmcb->save; - u16 cs_attrib; - - if (!(sa->cr0 & CR0_PE_MASK) || (sa->rflags & X86_EFLAGS_VM)) - return 2; - - cs_attrib = sa->cs.attrib; - - return (cs_attrib & SVM_SELECTOR_L_MASK) ? 8 : - (cs_attrib & SVM_SELECTOR_DB_MASK) ? 4 : 2; -} - -static inline u8 pop_irq(struct kvm_vcpu *vcpu) -{ - int word_index = __ffs(vcpu->irq_summary); - int bit_index = __ffs(vcpu->irq_pending[word_index]); - int irq = word_index * BITS_PER_LONG + bit_index; - - clear_bit(bit_index, &vcpu->irq_pending[word_index]); - if (!vcpu->irq_pending[word_index]) - clear_bit(word_index, &vcpu->irq_summary); - return irq; -} - -static inline void push_irq(struct kvm_vcpu *vcpu, u8 irq) -{ - set_bit(irq, vcpu->irq_pending); - set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary); -} - -static inline void clgi(void) -{ - asm volatile (SVM_CLGI); -} - -static inline void stgi(void) -{ - asm volatile (SVM_STGI); -} - -static inline void invlpga(unsigned long addr, u32 asid) -{ - asm volatile (SVM_INVLPGA :: "a"(addr), "c"(asid)); -} - -static inline unsigned long kvm_read_cr2(void) -{ - unsigned long cr2; - - asm volatile ("mov %%cr2, %0" : "=r" (cr2)); - return cr2; -} - -static inline void kvm_write_cr2(unsigned long val) -{ - asm volatile ("mov %0, %%cr2" :: "r" (val)); -} - -static inline unsigned long read_dr6(void) -{ - unsigned long dr6; - - asm volatile ("mov %%dr6, %0" : "=r" (dr6)); - return dr6; -} - -static inline void write_dr6(unsigned long val) -{ - asm volatile ("mov %0, %%dr6" :: "r" (val)); -} - -static inline unsigned long read_dr7(void) -{ - unsigned long dr7; - - asm volatile ("mov %%dr7, %0" : "=r" (dr7)); - return dr7; -} - -static inline void write_dr7(unsigned long val) -{ - asm volatile ("mov %0, %%dr7" :: "r" (val)); -} - -static inline int svm_is_long_mode(struct kvm_vcpu *vcpu) -{ - return vcpu->svm->vmcb->save.efer & KVM_EFER_LMA; -} - -static inline void force_new_asid(struct kvm_vcpu *vcpu) -{ - vcpu->svm->asid_generation--; -} - -static inline void flush_guest_tlb(struct kvm_vcpu *vcpu) -{ - force_new_asid(vcpu); -} - -static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) -{ - if (!(efer & KVM_EFER_LMA)) - efer &= ~KVM_EFER_LME; - - vcpu->svm->vmcb->save.efer = efer | MSR_EFER_SVME_MASK; - vcpu->shadow_efer = efer; -} - -static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code) -{ - vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | - SVM_EVTINJ_VALID_ERR | - SVM_EVTINJ_TYPE_EXEPT | - GP_VECTOR; - vcpu->svm->vmcb->control.event_inj_err = error_code; -} - -static void inject_ud(struct kvm_vcpu *vcpu) -{ - vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | - SVM_EVTINJ_TYPE_EXEPT | - UD_VECTOR; -} - -static void inject_db(struct kvm_vcpu *vcpu) -{ - vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | - SVM_EVTINJ_TYPE_EXEPT | - DB_VECTOR; -} - -static int is_page_fault(uint32_t info) -{ - info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID; - return info == (PF_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT); -} - -static int is_external_interrupt(u32 info) -{ - info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID; - return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR); -} - -static void skip_emulated_instruction(struct kvm_vcpu *vcpu) -{ - if (!vcpu->svm->next_rip) { - printk(KERN_DEBUG "%s: NOP\n", __FUNCTION__); - return; - } - if (vcpu->svm->next_rip - vcpu->svm->vmcb->save.rip > 15) { - printk(KERN_ERR "%s: ip 0x%llx next 0x%llx\n", - __FUNCTION__, - vcpu->svm->vmcb->save.rip, - vcpu->svm->next_rip); - } - - vcpu->rip = vcpu->svm->vmcb->save.rip = vcpu->svm->next_rip; - vcpu->svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK; -} - -static int has_svm(void) -{ - uint32_t eax, ebx, ecx, edx; - - if (current_cpu_data.x86_vendor != X86_VENDOR_AMD) { - printk(KERN_INFO "has_svm: not amd\n"); - return 0; - } - - cpuid(0x80000000, &eax, &ebx, &ecx, &edx); - if (eax < SVM_CPUID_FUNC) { - printk(KERN_INFO "has_svm: can't execute cpuid_8000000a\n"); - return 0; - } - - cpuid(0x80000001, &eax, &ebx, &ecx, &edx); - if (!(ecx & (1 << SVM_CPUID_FEATURE_SHIFT))) { - printk(KERN_DEBUG "has_svm: svm not available\n"); - return 0; - } - return 1; -} - -static void svm_hardware_disable(void *garbage) -{ - struct svm_cpu_data *svm_data - = per_cpu(svm_data, raw_smp_processor_id()); - - if (svm_data) { - uint64_t efer; - - wrmsrl(MSR_VM_HSAVE_PA, 0); - rdmsrl(MSR_EFER, efer); - wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK); - per_cpu(svm_data, raw_smp_processor_id()) = 0; - __free_page(svm_data->save_area); - kfree(svm_data); - } -} - -static void svm_hardware_enable(void *garbage) -{ - - struct svm_cpu_data *svm_data; - uint64_t efer; -#ifdef CONFIG_X86_64 - struct desc_ptr gdt_descr; -#else - struct Xgt_desc_struct gdt_descr; -#endif - struct desc_struct *gdt; - int me = raw_smp_processor_id(); - - if (!has_svm()) { - printk(KERN_ERR "svm_cpu_init: err EOPNOTSUPP on %d\n", me); - return; - } - svm_data = per_cpu(svm_data, me); - - if (!svm_data) { - printk(KERN_ERR "svm_cpu_init: svm_data is NULL on %d\n", - me); - return; - } - - svm_data->asid_generation = 1; - svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1; - svm_data->next_asid = svm_data->max_asid + 1; - - asm volatile ( "sgdt %0" : "=m"(gdt_descr) ); - gdt = (struct desc_struct *)gdt_descr.address; - svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); - - rdmsrl(MSR_EFER, efer); - wrmsrl(MSR_EFER, efer | MSR_EFER_SVME_MASK); - - wrmsrl(MSR_VM_HSAVE_PA, - page_to_pfn(svm_data->save_area) << PAGE_SHIFT); -} - -static int svm_cpu_init(int cpu) -{ - struct svm_cpu_data *svm_data; - int r; - - svm_data = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL); - if (!svm_data) - return -ENOMEM; - svm_data->cpu = cpu; - svm_data->save_area = alloc_page(GFP_KERNEL); - r = -ENOMEM; - if (!svm_data->save_area) - goto err_1; - - per_cpu(svm_data, cpu) = svm_data; - - return 0; - -err_1: - kfree(svm_data); - return r; - -} - -static int set_msr_interception(u32 *msrpm, unsigned msr, - int read, int write) -{ - int i; - - for (i = 0; i < NUM_MSR_MAPS; i++) { - if (msr >= msrpm_ranges[i] && - msr < msrpm_ranges[i] + MSRS_IN_RANGE) { - u32 msr_offset = (i * MSRS_IN_RANGE + msr - - msrpm_ranges[i]) * 2; - - u32 *base = msrpm + (msr_offset / 32); - u32 msr_shift = msr_offset % 32; - u32 mask = ((write) ? 0 : 2) | ((read) ? 0 : 1); - *base = (*base & ~(0x3 << msr_shift)) | - (mask << msr_shift); - return 1; - } - } - printk(KERN_DEBUG "%s: not found 0x%x\n", __FUNCTION__, msr); - return 0; -} - -static __init int svm_hardware_setup(void) -{ - int cpu; - struct page *iopm_pages; - struct page *msrpm_pages; - void *msrpm_va; - int r; - - kvm_emulator_want_group7_invlpg(); - - iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER); - - if (!iopm_pages) - return -ENOMEM; - memset(page_address(iopm_pages), 0xff, - PAGE_SIZE * (1 << IOPM_ALLOC_ORDER)); - iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT; - - - msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER); - - r = -ENOMEM; - if (!msrpm_pages) - goto err_1; - - msrpm_va = page_address(msrpm_pages); - memset(msrpm_va, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER)); - msrpm_base = page_to_pfn(msrpm_pages) << PAGE_SHIFT; - -#ifdef CONFIG_X86_64 - set_msr_interception(msrpm_va, MSR_GS_BASE, 1, 1); - set_msr_interception(msrpm_va, MSR_FS_BASE, 1, 1); - set_msr_interception(msrpm_va, MSR_KERNEL_GS_BASE, 1, 1); - set_msr_interception(msrpm_va, MSR_STAR, 1, 1); - set_msr_interception(msrpm_va, MSR_LSTAR, 1, 1); - set_msr_interception(msrpm_va, MSR_CSTAR, 1, 1); - set_msr_interception(msrpm_va, MSR_SYSCALL_MASK, 1, 1); -#endif - set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_CS, 1, 1); - set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_ESP, 1, 1); - set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_EIP, 1, 1); - - for_each_online_cpu(cpu) { - r = svm_cpu_init(cpu); - if (r) - goto err_2; - } - return 0; - -err_2: - __free_pages(msrpm_pages, MSRPM_ALLOC_ORDER); - msrpm_base = 0; -err_1: - __free_pages(iopm_pages, IOPM_ALLOC_ORDER); - iopm_base = 0; - return r; -} - -static __exit void svm_hardware_unsetup(void) -{ - __free_pages(pfn_to_page(msrpm_base >> PAGE_SHIFT), MSRPM_ALLOC_ORDER); - __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER); - iopm_base = msrpm_base = 0; -} - -static void init_seg(struct vmcb_seg *seg) -{ - seg->selector = 0; - seg->attrib = SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK | - SVM_SELECTOR_WRITE_MASK; /* Read/Write Data Segment */ - seg->limit = 0xffff; - seg->base = 0; -} - -static void init_sys_seg(struct vmcb_seg *seg, uint32_t type) -{ - seg->selector = 0; - seg->attrib = SVM_SELECTOR_P_MASK | type; - seg->limit = 0xffff; - seg->base = 0; -} - -static int svm_vcpu_setup(struct kvm_vcpu *vcpu) -{ - return 0; -} - -static void init_vmcb(struct vmcb *vmcb) -{ - struct vmcb_control_area *control = &vmcb->control; - struct vmcb_save_area *save = &vmcb->save; - u64 tsc; - - control->intercept_cr_read = INTERCEPT_CR0_MASK | - INTERCEPT_CR3_MASK | - INTERCEPT_CR4_MASK; - - control->intercept_cr_write = INTERCEPT_CR0_MASK | - INTERCEPT_CR3_MASK | - INTERCEPT_CR4_MASK; - - control->intercept_dr_read = INTERCEPT_DR0_MASK | - INTERCEPT_DR1_MASK | - INTERCEPT_DR2_MASK | - INTERCEPT_DR3_MASK; - - control->intercept_dr_write = INTERCEPT_DR0_MASK | - INTERCEPT_DR1_MASK | - INTERCEPT_DR2_MASK | - INTERCEPT_DR3_MASK | - INTERCEPT_DR5_MASK | - INTERCEPT_DR7_MASK; - - control->intercept_exceptions = 1 << PF_VECTOR; - - - control->intercept = (1ULL << INTERCEPT_INTR) | - (1ULL << INTERCEPT_NMI) | - /* - * selective cr0 intercept bug? - * 0: 0f 22 d8 mov %eax,%cr3 - * 3: 0f 20 c0 mov %cr0,%eax - * 6: 0d 00 00 00 80 or $0x80000000,%eax - * b: 0f 22 c0 mov %eax,%cr0 - * set cr3 ->interception - * get cr0 ->interception - * set cr0 -> no interception - */ - /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */ - (1ULL << INTERCEPT_CPUID) | - (1ULL << INTERCEPT_HLT) | - (1ULL << INTERCEPT_INVLPG) | - (1ULL << INTERCEPT_INVLPGA) | - (1ULL << INTERCEPT_IOIO_PROT) | - (1ULL << INTERCEPT_MSR_PROT) | - (1ULL << INTERCEPT_TASK_SWITCH) | - (1ULL << INTERCEPT_VMRUN) | - (1ULL << INTERCEPT_VMMCALL) | - (1ULL << INTERCEPT_VMLOAD) | - (1ULL << INTERCEPT_VMSAVE) | - (1ULL << INTERCEPT_STGI) | - (1ULL << INTERCEPT_CLGI) | - (1ULL << INTERCEPT_SKINIT); - - control->iopm_base_pa = iopm_base; - control->msrpm_base_pa = msrpm_base; - rdtscll(tsc); - control->tsc_offset = -tsc; - control->int_ctl = V_INTR_MASKING_MASK; - - init_seg(&save->es); - init_seg(&save->ss); - init_seg(&save->ds); - init_seg(&save->fs); - init_seg(&save->gs); - - save->cs.selector = 0xf000; - /* Executable/Readable Code Segment */ - save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK | - SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK; - save->cs.limit = 0xffff; - save->cs.base = 0xffff0000; - - save->gdtr.limit = 0xffff; - save->idtr.limit = 0xffff; - - init_sys_seg(&save->ldtr, SEG_TYPE_LDT); - init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16); - - save->efer = MSR_EFER_SVME_MASK; - - save->dr6 = 0xffff0ff0; - save->dr7 = 0x400; - save->rflags = 2; - save->rip = 0x0000fff0; - - /* - * cr0 val on cpu init should be 0x60000010, we enable cpu - * cache by default. the orderly way is to enable cache in bios. - */ - save->cr0 = 0x00000010 | CR0_PG_MASK; - save->cr4 = CR4_PAE_MASK; - /* rdx = ?? */ -} - -static int svm_create_vcpu(struct kvm_vcpu *vcpu) -{ - struct page *page; - int r; - - r = -ENOMEM; - vcpu->svm = kzalloc(sizeof *vcpu->svm, GFP_KERNEL); - if (!vcpu->svm) - goto out1; - page = alloc_page(GFP_KERNEL); - if (!page) - goto out2; - - vcpu->svm->vmcb = page_address(page); - memset(vcpu->svm->vmcb, 0, PAGE_SIZE); - vcpu->svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; - vcpu->svm->cr0 = 0x00000010; - vcpu->svm->asid_generation = 0; - memset(vcpu->svm->db_regs, 0, sizeof(vcpu->svm->db_regs)); - init_vmcb(vcpu->svm->vmcb); - - return 0; - -out2: - kfree(vcpu->svm); -out1: - return r; -} - -static void svm_free_vcpu(struct kvm_vcpu *vcpu) -{ - if (!vcpu->svm) - return; - if (vcpu->svm->vmcb) - __free_page(pfn_to_page(vcpu->svm->vmcb_pa >> PAGE_SHIFT)); - kfree(vcpu->svm); -} - -static struct kvm_vcpu *svm_vcpu_load(struct kvm_vcpu *vcpu) -{ - get_cpu(); - return vcpu; -} - -static void svm_vcpu_put(struct kvm_vcpu *vcpu) -{ - put_cpu(); -} - -static void svm_cache_regs(struct kvm_vcpu *vcpu) -{ - vcpu->regs[VCPU_REGS_RAX] = vcpu->svm->vmcb->save.rax; - vcpu->regs[VCPU_REGS_RSP] = vcpu->svm->vmcb->save.rsp; - vcpu->rip = vcpu->svm->vmcb->save.rip; -} - -static void svm_decache_regs(struct kvm_vcpu *vcpu) -{ - vcpu->svm->vmcb->save.rax = vcpu->regs[VCPU_REGS_RAX]; - vcpu->svm->vmcb->save.rsp = vcpu->regs[VCPU_REGS_RSP]; - vcpu->svm->vmcb->save.rip = vcpu->rip; -} - -static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu) -{ - return vcpu->svm->vmcb->save.rflags; -} - -static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) -{ - vcpu->svm->vmcb->save.rflags = rflags; -} - -static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg) -{ - struct vmcb_save_area *save = &vcpu->svm->vmcb->save; - - switch (seg) { - case VCPU_SREG_CS: return &save->cs; - case VCPU_SREG_DS: return &save->ds; - case VCPU_SREG_ES: return &save->es; - case VCPU_SREG_FS: return &save->fs; - case VCPU_SREG_GS: return &save->gs; - case VCPU_SREG_SS: return &save->ss; - case VCPU_SREG_TR: return &save->tr; - case VCPU_SREG_LDTR: return &save->ldtr; - } - BUG(); - return 0; -} - -static u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg) -{ - struct vmcb_seg *s = svm_seg(vcpu, seg); - - return s->base; -} - -static void svm_get_segment(struct kvm_vcpu *vcpu, - struct kvm_segment *var, int seg) -{ - struct vmcb_seg *s = svm_seg(vcpu, seg); - - var->base = s->base; - var->limit = s->limit; - var->selector = s->selector; - var->type = s->attrib & SVM_SELECTOR_TYPE_MASK; - var->s = (s->attrib >> SVM_SELECTOR_S_SHIFT) & 1; - var->dpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3; - var->present = (s->attrib >> SVM_SELECTOR_P_SHIFT) & 1; - var->avl = (s->attrib >> SVM_SELECTOR_AVL_SHIFT) & 1; - var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1; - var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1; - var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1; - var->unusable = !var->present; -} - -static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) -{ - struct vmcb_seg *s = svm_seg(vcpu, VCPU_SREG_CS); - - *db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1; - *l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1; -} - -static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) -{ - dt->limit = vcpu->svm->vmcb->save.ldtr.limit; - dt->base = vcpu->svm->vmcb->save.ldtr.base; -} - -static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) -{ - vcpu->svm->vmcb->save.ldtr.limit = dt->limit; - vcpu->svm->vmcb->save.ldtr.base = dt->base ; -} - -static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) -{ - dt->limit = vcpu->svm->vmcb->save.gdtr.limit; - dt->base = vcpu->svm->vmcb->save.gdtr.base; -} - -static void svm_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) -{ - vcpu->svm->vmcb->save.gdtr.limit = dt->limit; - vcpu->svm->vmcb->save.gdtr.base = dt->base ; -} - -static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) -{ -#ifdef CONFIG_X86_64 - if (vcpu->shadow_efer & KVM_EFER_LME) { - if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) { - vcpu->shadow_efer |= KVM_EFER_LMA; - vcpu->svm->vmcb->save.efer |= KVM_EFER_LMA | KVM_EFER_LME; - } - - if (is_paging(vcpu) && !(cr0 & CR0_PG_MASK) ) { - vcpu->shadow_efer &= ~KVM_EFER_LMA; - vcpu->svm->vmcb->save.efer &= ~(KVM_EFER_LMA | KVM_EFER_LME); - } - } -#endif - vcpu->svm->cr0 = cr0; - vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK; - vcpu->cr0 = cr0; -} - -static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) -{ - vcpu->cr4 = cr4; - vcpu->svm->vmcb->save.cr4 = cr4 | CR4_PAE_MASK; -} - -static void svm_set_segment(struct kvm_vcpu *vcpu, - struct kvm_segment *var, int seg) -{ - struct vmcb_seg *s = svm_seg(vcpu, seg); - - s->base = var->base; - s->limit = var->limit; - s->selector = var->selector; - if (var->unusable) - s->attrib = 0; - else { - s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK); - s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT; - s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT; - s->attrib |= (var->present & 1) << SVM_SELECTOR_P_SHIFT; - s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT; - s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT; - s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT; - s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT; - } - if (seg == VCPU_SREG_CS) - vcpu->svm->vmcb->save.cpl - = (vcpu->svm->vmcb->save.cs.attrib - >> SVM_SELECTOR_DPL_SHIFT) & 3; - -} - -/* FIXME: - - vcpu->svm->vmcb->control.int_ctl &= ~V_TPR_MASK; - vcpu->svm->vmcb->control.int_ctl |= (sregs->cr8 & V_TPR_MASK); - -*/ - -static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) -{ - return -EOPNOTSUPP; -} - -static void load_host_msrs(struct kvm_vcpu *vcpu) -{ - int i; - - for ( i = 0; i < NR_HOST_SAVE_MSRS; i++) - wrmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]); -} - -static void save_host_msrs(struct kvm_vcpu *vcpu) -{ - int i; - - for ( i = 0; i < NR_HOST_SAVE_MSRS; i++) - rdmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]); -} - -static void new_asid(struct kvm_vcpu *vcpu, struct svm_cpu_data *svm_data) -{ - if (svm_data->next_asid > svm_data->max_asid) { - ++svm_data->asid_generation; - svm_data->next_asid = 1; - vcpu->svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID; - } - - vcpu->cpu = svm_data->cpu; - vcpu->svm->asid_generation = svm_data->asid_generation; - vcpu->svm->vmcb->control.asid = svm_data->next_asid++; -} - -static void svm_invlpg(struct kvm_vcpu *vcpu, gva_t address) -{ - invlpga(address, vcpu->svm->vmcb->control.asid); // is needed? -} - -static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr) -{ - return vcpu->svm->db_regs[dr]; -} - -static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value, - int *exception) -{ - *exception = 0; - - if (vcpu->svm->vmcb->save.dr7 & DR7_GD_MASK) { - vcpu->svm->vmcb->save.dr7 &= ~DR7_GD_MASK; - vcpu->svm->vmcb->save.dr6 |= DR6_BD_MASK; - *exception = DB_VECTOR; - return; - } - - switch (dr) { - case 0 ... 3: - vcpu->svm->db_regs[dr] = value; - return; - case 4 ... 5: - if (vcpu->cr4 & CR4_DE_MASK) { - *exception = UD_VECTOR; - return; - } - case 7: { - if (value & ~((1ULL << 32) - 1)) { - *exception = GP_VECTOR; - return; - } - vcpu->svm->vmcb->save.dr7 = value; - return; - } - default: - printk(KERN_DEBUG "%s: unexpected dr %u\n", - __FUNCTION__, dr); - *exception = UD_VECTOR; - return; - } -} - -static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u32 exit_int_info = vcpu->svm->vmcb->control.exit_int_info; - u64 fault_address; - u32 error_code; - enum emulation_result er; - - if (is_external_interrupt(exit_int_info)) - push_irq(vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); - - spin_lock(&vcpu->kvm->lock); - - fault_address = vcpu->svm->vmcb->control.exit_info_2; - error_code = vcpu->svm->vmcb->control.exit_info_1; - if (!vcpu->mmu.page_fault(vcpu, fault_address, error_code)) { - spin_unlock(&vcpu->kvm->lock); - return 1; - } - er = emulate_instruction(vcpu, kvm_run, fault_address, error_code); - spin_unlock(&vcpu->kvm->lock); - - switch (er) { - case EMULATE_DONE: - return 1; - case EMULATE_DO_MMIO: - ++kvm_stat.mmio_exits; - kvm_run->exit_reason = KVM_EXIT_MMIO; - return 0; - case EMULATE_FAIL: - vcpu_printf(vcpu, "%s: emulate fail\n", __FUNCTION__); - break; - default: - BUG(); - } - - kvm_run->exit_reason = KVM_EXIT_UNKNOWN; - return 0; -} - -static int io_get_override(struct kvm_vcpu *vcpu, - struct vmcb_seg **seg, - int *addr_override) -{ - u8 inst[MAX_INST_SIZE]; - unsigned ins_length; - gva_t rip; - int i; - - rip = vcpu->svm->vmcb->save.rip; - ins_length = vcpu->svm->next_rip - rip; - rip += vcpu->svm->vmcb->save.cs.base; - - if (ins_length > MAX_INST_SIZE) - printk(KERN_DEBUG - "%s: inst length err, cs base 0x%llx rip 0x%llx " - "next rip 0x%llx ins_length %u\n", - __FUNCTION__, - vcpu->svm->vmcb->save.cs.base, - vcpu->svm->vmcb->save.rip, - vcpu->svm->vmcb->control.exit_info_2, - ins_length); - - if (kvm_read_guest(vcpu, rip, ins_length, inst) != ins_length) - /* #PF */ - return 0; - - *addr_override = 0; - *seg = 0; - for (i = 0; i < ins_length; i++) - switch (inst[i]) { - case 0xf0: - case 0xf2: - case 0xf3: - case 0x66: - continue; - case 0x67: - *addr_override = 1; - continue; - case 0x2e: - *seg = &vcpu->svm->vmcb->save.cs; - continue; - case 0x36: - *seg = &vcpu->svm->vmcb->save.ss; - continue; - case 0x3e: - *seg = &vcpu->svm->vmcb->save.ds; - continue; - case 0x26: - *seg = &vcpu->svm->vmcb->save.es; - continue; - case 0x64: - *seg = &vcpu->svm->vmcb->save.fs; - continue; - case 0x65: - *seg = &vcpu->svm->vmcb->save.gs; - continue; - default: - return 1; - } - printk(KERN_DEBUG "%s: unexpected\n", __FUNCTION__); - return 0; -} - -static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address) -{ - unsigned long addr_mask; - unsigned long *reg; - struct vmcb_seg *seg; - int addr_override; - struct vmcb_save_area *save_area = &vcpu->svm->vmcb->save; - u16 cs_attrib = save_area->cs.attrib; - unsigned addr_size = get_addr_size(vcpu); - - if (!io_get_override(vcpu, &seg, &addr_override)) - return 0; - - if (addr_override) - addr_size = (addr_size == 2) ? 4: (addr_size >> 1); - - if (ins) { - reg = &vcpu->regs[VCPU_REGS_RDI]; - seg = &vcpu->svm->vmcb->save.es; - } else { - reg = &vcpu->regs[VCPU_REGS_RSI]; - seg = (seg) ? seg : &vcpu->svm->vmcb->save.ds; - } - - addr_mask = ~0ULL >> (64 - (addr_size * 8)); - - if ((cs_attrib & SVM_SELECTOR_L_MASK) && - !(vcpu->svm->vmcb->save.rflags & X86_EFLAGS_VM)) { - *address = (*reg & addr_mask); - return addr_mask; - } - - if (!(seg->attrib & SVM_SELECTOR_P_SHIFT)) { - svm_inject_gp(vcpu, 0); - return 0; - } - - *address = (*reg & addr_mask) + seg->base; - return addr_mask; -} - -static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u32 io_info = vcpu->svm->vmcb->control.exit_info_1; //address size bug? - int _in = io_info & SVM_IOIO_TYPE_MASK; - - ++kvm_stat.io_exits; - - vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2; - - kvm_run->exit_reason = KVM_EXIT_IO; - kvm_run->io.port = io_info >> 16; - kvm_run->io.direction = (_in) ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; - kvm_run->io.size = ((io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT); - kvm_run->io.string = (io_info & SVM_IOIO_STR_MASK) != 0; - kvm_run->io.rep = (io_info & SVM_IOIO_REP_MASK) != 0; - - if (kvm_run->io.string) { - unsigned addr_mask; - - addr_mask = io_adress(vcpu, _in, &kvm_run->io.address); - if (!addr_mask) { - printk(KERN_DEBUG "%s: get io address failed\n", __FUNCTION__); - return 1; - } - - if (kvm_run->io.rep) { - kvm_run->io.count = vcpu->regs[VCPU_REGS_RCX] & addr_mask; - kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags - & X86_EFLAGS_DF) != 0; - } - } else { - kvm_run->io.value = vcpu->svm->vmcb->save.rax; - } - return 0; -} - - -static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - return 1; -} - -static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1; - skip_emulated_instruction(vcpu); - if (vcpu->irq_summary && (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF)) - return 1; - - kvm_run->exit_reason = KVM_EXIT_HLT; - return 0; -} - -static int invalid_op_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - inject_ud(vcpu); - return 1; -} - -static int task_switch_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - printk(KERN_DEBUG "%s: task swiche is unsupported\n", __FUNCTION__); - kvm_run->exit_reason = KVM_EXIT_UNKNOWN; - return 0; -} - -static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2; - kvm_run->exit_reason = KVM_EXIT_CPUID; - return 0; -} - -static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - if (emulate_instruction(vcpu, 0, 0, 0) != EMULATE_DONE) - printk(KERN_ERR "%s: failed\n", __FUNCTION__); - return 1; -} - -static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) -{ - switch (ecx) { - case MSR_IA32_MC0_CTL: - case MSR_IA32_MCG_STATUS: - case MSR_IA32_MCG_CAP: - case MSR_IA32_MC0_MISC: - case MSR_IA32_MC0_MISC+4: - case MSR_IA32_MC0_MISC+8: - case MSR_IA32_MC0_MISC+12: - case MSR_IA32_MC0_MISC+16: - case MSR_IA32_UCODE_REV: - /* MTRR registers */ - case 0xfe: - case 0x200 ... 0x2ff: - *data = 0; - break; - case MSR_IA32_TIME_STAMP_COUNTER: { - u64 tsc; - - rdtscll(tsc); - *data = vcpu->svm->vmcb->control.tsc_offset + tsc; - break; - } - case MSR_EFER: - *data = vcpu->shadow_efer; - break; - case MSR_IA32_APICBASE: - *data = vcpu->apic_base; - break; -#ifdef CONFIG_X86_64 - case MSR_STAR: - *data = vcpu->svm->vmcb->save.star; - break; - case MSR_LSTAR: - *data = vcpu->svm->vmcb->save.lstar; - break; - case MSR_CSTAR: - *data = vcpu->svm->vmcb->save.cstar; - break; - case MSR_KERNEL_GS_BASE: - *data = vcpu->svm->vmcb->save.kernel_gs_base; - break; - case MSR_SYSCALL_MASK: - *data = vcpu->svm->vmcb->save.sfmask; - break; -#endif - case MSR_IA32_SYSENTER_CS: - *data = vcpu->svm->vmcb->save.sysenter_cs; - break; - case MSR_IA32_SYSENTER_EIP: - *data = vcpu->svm->vmcb->save.sysenter_eip; - break; - case MSR_IA32_SYSENTER_ESP: - *data = vcpu->svm->vmcb->save.sysenter_esp; - break; - default: - printk(KERN_ERR "kvm: unhandled rdmsr: 0x%x\n", ecx); - return 1; - } - return 0; -} - -static int rdmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u32 ecx = vcpu->regs[VCPU_REGS_RCX]; - u64 data; - - if (svm_get_msr(vcpu, ecx, &data)) - svm_inject_gp(vcpu, 0); - else { - vcpu->svm->vmcb->save.rax = data & 0xffffffff; - vcpu->regs[VCPU_REGS_RDX] = data >> 32; - vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2; - skip_emulated_instruction(vcpu); - } - return 1; -} - -static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) -{ - switch (ecx) { -#ifdef CONFIG_X86_64 - case MSR_EFER: - set_efer(vcpu, data); - break; -#endif - case MSR_IA32_MC0_STATUS: - printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n" - , __FUNCTION__, data); - break; - case MSR_IA32_TIME_STAMP_COUNTER: { - u64 tsc; - - rdtscll(tsc); - vcpu->svm->vmcb->control.tsc_offset = data - tsc; - break; - } - case MSR_IA32_UCODE_REV: - case MSR_IA32_UCODE_WRITE: - case 0x200 ... 0x2ff: /* MTRRs */ - break; - case MSR_IA32_APICBASE: - vcpu->apic_base = data; - break; -#ifdef CONFIG_X86_64_ - case MSR_STAR: - vcpu->svm->vmcb->save.star = data; - break; - case MSR_LSTAR: - vcpu->svm->vmcb->save.lstar = data; - break; - case MSR_CSTAR: - vcpu->svm->vmcb->save.cstar = data; - break; - case MSR_KERNEL_GS_BASE: - vcpu->svm->vmcb->save.kernel_gs_base = data; - break; - case MSR_SYSCALL_MASK: - vcpu->svm->vmcb->save.sfmask = data; - break; -#endif - case MSR_IA32_SYSENTER_CS: - vcpu->svm->vmcb->save.sysenter_cs = data; - break; - case MSR_IA32_SYSENTER_EIP: - vcpu->svm->vmcb->save.sysenter_eip = data; - break; - case MSR_IA32_SYSENTER_ESP: - vcpu->svm->vmcb->save.sysenter_esp = data; - break; - default: - printk(KERN_ERR "kvm: unhandled wrmsr: %x\n", ecx); - return 1; - } - return 0; -} - -static int wrmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u32 ecx = vcpu->regs[VCPU_REGS_RCX]; - u64 data = (vcpu->svm->vmcb->save.rax & -1u) - | ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32); - vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2; - if (svm_set_msr(vcpu, ecx, data)) - svm_inject_gp(vcpu, 0); - else - skip_emulated_instruction(vcpu); - return 1; -} - -static int msr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - if (vcpu->svm->vmcb->control.exit_info_1) - return wrmsr_interception(vcpu, kvm_run); - else - return rdmsr_interception(vcpu, kvm_run); -} - -static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, - struct kvm_run *kvm_run) = { - [SVM_EXIT_READ_CR0] = emulate_on_interception, - [SVM_EXIT_READ_CR3] = emulate_on_interception, - [SVM_EXIT_READ_CR4] = emulate_on_interception, - /* for now: */ - [SVM_EXIT_WRITE_CR0] = emulate_on_interception, - [SVM_EXIT_WRITE_CR3] = emulate_on_interception, - [SVM_EXIT_WRITE_CR4] = emulate_on_interception, - [SVM_EXIT_READ_DR0] = emulate_on_interception, - [SVM_EXIT_READ_DR1] = emulate_on_interception, - [SVM_EXIT_READ_DR2] = emulate_on_interception, - [SVM_EXIT_READ_DR3] = emulate_on_interception, - [SVM_EXIT_WRITE_DR0] = emulate_on_interception, - [SVM_EXIT_WRITE_DR1] = emulate_on_interception, - [SVM_EXIT_WRITE_DR2] = emulate_on_interception, - [SVM_EXIT_WRITE_DR3] = emulate_on_interception, - [SVM_EXIT_WRITE_DR5] = emulate_on_interception, - [SVM_EXIT_WRITE_DR7] = emulate_on_interception, - [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, - [SVM_EXIT_INTR] = nop_on_interception, - [SVM_EXIT_NMI] = nop_on_interception, - [SVM_EXIT_SMI] = nop_on_interception, - [SVM_EXIT_INIT] = nop_on_interception, - /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */ - [SVM_EXIT_CPUID] = cpuid_interception, - [SVM_EXIT_HLT] = halt_interception, - [SVM_EXIT_INVLPG] = emulate_on_interception, - [SVM_EXIT_INVLPGA] = invalid_op_interception, - [SVM_EXIT_IOIO] = io_interception, - [SVM_EXIT_MSR] = msr_interception, - [SVM_EXIT_TASK_SWITCH] = task_switch_interception, - [SVM_EXIT_VMRUN] = invalid_op_interception, - [SVM_EXIT_VMMCALL] = invalid_op_interception, - [SVM_EXIT_VMLOAD] = invalid_op_interception, - [SVM_EXIT_VMSAVE] = invalid_op_interception, - [SVM_EXIT_STGI] = invalid_op_interception, - [SVM_EXIT_CLGI] = invalid_op_interception, - [SVM_EXIT_SKINIT] = invalid_op_interception, -}; - - -static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u32 exit_code = vcpu->svm->vmcb->control.exit_code; - - kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT; - - if (is_external_interrupt(vcpu->svm->vmcb->control.exit_int_info) && - exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR) - printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x " - "exit_code 0x%x\n", - __FUNCTION__, vcpu->svm->vmcb->control.exit_int_info, - exit_code); - - if (exit_code >= sizeof(svm_exit_handlers) / sizeof(*svm_exit_handlers) - || svm_exit_handlers[exit_code] == 0) { - kvm_run->exit_reason = KVM_EXIT_UNKNOWN; - printk(KERN_ERR "%s: 0x%x @ 0x%llx cr0 0x%lx rflags 0x%llx\n", - __FUNCTION__, - exit_code, - vcpu->svm->vmcb->save.rip, - vcpu->cr0, - vcpu->svm->vmcb->save.rflags); - return 0; - } - - return svm_exit_handlers[exit_code](vcpu, kvm_run); -} - -static void reload_tss(struct kvm_vcpu *vcpu) -{ - int cpu = raw_smp_processor_id(); - - struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); - svm_data->tss_desc->type = 9; //available 32/64-bit TSS - load_TR_desc(); -} - -static void pre_svm_run(struct kvm_vcpu *vcpu) -{ - int cpu = raw_smp_processor_id(); - - struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); - - vcpu->svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING; - if (vcpu->cpu != cpu || - vcpu->svm->asid_generation != svm_data->asid_generation) - new_asid(vcpu, svm_data); -} - - -static inline void kvm_try_inject_irq(struct kvm_vcpu *vcpu) -{ - struct vmcb_control_area *control; - - if (!vcpu->irq_summary) - return; - - control = &vcpu->svm->vmcb->control; - - control->int_vector = pop_irq(vcpu); - control->int_ctl &= ~V_INTR_PRIO_MASK; - control->int_ctl |= V_IRQ_MASK | - ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT); -} - -static void kvm_reput_irq(struct kvm_vcpu *vcpu) -{ - struct vmcb_control_area *control = &vcpu->svm->vmcb->control; - - if (control->int_ctl & V_IRQ_MASK) { - control->int_ctl &= ~V_IRQ_MASK; - push_irq(vcpu, control->int_vector); - } -} - -static void save_db_regs(unsigned long *db_regs) -{ - asm volatile ("mov %%dr0, %0" : "=r"(db_regs[0])); - asm volatile ("mov %%dr1, %0" : "=r"(db_regs[1])); - asm volatile ("mov %%dr2, %0" : "=r"(db_regs[2])); - asm volatile ("mov %%dr3, %0" : "=r"(db_regs[3])); -} - -static void load_db_regs(unsigned long *db_regs) -{ - asm volatile ("mov %0, %%dr0" : : "r"(db_regs[0])); - asm volatile ("mov %0, %%dr1" : : "r"(db_regs[1])); - asm volatile ("mov %0, %%dr2" : : "r"(db_regs[2])); - asm volatile ("mov %0, %%dr3" : : "r"(db_regs[3])); -} - -static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u16 fs_selector; - u16 gs_selector; - u16 ldt_selector; - -again: - kvm_try_inject_irq(vcpu); - - clgi(); - - pre_svm_run(vcpu); - - save_host_msrs(vcpu); - fs_selector = read_fs(); - gs_selector = read_gs(); - ldt_selector = read_ldt(); - vcpu->svm->host_cr2 = kvm_read_cr2(); - vcpu->svm->host_dr6 = read_dr6(); - vcpu->svm->host_dr7 = read_dr7(); - vcpu->svm->vmcb->save.cr2 = vcpu->cr2; - - if (vcpu->svm->vmcb->save.dr7 & 0xff) { - write_dr7(0); - save_db_regs(vcpu->svm->host_db_regs); - load_db_regs(vcpu->svm->db_regs); - } - asm volatile ( -#ifdef CONFIG_X86_64 - "push %%rbx; push %%rcx; push %%rdx;" - "push %%rsi; push %%rdi; push %%rbp;" - "push %%r8; push %%r9; push %%r10; push %%r11;" - "push %%r12; push %%r13; push %%r14; push %%r15;" -#else - "push %%ebx; push %%ecx; push %%edx;" - "push %%esi; push %%edi; push %%ebp;" -#endif - -#ifdef CONFIG_X86_64 - "mov %c[rbx](%[vcpu]), %%rbx \n\t" - "mov %c[rcx](%[vcpu]), %%rcx \n\t" - "mov %c[rdx](%[vcpu]), %%rdx \n\t" - "mov %c[rsi](%[vcpu]), %%rsi \n\t" - "mov %c[rdi](%[vcpu]), %%rdi \n\t" - "mov %c[rbp](%[vcpu]), %%rbp \n\t" - "mov %c[r8](%[vcpu]), %%r8 \n\t" - "mov %c[r9](%[vcpu]), %%r9 \n\t" - "mov %c[r10](%[vcpu]), %%r10 \n\t" - "mov %c[r11](%[vcpu]), %%r11 \n\t" - "mov %c[r12](%[vcpu]), %%r12 \n\t" - "mov %c[r13](%[vcpu]), %%r13 \n\t" - "mov %c[r14](%[vcpu]), %%r14 \n\t" - "mov %c[r15](%[vcpu]), %%r15 \n\t" -#else - "mov %c[rbx](%[vcpu]), %%ebx \n\t" - "mov %c[rcx](%[vcpu]), %%ecx \n\t" - "mov %c[rdx](%[vcpu]), %%edx \n\t" - "mov %c[rsi](%[vcpu]), %%esi \n\t" - "mov %c[rdi](%[vcpu]), %%edi \n\t" - "mov %c[rbp](%[vcpu]), %%ebp \n\t" -#endif - -#ifdef CONFIG_X86_64 - /* Enter guest mode */ - "push %%rax \n\t" - "mov %c[svm](%[vcpu]), %%rax \n\t" - "mov %c[vmcb](%%rax), %%rax \n\t" - SVM_VMLOAD "\n\t" - SVM_VMRUN "\n\t" - SVM_VMSAVE "\n\t" - "pop %%rax \n\t" -#else - /* Enter guest mode */ - "push %%eax \n\t" - "mov %c[svm](%[vcpu]), %%eax \n\t" - "mov %c[vmcb](%%eax), %%eax \n\t" - SVM_VMLOAD "\n\t" - SVM_VMRUN "\n\t" - SVM_VMSAVE "\n\t" - "pop %%eax \n\t" -#endif - - /* Save guest registers, load host registers */ -#ifdef CONFIG_X86_64 - "mov %%rbx, %c[rbx](%[vcpu]) \n\t" - "mov %%rcx, %c[rcx](%[vcpu]) \n\t" - "mov %%rdx, %c[rdx](%[vcpu]) \n\t" - "mov %%rsi, %c[rsi](%[vcpu]) \n\t" - "mov %%rdi, %c[rdi](%[vcpu]) \n\t" - "mov %%rbp, %c[rbp](%[vcpu]) \n\t" - "mov %%r8, %c[r8](%[vcpu]) \n\t" - "mov %%r9, %c[r9](%[vcpu]) \n\t" - "mov %%r10, %c[r10](%[vcpu]) \n\t" - "mov %%r11, %c[r11](%[vcpu]) \n\t" - "mov %%r12, %c[r12](%[vcpu]) \n\t" - "mov %%r13, %c[r13](%[vcpu]) \n\t" - "mov %%r14, %c[r14](%[vcpu]) \n\t" - "mov %%r15, %c[r15](%[vcpu]) \n\t" - - "pop %%r15; pop %%r14; pop %%r13; pop %%r12;" - "pop %%r11; pop %%r10; pop %%r9; pop %%r8;" - "pop %%rbp; pop %%rdi; pop %%rsi;" - "pop %%rdx; pop %%rcx; pop %%rbx; \n\t" -#else - "mov %%ebx, %c[rbx](%[vcpu]) \n\t" - "mov %%ecx, %c[rcx](%[vcpu]) \n\t" - "mov %%edx, %c[rdx](%[vcpu]) \n\t" - "mov %%esi, %c[rsi](%[vcpu]) \n\t" - "mov %%edi, %c[rdi](%[vcpu]) \n\t" - "mov %%ebp, %c[rbp](%[vcpu]) \n\t" - - "pop %%ebp; pop %%edi; pop %%esi;" - "pop %%edx; pop %%ecx; pop %%ebx; \n\t" -#endif - : - : [vcpu]"a"(vcpu), - [svm]"i"(offsetof(struct kvm_vcpu, svm)), - [vmcb]"i"(offsetof(struct vcpu_svm, vmcb_pa)), - [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])), - [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])), - [rdx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDX])), - [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])), - [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])), - [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP])) -#ifdef CONFIG_X86_64 - ,[r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])), - [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])), - [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])), - [r11]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R11])), - [r12]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R12])), - [r13]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R13])), - [r14]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R14])), - [r15]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R15])) -#endif - : "cc", "memory" ); - - if ((vcpu->svm->vmcb->save.dr7 & 0xff)) - load_db_regs(vcpu->svm->host_db_regs); - - vcpu->cr2 = vcpu->svm->vmcb->save.cr2; - - write_dr6(vcpu->svm->host_dr6); - write_dr7(vcpu->svm->host_dr7); - kvm_write_cr2(vcpu->svm->host_cr2); - - load_fs(fs_selector); - load_gs(gs_selector); - load_ldt(ldt_selector); - load_host_msrs(vcpu); - - reload_tss(vcpu); - - stgi(); - - kvm_reput_irq(vcpu); - - vcpu->svm->next_rip = 0; - - if (vcpu->svm->vmcb->control.exit_code == SVM_EXIT_ERR) { - kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY; - kvm_run->exit_reason = vcpu->svm->vmcb->control.exit_code; - return 0; - } - - if (handle_exit(vcpu, kvm_run)) { - if (signal_pending(current)) { - ++kvm_stat.signal_exits; - return -EINTR; - } - kvm_resched(vcpu); - goto again; - } - return 0; -} - -static void svm_flush_tlb(struct kvm_vcpu *vcpu) -{ - force_new_asid(vcpu); -} - -static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root) -{ - vcpu->svm->vmcb->save.cr3 = root; - force_new_asid(vcpu); -} - -static void svm_inject_page_fault(struct kvm_vcpu *vcpu, - unsigned long addr, - uint32_t err_code) -{ - uint32_t exit_int_info = vcpu->svm->vmcb->control.exit_int_info; - - ++kvm_stat.pf_guest; - - if (is_page_fault(exit_int_info)) { - - vcpu->svm->vmcb->control.event_inj_err = 0; - vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | - SVM_EVTINJ_VALID_ERR | - SVM_EVTINJ_TYPE_EXEPT | - DF_VECTOR; - return; - } - vcpu->cr2 = addr; - vcpu->svm->vmcb->save.cr2 = addr; - vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | - SVM_EVTINJ_VALID_ERR | - SVM_EVTINJ_TYPE_EXEPT | - PF_VECTOR; - vcpu->svm->vmcb->control.event_inj_err = err_code; -} - - -static int is_disabled(void) -{ - return 0; -} - -static struct kvm_arch_ops svm_arch_ops = { - .cpu_has_kvm_support = has_svm, - .disabled_by_bios = is_disabled, - .hardware_setup = svm_hardware_setup, - .hardware_unsetup = svm_hardware_unsetup, - .hardware_enable = svm_hardware_enable, - .hardware_disable = svm_hardware_disable, - - .vcpu_create = svm_create_vcpu, - .vcpu_free = svm_free_vcpu, - - .vcpu_load = svm_vcpu_load, - .vcpu_put = svm_vcpu_put, - - .set_guest_debug = svm_guest_debug, - .get_msr = svm_get_msr, - .set_msr = svm_set_msr, - .get_segment_base = svm_get_segment_base, - .get_segment = svm_get_segment, - .set_segment = svm_set_segment, - .is_long_mode = svm_is_long_mode, - .get_cs_db_l_bits = svm_get_cs_db_l_bits, - .set_cr0 = svm_set_cr0, - .set_cr0_no_modeswitch = svm_set_cr0, - .set_cr3 = svm_set_cr3, - .set_cr4 = svm_set_cr4, - .set_efer = svm_set_efer, - .get_idt = svm_get_idt, - .set_idt = svm_set_idt, - .get_gdt = svm_get_gdt, - .set_gdt = svm_set_gdt, - .get_dr = svm_get_dr, - .set_dr = svm_set_dr, - .cache_regs = svm_cache_regs, - .decache_regs = svm_decache_regs, - .get_rflags = svm_get_rflags, - .set_rflags = svm_set_rflags, - - .invlpg = svm_invlpg, - .tlb_flush = svm_flush_tlb, - .inject_page_fault = svm_inject_page_fault, - - .inject_gp = svm_inject_gp, - - .run = svm_vcpu_run, - .skip_emulated_instruction = skip_emulated_instruction, - .vcpu_setup = svm_vcpu_setup, -}; - -static int __init svm_init(void) -{ - return kvm_init_arch(&svm_arch_ops, THIS_MODULE); -} - -static void __exit svm_exit(void) -{ - kvm_exit_arch(); -} - -module_init(svm_init) -module_exit(svm_exit) diff --git a/trunk/drivers/kvm/svm.h b/trunk/drivers/kvm/svm.h deleted file mode 100644 index df731c3fb588..000000000000 --- a/trunk/drivers/kvm/svm.h +++ /dev/null @@ -1,315 +0,0 @@ -#ifndef __SVM_H -#define __SVM_H - -enum { - INTERCEPT_INTR, - INTERCEPT_NMI, - INTERCEPT_SMI, - INTERCEPT_INIT, - INTERCEPT_VINTR, - INTERCEPT_SELECTIVE_CR0, - INTERCEPT_STORE_IDTR, - INTERCEPT_STORE_GDTR, - INTERCEPT_STORE_LDTR, - INTERCEPT_STORE_TR, - INTERCEPT_LOAD_IDTR, - INTERCEPT_LOAD_GDTR, - INTERCEPT_LOAD_LDTR, - INTERCEPT_LOAD_TR, - INTERCEPT_RDTSC, - INTERCEPT_RDPMC, - INTERCEPT_PUSHF, - INTERCEPT_POPF, - INTERCEPT_CPUID, - INTERCEPT_RSM, - INTERCEPT_IRET, - INTERCEPT_INTn, - INTERCEPT_INVD, - INTERCEPT_PAUSE, - INTERCEPT_HLT, - INTERCEPT_INVLPG, - INTERCEPT_INVLPGA, - INTERCEPT_IOIO_PROT, - INTERCEPT_MSR_PROT, - INTERCEPT_TASK_SWITCH, - INTERCEPT_FERR_FREEZE, - INTERCEPT_SHUTDOWN, - INTERCEPT_VMRUN, - INTERCEPT_VMMCALL, - INTERCEPT_VMLOAD, - INTERCEPT_VMSAVE, - INTERCEPT_STGI, - INTERCEPT_CLGI, - INTERCEPT_SKINIT, - INTERCEPT_RDTSCP, - INTERCEPT_ICEBP, - INTERCEPT_WBINVD, -}; - - -struct __attribute__ ((__packed__)) vmcb_control_area { - u16 intercept_cr_read; - u16 intercept_cr_write; - u16 intercept_dr_read; - u16 intercept_dr_write; - u32 intercept_exceptions; - u64 intercept; - u8 reserved_1[44]; - u64 iopm_base_pa; - u64 msrpm_base_pa; - u64 tsc_offset; - u32 asid; - u8 tlb_ctl; - u8 reserved_2[3]; - u32 int_ctl; - u32 int_vector; - u32 int_state; - u8 reserved_3[4]; - u32 exit_code; - u32 exit_code_hi; - u64 exit_info_1; - u64 exit_info_2; - u32 exit_int_info; - u32 exit_int_info_err; - u64 nested_ctl; - u8 reserved_4[16]; - u32 event_inj; - u32 event_inj_err; - u64 nested_cr3; - u64 lbr_ctl; - u8 reserved_5[832]; -}; - - -#define TLB_CONTROL_DO_NOTHING 0 -#define TLB_CONTROL_FLUSH_ALL_ASID 1 - -#define V_TPR_MASK 0x0f - -#define V_IRQ_SHIFT 8 -#define V_IRQ_MASK (1 << V_IRQ_SHIFT) - -#define V_INTR_PRIO_SHIFT 16 -#define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT) - -#define V_IGN_TPR_SHIFT 20 -#define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT) - -#define V_INTR_MASKING_SHIFT 24 -#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT) - -#define SVM_INTERRUPT_SHADOW_MASK 1 - -#define SVM_IOIO_STR_SHIFT 2 -#define SVM_IOIO_REP_SHIFT 3 -#define SVM_IOIO_SIZE_SHIFT 4 -#define SVM_IOIO_ASIZE_SHIFT 7 - -#define SVM_IOIO_TYPE_MASK 1 -#define SVM_IOIO_STR_MASK (1 << SVM_IOIO_STR_SHIFT) -#define SVM_IOIO_REP_MASK (1 << SVM_IOIO_REP_SHIFT) -#define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT) -#define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT) - -struct __attribute__ ((__packed__)) vmcb_seg { - u16 selector; - u16 attrib; - u32 limit; - u64 base; -}; - -struct __attribute__ ((__packed__)) vmcb_save_area { - struct vmcb_seg es; - struct vmcb_seg cs; - struct vmcb_seg ss; - struct vmcb_seg ds; - struct vmcb_seg fs; - struct vmcb_seg gs; - struct vmcb_seg gdtr; - struct vmcb_seg ldtr; - struct vmcb_seg idtr; - struct vmcb_seg tr; - u8 reserved_1[43]; - u8 cpl; - u8 reserved_2[4]; - u64 efer; - u8 reserved_3[112]; - u64 cr4; - u64 cr3; - u64 cr0; - u64 dr7; - u64 dr6; - u64 rflags; - u64 rip; - u8 reserved_4[88]; - u64 rsp; - u8 reserved_5[24]; - u64 rax; - u64 star; - u64 lstar; - u64 cstar; - u64 sfmask; - u64 kernel_gs_base; - u64 sysenter_cs; - u64 sysenter_esp; - u64 sysenter_eip; - u64 cr2; - u8 reserved_6[32]; - u64 g_pat; - u64 dbgctl; - u64 br_from; - u64 br_to; - u64 last_excp_from; - u64 last_excp_to; -}; - -struct __attribute__ ((__packed__)) vmcb { - struct vmcb_control_area control; - struct vmcb_save_area save; -}; - -#define SVM_CPUID_FEATURE_SHIFT 2 -#define SVM_CPUID_FUNC 0x8000000a - -#define MSR_EFER_SVME_MASK (1ULL << 12) -#define MSR_VM_HSAVE_PA 0xc0010117ULL - -#define SVM_SELECTOR_S_SHIFT 4 -#define SVM_SELECTOR_DPL_SHIFT 5 -#define SVM_SELECTOR_P_SHIFT 7 -#define SVM_SELECTOR_AVL_SHIFT 8 -#define SVM_SELECTOR_L_SHIFT 9 -#define SVM_SELECTOR_DB_SHIFT 10 -#define SVM_SELECTOR_G_SHIFT 11 - -#define SVM_SELECTOR_TYPE_MASK (0xf) -#define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT) -#define SVM_SELECTOR_DPL_MASK (3 << SVM_SELECTOR_DPL_SHIFT) -#define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT) -#define SVM_SELECTOR_AVL_MASK (1 << SVM_SELECTOR_AVL_SHIFT) -#define SVM_SELECTOR_L_MASK (1 << SVM_SELECTOR_L_SHIFT) -#define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT) -#define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT) - -#define SVM_SELECTOR_WRITE_MASK (1 << 1) -#define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK -#define SVM_SELECTOR_CODE_MASK (1 << 3) - -#define INTERCEPT_CR0_MASK 1 -#define INTERCEPT_CR3_MASK (1 << 3) -#define INTERCEPT_CR4_MASK (1 << 4) - -#define INTERCEPT_DR0_MASK 1 -#define INTERCEPT_DR1_MASK (1 << 1) -#define INTERCEPT_DR2_MASK (1 << 2) -#define INTERCEPT_DR3_MASK (1 << 3) -#define INTERCEPT_DR4_MASK (1 << 4) -#define INTERCEPT_DR5_MASK (1 << 5) -#define INTERCEPT_DR6_MASK (1 << 6) -#define INTERCEPT_DR7_MASK (1 << 7) - -#define SVM_EVTINJ_VEC_MASK 0xff - -#define SVM_EVTINJ_TYPE_SHIFT 8 -#define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT) - -#define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT) -#define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT) -#define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT) -#define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT) - -#define SVM_EVTINJ_VALID (1 << 31) -#define SVM_EVTINJ_VALID_ERR (1 << 11) - -#define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK - -#define SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR -#define SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI -#define SVM_EXITINTINFO_TYPE_EXEPT SVM_EVTINJ_TYPE_EXEPT -#define SVM_EXITINTINFO_TYPE_SOFT SVM_EVTINJ_TYPE_SOFT - -#define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID -#define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR - -#define SVM_EXIT_READ_CR0 0x000 -#define SVM_EXIT_READ_CR3 0x003 -#define SVM_EXIT_READ_CR4 0x004 -#define SVM_EXIT_READ_CR8 0x008 -#define SVM_EXIT_WRITE_CR0 0x010 -#define SVM_EXIT_WRITE_CR3 0x013 -#define SVM_EXIT_WRITE_CR4 0x014 -#define SVM_EXIT_WRITE_CR8 0x018 -#define SVM_EXIT_READ_DR0 0x020 -#define SVM_EXIT_READ_DR1 0x021 -#define SVM_EXIT_READ_DR2 0x022 -#define SVM_EXIT_READ_DR3 0x023 -#define SVM_EXIT_READ_DR4 0x024 -#define SVM_EXIT_READ_DR5 0x025 -#define SVM_EXIT_READ_DR6 0x026 -#define SVM_EXIT_READ_DR7 0x027 -#define SVM_EXIT_WRITE_DR0 0x030 -#define SVM_EXIT_WRITE_DR1 0x031 -#define SVM_EXIT_WRITE_DR2 0x032 -#define SVM_EXIT_WRITE_DR3 0x033 -#define SVM_EXIT_WRITE_DR4 0x034 -#define SVM_EXIT_WRITE_DR5 0x035 -#define SVM_EXIT_WRITE_DR6 0x036 -#define SVM_EXIT_WRITE_DR7 0x037 -#define SVM_EXIT_EXCP_BASE 0x040 -#define SVM_EXIT_INTR 0x060 -#define SVM_EXIT_NMI 0x061 -#define SVM_EXIT_SMI 0x062 -#define SVM_EXIT_INIT 0x063 -#define SVM_EXIT_VINTR 0x064 -#define SVM_EXIT_CR0_SEL_WRITE 0x065 -#define SVM_EXIT_IDTR_READ 0x066 -#define SVM_EXIT_GDTR_READ 0x067 -#define SVM_EXIT_LDTR_READ 0x068 -#define SVM_EXIT_TR_READ 0x069 -#define SVM_EXIT_IDTR_WRITE 0x06a -#define SVM_EXIT_GDTR_WRITE 0x06b -#define SVM_EXIT_LDTR_WRITE 0x06c -#define SVM_EXIT_TR_WRITE 0x06d -#define SVM_EXIT_RDTSC 0x06e -#define SVM_EXIT_RDPMC 0x06f -#define SVM_EXIT_PUSHF 0x070 -#define SVM_EXIT_POPF 0x071 -#define SVM_EXIT_CPUID 0x072 -#define SVM_EXIT_RSM 0x073 -#define SVM_EXIT_IRET 0x074 -#define SVM_EXIT_SWINT 0x075 -#define SVM_EXIT_INVD 0x076 -#define SVM_EXIT_PAUSE 0x077 -#define SVM_EXIT_HLT 0x078 -#define SVM_EXIT_INVLPG 0x079 -#define SVM_EXIT_INVLPGA 0x07a -#define SVM_EXIT_IOIO 0x07b -#define SVM_EXIT_MSR 0x07c -#define SVM_EXIT_TASK_SWITCH 0x07d -#define SVM_EXIT_FERR_FREEZE 0x07e -#define SVM_EXIT_SHUTDOWN 0x07f -#define SVM_EXIT_VMRUN 0x080 -#define SVM_EXIT_VMMCALL 0x081 -#define SVM_EXIT_VMLOAD 0x082 -#define SVM_EXIT_VMSAVE 0x083 -#define SVM_EXIT_STGI 0x084 -#define SVM_EXIT_CLGI 0x085 -#define SVM_EXIT_SKINIT 0x086 -#define SVM_EXIT_RDTSCP 0x087 -#define SVM_EXIT_ICEBP 0x088 -#define SVM_EXIT_WBINVD 0x089 -#define SVM_EXIT_NPF 0x400 - -#define SVM_EXIT_ERR -1 - -#define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) // TS and MP - -#define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda" -#define SVM_VMRUN ".byte 0x0f, 0x01, 0xd8" -#define SVM_VMSAVE ".byte 0x0f, 0x01, 0xdb" -#define SVM_CLGI ".byte 0x0f, 0x01, 0xdd" -#define SVM_STGI ".byte 0x0f, 0x01, 0xdc" -#define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf" - -#endif - diff --git a/trunk/drivers/kvm/vmx.c b/trunk/drivers/kvm/vmx.c deleted file mode 100644 index f0f0b1a781f8..000000000000 --- a/trunk/drivers/kvm/vmx.c +++ /dev/null @@ -1,2014 +0,0 @@ -/* - * Kernel-based Virtual Machine driver for Linux - * - * This module enables machines with Intel VT-x extensions to run virtual - * machines without emulation or binary translation. - * - * Copyright (C) 2006 Qumranet, Inc. - * - * Authors: - * Avi Kivity - * Yaniv Kamay - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#include "kvm.h" -#include "vmx.h" -#include "kvm_vmx.h" -#include -#include -#include -#include -#include - -#include "segment_descriptor.h" - -#define MSR_IA32_FEATURE_CONTROL 0x03a - -MODULE_AUTHOR("Qumranet"); -MODULE_LICENSE("GPL"); - -static DEFINE_PER_CPU(struct vmcs *, vmxarea); -static DEFINE_PER_CPU(struct vmcs *, current_vmcs); - -#ifdef CONFIG_X86_64 -#define HOST_IS_64 1 -#else -#define HOST_IS_64 0 -#endif - -static struct vmcs_descriptor { - int size; - int order; - u32 revision_id; -} vmcs_descriptor; - -#define VMX_SEGMENT_FIELD(seg) \ - [VCPU_SREG_##seg] = { \ - .selector = GUEST_##seg##_SELECTOR, \ - .base = GUEST_##seg##_BASE, \ - .limit = GUEST_##seg##_LIMIT, \ - .ar_bytes = GUEST_##seg##_AR_BYTES, \ - } - -static struct kvm_vmx_segment_field { - unsigned selector; - unsigned base; - unsigned limit; - unsigned ar_bytes; -} kvm_vmx_segment_fields[] = { - VMX_SEGMENT_FIELD(CS), - VMX_SEGMENT_FIELD(DS), - VMX_SEGMENT_FIELD(ES), - VMX_SEGMENT_FIELD(FS), - VMX_SEGMENT_FIELD(GS), - VMX_SEGMENT_FIELD(SS), - VMX_SEGMENT_FIELD(TR), - VMX_SEGMENT_FIELD(LDTR), -}; - -static const u32 vmx_msr_index[] = { -#ifdef CONFIG_X86_64 - MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE, -#endif - MSR_EFER, MSR_K6_STAR, -}; -#define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index)) - -static inline int is_page_fault(u32 intr_info) -{ - return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | - INTR_INFO_VALID_MASK)) == - (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK); -} - -static inline int is_external_interrupt(u32 intr_info) -{ - return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) - == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); -} - -static struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr) -{ - int i; - - for (i = 0; i < vcpu->nmsrs; ++i) - if (vcpu->guest_msrs[i].index == msr) - return &vcpu->guest_msrs[i]; - return 0; -} - -static void vmcs_clear(struct vmcs *vmcs) -{ - u64 phys_addr = __pa(vmcs); - u8 error; - - asm volatile (ASM_VMX_VMCLEAR_RAX "; setna %0" - : "=g"(error) : "a"(&phys_addr), "m"(phys_addr) - : "cc", "memory"); - if (error) - printk(KERN_ERR "kvm: vmclear fail: %p/%llx\n", - vmcs, phys_addr); -} - -static void __vcpu_clear(void *arg) -{ - struct kvm_vcpu *vcpu = arg; - int cpu = smp_processor_id(); - - if (vcpu->cpu == cpu) - vmcs_clear(vcpu->vmcs); - if (per_cpu(current_vmcs, cpu) == vcpu->vmcs) - per_cpu(current_vmcs, cpu) = NULL; -} - -static unsigned long vmcs_readl(unsigned long field) -{ - unsigned long value; - - asm volatile (ASM_VMX_VMREAD_RDX_RAX - : "=a"(value) : "d"(field) : "cc"); - return value; -} - -static u16 vmcs_read16(unsigned long field) -{ - return vmcs_readl(field); -} - -static u32 vmcs_read32(unsigned long field) -{ - return vmcs_readl(field); -} - -static u64 vmcs_read64(unsigned long field) -{ -#ifdef CONFIG_X86_64 - return vmcs_readl(field); -#else - return vmcs_readl(field) | ((u64)vmcs_readl(field+1) << 32); -#endif -} - -static void vmcs_writel(unsigned long field, unsigned long value) -{ - u8 error; - - asm volatile (ASM_VMX_VMWRITE_RAX_RDX "; setna %0" - : "=q"(error) : "a"(value), "d"(field) : "cc" ); - if (error) - printk(KERN_ERR "vmwrite error: reg %lx value %lx (err %d)\n", - field, value, vmcs_read32(VM_INSTRUCTION_ERROR)); -} - -static void vmcs_write16(unsigned long field, u16 value) -{ - vmcs_writel(field, value); -} - -static void vmcs_write32(unsigned long field, u32 value) -{ - vmcs_writel(field, value); -} - -static void vmcs_write64(unsigned long field, u64 value) -{ -#ifdef CONFIG_X86_64 - vmcs_writel(field, value); -#else - vmcs_writel(field, value); - asm volatile (""); - vmcs_writel(field+1, value >> 32); -#endif -} - -/* - * Switches to specified vcpu, until a matching vcpu_put(), but assumes - * vcpu mutex is already taken. - */ -static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu) -{ - u64 phys_addr = __pa(vcpu->vmcs); - int cpu; - - cpu = get_cpu(); - - if (vcpu->cpu != cpu) { - smp_call_function(__vcpu_clear, vcpu, 0, 1); - vcpu->launched = 0; - } - - if (per_cpu(current_vmcs, cpu) != vcpu->vmcs) { - u8 error; - - per_cpu(current_vmcs, cpu) = vcpu->vmcs; - asm volatile (ASM_VMX_VMPTRLD_RAX "; setna %0" - : "=g"(error) : "a"(&phys_addr), "m"(phys_addr) - : "cc"); - if (error) - printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n", - vcpu->vmcs, phys_addr); - } - - if (vcpu->cpu != cpu) { - struct descriptor_table dt; - unsigned long sysenter_esp; - - vcpu->cpu = cpu; - /* - * Linux uses per-cpu TSS and GDT, so set these when switching - * processors. - */ - vmcs_writel(HOST_TR_BASE, read_tr_base()); /* 22.2.4 */ - get_gdt(&dt); - vmcs_writel(HOST_GDTR_BASE, dt.base); /* 22.2.4 */ - - rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp); - vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */ - } - return vcpu; -} - -static void vmx_vcpu_put(struct kvm_vcpu *vcpu) -{ - put_cpu(); -} - -static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu) -{ - return vmcs_readl(GUEST_RFLAGS); -} - -static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) -{ - vmcs_writel(GUEST_RFLAGS, rflags); -} - -static void skip_emulated_instruction(struct kvm_vcpu *vcpu) -{ - unsigned long rip; - u32 interruptibility; - - rip = vmcs_readl(GUEST_RIP); - rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN); - vmcs_writel(GUEST_RIP, rip); - - /* - * We emulated an instruction, so temporary interrupt blocking - * should be removed, if set. - */ - interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO); - if (interruptibility & 3) - vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, - interruptibility & ~3); -} - -static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code) -{ - printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n", - vmcs_readl(GUEST_RIP)); - vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, - GP_VECTOR | - INTR_TYPE_EXCEPTION | - INTR_INFO_DELIEVER_CODE_MASK | - INTR_INFO_VALID_MASK); -} - -/* - * reads and returns guest's timestamp counter "register" - * guest_tsc = host_tsc + tsc_offset -- 21.3 - */ -static u64 guest_read_tsc(void) -{ - u64 host_tsc, tsc_offset; - - rdtscll(host_tsc); - tsc_offset = vmcs_read64(TSC_OFFSET); - return host_tsc + tsc_offset; -} - -/* - * writes 'guest_tsc' into guest's timestamp counter "register" - * guest_tsc = host_tsc + tsc_offset ==> tsc_offset = guest_tsc - host_tsc - */ -static void guest_write_tsc(u64 guest_tsc) -{ - u64 host_tsc; - - rdtscll(host_tsc); - vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc); -} - -static void reload_tss(void) -{ -#ifndef CONFIG_X86_64 - - /* - * VT restores TR but not its size. Useless. - */ - struct descriptor_table gdt; - struct segment_descriptor *descs; - - get_gdt(&gdt); - descs = (void *)gdt.base; - descs[GDT_ENTRY_TSS].type = 9; /* available TSS */ - load_TR_desc(); -#endif -} - -/* - * Reads an msr value (of 'msr_index') into 'pdata'. - * Returns 0 on success, non-0 otherwise. - * Assumes vcpu_load() was already called. - */ -static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) -{ - u64 data; - struct vmx_msr_entry *msr; - - if (!pdata) { - printk(KERN_ERR "BUG: get_msr called with NULL pdata\n"); - return -EINVAL; - } - - switch (msr_index) { -#ifdef CONFIG_X86_64 - case MSR_FS_BASE: - data = vmcs_readl(GUEST_FS_BASE); - break; - case MSR_GS_BASE: - data = vmcs_readl(GUEST_GS_BASE); - break; - case MSR_EFER: - data = vcpu->shadow_efer; - break; -#endif - case MSR_IA32_TIME_STAMP_COUNTER: - data = guest_read_tsc(); - break; - case MSR_IA32_SYSENTER_CS: - data = vmcs_read32(GUEST_SYSENTER_CS); - break; - case MSR_IA32_SYSENTER_EIP: - data = vmcs_read32(GUEST_SYSENTER_EIP); - break; - case MSR_IA32_SYSENTER_ESP: - data = vmcs_read32(GUEST_SYSENTER_ESP); - break; - case MSR_IA32_MC0_CTL: - case MSR_IA32_MCG_STATUS: - case MSR_IA32_MCG_CAP: - case MSR_IA32_MC0_MISC: - case MSR_IA32_MC0_MISC+4: - case MSR_IA32_MC0_MISC+8: - case MSR_IA32_MC0_MISC+12: - case MSR_IA32_MC0_MISC+16: - case MSR_IA32_UCODE_REV: - /* MTRR registers */ - case 0xfe: - case 0x200 ... 0x2ff: - data = 0; - break; - case MSR_IA32_APICBASE: - data = vcpu->apic_base; - break; - default: - msr = find_msr_entry(vcpu, msr_index); - if (!msr) { - printk(KERN_ERR "kvm: unhandled rdmsr: %x\n", msr_index); - return 1; - } - data = msr->data; - break; - } - - *pdata = data; - return 0; -} - -/* - * Writes msr value into into the appropriate "register". - * Returns 0 on success, non-0 otherwise. - * Assumes vcpu_load() was already called. - */ -static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) -{ - struct vmx_msr_entry *msr; - switch (msr_index) { -#ifdef CONFIG_X86_64 - case MSR_FS_BASE: - vmcs_writel(GUEST_FS_BASE, data); - break; - case MSR_GS_BASE: - vmcs_writel(GUEST_GS_BASE, data); - break; -#endif - case MSR_IA32_SYSENTER_CS: - vmcs_write32(GUEST_SYSENTER_CS, data); - break; - case MSR_IA32_SYSENTER_EIP: - vmcs_write32(GUEST_SYSENTER_EIP, data); - break; - case MSR_IA32_SYSENTER_ESP: - vmcs_write32(GUEST_SYSENTER_ESP, data); - break; -#ifdef __x86_64 - case MSR_EFER: - set_efer(vcpu, data); - break; - case MSR_IA32_MC0_STATUS: - printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n" - , __FUNCTION__, data); - break; -#endif - case MSR_IA32_TIME_STAMP_COUNTER: { - guest_write_tsc(data); - break; - } - case MSR_IA32_UCODE_REV: - case MSR_IA32_UCODE_WRITE: - case 0x200 ... 0x2ff: /* MTRRs */ - break; - case MSR_IA32_APICBASE: - vcpu->apic_base = data; - break; - default: - msr = find_msr_entry(vcpu, msr_index); - if (!msr) { - printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr_index); - return 1; - } - msr->data = data; - break; - } - - return 0; -} - -/* - * Sync the rsp and rip registers into the vcpu structure. This allows - * registers to be accessed by indexing vcpu->regs. - */ -static void vcpu_load_rsp_rip(struct kvm_vcpu *vcpu) -{ - vcpu->regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP); - vcpu->rip = vmcs_readl(GUEST_RIP); -} - -/* - * Syncs rsp and rip back into the vmcs. Should be called after possible - * modification. - */ -static void vcpu_put_rsp_rip(struct kvm_vcpu *vcpu) -{ - vmcs_writel(GUEST_RSP, vcpu->regs[VCPU_REGS_RSP]); - vmcs_writel(GUEST_RIP, vcpu->rip); -} - -static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) -{ - unsigned long dr7 = 0x400; - u32 exception_bitmap; - int old_singlestep; - - exception_bitmap = vmcs_read32(EXCEPTION_BITMAP); - old_singlestep = vcpu->guest_debug.singlestep; - - vcpu->guest_debug.enabled = dbg->enabled; - if (vcpu->guest_debug.enabled) { - int i; - - dr7 |= 0x200; /* exact */ - for (i = 0; i < 4; ++i) { - if (!dbg->breakpoints[i].enabled) - continue; - vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address; - dr7 |= 2 << (i*2); /* global enable */ - dr7 |= 0 << (i*4+16); /* execution breakpoint */ - } - - exception_bitmap |= (1u << 1); /* Trap debug exceptions */ - - vcpu->guest_debug.singlestep = dbg->singlestep; - } else { - exception_bitmap &= ~(1u << 1); /* Ignore debug exceptions */ - vcpu->guest_debug.singlestep = 0; - } - - if (old_singlestep && !vcpu->guest_debug.singlestep) { - unsigned long flags; - - flags = vmcs_readl(GUEST_RFLAGS); - flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); - vmcs_writel(GUEST_RFLAGS, flags); - } - - vmcs_write32(EXCEPTION_BITMAP, exception_bitmap); - vmcs_writel(GUEST_DR7, dr7); - - return 0; -} - -static __init int cpu_has_kvm_support(void) -{ - unsigned long ecx = cpuid_ecx(1); - return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */ -} - -static __init int vmx_disabled_by_bios(void) -{ - u64 msr; - - rdmsrl(MSR_IA32_FEATURE_CONTROL, msr); - return (msr & 5) == 1; /* locked but not enabled */ -} - -static __init void hardware_enable(void *garbage) -{ - int cpu = raw_smp_processor_id(); - u64 phys_addr = __pa(per_cpu(vmxarea, cpu)); - u64 old; - - rdmsrl(MSR_IA32_FEATURE_CONTROL, old); - if ((old & 5) != 5) - /* enable and lock */ - wrmsrl(MSR_IA32_FEATURE_CONTROL, old | 5); - write_cr4(read_cr4() | CR4_VMXE); /* FIXME: not cpu hotplug safe */ - asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr), "m"(phys_addr) - : "memory", "cc"); -} - -static void hardware_disable(void *garbage) -{ - asm volatile (ASM_VMX_VMXOFF : : : "cc"); -} - -static __init void setup_vmcs_descriptor(void) -{ - u32 vmx_msr_low, vmx_msr_high; - - rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); - vmcs_descriptor.size = vmx_msr_high & 0x1fff; - vmcs_descriptor.order = get_order(vmcs_descriptor.size); - vmcs_descriptor.revision_id = vmx_msr_low; -}; - -static struct vmcs *alloc_vmcs_cpu(int cpu) -{ - int node = cpu_to_node(cpu); - struct page *pages; - struct vmcs *vmcs; - - pages = alloc_pages_node(node, GFP_KERNEL, vmcs_descriptor.order); - if (!pages) - return NULL; - vmcs = page_address(pages); - memset(vmcs, 0, vmcs_descriptor.size); - vmcs->revision_id = vmcs_descriptor.revision_id; /* vmcs revision id */ - return vmcs; -} - -static struct vmcs *alloc_vmcs(void) -{ - return alloc_vmcs_cpu(smp_processor_id()); -} - -static void free_vmcs(struct vmcs *vmcs) -{ - free_pages((unsigned long)vmcs, vmcs_descriptor.order); -} - -static __exit void free_kvm_area(void) -{ - int cpu; - - for_each_online_cpu(cpu) - free_vmcs(per_cpu(vmxarea, cpu)); -} - -extern struct vmcs *alloc_vmcs_cpu(int cpu); - -static __init int alloc_kvm_area(void) -{ - int cpu; - - for_each_online_cpu(cpu) { - struct vmcs *vmcs; - - vmcs = alloc_vmcs_cpu(cpu); - if (!vmcs) { - free_kvm_area(); - return -ENOMEM; - } - - per_cpu(vmxarea, cpu) = vmcs; - } - return 0; -} - -static __init int hardware_setup(void) -{ - setup_vmcs_descriptor(); - return alloc_kvm_area(); -} - -static __exit void hardware_unsetup(void) -{ - free_kvm_area(); -} - -static void update_exception_bitmap(struct kvm_vcpu *vcpu) -{ - if (vcpu->rmode.active) - vmcs_write32(EXCEPTION_BITMAP, ~0); - else - vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR); -} - -static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save) -{ - struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; - - if (vmcs_readl(sf->base) == save->base) { - vmcs_write16(sf->selector, save->selector); - vmcs_writel(sf->base, save->base); - vmcs_write32(sf->limit, save->limit); - vmcs_write32(sf->ar_bytes, save->ar); - } else { - u32 dpl = (vmcs_read16(sf->selector) & SELECTOR_RPL_MASK) - << AR_DPL_SHIFT; - vmcs_write32(sf->ar_bytes, 0x93 | dpl); - } -} - -static void enter_pmode(struct kvm_vcpu *vcpu) -{ - unsigned long flags; - - vcpu->rmode.active = 0; - - vmcs_writel(GUEST_TR_BASE, vcpu->rmode.tr.base); - vmcs_write32(GUEST_TR_LIMIT, vcpu->rmode.tr.limit); - vmcs_write32(GUEST_TR_AR_BYTES, vcpu->rmode.tr.ar); - - flags = vmcs_readl(GUEST_RFLAGS); - flags &= ~(IOPL_MASK | X86_EFLAGS_VM); - flags |= (vcpu->rmode.save_iopl << IOPL_SHIFT); - vmcs_writel(GUEST_RFLAGS, flags); - - vmcs_writel(GUEST_CR4, (vmcs_readl(GUEST_CR4) & ~CR4_VME_MASK) | - (vmcs_readl(CR4_READ_SHADOW) & CR4_VME_MASK)); - - update_exception_bitmap(vcpu); - - fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->rmode.es); - fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->rmode.ds); - fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->rmode.gs); - fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->rmode.fs); - - vmcs_write16(GUEST_SS_SELECTOR, 0); - vmcs_write32(GUEST_SS_AR_BYTES, 0x93); - - vmcs_write16(GUEST_CS_SELECTOR, - vmcs_read16(GUEST_CS_SELECTOR) & ~SELECTOR_RPL_MASK); - vmcs_write32(GUEST_CS_AR_BYTES, 0x9b); -} - -static int rmode_tss_base(struct kvm* kvm) -{ - gfn_t base_gfn = kvm->memslots[0].base_gfn + kvm->memslots[0].npages - 3; - return base_gfn << PAGE_SHIFT; -} - -static void fix_rmode_seg(int seg, struct kvm_save_segment *save) -{ - struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; - - save->selector = vmcs_read16(sf->selector); - save->base = vmcs_readl(sf->base); - save->limit = vmcs_read32(sf->limit); - save->ar = vmcs_read32(sf->ar_bytes); - vmcs_write16(sf->selector, vmcs_readl(sf->base) >> 4); - vmcs_write32(sf->limit, 0xffff); - vmcs_write32(sf->ar_bytes, 0xf3); -} - -static void enter_rmode(struct kvm_vcpu *vcpu) -{ - unsigned long flags; - - vcpu->rmode.active = 1; - - vcpu->rmode.tr.base = vmcs_readl(GUEST_TR_BASE); - vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm)); - - vcpu->rmode.tr.limit = vmcs_read32(GUEST_TR_LIMIT); - vmcs_write32(GUEST_TR_LIMIT, RMODE_TSS_SIZE - 1); - - vcpu->rmode.tr.ar = vmcs_read32(GUEST_TR_AR_BYTES); - vmcs_write32(GUEST_TR_AR_BYTES, 0x008b); - - flags = vmcs_readl(GUEST_RFLAGS); - vcpu->rmode.save_iopl = (flags & IOPL_MASK) >> IOPL_SHIFT; - - flags |= IOPL_MASK | X86_EFLAGS_VM; - - vmcs_writel(GUEST_RFLAGS, flags); - vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | CR4_VME_MASK); - update_exception_bitmap(vcpu); - - vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4); - vmcs_write32(GUEST_SS_LIMIT, 0xffff); - vmcs_write32(GUEST_SS_AR_BYTES, 0xf3); - - vmcs_write32(GUEST_CS_AR_BYTES, 0xf3); - vmcs_write16(GUEST_CS_SELECTOR, vmcs_readl(GUEST_CS_BASE) >> 4); - - fix_rmode_seg(VCPU_SREG_ES, &vcpu->rmode.es); - fix_rmode_seg(VCPU_SREG_DS, &vcpu->rmode.ds); - fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs); - fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs); -} - -#ifdef CONFIG_X86_64 - -static void enter_lmode(struct kvm_vcpu *vcpu) -{ - u32 guest_tr_ar; - - guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES); - if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) { - printk(KERN_DEBUG "%s: tss fixup for long mode. \n", - __FUNCTION__); - vmcs_write32(GUEST_TR_AR_BYTES, - (guest_tr_ar & ~AR_TYPE_MASK) - | AR_TYPE_BUSY_64_TSS); - } - - vcpu->shadow_efer |= EFER_LMA; - - find_msr_entry(vcpu, MSR_EFER)->data |= EFER_LMA | EFER_LME; - vmcs_write32(VM_ENTRY_CONTROLS, - vmcs_read32(VM_ENTRY_CONTROLS) - | VM_ENTRY_CONTROLS_IA32E_MASK); -} - -static void exit_lmode(struct kvm_vcpu *vcpu) -{ - vcpu->shadow_efer &= ~EFER_LMA; - - vmcs_write32(VM_ENTRY_CONTROLS, - vmcs_read32(VM_ENTRY_CONTROLS) - & ~VM_ENTRY_CONTROLS_IA32E_MASK); -} - -#endif - -static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) -{ - if (vcpu->rmode.active && (cr0 & CR0_PE_MASK)) - enter_pmode(vcpu); - - if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK)) - enter_rmode(vcpu); - -#ifdef CONFIG_X86_64 - if (vcpu->shadow_efer & EFER_LME) { - if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) - enter_lmode(vcpu); - if (is_paging(vcpu) && !(cr0 & CR0_PG_MASK)) - exit_lmode(vcpu); - } -#endif - - vmcs_writel(CR0_READ_SHADOW, cr0); - vmcs_writel(GUEST_CR0, - (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON); - vcpu->cr0 = cr0; -} - -/* - * Used when restoring the VM to avoid corrupting segment registers - */ -static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0) -{ - vcpu->rmode.active = ((cr0 & CR0_PE_MASK) == 0); - update_exception_bitmap(vcpu); - vmcs_writel(CR0_READ_SHADOW, cr0); - vmcs_writel(GUEST_CR0, - (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON); - vcpu->cr0 = cr0; -} - -static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) -{ - vmcs_writel(GUEST_CR3, cr3); -} - -static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) -{ - vmcs_writel(CR4_READ_SHADOW, cr4); - vmcs_writel(GUEST_CR4, cr4 | (vcpu->rmode.active ? - KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON)); - vcpu->cr4 = cr4; -} - -#ifdef CONFIG_X86_64 - -static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer) -{ - struct vmx_msr_entry *msr = find_msr_entry(vcpu, MSR_EFER); - - vcpu->shadow_efer = efer; - if (efer & EFER_LMA) { - vmcs_write32(VM_ENTRY_CONTROLS, - vmcs_read32(VM_ENTRY_CONTROLS) | - VM_ENTRY_CONTROLS_IA32E_MASK); - msr->data = efer; - - } else { - vmcs_write32(VM_ENTRY_CONTROLS, - vmcs_read32(VM_ENTRY_CONTROLS) & - ~VM_ENTRY_CONTROLS_IA32E_MASK); - - msr->data = efer & ~EFER_LME; - } -} - -#endif - -static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg) -{ - struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; - - return vmcs_readl(sf->base); -} - -static void vmx_get_segment(struct kvm_vcpu *vcpu, - struct kvm_segment *var, int seg) -{ - struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; - u32 ar; - - var->base = vmcs_readl(sf->base); - var->limit = vmcs_read32(sf->limit); - var->selector = vmcs_read16(sf->selector); - ar = vmcs_read32(sf->ar_bytes); - if (ar & AR_UNUSABLE_MASK) - ar = 0; - var->type = ar & 15; - var->s = (ar >> 4) & 1; - var->dpl = (ar >> 5) & 3; - var->present = (ar >> 7) & 1; - var->avl = (ar >> 12) & 1; - var->l = (ar >> 13) & 1; - var->db = (ar >> 14) & 1; - var->g = (ar >> 15) & 1; - var->unusable = (ar >> 16) & 1; -} - -static void vmx_set_segment(struct kvm_vcpu *vcpu, - struct kvm_segment *var, int seg) -{ - struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; - u32 ar; - - vmcs_writel(sf->base, var->base); - vmcs_write32(sf->limit, var->limit); - vmcs_write16(sf->selector, var->selector); - if (var->unusable) - ar = 1 << 16; - else { - ar = var->type & 15; - ar |= (var->s & 1) << 4; - ar |= (var->dpl & 3) << 5; - ar |= (var->present & 1) << 7; - ar |= (var->avl & 1) << 12; - ar |= (var->l & 1) << 13; - ar |= (var->db & 1) << 14; - ar |= (var->g & 1) << 15; - } - if (ar == 0) /* a 0 value means unusable */ - ar = AR_UNUSABLE_MASK; - vmcs_write32(sf->ar_bytes, ar); -} - -static int vmx_is_long_mode(struct kvm_vcpu *vcpu) -{ - return vmcs_read32(VM_ENTRY_CONTROLS) & VM_ENTRY_CONTROLS_IA32E_MASK; -} - -static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) -{ - u32 ar = vmcs_read32(GUEST_CS_AR_BYTES); - - *db = (ar >> 14) & 1; - *l = (ar >> 13) & 1; -} - -static void vmx_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) -{ - dt->limit = vmcs_read32(GUEST_IDTR_LIMIT); - dt->base = vmcs_readl(GUEST_IDTR_BASE); -} - -static void vmx_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) -{ - vmcs_write32(GUEST_IDTR_LIMIT, dt->limit); - vmcs_writel(GUEST_IDTR_BASE, dt->base); -} - -static void vmx_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) -{ - dt->limit = vmcs_read32(GUEST_GDTR_LIMIT); - dt->base = vmcs_readl(GUEST_GDTR_BASE); -} - -static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) -{ - vmcs_write32(GUEST_GDTR_LIMIT, dt->limit); - vmcs_writel(GUEST_GDTR_BASE, dt->base); -} - -static int init_rmode_tss(struct kvm* kvm) -{ - struct page *p1, *p2, *p3; - gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT; - char *page; - - p1 = _gfn_to_page(kvm, fn++); - p2 = _gfn_to_page(kvm, fn++); - p3 = _gfn_to_page(kvm, fn); - - if (!p1 || !p2 || !p3) { - kvm_printf(kvm,"%s: gfn_to_page failed\n", __FUNCTION__); - return 0; - } - - page = kmap_atomic(p1, KM_USER0); - memset(page, 0, PAGE_SIZE); - *(u16*)(page + 0x66) = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE; - kunmap_atomic(page, KM_USER0); - - page = kmap_atomic(p2, KM_USER0); - memset(page, 0, PAGE_SIZE); - kunmap_atomic(page, KM_USER0); - - page = kmap_atomic(p3, KM_USER0); - memset(page, 0, PAGE_SIZE); - *(page + RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1) = ~0; - kunmap_atomic(page, KM_USER0); - - return 1; -} - -static void vmcs_write32_fixedbits(u32 msr, u32 vmcs_field, u32 val) -{ - u32 msr_high, msr_low; - - rdmsr(msr, msr_low, msr_high); - - val &= msr_high; - val |= msr_low; - vmcs_write32(vmcs_field, val); -} - -static void seg_setup(int seg) -{ - struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; - - vmcs_write16(sf->selector, 0); - vmcs_writel(sf->base, 0); - vmcs_write32(sf->limit, 0xffff); - vmcs_write32(sf->ar_bytes, 0x93); -} - -/* - * Sets up the vmcs for emulated real mode. - */ -static int vmx_vcpu_setup(struct kvm_vcpu *vcpu) -{ - u32 host_sysenter_cs; - u32 junk; - unsigned long a; - struct descriptor_table dt; - int i; - int ret = 0; - int nr_good_msrs; - extern asmlinkage void kvm_vmx_return(void); - - if (!init_rmode_tss(vcpu->kvm)) { - ret = -ENOMEM; - goto out; - } - - memset(vcpu->regs, 0, sizeof(vcpu->regs)); - vcpu->regs[VCPU_REGS_RDX] = get_rdx_init_val(); - vcpu->cr8 = 0; - vcpu->apic_base = 0xfee00000 | - /*for vcpu 0*/ MSR_IA32_APICBASE_BSP | - MSR_IA32_APICBASE_ENABLE; - - fx_init(vcpu); - - /* - * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode - * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4. Sigh. - */ - vmcs_write16(GUEST_CS_SELECTOR, 0xf000); - vmcs_writel(GUEST_CS_BASE, 0x000f0000); - vmcs_write32(GUEST_CS_LIMIT, 0xffff); - vmcs_write32(GUEST_CS_AR_BYTES, 0x9b); - - seg_setup(VCPU_SREG_DS); - seg_setup(VCPU_SREG_ES); - seg_setup(VCPU_SREG_FS); - seg_setup(VCPU_SREG_GS); - seg_setup(VCPU_SREG_SS); - - vmcs_write16(GUEST_TR_SELECTOR, 0); - vmcs_writel(GUEST_TR_BASE, 0); - vmcs_write32(GUEST_TR_LIMIT, 0xffff); - vmcs_write32(GUEST_TR_AR_BYTES, 0x008b); - - vmcs_write16(GUEST_LDTR_SELECTOR, 0); - vmcs_writel(GUEST_LDTR_BASE, 0); - vmcs_write32(GUEST_LDTR_LIMIT, 0xffff); - vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082); - - vmcs_write32(GUEST_SYSENTER_CS, 0); - vmcs_writel(GUEST_SYSENTER_ESP, 0); - vmcs_writel(GUEST_SYSENTER_EIP, 0); - - vmcs_writel(GUEST_RFLAGS, 0x02); - vmcs_writel(GUEST_RIP, 0xfff0); - vmcs_writel(GUEST_RSP, 0); - - vmcs_writel(GUEST_CR3, 0); - - //todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0 - vmcs_writel(GUEST_DR7, 0x400); - - vmcs_writel(GUEST_GDTR_BASE, 0); - vmcs_write32(GUEST_GDTR_LIMIT, 0xffff); - - vmcs_writel(GUEST_IDTR_BASE, 0); - vmcs_write32(GUEST_IDTR_LIMIT, 0xffff); - - vmcs_write32(GUEST_ACTIVITY_STATE, 0); - vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0); - vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0); - - /* I/O */ - vmcs_write64(IO_BITMAP_A, 0); - vmcs_write64(IO_BITMAP_B, 0); - - guest_write_tsc(0); - - vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */ - - /* Special registers */ - vmcs_write64(GUEST_IA32_DEBUGCTL, 0); - - /* Control */ - vmcs_write32_fixedbits(MSR_IA32_VMX_PINBASED_CTLS_MSR, - PIN_BASED_VM_EXEC_CONTROL, - PIN_BASED_EXT_INTR_MASK /* 20.6.1 */ - | PIN_BASED_NMI_EXITING /* 20.6.1 */ - ); - vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS_MSR, - CPU_BASED_VM_EXEC_CONTROL, - CPU_BASED_HLT_EXITING /* 20.6.2 */ - | CPU_BASED_CR8_LOAD_EXITING /* 20.6.2 */ - | CPU_BASED_CR8_STORE_EXITING /* 20.6.2 */ - | CPU_BASED_UNCOND_IO_EXITING /* 20.6.2 */ - | CPU_BASED_INVDPG_EXITING - | CPU_BASED_MOV_DR_EXITING - | CPU_BASED_USE_TSC_OFFSETING /* 21.3 */ - ); - - vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR); - vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0); - vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0); - vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */ - - vmcs_writel(HOST_CR0, read_cr0()); /* 22.2.3 */ - vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */ - vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ - - vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ - vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ - vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */ - vmcs_write16(HOST_FS_SELECTOR, read_fs()); /* 22.2.4 */ - vmcs_write16(HOST_GS_SELECTOR, read_gs()); /* 22.2.4 */ - vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ -#ifdef CONFIG_X86_64 - rdmsrl(MSR_FS_BASE, a); - vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */ - rdmsrl(MSR_GS_BASE, a); - vmcs_writel(HOST_GS_BASE, a); /* 22.2.4 */ -#else - vmcs_writel(HOST_FS_BASE, 0); /* 22.2.4 */ - vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */ -#endif - - vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */ - - get_idt(&dt); - vmcs_writel(HOST_IDTR_BASE, dt.base); /* 22.2.4 */ - - - vmcs_writel(HOST_RIP, (unsigned long)kvm_vmx_return); /* 22.2.5 */ - - rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk); - vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs); - rdmsrl(MSR_IA32_SYSENTER_ESP, a); - vmcs_writel(HOST_IA32_SYSENTER_ESP, a); /* 22.2.3 */ - rdmsrl(MSR_IA32_SYSENTER_EIP, a); - vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */ - - ret = -ENOMEM; - vcpu->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!vcpu->guest_msrs) - goto out; - vcpu->host_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!vcpu->host_msrs) - goto out_free_guest_msrs; - - for (i = 0; i < NR_VMX_MSR; ++i) { - u32 index = vmx_msr_index[i]; - u32 data_low, data_high; - u64 data; - int j = vcpu->nmsrs; - - if (rdmsr_safe(index, &data_low, &data_high) < 0) - continue; - data = data_low | ((u64)data_high << 32); - vcpu->host_msrs[j].index = index; - vcpu->host_msrs[j].reserved = 0; - vcpu->host_msrs[j].data = data; - vcpu->guest_msrs[j] = vcpu->host_msrs[j]; - ++vcpu->nmsrs; - } - printk(KERN_DEBUG "kvm: msrs: %d\n", vcpu->nmsrs); - - nr_good_msrs = vcpu->nmsrs - NR_BAD_MSRS; - vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR, - virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS)); - vmcs_writel(VM_EXIT_MSR_STORE_ADDR, - virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS)); - vmcs_writel(VM_EXIT_MSR_LOAD_ADDR, - virt_to_phys(vcpu->host_msrs + NR_BAD_MSRS)); - vmcs_write32_fixedbits(MSR_IA32_VMX_EXIT_CTLS_MSR, VM_EXIT_CONTROLS, - (HOST_IS_64 << 9)); /* 22.2,1, 20.7.1 */ - vmcs_write32(VM_EXIT_MSR_STORE_COUNT, nr_good_msrs); /* 22.2.2 */ - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */ - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */ - - - /* 22.2.1, 20.8.1 */ - vmcs_write32_fixedbits(MSR_IA32_VMX_ENTRY_CTLS_MSR, - VM_ENTRY_CONTROLS, 0); - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */ - -#ifdef CONFIG_X86_64 - vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, 0); - vmcs_writel(TPR_THRESHOLD, 0); -#endif - - vmcs_writel(CR0_GUEST_HOST_MASK, KVM_GUEST_CR0_MASK); - vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK); - - vcpu->cr0 = 0x60000010; - vmx_set_cr0(vcpu, vcpu->cr0); // enter rmode - vmx_set_cr4(vcpu, 0); -#ifdef CONFIG_X86_64 - vmx_set_efer(vcpu, 0); -#endif - - return 0; - -out_free_guest_msrs: - kfree(vcpu->guest_msrs); -out: - return ret; -} - -static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) -{ - u16 ent[2]; - u16 cs; - u16 ip; - unsigned long flags; - unsigned long ss_base = vmcs_readl(GUEST_SS_BASE); - u16 sp = vmcs_readl(GUEST_RSP); - u32 ss_limit = vmcs_read32(GUEST_SS_LIMIT); - - if (sp > ss_limit || sp - 6 > sp) { - vcpu_printf(vcpu, "%s: #SS, rsp 0x%lx ss 0x%lx limit 0x%x\n", - __FUNCTION__, - vmcs_readl(GUEST_RSP), - vmcs_readl(GUEST_SS_BASE), - vmcs_read32(GUEST_SS_LIMIT)); - return; - } - - if (kvm_read_guest(vcpu, irq * sizeof(ent), sizeof(ent), &ent) != - sizeof(ent)) { - vcpu_printf(vcpu, "%s: read guest err\n", __FUNCTION__); - return; - } - - flags = vmcs_readl(GUEST_RFLAGS); - cs = vmcs_readl(GUEST_CS_BASE) >> 4; - ip = vmcs_readl(GUEST_RIP); - - - if (kvm_write_guest(vcpu, ss_base + sp - 2, 2, &flags) != 2 || - kvm_write_guest(vcpu, ss_base + sp - 4, 2, &cs) != 2 || - kvm_write_guest(vcpu, ss_base + sp - 6, 2, &ip) != 2) { - vcpu_printf(vcpu, "%s: write guest err\n", __FUNCTION__); - return; - } - - vmcs_writel(GUEST_RFLAGS, flags & - ~( X86_EFLAGS_IF | X86_EFLAGS_AC | X86_EFLAGS_TF)); - vmcs_write16(GUEST_CS_SELECTOR, ent[1]) ; - vmcs_writel(GUEST_CS_BASE, ent[1] << 4); - vmcs_writel(GUEST_RIP, ent[0]); - vmcs_writel(GUEST_RSP, (vmcs_readl(GUEST_RSP) & ~0xffff) | (sp - 6)); -} - -static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) -{ - int word_index = __ffs(vcpu->irq_summary); - int bit_index = __ffs(vcpu->irq_pending[word_index]); - int irq = word_index * BITS_PER_LONG + bit_index; - - clear_bit(bit_index, &vcpu->irq_pending[word_index]); - if (!vcpu->irq_pending[word_index]) - clear_bit(word_index, &vcpu->irq_summary); - - if (vcpu->rmode.active) { - inject_rmode_irq(vcpu, irq); - return; - } - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, - irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); -} - -static void kvm_try_inject_irq(struct kvm_vcpu *vcpu) -{ - if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) - && (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0) - /* - * Interrupts enabled, and not blocked by sti or mov ss. Good. - */ - kvm_do_inject_irq(vcpu); - else - /* - * Interrupts blocked. Wait for unblock. - */ - vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, - vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) - | CPU_BASED_VIRTUAL_INTR_PENDING); -} - -static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu) -{ - struct kvm_guest_debug *dbg = &vcpu->guest_debug; - - set_debugreg(dbg->bp[0], 0); - set_debugreg(dbg->bp[1], 1); - set_debugreg(dbg->bp[2], 2); - set_debugreg(dbg->bp[3], 3); - - if (dbg->singlestep) { - unsigned long flags; - - flags = vmcs_readl(GUEST_RFLAGS); - flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; - vmcs_writel(GUEST_RFLAGS, flags); - } -} - -static int handle_rmode_exception(struct kvm_vcpu *vcpu, - int vec, u32 err_code) -{ - if (!vcpu->rmode.active) - return 0; - - if (vec == GP_VECTOR && err_code == 0) - if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE) - return 1; - return 0; -} - -static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u32 intr_info, error_code; - unsigned long cr2, rip; - u32 vect_info; - enum emulation_result er; - - vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); - intr_info = vmcs_read32(VM_EXIT_INTR_INFO); - - if ((vect_info & VECTORING_INFO_VALID_MASK) && - !is_page_fault(intr_info)) { - printk(KERN_ERR "%s: unexpected, vectoring info 0x%x " - "intr info 0x%x\n", __FUNCTION__, vect_info, intr_info); - } - - if (is_external_interrupt(vect_info)) { - int irq = vect_info & VECTORING_INFO_VECTOR_MASK; - set_bit(irq, vcpu->irq_pending); - set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary); - } - - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */ - asm ("int $2"); - return 1; - } - error_code = 0; - rip = vmcs_readl(GUEST_RIP); - if (intr_info & INTR_INFO_DELIEVER_CODE_MASK) - error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE); - if (is_page_fault(intr_info)) { - cr2 = vmcs_readl(EXIT_QUALIFICATION); - - spin_lock(&vcpu->kvm->lock); - if (!vcpu->mmu.page_fault(vcpu, cr2, error_code)) { - spin_unlock(&vcpu->kvm->lock); - return 1; - } - - er = emulate_instruction(vcpu, kvm_run, cr2, error_code); - spin_unlock(&vcpu->kvm->lock); - - switch (er) { - case EMULATE_DONE: - return 1; - case EMULATE_DO_MMIO: - ++kvm_stat.mmio_exits; - kvm_run->exit_reason = KVM_EXIT_MMIO; - return 0; - case EMULATE_FAIL: - vcpu_printf(vcpu, "%s: emulate fail\n", __FUNCTION__); - break; - default: - BUG(); - } - } - - if (vcpu->rmode.active && - handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK, - error_code)) - return 1; - - if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == (INTR_TYPE_EXCEPTION | 1)) { - kvm_run->exit_reason = KVM_EXIT_DEBUG; - return 0; - } - kvm_run->exit_reason = KVM_EXIT_EXCEPTION; - kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK; - kvm_run->ex.error_code = error_code; - return 0; -} - -static int handle_external_interrupt(struct kvm_vcpu *vcpu, - struct kvm_run *kvm_run) -{ - ++kvm_stat.irq_exits; - return 1; -} - - -static int get_io_count(struct kvm_vcpu *vcpu, u64 *count) -{ - u64 inst; - gva_t rip; - int countr_size; - int i, n; - - if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) { - countr_size = 2; - } else { - u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES); - - countr_size = (cs_ar & AR_L_MASK) ? 8: - (cs_ar & AR_DB_MASK) ? 4: 2; - } - - rip = vmcs_readl(GUEST_RIP); - if (countr_size != 8) - rip += vmcs_readl(GUEST_CS_BASE); - - n = kvm_read_guest(vcpu, rip, sizeof(inst), &inst); - - for (i = 0; i < n; i++) { - switch (((u8*)&inst)[i]) { - case 0xf0: - case 0xf2: - case 0xf3: - case 0x2e: - case 0x36: - case 0x3e: - case 0x26: - case 0x64: - case 0x65: - case 0x66: - break; - case 0x67: - countr_size = (countr_size == 2) ? 4: (countr_size >> 1); - default: - goto done; - } - } - return 0; -done: - countr_size *= 8; - *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size)); - return 1; -} - -static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u64 exit_qualification; - - ++kvm_stat.io_exits; - exit_qualification = vmcs_read64(EXIT_QUALIFICATION); - kvm_run->exit_reason = KVM_EXIT_IO; - if (exit_qualification & 8) - kvm_run->io.direction = KVM_EXIT_IO_IN; - else - kvm_run->io.direction = KVM_EXIT_IO_OUT; - kvm_run->io.size = (exit_qualification & 7) + 1; - kvm_run->io.string = (exit_qualification & 16) != 0; - kvm_run->io.string_down - = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0; - kvm_run->io.rep = (exit_qualification & 32) != 0; - kvm_run->io.port = exit_qualification >> 16; - if (kvm_run->io.string) { - if (!get_io_count(vcpu, &kvm_run->io.count)) - return 1; - kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS); - } else - kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */ - return 0; -} - -static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u64 address = vmcs_read64(EXIT_QUALIFICATION); - int instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN); - spin_lock(&vcpu->kvm->lock); - vcpu->mmu.inval_page(vcpu, address); - spin_unlock(&vcpu->kvm->lock); - vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP) + instruction_length); - return 1; -} - -static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u64 exit_qualification; - int cr; - int reg; - - exit_qualification = vmcs_read64(EXIT_QUALIFICATION); - cr = exit_qualification & 15; - reg = (exit_qualification >> 8) & 15; - switch ((exit_qualification >> 4) & 3) { - case 0: /* mov to cr */ - switch (cr) { - case 0: - vcpu_load_rsp_rip(vcpu); - set_cr0(vcpu, vcpu->regs[reg]); - skip_emulated_instruction(vcpu); - return 1; - case 3: - vcpu_load_rsp_rip(vcpu); - set_cr3(vcpu, vcpu->regs[reg]); - skip_emulated_instruction(vcpu); - return 1; - case 4: - vcpu_load_rsp_rip(vcpu); - set_cr4(vcpu, vcpu->regs[reg]); - skip_emulated_instruction(vcpu); - return 1; - case 8: - vcpu_load_rsp_rip(vcpu); - set_cr8(vcpu, vcpu->regs[reg]); - skip_emulated_instruction(vcpu); - return 1; - }; - break; - case 1: /*mov from cr*/ - switch (cr) { - case 3: - vcpu_load_rsp_rip(vcpu); - vcpu->regs[reg] = vcpu->cr3; - vcpu_put_rsp_rip(vcpu); - skip_emulated_instruction(vcpu); - return 1; - case 8: - printk(KERN_DEBUG "handle_cr: read CR8 " - "cpu erratum AA15\n"); - vcpu_load_rsp_rip(vcpu); - vcpu->regs[reg] = vcpu->cr8; - vcpu_put_rsp_rip(vcpu); - skip_emulated_instruction(vcpu); - return 1; - } - break; - case 3: /* lmsw */ - lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f); - - skip_emulated_instruction(vcpu); - return 1; - default: - break; - } - kvm_run->exit_reason = 0; - printk(KERN_ERR "kvm: unhandled control register: op %d cr %d\n", - (int)(exit_qualification >> 4) & 3, cr); - return 0; -} - -static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u64 exit_qualification; - unsigned long val; - int dr, reg; - - /* - * FIXME: this code assumes the host is debugging the guest. - * need to deal with guest debugging itself too. - */ - exit_qualification = vmcs_read64(EXIT_QUALIFICATION); - dr = exit_qualification & 7; - reg = (exit_qualification >> 8) & 15; - vcpu_load_rsp_rip(vcpu); - if (exit_qualification & 16) { - /* mov from dr */ - switch (dr) { - case 6: - val = 0xffff0ff0; - break; - case 7: - val = 0x400; - break; - default: - val = 0; - } - vcpu->regs[reg] = val; - } else { - /* mov to dr */ - } - vcpu_put_rsp_rip(vcpu); - skip_emulated_instruction(vcpu); - return 1; -} - -static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - kvm_run->exit_reason = KVM_EXIT_CPUID; - return 0; -} - -static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u32 ecx = vcpu->regs[VCPU_REGS_RCX]; - u64 data; - - if (vmx_get_msr(vcpu, ecx, &data)) { - vmx_inject_gp(vcpu, 0); - return 1; - } - - /* FIXME: handling of bits 32:63 of rax, rdx */ - vcpu->regs[VCPU_REGS_RAX] = data & -1u; - vcpu->regs[VCPU_REGS_RDX] = (data >> 32) & -1u; - skip_emulated_instruction(vcpu); - return 1; -} - -static int handle_wrmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u32 ecx = vcpu->regs[VCPU_REGS_RCX]; - u64 data = (vcpu->regs[VCPU_REGS_RAX] & -1u) - | ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32); - - if (vmx_set_msr(vcpu, ecx, data) != 0) { - vmx_inject_gp(vcpu, 0); - return 1; - } - - skip_emulated_instruction(vcpu); - return 1; -} - -static int handle_interrupt_window(struct kvm_vcpu *vcpu, - struct kvm_run *kvm_run) -{ - /* Turn off interrupt window reporting. */ - vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, - vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) - & ~CPU_BASED_VIRTUAL_INTR_PENDING); - return 1; -} - -static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - skip_emulated_instruction(vcpu); - if (vcpu->irq_summary && (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF)) - return 1; - - kvm_run->exit_reason = KVM_EXIT_HLT; - return 0; -} - -/* - * The exit handlers return 1 if the exit was handled fully and guest execution - * may resume. Otherwise they set the kvm_run parameter to indicate what needs - * to be done to userspace and return 0. - */ -static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu, - struct kvm_run *kvm_run) = { - [EXIT_REASON_EXCEPTION_NMI] = handle_exception, - [EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt, - [EXIT_REASON_IO_INSTRUCTION] = handle_io, - [EXIT_REASON_INVLPG] = handle_invlpg, - [EXIT_REASON_CR_ACCESS] = handle_cr, - [EXIT_REASON_DR_ACCESS] = handle_dr, - [EXIT_REASON_CPUID] = handle_cpuid, - [EXIT_REASON_MSR_READ] = handle_rdmsr, - [EXIT_REASON_MSR_WRITE] = handle_wrmsr, - [EXIT_REASON_PENDING_INTERRUPT] = handle_interrupt_window, - [EXIT_REASON_HLT] = handle_halt, -}; - -static const int kvm_vmx_max_exit_handlers = - sizeof(kvm_vmx_exit_handlers) / sizeof(*kvm_vmx_exit_handlers); - -/* - * The guest has exited. See if we can fix it or if we need userspace - * assistance. - */ -static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) -{ - u32 vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); - u32 exit_reason = vmcs_read32(VM_EXIT_REASON); - - if ( (vectoring_info & VECTORING_INFO_VALID_MASK) && - exit_reason != EXIT_REASON_EXCEPTION_NMI ) - printk(KERN_WARNING "%s: unexpected, valid vectoring info and " - "exit reason is 0x%x\n", __FUNCTION__, exit_reason); - kvm_run->instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN); - if (exit_reason < kvm_vmx_max_exit_handlers - && kvm_vmx_exit_handlers[exit_reason]) - return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run); - else { - kvm_run->exit_reason = KVM_EXIT_UNKNOWN; - kvm_run->hw.hardware_exit_reason = exit_reason; - } - return 0; -} - -static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -{ - u8 fail; - u16 fs_sel, gs_sel, ldt_sel; - int fs_gs_ldt_reload_needed; - -again: - /* - * Set host fs and gs selectors. Unfortunately, 22.2.3 does not - * allow segment selectors with cpl > 0 or ti == 1. - */ - fs_sel = read_fs(); - gs_sel = read_gs(); - ldt_sel = read_ldt(); - fs_gs_ldt_reload_needed = (fs_sel & 7) | (gs_sel & 7) | ldt_sel; - if (!fs_gs_ldt_reload_needed) { - vmcs_write16(HOST_FS_SELECTOR, fs_sel); - vmcs_write16(HOST_GS_SELECTOR, gs_sel); - } else { - vmcs_write16(HOST_FS_SELECTOR, 0); - vmcs_write16(HOST_GS_SELECTOR, 0); - } - -#ifdef CONFIG_X86_64 - vmcs_writel(HOST_FS_BASE, read_msr(MSR_FS_BASE)); - vmcs_writel(HOST_GS_BASE, read_msr(MSR_GS_BASE)); -#else - vmcs_writel(HOST_FS_BASE, segment_base(fs_sel)); - vmcs_writel(HOST_GS_BASE, segment_base(gs_sel)); -#endif - - if (vcpu->irq_summary && - !(vmcs_read32(VM_ENTRY_INTR_INFO_FIELD) & INTR_INFO_VALID_MASK)) - kvm_try_inject_irq(vcpu); - - if (vcpu->guest_debug.enabled) - kvm_guest_debug_pre(vcpu); - - fx_save(vcpu->host_fx_image); - fx_restore(vcpu->guest_fx_image); - - save_msrs(vcpu->host_msrs, vcpu->nmsrs); - load_msrs(vcpu->guest_msrs, NR_BAD_MSRS); - - asm ( - /* Store host registers */ - "pushf \n\t" -#ifdef CONFIG_X86_64 - "push %%rax; push %%rbx; push %%rdx;" - "push %%rsi; push %%rdi; push %%rbp;" - "push %%r8; push %%r9; push %%r10; push %%r11;" - "push %%r12; push %%r13; push %%r14; push %%r15;" - "push %%rcx \n\t" - ASM_VMX_VMWRITE_RSP_RDX "\n\t" -#else - "pusha; push %%ecx \n\t" - ASM_VMX_VMWRITE_RSP_RDX "\n\t" -#endif - /* Check if vmlaunch of vmresume is needed */ - "cmp $0, %1 \n\t" - /* Load guest registers. Don't clobber flags. */ -#ifdef CONFIG_X86_64 - "mov %c[cr2](%3), %%rax \n\t" - "mov %%rax, %%cr2 \n\t" - "mov %c[rax](%3), %%rax \n\t" - "mov %c[rbx](%3), %%rbx \n\t" - "mov %c[rdx](%3), %%rdx \n\t" - "mov %c[rsi](%3), %%rsi \n\t" - "mov %c[rdi](%3), %%rdi \n\t" - "mov %c[rbp](%3), %%rbp \n\t" - "mov %c[r8](%3), %%r8 \n\t" - "mov %c[r9](%3), %%r9 \n\t" - "mov %c[r10](%3), %%r10 \n\t" - "mov %c[r11](%3), %%r11 \n\t" - "mov %c[r12](%3), %%r12 \n\t" - "mov %c[r13](%3), %%r13 \n\t" - "mov %c[r14](%3), %%r14 \n\t" - "mov %c[r15](%3), %%r15 \n\t" - "mov %c[rcx](%3), %%rcx \n\t" /* kills %3 (rcx) */ -#else - "mov %c[cr2](%3), %%eax \n\t" - "mov %%eax, %%cr2 \n\t" - "mov %c[rax](%3), %%eax \n\t" - "mov %c[rbx](%3), %%ebx \n\t" - "mov %c[rdx](%3), %%edx \n\t" - "mov %c[rsi](%3), %%esi \n\t" - "mov %c[rdi](%3), %%edi \n\t" - "mov %c[rbp](%3), %%ebp \n\t" - "mov %c[rcx](%3), %%ecx \n\t" /* kills %3 (ecx) */ -#endif - /* Enter guest mode */ - "jne launched \n\t" - ASM_VMX_VMLAUNCH "\n\t" - "jmp kvm_vmx_return \n\t" - "launched: " ASM_VMX_VMRESUME "\n\t" - ".globl kvm_vmx_return \n\t" - "kvm_vmx_return: " - /* Save guest registers, load host registers, keep flags */ -#ifdef CONFIG_X86_64 - "xchg %3, 0(%%rsp) \n\t" - "mov %%rax, %c[rax](%3) \n\t" - "mov %%rbx, %c[rbx](%3) \n\t" - "pushq 0(%%rsp); popq %c[rcx](%3) \n\t" - "mov %%rdx, %c[rdx](%3) \n\t" - "mov %%rsi, %c[rsi](%3) \n\t" - "mov %%rdi, %c[rdi](%3) \n\t" - "mov %%rbp, %c[rbp](%3) \n\t" - "mov %%r8, %c[r8](%3) \n\t" - "mov %%r9, %c[r9](%3) \n\t" - "mov %%r10, %c[r10](%3) \n\t" - "mov %%r11, %c[r11](%3) \n\t" - "mov %%r12, %c[r12](%3) \n\t" - "mov %%r13, %c[r13](%3) \n\t" - "mov %%r14, %c[r14](%3) \n\t" - "mov %%r15, %c[r15](%3) \n\t" - "mov %%cr2, %%rax \n\t" - "mov %%rax, %c[cr2](%3) \n\t" - "mov 0(%%rsp), %3 \n\t" - - "pop %%rcx; pop %%r15; pop %%r14; pop %%r13; pop %%r12;" - "pop %%r11; pop %%r10; pop %%r9; pop %%r8;" - "pop %%rbp; pop %%rdi; pop %%rsi;" - "pop %%rdx; pop %%rbx; pop %%rax \n\t" -#else - "xchg %3, 0(%%esp) \n\t" - "mov %%eax, %c[rax](%3) \n\t" - "mov %%ebx, %c[rbx](%3) \n\t" - "pushl 0(%%esp); popl %c[rcx](%3) \n\t" - "mov %%edx, %c[rdx](%3) \n\t" - "mov %%esi, %c[rsi](%3) \n\t" - "mov %%edi, %c[rdi](%3) \n\t" - "mov %%ebp, %c[rbp](%3) \n\t" - "mov %%cr2, %%eax \n\t" - "mov %%eax, %c[cr2](%3) \n\t" - "mov 0(%%esp), %3 \n\t" - - "pop %%ecx; popa \n\t" -#endif - "setbe %0 \n\t" - "popf \n\t" - : "=g" (fail) - : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP), - "c"(vcpu), - [rax]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RAX])), - [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])), - [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])), - [rdx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDX])), - [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])), - [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])), - [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP])), -#ifdef CONFIG_X86_64 - [r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])), - [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])), - [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])), - [r11]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R11])), - [r12]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R12])), - [r13]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R13])), - [r14]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R14])), - [r15]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R15])), -#endif - [cr2]"i"(offsetof(struct kvm_vcpu, cr2)) - : "cc", "memory" ); - - ++kvm_stat.exits; - - save_msrs(vcpu->guest_msrs, NR_BAD_MSRS); - load_msrs(vcpu->host_msrs, NR_BAD_MSRS); - - fx_save(vcpu->guest_fx_image); - fx_restore(vcpu->host_fx_image); - -#ifndef CONFIG_X86_64 - asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); -#endif - - kvm_run->exit_type = 0; - if (fail) { - kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY; - kvm_run->exit_reason = vmcs_read32(VM_INSTRUCTION_ERROR); - } else { - if (fs_gs_ldt_reload_needed) { - load_ldt(ldt_sel); - load_fs(fs_sel); - /* - * If we have to reload gs, we must take care to - * preserve our gs base. - */ - local_irq_disable(); - load_gs(gs_sel); -#ifdef CONFIG_X86_64 - wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE)); -#endif - local_irq_enable(); - - reload_tss(); - } - vcpu->launched = 1; - kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT; - if (kvm_handle_exit(kvm_run, vcpu)) { - /* Give scheduler a change to reschedule. */ - if (signal_pending(current)) { - ++kvm_stat.signal_exits; - return -EINTR; - } - kvm_resched(vcpu); - goto again; - } - } - return 0; -} - -static void vmx_flush_tlb(struct kvm_vcpu *vcpu) -{ - vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3)); -} - -static void vmx_inject_page_fault(struct kvm_vcpu *vcpu, - unsigned long addr, - u32 err_code) -{ - u32 vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); - - ++kvm_stat.pf_guest; - - if (is_page_fault(vect_info)) { - printk(KERN_DEBUG "inject_page_fault: " - "double fault 0x%lx @ 0x%lx\n", - addr, vmcs_readl(GUEST_RIP)); - vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, 0); - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, - DF_VECTOR | - INTR_TYPE_EXCEPTION | - INTR_INFO_DELIEVER_CODE_MASK | - INTR_INFO_VALID_MASK); - return; - } - vcpu->cr2 = addr; - vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, err_code); - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, - PF_VECTOR | - INTR_TYPE_EXCEPTION | - INTR_INFO_DELIEVER_CODE_MASK | - INTR_INFO_VALID_MASK); - -} - -static void vmx_free_vmcs(struct kvm_vcpu *vcpu) -{ - if (vcpu->vmcs) { - on_each_cpu(__vcpu_clear, vcpu, 0, 1); - free_vmcs(vcpu->vmcs); - vcpu->vmcs = NULL; - } -} - -static void vmx_free_vcpu(struct kvm_vcpu *vcpu) -{ - vmx_free_vmcs(vcpu); -} - -static int vmx_create_vcpu(struct kvm_vcpu *vcpu) -{ - struct vmcs *vmcs; - - vmcs = alloc_vmcs(); - if (!vmcs) - return -ENOMEM; - vmcs_clear(vmcs); - vcpu->vmcs = vmcs; - vcpu->launched = 0; - return 0; -} - -static struct kvm_arch_ops vmx_arch_ops = { - .cpu_has_kvm_support = cpu_has_kvm_support, - .disabled_by_bios = vmx_disabled_by_bios, - .hardware_setup = hardware_setup, - .hardware_unsetup = hardware_unsetup, - .hardware_enable = hardware_enable, - .hardware_disable = hardware_disable, - - .vcpu_create = vmx_create_vcpu, - .vcpu_free = vmx_free_vcpu, - - .vcpu_load = vmx_vcpu_load, - .vcpu_put = vmx_vcpu_put, - - .set_guest_debug = set_guest_debug, - .get_msr = vmx_get_msr, - .set_msr = vmx_set_msr, - .get_segment_base = vmx_get_segment_base, - .get_segment = vmx_get_segment, - .set_segment = vmx_set_segment, - .is_long_mode = vmx_is_long_mode, - .get_cs_db_l_bits = vmx_get_cs_db_l_bits, - .set_cr0 = vmx_set_cr0, - .set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch, - .set_cr3 = vmx_set_cr3, - .set_cr4 = vmx_set_cr4, -#ifdef CONFIG_X86_64 - .set_efer = vmx_set_efer, -#endif - .get_idt = vmx_get_idt, - .set_idt = vmx_set_idt, - .get_gdt = vmx_get_gdt, - .set_gdt = vmx_set_gdt, - .cache_regs = vcpu_load_rsp_rip, - .decache_regs = vcpu_put_rsp_rip, - .get_rflags = vmx_get_rflags, - .set_rflags = vmx_set_rflags, - - .tlb_flush = vmx_flush_tlb, - .inject_page_fault = vmx_inject_page_fault, - - .inject_gp = vmx_inject_gp, - - .run = vmx_vcpu_run, - .skip_emulated_instruction = skip_emulated_instruction, - .vcpu_setup = vmx_vcpu_setup, -}; - -static int __init vmx_init(void) -{ - return kvm_init_arch(&vmx_arch_ops, THIS_MODULE); -} - -static void __exit vmx_exit(void) -{ - kvm_exit_arch(); -} - -module_init(vmx_init) -module_exit(vmx_exit) diff --git a/trunk/drivers/kvm/vmx.h b/trunk/drivers/kvm/vmx.h deleted file mode 100644 index 797278341581..000000000000 --- a/trunk/drivers/kvm/vmx.h +++ /dev/null @@ -1,296 +0,0 @@ -#ifndef VMX_H -#define VMX_H - -/* - * vmx.h: VMX Architecture related definitions - * Copyright (c) 2004, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * A few random additions are: - * Copyright (C) 2006 Qumranet - * Avi Kivity - * Yaniv Kamay - * - */ - -#define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004 -#define CPU_BASED_USE_TSC_OFFSETING 0x00000008 -#define CPU_BASED_HLT_EXITING 0x00000080 -#define CPU_BASED_INVDPG_EXITING 0x00000200 -#define CPU_BASED_MWAIT_EXITING 0x00000400 -#define CPU_BASED_RDPMC_EXITING 0x00000800 -#define CPU_BASED_RDTSC_EXITING 0x00001000 -#define CPU_BASED_CR8_LOAD_EXITING 0x00080000 -#define CPU_BASED_CR8_STORE_EXITING 0x00100000 -#define CPU_BASED_TPR_SHADOW 0x00200000 -#define CPU_BASED_MOV_DR_EXITING 0x00800000 -#define CPU_BASED_UNCOND_IO_EXITING 0x01000000 -#define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000 -#define CPU_BASED_MSR_BITMAPS 0x10000000 -#define CPU_BASED_MONITOR_EXITING 0x20000000 -#define CPU_BASED_PAUSE_EXITING 0x40000000 - -#define PIN_BASED_EXT_INTR_MASK 0x1 -#define PIN_BASED_NMI_EXITING 0x8 - -#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 -#define VM_EXIT_HOST_ADD_SPACE_SIZE 0x00000200 - - -/* VMCS Encodings */ -enum vmcs_field { - GUEST_ES_SELECTOR = 0x00000800, - GUEST_CS_SELECTOR = 0x00000802, - GUEST_SS_SELECTOR = 0x00000804, - GUEST_DS_SELECTOR = 0x00000806, - GUEST_FS_SELECTOR = 0x00000808, - GUEST_GS_SELECTOR = 0x0000080a, - GUEST_LDTR_SELECTOR = 0x0000080c, - GUEST_TR_SELECTOR = 0x0000080e, - HOST_ES_SELECTOR = 0x00000c00, - HOST_CS_SELECTOR = 0x00000c02, - HOST_SS_SELECTOR = 0x00000c04, - HOST_DS_SELECTOR = 0x00000c06, - HOST_FS_SELECTOR = 0x00000c08, - HOST_GS_SELECTOR = 0x00000c0a, - HOST_TR_SELECTOR = 0x00000c0c, - IO_BITMAP_A = 0x00002000, - IO_BITMAP_A_HIGH = 0x00002001, - IO_BITMAP_B = 0x00002002, - IO_BITMAP_B_HIGH = 0x00002003, - MSR_BITMAP = 0x00002004, - MSR_BITMAP_HIGH = 0x00002005, - VM_EXIT_MSR_STORE_ADDR = 0x00002006, - VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007, - VM_EXIT_MSR_LOAD_ADDR = 0x00002008, - VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009, - VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a, - VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b, - TSC_OFFSET = 0x00002010, - TSC_OFFSET_HIGH = 0x00002011, - VIRTUAL_APIC_PAGE_ADDR = 0x00002012, - VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013, - VMCS_LINK_POINTER = 0x00002800, - VMCS_LINK_POINTER_HIGH = 0x00002801, - GUEST_IA32_DEBUGCTL = 0x00002802, - GUEST_IA32_DEBUGCTL_HIGH = 0x00002803, - PIN_BASED_VM_EXEC_CONTROL = 0x00004000, - CPU_BASED_VM_EXEC_CONTROL = 0x00004002, - EXCEPTION_BITMAP = 0x00004004, - PAGE_FAULT_ERROR_CODE_MASK = 0x00004006, - PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008, - CR3_TARGET_COUNT = 0x0000400a, - VM_EXIT_CONTROLS = 0x0000400c, - VM_EXIT_MSR_STORE_COUNT = 0x0000400e, - VM_EXIT_MSR_LOAD_COUNT = 0x00004010, - VM_ENTRY_CONTROLS = 0x00004012, - VM_ENTRY_MSR_LOAD_COUNT = 0x00004014, - VM_ENTRY_INTR_INFO_FIELD = 0x00004016, - VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018, - VM_ENTRY_INSTRUCTION_LEN = 0x0000401a, - TPR_THRESHOLD = 0x0000401c, - SECONDARY_VM_EXEC_CONTROL = 0x0000401e, - VM_INSTRUCTION_ERROR = 0x00004400, - VM_EXIT_REASON = 0x00004402, - VM_EXIT_INTR_INFO = 0x00004404, - VM_EXIT_INTR_ERROR_CODE = 0x00004406, - IDT_VECTORING_INFO_FIELD = 0x00004408, - IDT_VECTORING_ERROR_CODE = 0x0000440a, - VM_EXIT_INSTRUCTION_LEN = 0x0000440c, - VMX_INSTRUCTION_INFO = 0x0000440e, - GUEST_ES_LIMIT = 0x00004800, - GUEST_CS_LIMIT = 0x00004802, - GUEST_SS_LIMIT = 0x00004804, - GUEST_DS_LIMIT = 0x00004806, - GUEST_FS_LIMIT = 0x00004808, - GUEST_GS_LIMIT = 0x0000480a, - GUEST_LDTR_LIMIT = 0x0000480c, - GUEST_TR_LIMIT = 0x0000480e, - GUEST_GDTR_LIMIT = 0x00004810, - GUEST_IDTR_LIMIT = 0x00004812, - GUEST_ES_AR_BYTES = 0x00004814, - GUEST_CS_AR_BYTES = 0x00004816, - GUEST_SS_AR_BYTES = 0x00004818, - GUEST_DS_AR_BYTES = 0x0000481a, - GUEST_FS_AR_BYTES = 0x0000481c, - GUEST_GS_AR_BYTES = 0x0000481e, - GUEST_LDTR_AR_BYTES = 0x00004820, - GUEST_TR_AR_BYTES = 0x00004822, - GUEST_INTERRUPTIBILITY_INFO = 0x00004824, - GUEST_ACTIVITY_STATE = 0X00004826, - GUEST_SYSENTER_CS = 0x0000482A, - HOST_IA32_SYSENTER_CS = 0x00004c00, - CR0_GUEST_HOST_MASK = 0x00006000, - CR4_GUEST_HOST_MASK = 0x00006002, - CR0_READ_SHADOW = 0x00006004, - CR4_READ_SHADOW = 0x00006006, - CR3_TARGET_VALUE0 = 0x00006008, - CR3_TARGET_VALUE1 = 0x0000600a, - CR3_TARGET_VALUE2 = 0x0000600c, - CR3_TARGET_VALUE3 = 0x0000600e, - EXIT_QUALIFICATION = 0x00006400, - GUEST_LINEAR_ADDRESS = 0x0000640a, - GUEST_CR0 = 0x00006800, - GUEST_CR3 = 0x00006802, - GUEST_CR4 = 0x00006804, - GUEST_ES_BASE = 0x00006806, - GUEST_CS_BASE = 0x00006808, - GUEST_SS_BASE = 0x0000680a, - GUEST_DS_BASE = 0x0000680c, - GUEST_FS_BASE = 0x0000680e, - GUEST_GS_BASE = 0x00006810, - GUEST_LDTR_BASE = 0x00006812, - GUEST_TR_BASE = 0x00006814, - GUEST_GDTR_BASE = 0x00006816, - GUEST_IDTR_BASE = 0x00006818, - GUEST_DR7 = 0x0000681a, - GUEST_RSP = 0x0000681c, - GUEST_RIP = 0x0000681e, - GUEST_RFLAGS = 0x00006820, - GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822, - GUEST_SYSENTER_ESP = 0x00006824, - GUEST_SYSENTER_EIP = 0x00006826, - HOST_CR0 = 0x00006c00, - HOST_CR3 = 0x00006c02, - HOST_CR4 = 0x00006c04, - HOST_FS_BASE = 0x00006c06, - HOST_GS_BASE = 0x00006c08, - HOST_TR_BASE = 0x00006c0a, - HOST_GDTR_BASE = 0x00006c0c, - HOST_IDTR_BASE = 0x00006c0e, - HOST_IA32_SYSENTER_ESP = 0x00006c10, - HOST_IA32_SYSENTER_EIP = 0x00006c12, - HOST_RSP = 0x00006c14, - HOST_RIP = 0x00006c16, -}; - -#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 - -#define EXIT_REASON_EXCEPTION_NMI 0 -#define EXIT_REASON_EXTERNAL_INTERRUPT 1 - -#define EXIT_REASON_PENDING_INTERRUPT 7 - -#define EXIT_REASON_TASK_SWITCH 9 -#define EXIT_REASON_CPUID 10 -#define EXIT_REASON_HLT 12 -#define EXIT_REASON_INVLPG 14 -#define EXIT_REASON_RDPMC 15 -#define EXIT_REASON_RDTSC 16 -#define EXIT_REASON_VMCALL 18 -#define EXIT_REASON_VMCLEAR 19 -#define EXIT_REASON_VMLAUNCH 20 -#define EXIT_REASON_VMPTRLD 21 -#define EXIT_REASON_VMPTRST 22 -#define EXIT_REASON_VMREAD 23 -#define EXIT_REASON_VMRESUME 24 -#define EXIT_REASON_VMWRITE 25 -#define EXIT_REASON_VMOFF 26 -#define EXIT_REASON_VMON 27 -#define EXIT_REASON_CR_ACCESS 28 -#define EXIT_REASON_DR_ACCESS 29 -#define EXIT_REASON_IO_INSTRUCTION 30 -#define EXIT_REASON_MSR_READ 31 -#define EXIT_REASON_MSR_WRITE 32 -#define EXIT_REASON_MWAIT_INSTRUCTION 36 - -/* - * Interruption-information format - */ -#define INTR_INFO_VECTOR_MASK 0xff /* 7:0 */ -#define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */ -#define INTR_INFO_DELIEVER_CODE_MASK 0x800 /* 11 */ -#define INTR_INFO_VALID_MASK 0x80000000 /* 31 */ - -#define VECTORING_INFO_VECTOR_MASK INTR_INFO_VECTOR_MASK -#define VECTORING_INFO_TYPE_MASK INTR_INFO_INTR_TYPE_MASK -#define VECTORING_INFO_DELIEVER_CODE_MASK INTR_INFO_DELIEVER_CODE_MASK -#define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK - -#define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */ -#define INTR_TYPE_EXCEPTION (3 << 8) /* processor exception */ - -/* - * Exit Qualifications for MOV for Control Register Access - */ -#define CONTROL_REG_ACCESS_NUM 0x7 /* 2:0, number of control register */ -#define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */ -#define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose register */ -#define LMSW_SOURCE_DATA_SHIFT 16 -#define LMSW_SOURCE_DATA (0xFFFF << LMSW_SOURCE_DATA_SHIFT) /* 16:31 lmsw source */ -#define REG_EAX (0 << 8) -#define REG_ECX (1 << 8) -#define REG_EDX (2 << 8) -#define REG_EBX (3 << 8) -#define REG_ESP (4 << 8) -#define REG_EBP (5 << 8) -#define REG_ESI (6 << 8) -#define REG_EDI (7 << 8) -#define REG_R8 (8 << 8) -#define REG_R9 (9 << 8) -#define REG_R10 (10 << 8) -#define REG_R11 (11 << 8) -#define REG_R12 (12 << 8) -#define REG_R13 (13 << 8) -#define REG_R14 (14 << 8) -#define REG_R15 (15 << 8) - -/* - * Exit Qualifications for MOV for Debug Register Access - */ -#define DEBUG_REG_ACCESS_NUM 0x7 /* 2:0, number of debug register */ -#define DEBUG_REG_ACCESS_TYPE 0x10 /* 4, direction of access */ -#define TYPE_MOV_TO_DR (0 << 4) -#define TYPE_MOV_FROM_DR (1 << 4) -#define DEBUG_REG_ACCESS_REG 0xf00 /* 11:8, general purpose register */ - - -/* segment AR */ -#define SEGMENT_AR_L_MASK (1 << 13) - -/* entry controls */ -#define VM_ENTRY_CONTROLS_IA32E_MASK (1 << 9) - -#define AR_TYPE_ACCESSES_MASK 1 -#define AR_TYPE_READABLE_MASK (1 << 1) -#define AR_TYPE_WRITEABLE_MASK (1 << 2) -#define AR_TYPE_CODE_MASK (1 << 3) -#define AR_TYPE_MASK 0x0f -#define AR_TYPE_BUSY_64_TSS 11 -#define AR_TYPE_BUSY_32_TSS 11 -#define AR_TYPE_BUSY_16_TSS 3 -#define AR_TYPE_LDT 2 - -#define AR_UNUSABLE_MASK (1 << 16) -#define AR_S_MASK (1 << 4) -#define AR_P_MASK (1 << 7) -#define AR_L_MASK (1 << 13) -#define AR_DB_MASK (1 << 14) -#define AR_G_MASK (1 << 15) -#define AR_DPL_SHIFT 5 -#define AR_DPL(ar) (((ar) >> AR_DPL_SHIFT) & 3) - -#define AR_RESERVD_MASK 0xfffe0f00 - -#define CR4_VMXE 0x2000 - -#define MSR_IA32_VMX_BASIC_MSR 0x480 -#define MSR_IA32_FEATURE_CONTROL 0x03a -#define MSR_IA32_VMX_PINBASED_CTLS_MSR 0x481 -#define MSR_IA32_VMX_PROCBASED_CTLS_MSR 0x482 -#define MSR_IA32_VMX_EXIT_CTLS_MSR 0x483 -#define MSR_IA32_VMX_ENTRY_CTLS_MSR 0x484 - -#endif diff --git a/trunk/drivers/kvm/x86_emulate.c b/trunk/drivers/kvm/x86_emulate.c deleted file mode 100644 index 1bff3e925fda..000000000000 --- a/trunk/drivers/kvm/x86_emulate.c +++ /dev/null @@ -1,1409 +0,0 @@ -/****************************************************************************** - * x86_emulate.c - * - * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. - * - * Copyright (c) 2005 Keir Fraser - * - * Linux coding style, mod r/m decoder, segment base fixes, real-mode - * privieged instructions: - * - * Copyright (C) 2006 Qumranet - * - * Avi Kivity - * Yaniv Kamay - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 - */ - -#ifndef __KERNEL__ -#include -#include -#include -#define DPRINTF(_f, _a ...) printf( _f , ## _a ) -#else -#include "kvm.h" -#define DPRINTF(x...) do {} while (0) -#endif -#include "x86_emulate.h" -#include - -/* - * Opcode effective-address decode tables. - * Note that we only emulate instructions that have at least one memory - * operand (excluding implicit stack references). We assume that stack - * references and instruction fetches will never occur in special memory - * areas that require emulation. So, for example, 'mov ,' need - * not be handled. - */ - -/* Operand sizes: 8-bit operands or specified/overridden size. */ -#define ByteOp (1<<0) /* 8-bit operands. */ -/* Destination operand type. */ -#define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */ -#define DstReg (2<<1) /* Register operand. */ -#define DstMem (3<<1) /* Memory operand. */ -#define DstMask (3<<1) -/* Source operand type. */ -#define SrcNone (0<<3) /* No source operand. */ -#define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */ -#define SrcReg (1<<3) /* Register operand. */ -#define SrcMem (2<<3) /* Memory operand. */ -#define SrcMem16 (3<<3) /* Memory operand (16-bit). */ -#define SrcMem32 (4<<3) /* Memory operand (32-bit). */ -#define SrcImm (5<<3) /* Immediate operand. */ -#define SrcImmByte (6<<3) /* 8-bit sign-extended immediate operand. */ -#define SrcMask (7<<3) -/* Generic ModRM decode. */ -#define ModRM (1<<6) -/* Destination is only written; never read. */ -#define Mov (1<<7) - -static u8 opcode_table[256] = { - /* 0x00 - 0x07 */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, - 0, 0, 0, 0, - /* 0x08 - 0x0F */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, - 0, 0, 0, 0, - /* 0x10 - 0x17 */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, - 0, 0, 0, 0, - /* 0x18 - 0x1F */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, - 0, 0, 0, 0, - /* 0x20 - 0x27 */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, - 0, 0, 0, 0, - /* 0x28 - 0x2F */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, - 0, 0, 0, 0, - /* 0x30 - 0x37 */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, - 0, 0, 0, 0, - /* 0x38 - 0x3F */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, - 0, 0, 0, 0, - /* 0x40 - 0x4F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x50 - 0x5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x60 - 0x6F */ - 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x70 - 0x7F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x80 - 0x87 */ - ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, - ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, - /* 0x88 - 0x8F */ - ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov, - ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - 0, 0, 0, DstMem | SrcNone | ModRM | Mov, - /* 0x90 - 0x9F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xA0 - 0xA7 */ - ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov, - ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov, - ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, - ByteOp | ImplicitOps, ImplicitOps, - /* 0xA8 - 0xAF */ - 0, 0, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, - ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, - ByteOp | ImplicitOps, ImplicitOps, - /* 0xB0 - 0xBF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xC0 - 0xC7 */ - ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0, - 0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov, - DstMem | SrcImm | ModRM | Mov, - /* 0xC8 - 0xCF */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xD0 - 0xD7 */ - ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, - ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, - 0, 0, 0, 0, - /* 0xD8 - 0xDF */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xE0 - 0xEF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xF0 - 0xF7 */ - 0, 0, 0, 0, - 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, - /* 0xF8 - 0xFF */ - 0, 0, 0, 0, - 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM -}; - -static u8 twobyte_table[256] = { - /* 0x00 - 0x0F */ - 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, - 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, - /* 0x10 - 0x1F */ - 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, - /* 0x20 - 0x2F */ - ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x30 - 0x3F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x40 - 0x47 */ - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - /* 0x48 - 0x4F */ - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - /* 0x50 - 0x5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x60 - 0x6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x70 - 0x7F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x80 - 0x8F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x90 - 0x9F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xA0 - 0xA7 */ - 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, - /* 0xA8 - 0xAF */ - 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, - /* 0xB0 - 0xB7 */ - ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0, - DstMem | SrcReg | ModRM, - 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem16 | ModRM | Mov, - /* 0xB8 - 0xBF */ - 0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM, - 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem16 | ModRM | Mov, - /* 0xC0 - 0xCF */ - 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xD0 - 0xDF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xE0 - 0xEF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xF0 - 0xFF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * Tell the emulator that of the Group 7 instructions (sgdt, lidt, etc.) we - * are interested only in invlpg and not in any of the rest. - * - * invlpg is a special instruction in that the data it references may not - * be mapped. - */ -void kvm_emulator_want_group7_invlpg(void) -{ - twobyte_table[1] &= ~SrcMem; -} -EXPORT_SYMBOL_GPL(kvm_emulator_want_group7_invlpg); - -/* Type, address-of, and value of an instruction's operand. */ -struct operand { - enum { OP_REG, OP_MEM, OP_IMM } type; - unsigned int bytes; - unsigned long val, orig_val, *ptr; -}; - -/* EFLAGS bit definitions. */ -#define EFLG_OF (1<<11) -#define EFLG_DF (1<<10) -#define EFLG_SF (1<<7) -#define EFLG_ZF (1<<6) -#define EFLG_AF (1<<4) -#define EFLG_PF (1<<2) -#define EFLG_CF (1<<0) - -/* - * Instruction emulation: - * Most instructions are emulated directly via a fragment of inline assembly - * code. This allows us to save/restore EFLAGS and thus very easily pick up - * any modified flags. - */ - -#if defined(CONFIG_X86_64) -#define _LO32 "k" /* force 32-bit operand */ -#define _STK "%%rsp" /* stack pointer */ -#elif defined(__i386__) -#define _LO32 "" /* force 32-bit operand */ -#define _STK "%%esp" /* stack pointer */ -#endif - -/* - * These EFLAGS bits are restored from saved value during emulation, and - * any changes are written back to the saved value after emulation. - */ -#define EFLAGS_MASK (EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_AF|EFLG_PF|EFLG_CF) - -/* Before executing instruction: restore necessary bits in EFLAGS. */ -#define _PRE_EFLAGS(_sav, _msk, _tmp) \ - /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); */ \ - "push %"_sav"; " \ - "movl %"_msk",%"_LO32 _tmp"; " \ - "andl %"_LO32 _tmp",("_STK"); " \ - "pushf; " \ - "notl %"_LO32 _tmp"; " \ - "andl %"_LO32 _tmp",("_STK"); " \ - "pop %"_tmp"; " \ - "orl %"_LO32 _tmp",("_STK"); " \ - "popf; " \ - /* _sav &= ~msk; */ \ - "movl %"_msk",%"_LO32 _tmp"; " \ - "notl %"_LO32 _tmp"; " \ - "andl %"_LO32 _tmp",%"_sav"; " - -/* After executing instruction: write-back necessary bits in EFLAGS. */ -#define _POST_EFLAGS(_sav, _msk, _tmp) \ - /* _sav |= EFLAGS & _msk; */ \ - "pushf; " \ - "pop %"_tmp"; " \ - "andl %"_msk",%"_LO32 _tmp"; " \ - "orl %"_LO32 _tmp",%"_sav"; " - -/* Raw emulation: instruction has two explicit operands. */ -#define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \ - do { \ - unsigned long _tmp; \ - \ - switch ((_dst).bytes) { \ - case 2: \ - __asm__ __volatile__ ( \ - _PRE_EFLAGS("0","4","2") \ - _op"w %"_wx"3,%1; " \ - _POST_EFLAGS("0","4","2") \ - : "=m" (_eflags), "=m" ((_dst).val), \ - "=&r" (_tmp) \ - : _wy ((_src).val), "i" (EFLAGS_MASK) ); \ - break; \ - case 4: \ - __asm__ __volatile__ ( \ - _PRE_EFLAGS("0","4","2") \ - _op"l %"_lx"3,%1; " \ - _POST_EFLAGS("0","4","2") \ - : "=m" (_eflags), "=m" ((_dst).val), \ - "=&r" (_tmp) \ - : _ly ((_src).val), "i" (EFLAGS_MASK) ); \ - break; \ - case 8: \ - __emulate_2op_8byte(_op, _src, _dst, \ - _eflags, _qx, _qy); \ - break; \ - } \ - } while (0) - -#define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \ - do { \ - unsigned long _tmp; \ - switch ( (_dst).bytes ) \ - { \ - case 1: \ - __asm__ __volatile__ ( \ - _PRE_EFLAGS("0","4","2") \ - _op"b %"_bx"3,%1; " \ - _POST_EFLAGS("0","4","2") \ - : "=m" (_eflags), "=m" ((_dst).val), \ - "=&r" (_tmp) \ - : _by ((_src).val), "i" (EFLAGS_MASK) ); \ - break; \ - default: \ - __emulate_2op_nobyte(_op, _src, _dst, _eflags, \ - _wx, _wy, _lx, _ly, _qx, _qy); \ - break; \ - } \ - } while (0) - -/* Source operand is byte-sized and may be restricted to just %cl. */ -#define emulate_2op_SrcB(_op, _src, _dst, _eflags) \ - __emulate_2op(_op, _src, _dst, _eflags, \ - "b", "c", "b", "c", "b", "c", "b", "c") - -/* Source operand is byte, word, long or quad sized. */ -#define emulate_2op_SrcV(_op, _src, _dst, _eflags) \ - __emulate_2op(_op, _src, _dst, _eflags, \ - "b", "q", "w", "r", _LO32, "r", "", "r") - -/* Source operand is word, long or quad sized. */ -#define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags) \ - __emulate_2op_nobyte(_op, _src, _dst, _eflags, \ - "w", "r", _LO32, "r", "", "r") - -/* Instruction has only one explicit operand (no source operand). */ -#define emulate_1op(_op, _dst, _eflags) \ - do { \ - unsigned long _tmp; \ - \ - switch ( (_dst).bytes ) \ - { \ - case 1: \ - __asm__ __volatile__ ( \ - _PRE_EFLAGS("0","3","2") \ - _op"b %1; " \ - _POST_EFLAGS("0","3","2") \ - : "=m" (_eflags), "=m" ((_dst).val), \ - "=&r" (_tmp) \ - : "i" (EFLAGS_MASK) ); \ - break; \ - case 2: \ - __asm__ __volatile__ ( \ - _PRE_EFLAGS("0","3","2") \ - _op"w %1; " \ - _POST_EFLAGS("0","3","2") \ - : "=m" (_eflags), "=m" ((_dst).val), \ - "=&r" (_tmp) \ - : "i" (EFLAGS_MASK) ); \ - break; \ - case 4: \ - __asm__ __volatile__ ( \ - _PRE_EFLAGS("0","3","2") \ - _op"l %1; " \ - _POST_EFLAGS("0","3","2") \ - : "=m" (_eflags), "=m" ((_dst).val), \ - "=&r" (_tmp) \ - : "i" (EFLAGS_MASK) ); \ - break; \ - case 8: \ - __emulate_1op_8byte(_op, _dst, _eflags); \ - break; \ - } \ - } while (0) - -/* Emulate an instruction with quadword operands (x86/64 only). */ -#if defined(CONFIG_X86_64) -#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) \ - do { \ - __asm__ __volatile__ ( \ - _PRE_EFLAGS("0","4","2") \ - _op"q %"_qx"3,%1; " \ - _POST_EFLAGS("0","4","2") \ - : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : _qy ((_src).val), "i" (EFLAGS_MASK) ); \ - } while (0) - -#define __emulate_1op_8byte(_op, _dst, _eflags) \ - do { \ - __asm__ __volatile__ ( \ - _PRE_EFLAGS("0","3","2") \ - _op"q %1; " \ - _POST_EFLAGS("0","3","2") \ - : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : "i" (EFLAGS_MASK) ); \ - } while (0) - -#elif defined(__i386__) -#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) -#define __emulate_1op_8byte(_op, _dst, _eflags) -#endif /* __i386__ */ - -/* Fetch next part of the instruction being emulated. */ -#define insn_fetch(_type, _size, _eip) \ -({ unsigned long _x; \ - rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x, \ - (_size), ctxt); \ - if ( rc != 0 ) \ - goto done; \ - (_eip) += (_size); \ - (_type)_x; \ -}) - -/* Access/update address held in a register, based on addressing mode. */ -#define register_address(base, reg) \ - ((base) + ((ad_bytes == sizeof(unsigned long)) ? (reg) : \ - ((reg) & ((1UL << (ad_bytes << 3)) - 1)))) - -#define register_address_increment(reg, inc) \ - do { \ - /* signed type ensures sign extension to long */ \ - int _inc = (inc); \ - if ( ad_bytes == sizeof(unsigned long) ) \ - (reg) += _inc; \ - else \ - (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \ - (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \ - } while (0) - -void *decode_register(u8 modrm_reg, unsigned long *regs, - int highbyte_regs) -{ - void *p; - - p = ®s[modrm_reg]; - if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8) - p = (unsigned char *)®s[modrm_reg & 3] + 1; - return p; -} - -static int read_descriptor(struct x86_emulate_ctxt *ctxt, - struct x86_emulate_ops *ops, - void *ptr, - u16 *size, unsigned long *address, int op_bytes) -{ - int rc; - - if (op_bytes == 2) - op_bytes = 3; - *address = 0; - rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2, ctxt); - if (rc) - return rc; - rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes, ctxt); - return rc; -} - -int -x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) -{ - u8 b, d, sib, twobyte = 0, rex_prefix = 0; - u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; - unsigned long *override_base = NULL; - unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; - int rc = 0; - struct operand src, dst; - unsigned long cr2 = ctxt->cr2; - int mode = ctxt->mode; - unsigned long modrm_ea; - int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0; - - /* Shadow copy of register state. Committed on successful emulation. */ - unsigned long _regs[NR_VCPU_REGS]; - unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags; - unsigned long modrm_val = 0; - - memcpy(_regs, ctxt->vcpu->regs, sizeof _regs); - - switch (mode) { - case X86EMUL_MODE_REAL: - case X86EMUL_MODE_PROT16: - op_bytes = ad_bytes = 2; - break; - case X86EMUL_MODE_PROT32: - op_bytes = ad_bytes = 4; - break; -#ifdef CONFIG_X86_64 - case X86EMUL_MODE_PROT64: - op_bytes = 4; - ad_bytes = 8; - break; -#endif - default: - return -1; - } - - /* Legacy prefixes. */ - for (i = 0; i < 8; i++) { - switch (b = insn_fetch(u8, 1, _eip)) { - case 0x66: /* operand-size override */ - op_bytes ^= 6; /* switch between 2/4 bytes */ - break; - case 0x67: /* address-size override */ - if (mode == X86EMUL_MODE_PROT64) - ad_bytes ^= 12; /* switch between 4/8 bytes */ - else - ad_bytes ^= 6; /* switch between 2/4 bytes */ - break; - case 0x2e: /* CS override */ - override_base = &ctxt->cs_base; - break; - case 0x3e: /* DS override */ - override_base = &ctxt->ds_base; - break; - case 0x26: /* ES override */ - override_base = &ctxt->es_base; - break; - case 0x64: /* FS override */ - override_base = &ctxt->fs_base; - break; - case 0x65: /* GS override */ - override_base = &ctxt->gs_base; - break; - case 0x36: /* SS override */ - override_base = &ctxt->ss_base; - break; - case 0xf0: /* LOCK */ - lock_prefix = 1; - break; - case 0xf3: /* REP/REPE/REPZ */ - rep_prefix = 1; - break; - case 0xf2: /* REPNE/REPNZ */ - break; - default: - goto done_prefixes; - } - } - -done_prefixes: - - /* REX prefix. */ - if ((mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40)) { - rex_prefix = b; - if (b & 8) - op_bytes = 8; /* REX.W */ - modrm_reg = (b & 4) << 1; /* REX.R */ - index_reg = (b & 2) << 2; /* REX.X */ - modrm_rm = base_reg = (b & 1) << 3; /* REG.B */ - b = insn_fetch(u8, 1, _eip); - } - - /* Opcode byte(s). */ - d = opcode_table[b]; - if (d == 0) { - /* Two-byte opcode? */ - if (b == 0x0f) { - twobyte = 1; - b = insn_fetch(u8, 1, _eip); - d = twobyte_table[b]; - } - - /* Unrecognised? */ - if (d == 0) - goto cannot_emulate; - } - - /* ModRM and SIB bytes. */ - if (d & ModRM) { - modrm = insn_fetch(u8, 1, _eip); - modrm_mod |= (modrm & 0xc0) >> 6; - modrm_reg |= (modrm & 0x38) >> 3; - modrm_rm |= (modrm & 0x07); - modrm_ea = 0; - use_modrm_ea = 1; - - if (modrm_mod == 3) { - modrm_val = *(unsigned long *) - decode_register(modrm_rm, _regs, d & ByteOp); - goto modrm_done; - } - - if (ad_bytes == 2) { - unsigned bx = _regs[VCPU_REGS_RBX]; - unsigned bp = _regs[VCPU_REGS_RBP]; - unsigned si = _regs[VCPU_REGS_RSI]; - unsigned di = _regs[VCPU_REGS_RDI]; - - /* 16-bit ModR/M decode. */ - switch (modrm_mod) { - case 0: - if (modrm_rm == 6) - modrm_ea += insn_fetch(u16, 2, _eip); - break; - case 1: - modrm_ea += insn_fetch(s8, 1, _eip); - break; - case 2: - modrm_ea += insn_fetch(u16, 2, _eip); - break; - } - switch (modrm_rm) { - case 0: - modrm_ea += bx + si; - break; - case 1: - modrm_ea += bx + di; - break; - case 2: - modrm_ea += bp + si; - break; - case 3: - modrm_ea += bp + di; - break; - case 4: - modrm_ea += si; - break; - case 5: - modrm_ea += di; - break; - case 6: - if (modrm_mod != 0) - modrm_ea += bp; - break; - case 7: - modrm_ea += bx; - break; - } - if (modrm_rm == 2 || modrm_rm == 3 || - (modrm_rm == 6 && modrm_mod != 0)) - if (!override_base) - override_base = &ctxt->ss_base; - modrm_ea = (u16)modrm_ea; - } else { - /* 32/64-bit ModR/M decode. */ - switch (modrm_rm) { - case 4: - case 12: - sib = insn_fetch(u8, 1, _eip); - index_reg |= (sib >> 3) & 7; - base_reg |= sib & 7; - scale = sib >> 6; - - switch (base_reg) { - case 5: - if (modrm_mod != 0) - modrm_ea += _regs[base_reg]; - else - modrm_ea += insn_fetch(s32, 4, _eip); - break; - default: - modrm_ea += _regs[base_reg]; - } - switch (index_reg) { - case 4: - break; - default: - modrm_ea += _regs[index_reg] << scale; - - } - break; - case 5: - if (modrm_mod != 0) - modrm_ea += _regs[modrm_rm]; - else if (mode == X86EMUL_MODE_PROT64) - rip_relative = 1; - break; - default: - modrm_ea += _regs[modrm_rm]; - break; - } - switch (modrm_mod) { - case 0: - if (modrm_rm == 5) - modrm_ea += insn_fetch(s32, 4, _eip); - break; - case 1: - modrm_ea += insn_fetch(s8, 1, _eip); - break; - case 2: - modrm_ea += insn_fetch(s32, 4, _eip); - break; - } - } - if (!override_base) - override_base = &ctxt->ds_base; - if (mode == X86EMUL_MODE_PROT64 && - override_base != &ctxt->fs_base && - override_base != &ctxt->gs_base) - override_base = NULL; - - if (override_base) - modrm_ea += *override_base; - - if (rip_relative) { - modrm_ea += _eip; - switch (d & SrcMask) { - case SrcImmByte: - modrm_ea += 1; - break; - case SrcImm: - if (d & ByteOp) - modrm_ea += 1; - else - if (op_bytes == 8) - modrm_ea += 4; - else - modrm_ea += op_bytes; - } - } - if (ad_bytes != 8) - modrm_ea = (u32)modrm_ea; - cr2 = modrm_ea; - modrm_done: - ; - } - - /* Decode and fetch the destination operand: register or memory. */ - switch (d & DstMask) { - case ImplicitOps: - /* Special instructions do their own operand decoding. */ - goto special_insn; - case DstReg: - dst.type = OP_REG; - if ((d & ByteOp) - && !(twobyte_table && (b == 0xb6 || b == 0xb7))) { - dst.ptr = decode_register(modrm_reg, _regs, - (rex_prefix == 0)); - dst.val = *(u8 *) dst.ptr; - dst.bytes = 1; - } else { - dst.ptr = decode_register(modrm_reg, _regs, 0); - switch ((dst.bytes = op_bytes)) { - case 2: - dst.val = *(u16 *)dst.ptr; - break; - case 4: - dst.val = *(u32 *)dst.ptr; - break; - case 8: - dst.val = *(u64 *)dst.ptr; - break; - } - } - break; - case DstMem: - dst.type = OP_MEM; - dst.ptr = (unsigned long *)cr2; - dst.bytes = (d & ByteOp) ? 1 : op_bytes; - if (!(d & Mov) && /* optimisation - avoid slow emulated read */ - ((rc = ops->read_emulated((unsigned long)dst.ptr, - &dst.val, dst.bytes, ctxt)) != 0)) - goto done; - break; - } - dst.orig_val = dst.val; - - /* - * Decode and fetch the source operand: register, memory - * or immediate. - */ - switch (d & SrcMask) { - case SrcNone: - break; - case SrcReg: - src.type = OP_REG; - if (d & ByteOp) { - src.ptr = decode_register(modrm_reg, _regs, - (rex_prefix == 0)); - src.val = src.orig_val = *(u8 *) src.ptr; - src.bytes = 1; - } else { - src.ptr = decode_register(modrm_reg, _regs, 0); - switch ((src.bytes = op_bytes)) { - case 2: - src.val = src.orig_val = *(u16 *) src.ptr; - break; - case 4: - src.val = src.orig_val = *(u32 *) src.ptr; - break; - case 8: - src.val = src.orig_val = *(u64 *) src.ptr; - break; - } - } - break; - case SrcMem16: - src.bytes = 2; - goto srcmem_common; - case SrcMem32: - src.bytes = 4; - goto srcmem_common; - case SrcMem: - src.bytes = (d & ByteOp) ? 1 : op_bytes; - srcmem_common: - src.type = OP_MEM; - src.ptr = (unsigned long *)cr2; - if ((rc = ops->read_emulated((unsigned long)src.ptr, - &src.val, src.bytes, ctxt)) != 0) - goto done; - src.orig_val = src.val; - break; - case SrcImm: - src.type = OP_IMM; - src.ptr = (unsigned long *)_eip; - src.bytes = (d & ByteOp) ? 1 : op_bytes; - if (src.bytes == 8) - src.bytes = 4; - /* NB. Immediates are sign-extended as necessary. */ - switch (src.bytes) { - case 1: - src.val = insn_fetch(s8, 1, _eip); - break; - case 2: - src.val = insn_fetch(s16, 2, _eip); - break; - case 4: - src.val = insn_fetch(s32, 4, _eip); - break; - } - break; - case SrcImmByte: - src.type = OP_IMM; - src.ptr = (unsigned long *)_eip; - src.bytes = 1; - src.val = insn_fetch(s8, 1, _eip); - break; - } - - if (twobyte) - goto twobyte_insn; - - switch (b) { - case 0x00 ... 0x05: - add: /* add */ - emulate_2op_SrcV("add", src, dst, _eflags); - break; - case 0x08 ... 0x0d: - or: /* or */ - emulate_2op_SrcV("or", src, dst, _eflags); - break; - case 0x10 ... 0x15: - adc: /* adc */ - emulate_2op_SrcV("adc", src, dst, _eflags); - break; - case 0x18 ... 0x1d: - sbb: /* sbb */ - emulate_2op_SrcV("sbb", src, dst, _eflags); - break; - case 0x20 ... 0x25: - and: /* and */ - emulate_2op_SrcV("and", src, dst, _eflags); - break; - case 0x28 ... 0x2d: - sub: /* sub */ - emulate_2op_SrcV("sub", src, dst, _eflags); - break; - case 0x30 ... 0x35: - xor: /* xor */ - emulate_2op_SrcV("xor", src, dst, _eflags); - break; - case 0x38 ... 0x3d: - cmp: /* cmp */ - emulate_2op_SrcV("cmp", src, dst, _eflags); - break; - case 0x63: /* movsxd */ - if (mode != X86EMUL_MODE_PROT64) - goto cannot_emulate; - dst.val = (s32) src.val; - break; - case 0x80 ... 0x83: /* Grp1 */ - switch (modrm_reg) { - case 0: - goto add; - case 1: - goto or; - case 2: - goto adc; - case 3: - goto sbb; - case 4: - goto and; - case 5: - goto sub; - case 6: - goto xor; - case 7: - goto cmp; - } - break; - case 0x84 ... 0x85: - test: /* test */ - emulate_2op_SrcV("test", src, dst, _eflags); - break; - case 0x86 ... 0x87: /* xchg */ - /* Write back the register source. */ - switch (dst.bytes) { - case 1: - *(u8 *) src.ptr = (u8) dst.val; - break; - case 2: - *(u16 *) src.ptr = (u16) dst.val; - break; - case 4: - *src.ptr = (u32) dst.val; - break; /* 64b reg: zero-extend */ - case 8: - *src.ptr = dst.val; - break; - } - /* - * Write back the memory destination with implicit LOCK - * prefix. - */ - dst.val = src.val; - lock_prefix = 1; - break; - case 0xa0 ... 0xa1: /* mov */ - dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; - dst.val = src.val; - _eip += ad_bytes; /* skip src displacement */ - break; - case 0xa2 ... 0xa3: /* mov */ - dst.val = (unsigned long)_regs[VCPU_REGS_RAX]; - _eip += ad_bytes; /* skip dst displacement */ - break; - case 0x88 ... 0x8b: /* mov */ - case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ - dst.val = src.val; - break; - case 0x8f: /* pop (sole member of Grp1a) */ - /* 64-bit mode: POP always pops a 64-bit operand. */ - if (mode == X86EMUL_MODE_PROT64) - dst.bytes = 8; - if ((rc = ops->read_std(register_address(ctxt->ss_base, - _regs[VCPU_REGS_RSP]), - &dst.val, dst.bytes, ctxt)) != 0) - goto done; - register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes); - break; - case 0xc0 ... 0xc1: - grp2: /* Grp2 */ - switch (modrm_reg) { - case 0: /* rol */ - emulate_2op_SrcB("rol", src, dst, _eflags); - break; - case 1: /* ror */ - emulate_2op_SrcB("ror", src, dst, _eflags); - break; - case 2: /* rcl */ - emulate_2op_SrcB("rcl", src, dst, _eflags); - break; - case 3: /* rcr */ - emulate_2op_SrcB("rcr", src, dst, _eflags); - break; - case 4: /* sal/shl */ - case 6: /* sal/shl */ - emulate_2op_SrcB("sal", src, dst, _eflags); - break; - case 5: /* shr */ - emulate_2op_SrcB("shr", src, dst, _eflags); - break; - case 7: /* sar */ - emulate_2op_SrcB("sar", src, dst, _eflags); - break; - } - break; - case 0xd0 ... 0xd1: /* Grp2 */ - src.val = 1; - goto grp2; - case 0xd2 ... 0xd3: /* Grp2 */ - src.val = _regs[VCPU_REGS_RCX]; - goto grp2; - case 0xf6 ... 0xf7: /* Grp3 */ - switch (modrm_reg) { - case 0 ... 1: /* test */ - /* - * Special case in Grp3: test has an immediate - * source operand. - */ - src.type = OP_IMM; - src.ptr = (unsigned long *)_eip; - src.bytes = (d & ByteOp) ? 1 : op_bytes; - if (src.bytes == 8) - src.bytes = 4; - switch (src.bytes) { - case 1: - src.val = insn_fetch(s8, 1, _eip); - break; - case 2: - src.val = insn_fetch(s16, 2, _eip); - break; - case 4: - src.val = insn_fetch(s32, 4, _eip); - break; - } - goto test; - case 2: /* not */ - dst.val = ~dst.val; - break; - case 3: /* neg */ - emulate_1op("neg", dst, _eflags); - break; - default: - goto cannot_emulate; - } - break; - case 0xfe ... 0xff: /* Grp4/Grp5 */ - switch (modrm_reg) { - case 0: /* inc */ - emulate_1op("inc", dst, _eflags); - break; - case 1: /* dec */ - emulate_1op("dec", dst, _eflags); - break; - case 6: /* push */ - /* 64-bit mode: PUSH always pushes a 64-bit operand. */ - if (mode == X86EMUL_MODE_PROT64) { - dst.bytes = 8; - if ((rc = ops->read_std((unsigned long)dst.ptr, - &dst.val, 8, - ctxt)) != 0) - goto done; - } - register_address_increment(_regs[VCPU_REGS_RSP], - -dst.bytes); - if ((rc = ops->write_std( - register_address(ctxt->ss_base, - _regs[VCPU_REGS_RSP]), - dst.val, dst.bytes, ctxt)) != 0) - goto done; - dst.val = dst.orig_val; /* skanky: disable writeback */ - break; - default: - goto cannot_emulate; - } - break; - } - -writeback: - if ((d & Mov) || (dst.orig_val != dst.val)) { - switch (dst.type) { - case OP_REG: - /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ - switch (dst.bytes) { - case 1: - *(u8 *)dst.ptr = (u8)dst.val; - break; - case 2: - *(u16 *)dst.ptr = (u16)dst.val; - break; - case 4: - *dst.ptr = (u32)dst.val; - break; /* 64b: zero-ext */ - case 8: - *dst.ptr = dst.val; - break; - } - break; - case OP_MEM: - if (lock_prefix) - rc = ops->cmpxchg_emulated((unsigned long)dst. - ptr, dst.orig_val, - dst.val, dst.bytes, - ctxt); - else - rc = ops->write_emulated((unsigned long)dst.ptr, - dst.val, dst.bytes, - ctxt); - if (rc != 0) - goto done; - default: - break; - } - } - - /* Commit shadow register state. */ - memcpy(ctxt->vcpu->regs, _regs, sizeof _regs); - ctxt->eflags = _eflags; - ctxt->vcpu->rip = _eip; - -done: - return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; - -special_insn: - if (twobyte) - goto twobyte_special_insn; - if (rep_prefix) { - if (_regs[VCPU_REGS_RCX] == 0) { - ctxt->vcpu->rip = _eip; - goto done; - } - _regs[VCPU_REGS_RCX]--; - _eip = ctxt->vcpu->rip; - } - switch (b) { - case 0xa4 ... 0xa5: /* movs */ - dst.type = OP_MEM; - dst.bytes = (d & ByteOp) ? 1 : op_bytes; - dst.ptr = (unsigned long *)register_address(ctxt->es_base, - _regs[VCPU_REGS_RDI]); - if ((rc = ops->read_emulated(register_address( - override_base ? *override_base : ctxt->ds_base, - _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt)) != 0) - goto done; - register_address_increment(_regs[VCPU_REGS_RSI], - (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - register_address_increment(_regs[VCPU_REGS_RDI], - (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - break; - case 0xa6 ... 0xa7: /* cmps */ - DPRINTF("Urk! I don't handle CMPS.\n"); - goto cannot_emulate; - case 0xaa ... 0xab: /* stos */ - dst.type = OP_MEM; - dst.bytes = (d & ByteOp) ? 1 : op_bytes; - dst.ptr = (unsigned long *)cr2; - dst.val = _regs[VCPU_REGS_RAX]; - register_address_increment(_regs[VCPU_REGS_RDI], - (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - break; - case 0xac ... 0xad: /* lods */ - dst.type = OP_REG; - dst.bytes = (d & ByteOp) ? 1 : op_bytes; - dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; - if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes, ctxt)) != 0) - goto done; - register_address_increment(_regs[VCPU_REGS_RSI], - (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - break; - case 0xae ... 0xaf: /* scas */ - DPRINTF("Urk! I don't handle SCAS.\n"); - goto cannot_emulate; - } - goto writeback; - -twobyte_insn: - switch (b) { - case 0x01: /* lgdt, lidt, lmsw */ - switch (modrm_reg) { - u16 size; - unsigned long address; - - case 2: /* lgdt */ - rc = read_descriptor(ctxt, ops, src.ptr, - &size, &address, op_bytes); - if (rc) - goto done; - realmode_lgdt(ctxt->vcpu, size, address); - break; - case 3: /* lidt */ - rc = read_descriptor(ctxt, ops, src.ptr, - &size, &address, op_bytes); - if (rc) - goto done; - realmode_lidt(ctxt->vcpu, size, address); - break; - case 4: /* smsw */ - if (modrm_mod != 3) - goto cannot_emulate; - *(u16 *)&_regs[modrm_rm] - = realmode_get_cr(ctxt->vcpu, 0); - break; - case 6: /* lmsw */ - if (modrm_mod != 3) - goto cannot_emulate; - realmode_lmsw(ctxt->vcpu, (u16)modrm_val, &_eflags); - break; - case 7: /* invlpg*/ - emulate_invlpg(ctxt->vcpu, cr2); - break; - default: - goto cannot_emulate; - } - break; - case 0x21: /* mov from dr to reg */ - if (modrm_mod != 3) - goto cannot_emulate; - rc = emulator_get_dr(ctxt, modrm_reg, &_regs[modrm_rm]); - break; - case 0x23: /* mov from reg to dr */ - if (modrm_mod != 3) - goto cannot_emulate; - rc = emulator_set_dr(ctxt, modrm_reg, _regs[modrm_rm]); - break; - case 0x40 ... 0x4f: /* cmov */ - dst.val = dst.orig_val = src.val; - d &= ~Mov; /* default to no move */ - /* - * First, assume we're decoding an even cmov opcode - * (lsb == 0). - */ - switch ((b & 15) >> 1) { - case 0: /* cmovo */ - d |= (_eflags & EFLG_OF) ? Mov : 0; - break; - case 1: /* cmovb/cmovc/cmovnae */ - d |= (_eflags & EFLG_CF) ? Mov : 0; - break; - case 2: /* cmovz/cmove */ - d |= (_eflags & EFLG_ZF) ? Mov : 0; - break; - case 3: /* cmovbe/cmovna */ - d |= (_eflags & (EFLG_CF | EFLG_ZF)) ? Mov : 0; - break; - case 4: /* cmovs */ - d |= (_eflags & EFLG_SF) ? Mov : 0; - break; - case 5: /* cmovp/cmovpe */ - d |= (_eflags & EFLG_PF) ? Mov : 0; - break; - case 7: /* cmovle/cmovng */ - d |= (_eflags & EFLG_ZF) ? Mov : 0; - /* fall through */ - case 6: /* cmovl/cmovnge */ - d |= (!(_eflags & EFLG_SF) != - !(_eflags & EFLG_OF)) ? Mov : 0; - break; - } - /* Odd cmov opcodes (lsb == 1) have inverted sense. */ - d ^= (b & 1) ? Mov : 0; - break; - case 0xb0 ... 0xb1: /* cmpxchg */ - /* - * Save real source value, then compare EAX against - * destination. - */ - src.orig_val = src.val; - src.val = _regs[VCPU_REGS_RAX]; - emulate_2op_SrcV("cmp", src, dst, _eflags); - /* Always write back. The question is: where to? */ - d |= Mov; - if (_eflags & EFLG_ZF) { - /* Success: write back to memory. */ - dst.val = src.orig_val; - } else { - /* Failure: write the value we saw to EAX. */ - dst.type = OP_REG; - dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; - } - break; - case 0xa3: - bt: /* bt */ - src.val &= (dst.bytes << 3) - 1; /* only subword offset */ - emulate_2op_SrcV_nobyte("bt", src, dst, _eflags); - break; - case 0xb3: - btr: /* btr */ - src.val &= (dst.bytes << 3) - 1; /* only subword offset */ - emulate_2op_SrcV_nobyte("btr", src, dst, _eflags); - break; - case 0xab: - bts: /* bts */ - src.val &= (dst.bytes << 3) - 1; /* only subword offset */ - emulate_2op_SrcV_nobyte("bts", src, dst, _eflags); - break; - case 0xb6 ... 0xb7: /* movzx */ - dst.bytes = op_bytes; - dst.val = (d & ByteOp) ? (u8) src.val : (u16) src.val; - break; - case 0xbb: - btc: /* btc */ - src.val &= (dst.bytes << 3) - 1; /* only subword offset */ - emulate_2op_SrcV_nobyte("btc", src, dst, _eflags); - break; - case 0xba: /* Grp8 */ - switch (modrm_reg & 3) { - case 0: - goto bt; - case 1: - goto bts; - case 2: - goto btr; - case 3: - goto btc; - } - break; - case 0xbe ... 0xbf: /* movsx */ - dst.bytes = op_bytes; - dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val; - break; - } - goto writeback; - -twobyte_special_insn: - /* Disable writeback. */ - dst.orig_val = dst.val; - switch (b) { - case 0x0d: /* GrpP (prefetch) */ - case 0x18: /* Grp16 (prefetch/nop) */ - break; - case 0x06: - emulate_clts(ctxt->vcpu); - break; - case 0x20: /* mov cr, reg */ - if (modrm_mod != 3) - goto cannot_emulate; - _regs[modrm_rm] = realmode_get_cr(ctxt->vcpu, modrm_reg); - break; - case 0x22: /* mov reg, cr */ - if (modrm_mod != 3) - goto cannot_emulate; - realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags); - break; - case 0xc7: /* Grp9 (cmpxchg8b) */ -#if defined(__i386__) - { - unsigned long old_lo, old_hi; - if (((rc = ops->read_emulated(cr2 + 0, &old_lo, 4, - ctxt)) != 0) - || ((rc = ops->read_emulated(cr2 + 4, &old_hi, 4, - ctxt)) != 0)) - goto done; - if ((old_lo != _regs[VCPU_REGS_RAX]) - || (old_hi != _regs[VCPU_REGS_RDI])) { - _regs[VCPU_REGS_RAX] = old_lo; - _regs[VCPU_REGS_RDX] = old_hi; - _eflags &= ~EFLG_ZF; - } else if (ops->cmpxchg8b_emulated == NULL) { - rc = X86EMUL_UNHANDLEABLE; - goto done; - } else { - if ((rc = ops->cmpxchg8b_emulated(cr2, old_lo, - old_hi, - _regs[VCPU_REGS_RBX], - _regs[VCPU_REGS_RCX], - ctxt)) != 0) - goto done; - _eflags |= EFLG_ZF; - } - break; - } -#elif defined(CONFIG_X86_64) - { - unsigned long old, new; - if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0) - goto done; - if (((u32) (old >> 0) != (u32) _regs[VCPU_REGS_RAX]) || - ((u32) (old >> 32) != (u32) _regs[VCPU_REGS_RDX])) { - _regs[VCPU_REGS_RAX] = (u32) (old >> 0); - _regs[VCPU_REGS_RDX] = (u32) (old >> 32); - _eflags &= ~EFLG_ZF; - } else { - new = (_regs[VCPU_REGS_RCX] << 32) | (u32) _regs[VCPU_REGS_RBX]; - if ((rc = ops->cmpxchg_emulated(cr2, old, - new, 8, ctxt)) != 0) - goto done; - _eflags |= EFLG_ZF; - } - break; - } -#endif - } - goto writeback; - -cannot_emulate: - DPRINTF("Cannot emulate %02x\n", b); - return -1; -} - -#ifdef __XEN__ - -#include -#include - -int -x86_emulate_read_std(unsigned long addr, - unsigned long *val, - unsigned int bytes, struct x86_emulate_ctxt *ctxt) -{ - unsigned int rc; - - *val = 0; - - if ((rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0) { - propagate_page_fault(addr + bytes - rc, 0); /* read fault */ - return X86EMUL_PROPAGATE_FAULT; - } - - return X86EMUL_CONTINUE; -} - -int -x86_emulate_write_std(unsigned long addr, - unsigned long val, - unsigned int bytes, struct x86_emulate_ctxt *ctxt) -{ - unsigned int rc; - - if ((rc = copy_to_user((void *)addr, (void *)&val, bytes)) != 0) { - propagate_page_fault(addr + bytes - rc, PGERR_write_access); - return X86EMUL_PROPAGATE_FAULT; - } - - return X86EMUL_CONTINUE; -} - -#endif diff --git a/trunk/drivers/kvm/x86_emulate.h b/trunk/drivers/kvm/x86_emulate.h deleted file mode 100644 index 5d41bd55125e..000000000000 --- a/trunk/drivers/kvm/x86_emulate.h +++ /dev/null @@ -1,185 +0,0 @@ -/****************************************************************************** - * x86_emulate.h - * - * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. - * - * Copyright (c) 2005 Keir Fraser - * - * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 - */ - -#ifndef __X86_EMULATE_H__ -#define __X86_EMULATE_H__ - -struct x86_emulate_ctxt; - -/* - * x86_emulate_ops: - * - * These operations represent the instruction emulator's interface to memory. - * There are two categories of operation: those that act on ordinary memory - * regions (*_std), and those that act on memory regions known to require - * special treatment or emulation (*_emulated). - * - * The emulator assumes that an instruction accesses only one 'emulated memory' - * location, that this location is the given linear faulting address (cr2), and - * that this is one of the instruction's data operands. Instruction fetches and - * stack operations are assumed never to access emulated memory. The emulator - * automatically deduces which operand of a string-move operation is accessing - * emulated memory, and assumes that the other operand accesses normal memory. - * - * NOTES: - * 1. The emulator isn't very smart about emulated vs. standard memory. - * 'Emulated memory' access addresses should be checked for sanity. - * 'Normal memory' accesses may fault, and the caller must arrange to - * detect and handle reentrancy into the emulator via recursive faults. - * Accesses may be unaligned and may cross page boundaries. - * 2. If the access fails (cannot emulate, or a standard access faults) then - * it is up to the memop to propagate the fault to the guest VM via - * some out-of-band mechanism, unknown to the emulator. The memop signals - * failure by returning X86EMUL_PROPAGATE_FAULT to the emulator, which will - * then immediately bail. - * 3. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only - * cmpxchg8b_emulated need support 8-byte accesses. - * 4. The emulator cannot handle 64-bit mode emulation on an x86/32 system. - */ -/* Access completed successfully: continue emulation as normal. */ -#define X86EMUL_CONTINUE 0 -/* Access is unhandleable: bail from emulation and return error to caller. */ -#define X86EMUL_UNHANDLEABLE 1 -/* Terminate emulation but return success to the caller. */ -#define X86EMUL_PROPAGATE_FAULT 2 /* propagate a generated fault to guest */ -#define X86EMUL_RETRY_INSTR 2 /* retry the instruction for some reason */ -#define X86EMUL_CMPXCHG_FAILED 2 /* cmpxchg did not see expected value */ -struct x86_emulate_ops { - /* - * read_std: Read bytes of standard (non-emulated/special) memory. - * Used for instruction fetch, stack operations, and others. - * @addr: [IN ] Linear address from which to read. - * @val: [OUT] Value read from memory, zero-extended to 'u_long'. - * @bytes: [IN ] Number of bytes to read from memory. - */ - int (*read_std)(unsigned long addr, - unsigned long *val, - unsigned int bytes, struct x86_emulate_ctxt * ctxt); - - /* - * write_std: Write bytes of standard (non-emulated/special) memory. - * Used for stack operations, and others. - * @addr: [IN ] Linear address to which to write. - * @val: [IN ] Value to write to memory (low-order bytes used as - * required). - * @bytes: [IN ] Number of bytes to write to memory. - */ - int (*write_std)(unsigned long addr, - unsigned long val, - unsigned int bytes, struct x86_emulate_ctxt * ctxt); - - /* - * read_emulated: Read bytes from emulated/special memory area. - * @addr: [IN ] Linear address from which to read. - * @val: [OUT] Value read from memory, zero-extended to 'u_long'. - * @bytes: [IN ] Number of bytes to read from memory. - */ - int (*read_emulated) (unsigned long addr, - unsigned long *val, - unsigned int bytes, - struct x86_emulate_ctxt * ctxt); - - /* - * write_emulated: Read bytes from emulated/special memory area. - * @addr: [IN ] Linear address to which to write. - * @val: [IN ] Value to write to memory (low-order bytes used as - * required). - * @bytes: [IN ] Number of bytes to write to memory. - */ - int (*write_emulated) (unsigned long addr, - unsigned long val, - unsigned int bytes, - struct x86_emulate_ctxt * ctxt); - - /* - * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG operation on an - * emulated/special memory area. - * @addr: [IN ] Linear address to access. - * @old: [IN ] Value expected to be current at @addr. - * @new: [IN ] Value to write to @addr. - * @bytes: [IN ] Number of bytes to access using CMPXCHG. - */ - int (*cmpxchg_emulated) (unsigned long addr, - unsigned long old, - unsigned long new, - unsigned int bytes, - struct x86_emulate_ctxt * ctxt); - - /* - * cmpxchg8b_emulated: Emulate an atomic (LOCKed) CMPXCHG8B operation on an - * emulated/special memory area. - * @addr: [IN ] Linear address to access. - * @old: [IN ] Value expected to be current at @addr. - * @new: [IN ] Value to write to @addr. - * NOTES: - * 1. This function is only ever called when emulating a real CMPXCHG8B. - * 2. This function is *never* called on x86/64 systems. - * 2. Not defining this function (i.e., specifying NULL) is equivalent - * to defining a function that always returns X86EMUL_UNHANDLEABLE. - */ - int (*cmpxchg8b_emulated) (unsigned long addr, - unsigned long old_lo, - unsigned long old_hi, - unsigned long new_lo, - unsigned long new_hi, - struct x86_emulate_ctxt * ctxt); -}; - -struct cpu_user_regs; - -struct x86_emulate_ctxt { - /* Register state before/after emulation. */ - struct kvm_vcpu *vcpu; - - /* Linear faulting address (if emulating a page-faulting instruction). */ - unsigned long eflags; - unsigned long cr2; - - /* Emulated execution mode, represented by an X86EMUL_MODE value. */ - int mode; - - unsigned long cs_base; - unsigned long ds_base; - unsigned long es_base; - unsigned long ss_base; - unsigned long gs_base; - unsigned long fs_base; -}; - -/* Execution mode, passed to the emulator. */ -#define X86EMUL_MODE_REAL 0 /* Real mode. */ -#define X86EMUL_MODE_PROT16 2 /* 16-bit protected mode. */ -#define X86EMUL_MODE_PROT32 4 /* 32-bit protected mode. */ -#define X86EMUL_MODE_PROT64 8 /* 64-bit (long) mode. */ - -/* Host execution mode. */ -#if defined(__i386__) -#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32 -#elif defined(CONFIG_X86_64) -#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64 -#endif - -/* - * x86_emulate_memop: Emulate an instruction that faulted attempting to - * read/write a 'special' memory area. - * Returns -1 on failure, 0 on success. - */ -int x86_emulate_memop(struct x86_emulate_ctxt *ctxt, - struct x86_emulate_ops *ops); - -/* - * Given the 'reg' portion of a ModRM byte, and a register block, return a - * pointer into the block that addresses the relevant register. - * @highbyte_regs specifies whether to decode AH,CH,DH,BH. - */ -void *decode_register(u8 modrm_reg, unsigned long *regs, - int highbyte_regs); - -#endif /* __X86_EMULATE_H__ */ diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index 7399ba791116..176142c61492 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -12,7 +12,7 @@ config NEW_LEDS config LEDS_CLASS tristate "LED Class Support" - depends on NEW_LEDS + depends NEW_LEDS help This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. @@ -21,28 +21,28 @@ comment "LED drivers" config LEDS_CORGI tristate "LED Support for the Sharp SL-C7x0 series" - depends on LEDS_CLASS && PXA_SHARP_C7xx + depends LEDS_CLASS && PXA_SHARP_C7xx help This option enables support for the LEDs on Sharp Zaurus SL-C7x0 series (C700, C750, C760, C860). config LEDS_LOCOMO tristate "LED Support for Locomo device" - depends on LEDS_CLASS && SHARP_LOCOMO + depends LEDS_CLASS && SHARP_LOCOMO help This option enables support for the LEDs on Sharp Locomo. Zaurus models SL-5500 and SL-5600. config LEDS_SPITZ tristate "LED Support for the Sharp SL-Cxx00 series" - depends on LEDS_CLASS && PXA_SHARP_Cxx00 + depends LEDS_CLASS && PXA_SHARP_Cxx00 help This option enables support for the LEDs on Sharp Zaurus SL-Cxx00 series (C1000, C3000, C3100). config LEDS_IXP4XX tristate "LED Support for GPIO connected LEDs on IXP4XX processors" - depends on LEDS_CLASS && ARCH_IXP4XX + depends LEDS_CLASS && ARCH_IXP4XX help This option enables support for the LEDs connected to GPIO outputs of the Intel IXP4XX processors. To be useful the @@ -51,7 +51,7 @@ config LEDS_IXP4XX config LEDS_TOSA tristate "LED Support for the Sharp SL-6000 series" - depends on LEDS_CLASS && PXA_SHARPSL + depends LEDS_CLASS && PXA_SHARPSL help This option enables support for the LEDs on Sharp Zaurus SL-6000 series. @@ -65,7 +65,7 @@ config LEDS_S3C24XX config LEDS_AMS_DELTA tristate "LED Support for the Amstrad Delta (E3)" - depends on LEDS_CLASS && MACH_AMS_DELTA + depends LEDS_CLASS && MACH_AMS_DELTA help This option enables support for the LEDs on Amstrad Delta (E3). @@ -86,7 +86,7 @@ comment "LED Triggers" config LEDS_TRIGGERS bool "LED Trigger support" - depends on NEW_LEDS + depends NEW_LEDS help This option enables trigger support for the leds class. These triggers allow kernel events to drive the LEDs and can @@ -94,21 +94,21 @@ config LEDS_TRIGGERS config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" - depends on LEDS_TRIGGERS + depends LEDS_TRIGGERS help This allows LEDs to be controlled by a programmable timer via sysfs. If unsure, say Y. config LEDS_TRIGGER_IDE_DISK bool "LED IDE Disk Trigger" - depends on LEDS_TRIGGERS && BLK_DEV_IDEDISK + depends LEDS_TRIGGERS && BLK_DEV_IDEDISK help This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. config LEDS_TRIGGER_HEARTBEAT tristate "LED Heartbeat Trigger" - depends on LEDS_TRIGGERS + depends LEDS_TRIGGERS help This allows LEDs to be controlled by a CPU load average. The flash frequency is a hyperbolic function of the 1-minute diff --git a/trunk/drivers/macintosh/adb.c b/trunk/drivers/macintosh/adb.c index 7cec6de5e2b0..d43ea81d6df9 100644 --- a/trunk/drivers/macintosh/adb.c +++ b/trunk/drivers/macintosh/adb.c @@ -828,7 +828,7 @@ static ssize_t adb_write(struct file *file, const char __user *buf, if (!access_ok(VERIFY_READ, buf, count)) return -EFAULT; - req = kmalloc(sizeof(struct adb_request), + req = (struct adb_request *) kmalloc(sizeof(struct adb_request), GFP_KERNEL); if (req == NULL) return -ENOMEM; diff --git a/trunk/drivers/macintosh/apm_emu.c b/trunk/drivers/macintosh/apm_emu.c index 4300c628f8af..8862a83b8d84 100644 --- a/trunk/drivers/macintosh/apm_emu.c +++ b/trunk/drivers/macintosh/apm_emu.c @@ -321,7 +321,7 @@ static int do_open(struct inode * inode, struct file * filp) { struct apm_user * as; - as = kmalloc(sizeof(*as), GFP_KERNEL); + as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); if (as == NULL) { printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", sizeof(*as)); diff --git a/trunk/drivers/macintosh/smu.c b/trunk/drivers/macintosh/smu.c index 6f30459b9385..6dde27ab79a8 100644 --- a/trunk/drivers/macintosh/smu.c +++ b/trunk/drivers/macintosh/smu.c @@ -945,7 +945,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id) */ tlen = sizeof(struct property) + len + 18; - prop = kzalloc(tlen, GFP_KERNEL); + prop = kcalloc(tlen, 1, GFP_KERNEL); if (prop == NULL) return NULL; hdr = (struct smu_sdbp_header *)(prop + 1); diff --git a/trunk/drivers/macintosh/via-pmu68k.c b/trunk/drivers/macintosh/via-pmu68k.c index 93e6ef9233f9..d9986f3a3fbf 100644 --- a/trunk/drivers/macintosh/via-pmu68k.c +++ b/trunk/drivers/macintosh/via-pmu68k.c @@ -847,7 +847,7 @@ pbook_pci_save(void) n_pbook_pci_saves = npci; if (npci == 0) return; - ps = kmalloc(npci * sizeof(*ps), GFP_KERNEL); + ps = (struct pci_save *) kmalloc(npci * sizeof(*ps), GFP_KERNEL); pbook_pci_saves = ps; if (ps == NULL) return; diff --git a/trunk/drivers/md/Kconfig b/trunk/drivers/md/Kconfig index 4540ade6b6b5..c92c1521546d 100644 --- a/trunk/drivers/md/Kconfig +++ b/trunk/drivers/md/Kconfig @@ -215,7 +215,6 @@ config DM_CRYPT tristate "Crypt target support" depends on BLK_DEV_DM && EXPERIMENTAL select CRYPTO - select CRYPTO_CBC ---help--- This device-mapper target allows you to create a device that transparently encrypts the data on it. You'll need to activate diff --git a/trunk/drivers/md/faulty.c b/trunk/drivers/md/faulty.c index 4ebd0f2a75ec..a7a5ab554338 100644 --- a/trunk/drivers/md/faulty.c +++ b/trunk/drivers/md/faulty.c @@ -173,7 +173,7 @@ static int make_request(request_queue_t *q, struct bio *bio) conf_t *conf = (conf_t*)mddev->private; int failit = 0; - if (bio_data_dir(bio) == WRITE) { + if (bio->bi_rw & 1) { /* write request */ if (atomic_read(&conf->counters[WriteAll])) { /* special case - don't decrement, don't generic_make_request, diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 21e2a7b08841..53bd46dba0cb 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -3314,10 +3314,6 @@ static int do_md_stop(mddev_t * mddev, int mode) module_put(mddev->pers->owner); mddev->pers = NULL; - - set_capacity(disk, 0); - mddev->changed = 1; - if (mddev->ro) mddev->ro = 0; } @@ -3337,7 +3333,7 @@ static int do_md_stop(mddev_t * mddev, int mode) if (mode == 0) { mdk_rdev_t *rdev; struct list_head *tmp; - + struct gendisk *disk; printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); bitmap_destroy(mddev); @@ -3362,6 +3358,10 @@ static int do_md_stop(mddev_t * mddev, int mode) mddev->raid_disks = 0; mddev->recovery_cp = 0; + disk = mddev->gendisk; + if (disk) + set_capacity(disk, 0); + mddev->changed = 1; } else if (mddev->pers) printk(KERN_INFO "md: %s switched to read-only mode.\n", mdname(mddev)); @@ -3371,7 +3371,6 @@ static int do_md_stop(mddev_t * mddev, int mode) return err; } -#ifndef MODULE static void autorun_array(mddev_t *mddev) { mdk_rdev_t *rdev; @@ -3486,7 +3485,6 @@ static void autorun_devices(int part) } printk(KERN_INFO "md: ... autorun DONE.\n"); } -#endif /* !MODULE */ static int get_version(void __user * arg) { @@ -3724,7 +3722,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) if (err) export_rdev(rdev); - md_update_sb(mddev, 1); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); return err; @@ -5276,6 +5273,7 @@ void md_do_sync(mddev_t *mddev) mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && + test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && mddev->curr_resync > 2) { if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { @@ -5299,7 +5297,6 @@ void md_do_sync(mddev_t *mddev) rdev->recovery_offset = mddev->curr_resync; } } - set_bit(MD_CHANGE_DEVS, &mddev->flags); skip: mddev->curr_resync = 0; @@ -5596,7 +5593,7 @@ static void autostart_arrays(int part) autorun_devices(part); } -#endif /* !MODULE */ +#endif static __exit void md_exit(void) { diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index b30f74be3982..656fae912fe3 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -1736,7 +1736,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i /* take from bio_init */ bio->bi_next = NULL; bio->bi_flags |= 1 << BIO_UPTODATE; - bio->bi_rw = READ; + bio->bi_rw = 0; bio->bi_vcnt = 0; bio->bi_idx = 0; bio->bi_phys_segments = 0; @@ -1951,7 +1951,6 @@ static int run(mddev_t *mddev) !test_bit(In_sync, &disk->rdev->flags)) { disk->head_position = 0; mddev->degraded++; - conf->fullsync = 1; } } if (mddev->degraded == conf->raid_disks) { diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index f0141910bb8d..7492d6033ac6 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -1785,7 +1785,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i biolist = bio; bio->bi_private = r10_bio; bio->bi_end_io = end_sync_read; - bio->bi_rw = READ; + bio->bi_rw = 0; bio->bi_sector = r10_bio->devs[j].addr + conf->mirrors[d].rdev->data_offset; bio->bi_bdev = conf->mirrors[d].rdev->bdev; @@ -1801,7 +1801,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i biolist = bio; bio->bi_private = r10_bio; bio->bi_end_io = end_sync_write; - bio->bi_rw = WRITE; + bio->bi_rw = 1; bio->bi_sector = r10_bio->devs[k].addr + conf->mirrors[i].rdev->data_offset; bio->bi_bdev = conf->mirrors[i].rdev->bdev; @@ -1870,7 +1870,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i biolist = bio; bio->bi_private = r10_bio; bio->bi_end_io = end_sync_read; - bio->bi_rw = READ; + bio->bi_rw = 0; bio->bi_sector = r10_bio->devs[i].addr + conf->mirrors[d].rdev->data_offset; bio->bi_bdev = conf->mirrors[d].rdev->bdev; diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index be008f034ada..52914d5cec76 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -134,8 +134,6 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) if (!test_bit(STRIPE_EXPANDING, &sh->state)) { list_add_tail(&sh->lru, &conf->inactive_list); wake_up(&conf->wait_for_stripe); - if (conf->retry_read_aligned) - md_wakeup_thread(conf->mddev->thread); } } } @@ -544,7 +542,35 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, } if (uptodate) { +#if 0 + struct bio *bio; + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); + /* we can return a buffer if we bypassed the cache or + * if the top buffer is not in highmem. If there are + * multiple buffers, leave the extra work to + * handle_stripe + */ + buffer = sh->bh_read[i]; + if (buffer && + (!PageHighMem(buffer->b_page) + || buffer->b_page == bh->b_page ) + ) { + sh->bh_read[i] = buffer->b_reqnext; + buffer->b_reqnext = NULL; + } else + buffer = NULL; + spin_unlock_irqrestore(&conf->device_lock, flags); + if (sh->bh_page[i]==bh->b_page) + set_buffer_uptodate(bh); + if (buffer) { + if (buffer->b_page != bh->b_page) + memcpy(buffer->b_data, bh->b_data, bh->b_size); + buffer->b_end_io(buffer, 1); + } +#else set_bit(R5_UPTODATE, &sh->dev[i].flags); +#endif if (test_bit(R5_ReadError, &sh->dev[i].flags)) { rdev = conf->disks[i].rdev; printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n", @@ -590,6 +616,14 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, } } rdev_dec_pending(conf->disks[i].rdev, conf->mddev); +#if 0 + /* must restore b_page before unlocking buffer... */ + if (sh->bh_page[i] != bh->b_page) { + bh->b_page = sh->bh_page[i]; + bh->b_data = page_address(bh->b_page); + clear_buffer_uptodate(bh); + } +#endif clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); release_stripe(sh); @@ -787,8 +821,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks, static sector_t compute_blocknr(struct stripe_head *sh, int i) { raid5_conf_t *conf = sh->raid_conf; - int raid_disks = sh->disks; - int data_disks = raid_disks - conf->max_degraded; + int raid_disks = sh->disks, data_disks = raid_disks - 1; sector_t new_sector = sh->sector, check; int sectors_per_chunk = conf->chunk_size >> 9; sector_t stripe; @@ -824,6 +857,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i) } break; case 6: + data_disks = raid_disks - 2; if (i == raid6_next_disk(sh->pd_idx, raid_disks)) return 0; /* It is the Q disk */ switch (conf->algorithm) { @@ -1319,10 +1353,8 @@ static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks) int pd_idx, dd_idx; int chunk_offset = sector_div(stripe, sectors_per_chunk); - raid5_compute_sector(stripe * (disks - conf->max_degraded) - *sectors_per_chunk + chunk_offset, - disks, disks - conf->max_degraded, - &dd_idx, &pd_idx, conf); + raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk + + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf); return pd_idx; } @@ -1583,6 +1615,15 @@ static void handle_stripe5(struct stripe_head *sh) } else if (test_bit(R5_Insync, &dev->flags)) { set_bit(R5_LOCKED, &dev->flags); set_bit(R5_Wantread, &dev->flags); +#if 0 + /* if I am just reading this block and we don't have + a failed drive, or any pending writes then sidestep the cache */ + if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext && + ! syncing && !failed && !to_write) { + sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page; + sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data; + } +#endif locked++; PRINTK("Reading block %d (sync=%d)\n", i, syncing); @@ -1600,6 +1641,9 @@ static void handle_stripe5(struct stripe_head *sh) dev = &sh->dev[i]; if ((dev->towrite || i == sh->pd_idx) && (!test_bit(R5_LOCKED, &dev->flags) +#if 0 +|| sh->bh_page[i]!=bh->b_page +#endif ) && !test_bit(R5_UPTODATE, &dev->flags)) { if (test_bit(R5_Insync, &dev->flags) @@ -1611,6 +1655,9 @@ static void handle_stripe5(struct stripe_head *sh) /* Would I have to read this buffer for reconstruct_write */ if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx && (!test_bit(R5_LOCKED, &dev->flags) +#if 0 +|| sh->bh_page[i] != bh->b_page +#endif ) && !test_bit(R5_UPTODATE, &dev->flags)) { if (test_bit(R5_Insync, &dev->flags)) rcw++; @@ -1818,25 +1865,23 @@ static void handle_stripe5(struct stripe_head *sh) return_bi = bi->bi_next; bi->bi_next = NULL; bi->bi_size = 0; - bi->bi_end_io(bi, bytes, - test_bit(BIO_UPTODATE, &bi->bi_flags) - ? 0 : -EIO); + bi->bi_end_io(bi, bytes, 0); } for (i=disks; i-- ;) { int rw; struct bio *bi; mdk_rdev_t *rdev; if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) - rw = WRITE; + rw = 1; else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags)) - rw = READ; + rw = 0; else continue; bi = &sh->dev[i].req; bi->bi_rw = rw; - if (rw == WRITE) + if (rw) bi->bi_end_io = raid5_end_write_request; else bi->bi_end_io = raid5_end_read_request; @@ -1872,7 +1917,7 @@ static void handle_stripe5(struct stripe_head *sh) atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); generic_make_request(bi); } else { - if (rw == WRITE) + if (rw == 1) set_bit(STRIPE_DEGRADED, &sh->state); PRINTK("skip op %ld on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); @@ -2148,6 +2193,15 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) } else if (test_bit(R5_Insync, &dev->flags)) { set_bit(R5_LOCKED, &dev->flags); set_bit(R5_Wantread, &dev->flags); +#if 0 + /* if I am just reading this block and we don't have + a failed drive, or any pending writes then sidestep the cache */ + if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext && + ! syncing && !failed && !to_write) { + sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page; + sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data; + } +#endif locked++; PRINTK("Reading block %d (sync=%d)\n", i, syncing); @@ -2166,6 +2220,9 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) if (!test_bit(R5_OVERWRITE, &dev->flags) && i != pd_idx && i != qd_idx && (!test_bit(R5_LOCKED, &dev->flags) +#if 0 + || sh->bh_page[i] != bh->b_page +#endif ) && !test_bit(R5_UPTODATE, &dev->flags)) { if (test_bit(R5_Insync, &dev->flags)) rcw++; @@ -2361,25 +2418,23 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) return_bi = bi->bi_next; bi->bi_next = NULL; bi->bi_size = 0; - bi->bi_end_io(bi, bytes, - test_bit(BIO_UPTODATE, &bi->bi_flags) - ? 0 : -EIO); + bi->bi_end_io(bi, bytes, 0); } for (i=disks; i-- ;) { int rw; struct bio *bi; mdk_rdev_t *rdev; if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) - rw = WRITE; + rw = 1; else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags)) - rw = READ; + rw = 0; else continue; bi = &sh->dev[i].req; bi->bi_rw = rw; - if (rw == WRITE) + if (rw) bi->bi_end_io = raid5_end_write_request; else bi->bi_end_io = raid5_end_read_request; @@ -2415,7 +2470,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); generic_make_request(bi); } else { - if (rw == WRITE) + if (rw == 1) set_bit(STRIPE_DEGRADED, &sh->state); PRINTK("skip op %ld on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); @@ -2556,180 +2611,6 @@ static int raid5_congested(void *data, int bits) return 0; } -/* We want read requests to align with chunks where possible, - * but write requests don't need to. - */ -static int raid5_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec) -{ - mddev_t *mddev = q->queuedata; - sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); - int max; - unsigned int chunk_sectors = mddev->chunk_size >> 9; - unsigned int bio_sectors = bio->bi_size >> 9; - - if (bio_data_dir(bio) == WRITE) - return biovec->bv_len; /* always allow writes to be mergeable */ - - max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9; - if (max < 0) max = 0; - if (max <= biovec->bv_len && bio_sectors == 0) - return biovec->bv_len; - else - return max; -} - - -static int in_chunk_boundary(mddev_t *mddev, struct bio *bio) -{ - sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); - unsigned int chunk_sectors = mddev->chunk_size >> 9; - unsigned int bio_sectors = bio->bi_size >> 9; - - return chunk_sectors >= - ((sector & (chunk_sectors - 1)) + bio_sectors); -} - -/* - * add bio to the retry LIFO ( in O(1) ... we are in interrupt ) - * later sampled by raid5d. - */ -static void add_bio_to_retry(struct bio *bi,raid5_conf_t *conf) -{ - unsigned long flags; - - spin_lock_irqsave(&conf->device_lock, flags); - - bi->bi_next = conf->retry_read_aligned_list; - conf->retry_read_aligned_list = bi; - - spin_unlock_irqrestore(&conf->device_lock, flags); - md_wakeup_thread(conf->mddev->thread); -} - - -static struct bio *remove_bio_from_retry(raid5_conf_t *conf) -{ - struct bio *bi; - - bi = conf->retry_read_aligned; - if (bi) { - conf->retry_read_aligned = NULL; - return bi; - } - bi = conf->retry_read_aligned_list; - if(bi) { - conf->retry_read_aligned = bi->bi_next; - bi->bi_next = NULL; - bi->bi_phys_segments = 1; /* biased count of active stripes */ - bi->bi_hw_segments = 0; /* count of processed stripes */ - } - - return bi; -} - - -/* - * The "raid5_align_endio" should check if the read succeeded and if it - * did, call bio_endio on the original bio (having bio_put the new bio - * first). - * If the read failed.. - */ -static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) -{ - struct bio* raid_bi = bi->bi_private; - mddev_t *mddev; - raid5_conf_t *conf; - int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); - mdk_rdev_t *rdev; - - if (bi->bi_size) - return 1; - bio_put(bi); - - mddev = raid_bi->bi_bdev->bd_disk->queue->queuedata; - conf = mddev_to_conf(mddev); - rdev = (void*)raid_bi->bi_next; - raid_bi->bi_next = NULL; - - rdev_dec_pending(rdev, conf->mddev); - - if (!error && uptodate) { - bio_endio(raid_bi, bytes, 0); - if (atomic_dec_and_test(&conf->active_aligned_reads)) - wake_up(&conf->wait_for_stripe); - return 0; - } - - - PRINTK("raid5_align_endio : io error...handing IO for a retry\n"); - - add_bio_to_retry(raid_bi, conf); - return 0; -} - -static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio) -{ - mddev_t *mddev = q->queuedata; - raid5_conf_t *conf = mddev_to_conf(mddev); - const unsigned int raid_disks = conf->raid_disks; - const unsigned int data_disks = raid_disks - conf->max_degraded; - unsigned int dd_idx, pd_idx; - struct bio* align_bi; - mdk_rdev_t *rdev; - - if (!in_chunk_boundary(mddev, raid_bio)) { - printk("chunk_aligned_read : non aligned\n"); - return 0; - } - /* - * use bio_clone to make a copy of the bio - */ - align_bi = bio_clone(raid_bio, GFP_NOIO); - if (!align_bi) - return 0; - /* - * set bi_end_io to a new function, and set bi_private to the - * original bio. - */ - align_bi->bi_end_io = raid5_align_endio; - align_bi->bi_private = raid_bio; - /* - * compute position - */ - align_bi->bi_sector = raid5_compute_sector(raid_bio->bi_sector, - raid_disks, - data_disks, - &dd_idx, - &pd_idx, - conf); - - rcu_read_lock(); - rdev = rcu_dereference(conf->disks[dd_idx].rdev); - if (rdev && test_bit(In_sync, &rdev->flags)) { - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); - raid_bio->bi_next = (void*)rdev; - align_bi->bi_bdev = rdev->bdev; - align_bi->bi_flags &= ~(1 << BIO_SEG_VALID); - align_bi->bi_sector += rdev->data_offset; - - spin_lock_irq(&conf->device_lock); - wait_event_lock_irq(conf->wait_for_stripe, - conf->quiesce == 0, - conf->device_lock, /* nothing */); - atomic_inc(&conf->active_aligned_reads); - spin_unlock_irq(&conf->device_lock); - - generic_make_request(align_bi); - return 1; - } else { - rcu_read_unlock(); - bio_put(align_bi); - return 0; - } -} - - static int make_request(request_queue_t *q, struct bio * bi) { mddev_t *mddev = q->queuedata; @@ -2751,11 +2632,6 @@ static int make_request(request_queue_t *q, struct bio * bi) disk_stat_inc(mddev->gendisk, ios[rw]); disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi)); - if (rw == READ && - mddev->reshape_position == MaxSector && - chunk_aligned_read(q,bi)) - return 0; - logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1); last_sector = bi->bi_sector + (bi->bi_size>>9); bi->bi_next = NULL; @@ -2863,9 +2739,7 @@ static int make_request(request_queue_t *q, struct bio * bi) if ( rw == WRITE ) md_write_end(mddev); bi->bi_size = 0; - bi->bi_end_io(bi, bytes, - test_bit(BIO_UPTODATE, &bi->bi_flags) - ? 0 : -EIO); + bi->bi_end_io(bi, bytes, 0); } return 0; } @@ -3076,74 +2950,6 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski return STRIPE_SECTORS; } -static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) -{ - /* We may not be able to submit a whole bio at once as there - * may not be enough stripe_heads available. - * We cannot pre-allocate enough stripe_heads as we may need - * more than exist in the cache (if we allow ever large chunks). - * So we do one stripe head at a time and record in - * ->bi_hw_segments how many have been done. - * - * We *know* that this entire raid_bio is in one chunk, so - * it will be only one 'dd_idx' and only need one call to raid5_compute_sector. - */ - struct stripe_head *sh; - int dd_idx, pd_idx; - sector_t sector, logical_sector, last_sector; - int scnt = 0; - int remaining; - int handled = 0; - - logical_sector = raid_bio->bi_sector & ~((sector_t)STRIPE_SECTORS-1); - sector = raid5_compute_sector( logical_sector, - conf->raid_disks, - conf->raid_disks - conf->max_degraded, - &dd_idx, - &pd_idx, - conf); - last_sector = raid_bio->bi_sector + (raid_bio->bi_size>>9); - - for (; logical_sector < last_sector; - logical_sector += STRIPE_SECTORS, scnt++) { - - if (scnt < raid_bio->bi_hw_segments) - /* already done this stripe */ - continue; - - sh = get_active_stripe(conf, sector, conf->raid_disks, pd_idx, 1); - - if (!sh) { - /* failed to get a stripe - must wait */ - raid_bio->bi_hw_segments = scnt; - conf->retry_read_aligned = raid_bio; - return handled; - } - - set_bit(R5_ReadError, &sh->dev[dd_idx].flags); - add_stripe_bio(sh, raid_bio, dd_idx, 0); - handle_stripe(sh, NULL); - release_stripe(sh); - handled++; - } - spin_lock_irq(&conf->device_lock); - remaining = --raid_bio->bi_phys_segments; - spin_unlock_irq(&conf->device_lock); - if (remaining == 0) { - int bytes = raid_bio->bi_size; - - raid_bio->bi_size = 0; - raid_bio->bi_end_io(raid_bio, bytes, - test_bit(BIO_UPTODATE, &raid_bio->bi_flags) - ? 0 : -EIO); - } - if (atomic_dec_and_test(&conf->active_aligned_reads)) - wake_up(&conf->wait_for_stripe); - return handled; -} - - - /* * This is our raid5 kernel thread. * @@ -3165,7 +2971,6 @@ static void raid5d (mddev_t *mddev) spin_lock_irq(&conf->device_lock); while (1) { struct list_head *first; - struct bio *bio; if (conf->seq_flush != conf->seq_write) { int seq = conf->seq_flush; @@ -3182,16 +2987,6 @@ static void raid5d (mddev_t *mddev) !list_empty(&conf->delayed_list)) raid5_activate_delayed(conf); - while ((bio = remove_bio_from_retry(conf))) { - int ok; - spin_unlock_irq(&conf->device_lock); - ok = retry_aligned_read(conf, bio); - spin_lock_irq(&conf->device_lock); - if (!ok) - break; - handled++; - } - if (list_empty(&conf->handle_list)) break; @@ -3379,7 +3174,6 @@ static int run(mddev_t *mddev) INIT_LIST_HEAD(&conf->inactive_list); atomic_set(&conf->active_stripes, 0); atomic_set(&conf->preread_active_stripes, 0); - atomic_set(&conf->active_aligned_reads, 0); PRINTK("raid5: run(%s) called.\n", mdname(mddev)); @@ -3526,8 +3320,6 @@ static int run(mddev_t *mddev) mddev->array_size = mddev->size * (conf->previous_raid_disks - conf->max_degraded); - blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); - return 0; abort: if (conf) { @@ -3902,8 +3694,7 @@ static void raid5_quiesce(mddev_t *mddev, int state) spin_lock_irq(&conf->device_lock); conf->quiesce = 1; wait_event_lock_irq(conf->wait_for_stripe, - atomic_read(&conf->active_stripes) == 0 && - atomic_read(&conf->active_aligned_reads) == 0, + atomic_read(&conf->active_stripes) == 0, conf->device_lock, /* nothing */); spin_unlock_irq(&conf->device_lock); break; diff --git a/trunk/drivers/media/Kconfig b/trunk/drivers/media/Kconfig index 87410dbd3df4..9f7e1fe8c97e 100644 --- a/trunk/drivers/media/Kconfig +++ b/trunk/drivers/media/Kconfig @@ -67,7 +67,6 @@ source "drivers/media/common/Kconfig" config VIDEO_TUNER tristate - depends on I2C config VIDEO_BUF tristate @@ -83,7 +82,6 @@ config VIDEO_IR config VIDEO_TVEEPROM tristate - depends on I2C config USB_DABUSB tristate "DABUSB driver" diff --git a/trunk/drivers/media/common/ir-keymaps.c b/trunk/drivers/media/common/ir-keymaps.c index f51e02fe3655..db753443587a 100644 --- a/trunk/drivers/media/common/ir-keymaps.c +++ b/trunk/drivers/media/common/ir-keymaps.c @@ -1552,58 +1552,3 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_norwood); - -/* From reading the following remotes: - * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 - * Hauppauge (from NOVA-CI-s box product) - * This is a "middle of the road" approach, differences are noted - */ -IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - [ 0x0a ] = KEY_ENTER, - [ 0x0b ] = KEY_RED, - [ 0x0c ] = KEY_POWER, /* RADIO on Hauppauge */ - [ 0x0d ] = KEY_MUTE, - [ 0x0f ] = KEY_A, /* TV on Hauppauge */ - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x14 ] = KEY_B, - [ 0x1c ] = KEY_UP, - [ 0x1d ] = KEY_DOWN, - [ 0x1e ] = KEY_OPTION, /* RESERVED on Hauppauge */ - [ 0x1f ] = KEY_BREAK, - [ 0x20 ] = KEY_CHANNELUP, - [ 0x21 ] = KEY_CHANNELDOWN, - [ 0x22 ] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ - [ 0x24 ] = KEY_RESTART, - [ 0x25 ] = KEY_OK, - [ 0x26 ] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ - [ 0x28 ] = KEY_ENTER, /* VCR mode on Zenith */ - [ 0x29 ] = KEY_PAUSE, - [ 0x2b ] = KEY_RIGHT, - [ 0x2c ] = KEY_LEFT, - [ 0x2e ] = KEY_MENU, /* FULL SCREEN on Hauppauge */ - [ 0x30 ] = KEY_SLOW, - [ 0x31 ] = KEY_PREVIOUS, /* VCR mode on Zenith */ - [ 0x32 ] = KEY_REWIND, - [ 0x34 ] = KEY_FASTFORWARD, - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, - [ 0x38 ] = KEY_TUNER, /* TV/VCR on Zenith */ - [ 0x3a ] = KEY_C, - [ 0x3c ] = KEY_EXIT, - [ 0x3d ] = KEY_POWER2, - [ 0x3e ] = KEY_TUNER, -}; - -EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); diff --git a/trunk/drivers/media/common/saa7146_i2c.c b/trunk/drivers/media/common/saa7146_i2c.c index 8c85efc26527..5297a365c928 100644 --- a/trunk/drivers/media/common/saa7146_i2c.c +++ b/trunk/drivers/media/common/saa7146_i2c.c @@ -189,21 +189,13 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d saa7146_write(dev, I2C_TRANSFER, *dword); dev->i2c_op = 1; - SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); - timeout = HZ/100 + 1; /* 10ms */ - timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout); - if (timeout == -ERESTARTSYS || dev->i2c_op) { - SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); - SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); - if (timeout == -ERESTARTSYS) - /* a signal arrived */ - return -ERESTARTSYS; - - printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n"); - return -EIO; + wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0); + if (signal_pending (current)) { + /* a signal arrived */ + return -ERESTARTSYS; } status = saa7146_read(dev, I2C_STATUS); } else { diff --git a/trunk/drivers/media/dvb/b2c2/Kconfig b/trunk/drivers/media/dvb/b2c2/Kconfig index 79875958930e..a0dcd59da76e 100644 --- a/trunk/drivers/media/dvb/b2c2/Kconfig +++ b/trunk/drivers/media/dvb/b2c2/Kconfig @@ -9,7 +9,6 @@ config DVB_B2C2_FLEXCOP select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_BCM3510 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/trunk/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/trunk/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index c2b35e366242..b8ba87863457 100644 --- a/trunk/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/trunk/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -14,7 +14,7 @@ #include "stv0297.h" #include "mt312.h" #include "lgdt330x.h" -#include "lgh06xf.h" +#include "lg_h06xf.h" #include "dvb-pll.h" /* lnb control */ @@ -303,6 +303,12 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir return request_firmware(fw, name, fc->dev); } +static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) +{ + struct flexcop_device *fc = fe->dvb->priv; + return lg_h06xf_pll_set(fe, &fc->i2c_adap, params); +} + static struct lgdt330x_config air2pc_atsc_hd5000_config = { .demod_address = 0x59, .demod_chip = LGDT3303, @@ -527,7 +533,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) /* try the air atsc 3nd generation (lgdt3303) */ if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC3; - dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap); + fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); } else /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ diff --git a/trunk/drivers/media/dvb/bt8xx/Kconfig b/trunk/drivers/media/dvb/bt8xx/Kconfig index dd66b60fbc98..ae2ff5dc238d 100644 --- a/trunk/drivers/media/dvb/bt8xx/Kconfig +++ b/trunk/drivers/media/dvb/bt8xx/Kconfig @@ -1,13 +1,13 @@ config DVB_BT8XX tristate "BT8xx based PCI cards" depends on DVB_CORE && PCI && I2C && VIDEO_BT848 + select DVB_PLL select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_SP887X if !DVB_FE_CUSTOMISE select DVB_NXT6000 if !DVB_FE_CUSTOMISE select DVB_CX24110 if !DVB_FE_CUSTOMISE select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select FW_LOADER help diff --git a/trunk/drivers/media/dvb/bt8xx/dst_ca.c b/trunk/drivers/media/dvb/bt8xx/dst_ca.c index 50bc32a8bd55..240ad084fa78 100644 --- a/trunk/drivers/media/dvb/bt8xx/dst_ca.c +++ b/trunk/drivers/media/dvb/bt8xx/dst_ca.c @@ -480,7 +480,7 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer; int result = 0; - if ((hw_buffer = kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { + if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); return -ENOMEM; } diff --git a/trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 3e35931af35d..14e69a736eda 100644 --- a/trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -34,6 +34,7 @@ #include "dvb_frontend.h" #include "dvb-bt8xx.h" #include "bt878.h" +#include "dvb-pll.h" static int debug; @@ -567,6 +568,12 @@ static struct mt352_config digitv_alps_tded4_config = { .demod_init = digitv_alps_tded4_demod_init, }; +static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; + return lg_h06xf_pll_set(fe, card->i2c_adapter, params); +} + static struct lgdt330x_config tdvs_tua6034_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, @@ -609,7 +616,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) lgdt330x_reset(card); card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); if (card->fe != NULL) { - dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter); + card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params; dprintk ("dvb_bt8xx: lgdt330x detected\n"); } break; @@ -657,7 +664,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) case BTTV_BOARD_TWINHAN_DST: /* DST is not a frontend driver !!! */ - state = kmalloc(sizeof (struct dst_state), GFP_KERNEL); + state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL); if (!state) { printk("dvb_bt8xx: No memory\n"); break; diff --git a/trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.h index e75f4173c059..4745a9017a19 100644 --- a/trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/trunk/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -37,7 +37,7 @@ #include "cx24110.h" #include "or51211.h" #include "lgdt330x.h" -#include "lgh06xf.h" +#include "lg_h06xf.h" #include "zl10353.h" struct dvb_bt8xx_card { diff --git a/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c b/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c index d64b96cb0c46..9123147e376f 100644 --- a/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -746,7 +746,6 @@ static void cinergyt2_query_rc (struct work_struct *work) dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); input_report_key(cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0); - input_sync(cinergyt2->rc_input_dev); cinergyt2->rc_input_event = KEY_MAX; } cinergyt2->rc_last_code = ~0; @@ -784,7 +783,6 @@ static void cinergyt2_query_rc (struct work_struct *work) dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); input_report_key(cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1); - input_sync(cinergyt2->rc_input_dev); cinergyt2->rc_last_code = rc_events[n].value; } } @@ -800,9 +798,8 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { struct input_dev *input_dev; int i; - int err; - input_dev = input_allocate_device(); + cinergyt2->rc_input_dev = input_dev = input_allocate_device(); if (!input_dev) return -ENOMEM; @@ -820,13 +817,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) input_dev->keycodesize = 0; input_dev->keycodemax = 0; - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } - - cinergyt2->rc_input_dev = input_dev; + input_register_device(cinergyt2->rc_input_dev); schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); return 0; diff --git a/trunk/drivers/media/dvb/dvb-usb/Kconfig b/trunk/drivers/media/dvb/dvb-usb/Kconfig index ad52143602cd..a263b3f3c21d 100644 --- a/trunk/drivers/media/dvb/dvb-usb/Kconfig +++ b/trunk/drivers/media/dvb/dvb-usb/Kconfig @@ -69,8 +69,6 @@ config DVB_USB_DIBUSB_MC config DVB_USB_DIB0700 tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" depends on DVB_USB - select DVB_DIB7000P - select DVB_DIB7000M select DVB_DIB3000MC select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help @@ -98,7 +96,6 @@ config DVB_USB_CXUSB depends on DVB_USB select DVB_CX22702 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE help @@ -160,17 +157,6 @@ config DVB_USB_NOVA_T_USB2 help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. -config DVB_USB_TTUSB2 - tristate "Pinnacle 400e DVB-S USB2.0 support" - depends on DVB_USB - select DVB_TDA10086 if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_TDA826X if !DVB_FE_CUSTOMISE - help - Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The - firmware protocol used by this module is similar to the one used by the - old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko. - config DVB_USB_DTT200U tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" depends on DVB_USB diff --git a/trunk/drivers/media/dvb/dvb-usb/Makefile b/trunk/drivers/media/dvb/dvb-usb/Makefile index 154d593bbb02..e239107998e5 100644 --- a/trunk/drivers/media/dvb/dvb-usb/Makefile +++ b/trunk/drivers/media/dvb/dvb-usb/Makefile @@ -36,9 +36,6 @@ obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o dvb-usb-cxusb-objs = cxusb.o obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o -dvb-usb-ttusb2-objs = ttusb2.o -obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o - dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o diff --git a/trunk/drivers/media/dvb/dvb-usb/a800.c b/trunk/drivers/media/dvb/dvb-usb/a800.c index a6c5f19f680d..2ed3eb62d787 100644 --- a/trunk/drivers/media/dvb/dvb-usb/a800.c +++ b/trunk/drivers/media/dvb/dvb-usb/a800.c @@ -116,24 +116,24 @@ static struct dvb_usb_device_properties a800_properties = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), }, diff --git a/trunk/drivers/media/dvb/dvb-usb/cxusb.c b/trunk/drivers/media/dvb/dvb-usb/cxusb.c index 15d12fce34df..43f39069ef34 100644 --- a/trunk/drivers/media/dvb/dvb-usb/cxusb.c +++ b/trunk/drivers/media/dvb/dvb-usb/cxusb.c @@ -14,12 +14,12 @@ * TODO: Use the cx25840-driver for the analogue part * * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) - * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) + * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net) * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) * - * 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, version 2. + * 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, version 2. * * see Documentation/dvb/README.dvb-usb for more information */ @@ -27,29 +27,29 @@ #include "cx22702.h" #include "lgdt330x.h" -#include "lgh06xf.h" +#include "lg_h06xf.h" #include "mt352.h" #include "mt352_priv.h" #include "zl10353.h" /* debug */ int dvb_usb_cxusb_debug; -module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); +module_param_named(debug,dvb_usb_cxusb_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); static int cxusb_ctrl_msg(struct dvb_usb_device *d, - u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) + u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { int wo = (rbuf == NULL || rlen == 0); /* write-only */ u8 sndbuf[1+wlen]; - memset(sndbuf, 0, 1+wlen); + memset(sndbuf,0,1+wlen); sndbuf[0] = cmd; - memcpy(&sndbuf[1], wbuf, wlen); + memcpy(&sndbuf[1],wbuf,wlen); if (wo) - dvb_usb_generic_write(d, sndbuf, 1+wlen); + dvb_usb_generic_write(d,sndbuf,1+wlen); else - dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); + dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0); return 0; } @@ -58,14 +58,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d, static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) { struct cxusb_state *st = d->priv; - u8 o[2], i; + u8 o[2],i; if (st->gpio_write_state[GPIO_TUNER] == onoff) return; o[0] = GPIO_TUNER; o[1] = onoff; - cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); + cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1); if (i != 0x01) deb_info("gpio_write failed.\n"); @@ -74,8 +74,7 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) } /* I2C */ -static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) +static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; @@ -90,12 +89,12 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (d->udev->descriptor.idVendor == USB_VID_MEDION) switch (msg[i].addr) { - case 0x63: - cxusb_gpio_tuner(d, 0); - break; - default: - cxusb_gpio_tuner(d, 1); - break; + case 0x63: + cxusb_gpio_tuner(d,0); + break; + default: + cxusb_gpio_tuner(d,1); + break; } /* read request */ @@ -104,27 +103,26 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], obuf[0] = msg[i].len; obuf[1] = msg[i+1].len; obuf[2] = msg[i].addr; - memcpy(&obuf[3], msg[i].buf, msg[i].len); + memcpy(&obuf[3],msg[i].buf,msg[i].len); if (cxusb_ctrl_msg(d, CMD_I2C_READ, - obuf, 3+msg[i].len, - ibuf, 1+msg[i+1].len) < 0) + obuf, 3+msg[i].len, + ibuf, 1+msg[i+1].len) < 0) break; if (ibuf[0] != 0x08) deb_i2c("i2c read may have failed\n"); - memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len); + memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len); i++; } else { /* write */ u8 obuf[2+msg[i].len], ibuf; obuf[0] = msg[i].addr; obuf[1] = msg[i].len; - memcpy(&obuf[2], msg[i].buf, msg[i].len); + memcpy(&obuf[2],msg[i].buf,msg[i].len); - if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf, - 2+msg[i].len, &ibuf,1) < 0) + if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0) break; if (ibuf != 0x08) deb_i2c("i2c write may have failed\n"); @@ -326,8 +324,16 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) return 0; } +static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + struct dvb_usb_adapter *adap = fe->dvb->priv; + return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep); +} + static struct cx22702_config cxusb_cx22702_config = { .demod_address = 0x63, + .output_mode = CX22702_PARALLEL_OUTPUT, }; @@ -368,27 +374,31 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap) { - dvb_attach(dvb_pll_attach, adap->fe, 0x61, - NULL, &dvb_pll_thomson_dtt7579); + adap->pll_addr = 0x61; + adap->pll_desc = &dvb_pll_thomson_dtt7579; + adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; return 0; } static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap) { - dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201); + adap->pll_addr = 0x61; + adap->pll_desc = &dvb_pll_lg_z201; + adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; return 0; } static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) { - dvb_attach(dvb_pll_attach, adap->fe, 0x60, - NULL, &dvb_pll_thomson_dtt7579); + adap->pll_addr = 0x60; + adap->pll_desc = &dvb_pll_thomson_dtt7579; + adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; return 0; } -static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) +static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap) { - dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap); + adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params; return 0; } @@ -400,8 +410,7 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1); - if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, - &adap->dev->i2c_adap)) != NULL) + if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL) return 0; return -EIO; @@ -414,8 +423,7 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); - if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, - &adap->dev->i2c_adap)) != NULL) + if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL) return 0; return -EIO; @@ -429,8 +437,7 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); - if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, - &adap->dev->i2c_adap)) != NULL) + if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL) return 0; return -EIO; @@ -443,11 +450,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); - if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, - &adap->dev->i2c_adap)) != NULL) || - ((adap->fe = dvb_attach(zl10353_attach, - &cxusb_zl10353_dee1601_config, - &adap->dev->i2c_adap)) != NULL)) + if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) || + ((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL)) return 0; return -EIO; @@ -459,8 +463,7 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) */ #define BLUEBIRD_01_ID_OFFSET 6638 -static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, - const struct firmware *fw) +static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw) { if (fw->size < BLUEBIRD_01_ID_OFFSET + 4) return -EINVAL; @@ -468,12 +471,10 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { - fw->data[BLUEBIRD_01_ID_OFFSET + 2] = - udev->descriptor.idProduct + 1; - fw->data[BLUEBIRD_01_ID_OFFSET + 3] = - udev->descriptor.idProduct >> 8; + fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1; + fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8; - return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2); + return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2); } return -EINVAL; @@ -487,7 +488,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; static int cxusb_probe(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id) { if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || @@ -501,20 +502,20 @@ static int cxusb_probe(struct usb_interface *intf, } static struct usb_device_id cxusb_table [] = { - { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, - { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, - {} /* Terminating entry */ + { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, + {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, cxusb_table); @@ -528,20 +529,20 @@ static struct dvb_usb_device_properties cxusb_medion_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_cx22702_frontend_attach, - .tuner_attach = cxusb_fmd1216me_tuner_attach, - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 5, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_cx22702_frontend_attach, + .tuner_attach = cxusb_fmd1216me_tuner_attach, + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -574,21 +575,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_lgdt3303_frontend_attach, - .tuner_attach = cxusb_lgh064f_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 5, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_lgdt3303_frontend_attach, + .tuner_attach = cxusb_lgdt3303_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -626,20 +627,20 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_dee1601_frontend_attach, - .tuner_attach = cxusb_dee1601_tuner_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_dee1601_frontend_attach, + .tuner_attach = cxusb_dee1601_tuner_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -685,21 +686,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { .num_adapters = 2, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_mt352_frontend_attach, - .tuner_attach = cxusb_lgz201_tuner_attach, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_mt352_frontend_attach, + .tuner_attach = cxusb_lgz201_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, .power_ctrl = cxusb_bluebird_power_ctrl, @@ -735,21 +736,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_mt352_frontend_attach, - .tuner_attach = cxusb_dtt7579_tuner_attach, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_mt352_frontend_attach, + .tuner_attach = cxusb_dtt7579_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, .power_ctrl = cxusb_bluebird_power_ctrl, @@ -775,7 +776,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { static struct usb_driver cxusb_driver = { .name = "dvb_usb_cxusb", .probe = cxusb_probe, - .disconnect = dvb_usb_device_exit, + .disconnect = dvb_usb_device_exit, .id_table = cxusb_table, }; @@ -801,7 +802,7 @@ module_init (cxusb_module_init); module_exit (cxusb_module_exit); MODULE_AUTHOR("Patrick Boettcher "); -MODULE_AUTHOR("Michael Krufky "); +MODULE_AUTHOR("Michael Krufky "); MODULE_AUTHOR("Chris Pascoe "); MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); MODULE_VERSION("1.0-alpha"); diff --git a/trunk/drivers/media/dvb/dvb-usb/dib0700.h b/trunk/drivers/media/dvb/dvb-usb/dib0700.h index cda3adea24fb..ac84347f9d4c 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dib0700.h +++ b/trunk/drivers/media/dvb/dvb-usb/dib0700.h @@ -24,23 +24,18 @@ extern int dvb_usb_dib0700_debug; #define REQUEST_I2C_WRITE 0x3 #define REQUEST_POLL_RC 0x4 #define REQUEST_JUMPRAM 0x8 -#define REQUEST_SET_CLOCK 0xB #define REQUEST_SET_GPIO 0xC #define REQUEST_ENABLE_VIDEO 0xF // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) -#define REQUEST_GET_VERSION 0x15 struct dib0700_state { u8 channel_state; u16 mt2060_if1[2]; - - u8 is_dib7000pc; }; extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); -extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); extern struct i2c_algorithm dib0700_i2c_algo; diff --git a/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c b/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c index 6a4d150784a6..dca6c6985661 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/trunk/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -135,46 +135,14 @@ struct i2c_algorithm dib0700_i2c_algo = { int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold) { - u8 b[16]; - s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), - REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); - - deb_info("FW GET_VERSION length: %d\n",ret); - - *cold = ret <= 0; + u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C + *cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0), + buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3; deb_info("cold: %d\n", *cold); return 0; } -static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, - u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, - u16 pll_loopdiv, u16 free_div, u16 dsuScaler) -{ - u8 b[10]; - b[0] = REQUEST_SET_CLOCK; - b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4); - b[2] = (pll_prediv >> 8) & 0xff; // MSB - b[3] = pll_prediv & 0xff; // LSB - b[4] = (pll_loopdiv >> 8) & 0xff; // MSB - b[5] = pll_loopdiv & 0xff; // LSB - b[6] = (free_div >> 8) & 0xff; // MSB - b[7] = free_div & 0xff; // LSB - b[8] = (dsuScaler >> 8) & 0xff; // MSB - b[9] = dsuScaler & 0xff; // LSB - - return dib0700_ctrl_wr(d, b, 10); -} - -int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) -{ - switch (clk_MHz) { - case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break; - default: return -EINVAL; - } - return 0; -} - static int dib0700_jumpram(struct usb_device *udev, u32 address) { int ret, actlen; @@ -229,7 +197,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw /* start the firmware */ if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { info("firmware started successfully."); - msleep(500); + msleep(100); } } else ret = -EIO; diff --git a/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c b/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c index 2208757d9017..e473bfed226b 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/trunk/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -9,8 +9,6 @@ #include "dib0700.h" #include "dib3000mc.h" -#include "dib7000m.h" -#include "dib7000p.h" #include "mt2060.h" static int force_lna_activation; @@ -97,189 +95,37 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) } /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ -static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { - BAND_UHF | BAND_VHF, // band_caps - - /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, - * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup - - 712, // inv_gain - 41, // time_stabiliz - - 0, // alpha_level - 118, // thlock - - 0, // wbd_inv - 4095, // wbd_ref - 0, // wbd_sel - 0, // wbd_alpha - - 42598, // agc1_max - 17694, // agc1_min - 45875, // agc2_max - 2621, // agc2_min - 0, // agc1_pt1 - 76, // agc1_pt2 - 139, // agc1_pt3 - 52, // agc1_slope1 - 59, // agc1_slope2 - 107, // agc2_pt1 - 172, // agc2_pt2 - 57, // agc2_slope1 - 70, // agc2_slope2 - - 21, // alpha_mant - 25, // alpha_exp - 28, // beta_mant - 48, // beta_exp - - 1, // perform_agc_softsplit - { 0, // split_min - 107, // split_max - 51800, // global_split_min - 24700 // global_split_max - }, -}; - -static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { - BAND_UHF | BAND_VHF, - - /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, - * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup - - 712, // inv_gain - 41, // time_stabiliz - - 0, // alpha_level - 118, // thlock - - 0, // wbd_inv - 4095, // wbd_ref - 0, // wbd_sel - 0, // wbd_alpha - - 42598, // agc1_max - 16384, // agc1_min - 42598, // agc2_max - 0, // agc2_min - - 0, // agc1_pt1 - 137, // agc1_pt2 - 255, // agc1_pt3 - - 0, // agc1_slope1 - 255, // agc1_slope2 - - 0, // agc2_pt1 - 0, // agc2_pt2 - - 0, // agc2_slope1 - 41, // agc2_slope2 - - 15, // alpha_mant - 25, // alpha_exp - - 28, // beta_mant - 48, // beta_exp - - 0, // perform_agc_softsplit -}; - -static struct dibx000_bandwidth_config stk7700p_pll_config = { - 60000, 30000, // internal, sampling - 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass - 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo - (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k - 60258167, // ifreq - 20452225, // timf -}; - -static struct dib7000m_config stk7700p_dib7000m_config = { - .dvbt_mode = 1, - .output_mpeg2_in_188_bytes = 1, - .quartz_direct = 1, - - .agc_config_count = 1, - .agc = &stk7700p_7000m_mt2060_agc_config, - .bw = &stk7700p_pll_config, - - .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, - .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, - .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, -}; - -static struct dib7000p_config stk7700p_dib7000p_config = { - .output_mpeg2_in_188_bytes = 1, - - .agc = &stk7700p_7000p_mt2060_agc_config, - .bw = &stk7700p_pll_config, - - .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, - .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, - .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, +/* +static struct mt2060_config stk7000p_mt2060_config = { + 0x60 }; +*/ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) { - struct dib0700_state *st = adap->dev->priv; /* unless there is no real power management in DVB - we leave the device on GPIO6 */ - - dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50); - - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); - dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); - + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); - dib0700_ctrl_clock(adap->dev, 72, 1); - dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100); - - dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); - - st->mt2060_if1[0] = 1220; - - if (dib7000pc_detection(&adap->dev->i2c_adap)) { - adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); - st->is_dib7000pc = 1; - } else - adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); - return adap->fe == NULL ? -ENODEV : 0; +// adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18); + return 0; } -static struct mt2060_config stk7700p_mt2060_config = { - 0x60 -}; - static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) { - struct dib0700_state *st = adap->dev->priv; - struct i2c_adapter *tun_i2c; - - if (st->is_dib7000pc) - tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); - else - tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); - - return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config, - st->mt2060_if1[0]) == NULL ? -ENODEV : 0; +// tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1); +// return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1); + return 0; } struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, - { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, - { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, - { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, - { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, - { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -321,32 +167,20 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 6, + .num_device_descs = 3, .devices = { { "DiBcom STK7700P reference design", - { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, + { &dib0700_usb_id_table[0], NULL }, { NULL }, }, { "Hauppauge Nova-T Stick", - { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL }, + { &dib0700_usb_id_table[3], NULL }, { NULL }, }, { "AVerMedia AVerTV DVB-T Volar", - { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] }, + { &dib0700_usb_id_table[4], NULL }, { NULL }, }, - { "Compro Videomate U500", - { &dib0700_usb_id_table[6], NULL }, - { NULL }, - }, - { "Uniwill STK7700P based (Hama and others)", - { &dib0700_usb_id_table[7], NULL }, - { NULL }, - }, - { "Leadtek Winfast DTV Dongle (STK7700P based)", - { &dib0700_usb_id_table[8], NULL }, - { NULL }, - } } }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -368,7 +202,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_device_descs = 1, .devices = { { "Hauppauge Nova-T 500 Dual DVB-T", - { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, + { &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL }, { NULL }, }, } diff --git a/trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c b/trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c index 7a6ae8f482e0..4fe363e48352 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/trunk/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -163,23 +163,23 @@ static struct dvb_usb_device_properties dibusb1_1_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, + .streaming_ctrl = dibusb_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, @@ -248,23 +248,23 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, .pid_filter_count = 16, - .streaming_ctrl = dibusb_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, + .streaming_ctrl = dibusb_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), }, }, @@ -312,23 +312,22 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_thomson_tuner_attach, - - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_thomson_tuner_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, @@ -370,22 +369,22 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, diff --git a/trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c b/trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c index e7ea3e753d6d..a0fd37efc04b 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/trunk/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -54,23 +54,23 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, diff --git a/trunk/drivers/media/dvb/dvb-usb/digitv.c b/trunk/drivers/media/dvb/dvb-usb/digitv.c index 4a198d4755b0..8fb34375c1fb 100644 --- a/trunk/drivers/media/dvb/dvb-usb/digitv.c +++ b/trunk/drivers/media/dvb/dvb-usb/digitv.c @@ -274,20 +274,20 @@ static struct dvb_usb_device_properties digitv_properties = { .num_adapters = 1, .adapter = { { - .frontend_attach = digitv_frontend_attach, - .tuner_attach = digitv_tuner_attach, + .frontend_attach = digitv_frontend_attach, + .tuner_attach = digitv_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .identify_state = digitv_identify_state, diff --git a/trunk/drivers/media/dvb/dvb-usb/dtt200u.c b/trunk/drivers/media/dvb/dvb-usb/dtt200u.c index 7dbe14321019..fa43a41d753b 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/trunk/drivers/media/dvb/dvb-usb/dtt200u.c @@ -268,20 +268,20 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, .pid_filter_count = 15, - .streaming_ctrl = dtt200u_streaming_ctrl, - .pid_filter = dtt200u_pid_filter, - .frontend_attach = dtt200u_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dtt200u_streaming_ctrl, + .pid_filter = dtt200u_pid_filter, + .frontend_attach = dtt200u_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .power_ctrl = dtt200u_power_ctrl, diff --git a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 299382dcb81d..4d6b069536ce 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -33,7 +33,6 @@ #define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_TWINHAN 0x1822 #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 -#define USB_VID_UNIWILL 0x1584 #define USB_VID_WIDEVIEW 0x14aa /* Product IDs */ @@ -47,7 +46,6 @@ #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d -#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 @@ -55,9 +53,7 @@ #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 #define USB_PID_DIBCOM_STK7700P 0x1e14 -#define USB_PID_DIBCOM_STK7700P_PC 0x1e78 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 -#define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de @@ -101,9 +97,7 @@ #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 -#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 -#define USB_PID_AVERMEDIA_VOLAR 0xa807 -#define USB_PID_AVERMEDIA_VOLAR_2 0xb808 +#define USB_PID_AVERMEDIA_VOLAR 0x1234 #define USB_PID_NEBULA_DIGITV 0x0201 #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 @@ -116,8 +110,8 @@ #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 -#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 -#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 +#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 +#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 #define USB_PID_MEDION_MD95700 0x0932 #define USB_PID_KYE_DVB_T_COLD 0x701e #define USB_PID_KYE_DVB_T_WARM 0x701f @@ -131,9 +125,7 @@ #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 -#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 #define USB_PID_GENPIX_8PSK_COLD 0x0200 #define USB_PID_GENPIX_8PSK_WARM 0x0201 - #endif diff --git a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 19ff5978bc91..794e4471561c 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -90,9 +90,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work) int dvb_usb_remote_init(struct dvb_usb_device *d) { - struct input_dev *input_dev; int i; - int err; if (d->props.rc_key_map == NULL || d->props.rc_query == NULL || @@ -102,24 +100,23 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); - input_dev = input_allocate_device(); - if (!input_dev) + d->rc_input_dev = input_allocate_device(); + if (!d->rc_input_dev) return -ENOMEM; - input_dev->evbit[0] = BIT(EV_KEY); - input_dev->keycodesize = sizeof(unsigned char); - input_dev->keycodemax = KEY_MAX; - input_dev->name = "IR-receiver inside an USB DVB receiver"; - input_dev->phys = d->rc_phys; - usb_to_input_id(d->udev, &input_dev->id); - input_dev->cdev.dev = &d->udev->dev; + d->rc_input_dev->evbit[0] = BIT(EV_KEY); + d->rc_input_dev->keycodesize = sizeof(unsigned char); + d->rc_input_dev->keycodemax = KEY_MAX; + d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver"; + d->rc_input_dev->phys = d->rc_phys; + usb_to_input_id(d->udev, &d->rc_input_dev->id); + d->rc_input_dev->cdev.dev = &d->udev->dev; /* set the bits for the keys */ deb_rc("key map size: %d\n", d->props.rc_key_map_size); for (i = 0; i < d->props.rc_key_map_size; i++) { - deb_rc("setting bit for event %d item %d\n", - d->props.rc_key_map[i].event, i); - set_bit(d->props.rc_key_map[i].event, input_dev->keybit); + deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i); + set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit); } /* Start the remote-control polling. */ @@ -127,16 +124,10 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) d->props.rc_interval = 100; /* default */ /* setting these two values to non-zero, we have to manage key repeats */ - input_dev->rep[REP_PERIOD] = d->props.rc_interval; - input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; + d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval; + d->rc_input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } - - d->rc_input_dev = input_dev; + input_register_device(d->rc_input_dev); INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); diff --git a/trunk/drivers/media/dvb/dvb-usb/gp8psk.c b/trunk/drivers/media/dvb/dvb-usb/gp8psk.c index 518d67fca5e8..7375eb20166d 100644 --- a/trunk/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/trunk/drivers/media/dvb/dvb-usb/gp8psk.c @@ -194,19 +194,19 @@ static struct dvb_usb_device_properties gp8psk_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = gp8psk_streaming_ctrl, - .frontend_attach = gp8psk_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = gp8psk_streaming_ctrl, + .frontend_attach = gp8psk_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x82, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 7, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, } }, .power_ctrl = gp8psk_power_ctrl, diff --git a/trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c index d48622e76b1b..a58874c790b2 100644 --- a/trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/trunk/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -163,23 +163,23 @@ static struct dvb_usb_device_properties nova_t_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } diff --git a/trunk/drivers/media/dvb/dvb-usb/ttusb2.c b/trunk/drivers/media/dvb/dvb-usb/ttusb2.c deleted file mode 100644 index 95d29976ed78..000000000000 --- a/trunk/drivers/media/dvb/dvb-usb/ttusb2.c +++ /dev/null @@ -1,270 +0,0 @@ -/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones - * (e.g. Pinnacle 400e DVB-S USB2.0). - * - * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes. - * - * TDA8263 + TDA10086 - * - * I2C addresses: - * 0x08 - LNBP21PD - LNB power supply - * 0x0e - TDA10086 - Demodulator - * 0x50 - FX2 eeprom - * 0x60 - TDA8263 - Tuner - * 0x78 ??? - * - * Copyright (c) 2002 Holger Waechtler - * Copyright (c) 2003 Felix Domke - * Copyright (C) 2005-6 Patrick Boettcher - * - * 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, version 2. - * - * see Documentation/dvb/README.dvb-usb for more information - */ -#define DVB_USB_LOG_PREFIX "ttusb2" -#include "dvb-usb.h" - -#include "ttusb2.h" - -#include "tda826x.h" -#include "tda10086.h" -#include "lnbp21.h" - -/* debug */ -static int dvb_usb_ttusb2_debug; -#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args) -module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); - -struct ttusb2_state { - u8 id; -}; - -static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, - u8 *wbuf, int wlen, u8 *rbuf, int rlen) -{ - struct ttusb2_state *st = d->priv; - u8 s[wlen+4],r[64] = { 0 }; - int ret = 0; - - memset(s,0,wlen+4); - - s[0] = 0xaa; - s[1] = ++st->id; - s[2] = cmd; - s[3] = wlen; - memcpy(&s[4],wbuf,wlen); - - ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0); - - if (ret != 0 || - r[0] != 0x55 || - r[1] != s[1] || - r[2] != cmd || - (rlen > 0 && r[3] != rlen)) { - warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); - return -EIO; - } - - if (rlen > 0) - memcpy(rbuf, &r[4], rlen); - - return 0; -} - -static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) -{ - struct dvb_usb_device *d = i2c_get_adapdata(adap); - static u8 obuf[60], ibuf[60]; - int i,read; - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - - if (num > 2) - warn("more than 2 i2c messages at a time is not handled yet. TODO."); - - for (i = 0; i < num; i++) { - read = i+1 < num && (msg[i+1].flags & I2C_M_RD); - - obuf[0] = (msg[i].addr << 1) | read; - obuf[1] = msg[i].len; - - /* read request */ - if (read) - obuf[2] = msg[i+1].len; - else - obuf[2] = 0; - - memcpy(&obuf[3],msg[i].buf,msg[i].len); - - if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) { - err("i2c transfer failed."); - break; - } - - if (read) { - memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len); - i++; - } - } - - mutex_unlock(&d->i2c_mutex); - return i; -} - -static u32 ttusb2_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C; -} - -static struct i2c_algorithm ttusb2_i2c_algo = { - .master_xfer = ttusb2_i2c_xfer, - .functionality = ttusb2_i2c_func, -}; - -/* Callbacks for DVB USB */ -static int ttusb2_identify_state (struct usb_device *udev, struct - dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, - int *cold) -{ - *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; - return 0; -} - -static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) -{ - u8 b = onoff; - ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); - return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); -} - - -static struct tda10086_config tda10086_config = { - .demod_address = 0x0e, - .invert = 0, -}; - -static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) -{ - if (usb_set_interface(adap->dev->udev,0,3) < 0) - err("set interface to alts=3 failed"); - - if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) { - deb_info("TDA10086 attach failed\n"); - return -ENODEV; - } - - return 0; -} - -static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap) -{ - if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { - deb_info("TDA8263 attach failed\n"); - return -ENODEV; - } - - if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) { - deb_info("LNBP21 attach failed\n"); - return -ENODEV; - } - return 0; -} - -/* DVB USB Driver stuff */ -static struct dvb_usb_device_properties ttusb2_properties; - -static int ttusb2_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL); -} - -static struct usb_device_id ttusb2_table [] = { - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, - {} /* Terminating entry */ -}; -MODULE_DEVICE_TABLE (usb, ttusb2_table); - -static struct dvb_usb_device_properties ttusb2_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = CYPRESS_FX2, - .firmware = "dvb-usb-pctv-400e-01.fw", - - .size_of_priv = sizeof(struct ttusb2_state), - - .num_adapters = 1, - .adapter = { - { - .streaming_ctrl = NULL, // ttusb2_streaming_ctrl, - - .frontend_attach = ttusb2_frontend_attach, - .tuner_attach = ttusb2_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_ISOC, - .count = 5, - .endpoint = 0x02, - .u = { - .isoc = { - .framesperurb = 4, - .framesize = 940, - .interval = 1, - } - } - } - } - }, - - .power_ctrl = ttusb2_power_ctrl, - .identify_state = ttusb2_identify_state, - - .i2c_algo = &ttusb2_i2c_algo, - - .generic_bulk_ctrl_endpoint = 0x01, - - .num_device_descs = 1, - .devices = { - { "Pinnacle 400e DVB-S USB2.0", - { &ttusb2_table[0], NULL }, - { NULL }, - }, - } -}; - -static struct usb_driver ttusb2_driver = { - .name = "dvb_usb_ttusb2", - .probe = ttusb2_probe, - .disconnect = dvb_usb_device_exit, - .id_table = ttusb2_table, -}; - -/* module stuff */ -static int __init ttusb2_module_init(void) -{ - int result; - if ((result = usb_register(&ttusb2_driver))) { - err("usb_register failed. Error number %d",result); - return result; - } - - return 0; -} - -static void __exit ttusb2_module_exit(void) -{ - /* deregister this driver from the USB subsystem */ - usb_deregister(&ttusb2_driver); -} - -module_init (ttusb2_module_init); -module_exit (ttusb2_module_exit); - -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); -MODULE_VERSION("1.0"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/media/dvb/dvb-usb/ttusb2.h b/trunk/drivers/media/dvb/dvb-usb/ttusb2.h deleted file mode 100644 index 52a63af40896..000000000000 --- a/trunk/drivers/media/dvb/dvb-usb/ttusb2.h +++ /dev/null @@ -1,70 +0,0 @@ -/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones - * (e.g. Pinnacle 400e DVB-S USB2.0). - * - * Copyright (c) 2002 Holger Waechtler - * Copyright (c) 2003 Felix Domke - * Copyright (C) 2005-6 Patrick Boettcher - * - * 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, version 2. - * - * see Documentation/dvb/README.dvb-usb for more information - */ -#ifndef _DVB_USB_TTUSB2_H_ -#define _DVB_USB_TTUSB2_H_ - -/* TTUSB protocol - * - * always to messages (out/in) - * out message: - * 0xaa - * - * in message (complete block is always 0x40 bytes long) - * 0x55 - * - * id is incremented for each transaction - */ - -#define CMD_DSP_DOWNLOAD 0x13 -/* out data: [28] - * last block must be empty */ - -#define CMD_DSP_BOOT 0x14 -/* out data: nothing */ - -#define CMD_POWER 0x15 -/* out data: */ - -#define CMD_LNB 0x16 -/* out data: <18V=0,13V=1> */ - -#define CMD_GET_VERSION 0x17 -/* in data: [5] */ - -#define CMD_DISEQC 0x18 -/* out data: [cmdlen] */ - -#define CMD_PID_ENABLE 0x22 -/* out data: */ - -#define CMD_PID_DISABLE 0x23 -/* out data: */ - -#define CMD_FILTER_ENABLE 0x24 -/* out data: [12] [12] */ - -#define CMD_FILTER_DISABLE 0x25 -/* out data: */ - -#define CMD_GET_DSP_VERSION 0x26 -/* in data: [28] */ - -#define CMD_I2C_XFER 0x31 -/* out data: [sndlen] - * in data: [rcvlen] */ - -#define CMD_I2C_BITRATE 0x32 -/* out data: */ - -#endif diff --git a/trunk/drivers/media/dvb/dvb-usb/umt-010.c b/trunk/drivers/media/dvb/dvb-usb/umt-010.c index f77b48f76582..f9941ea88b3e 100644 --- a/trunk/drivers/media/dvb/dvb-usb/umt-010.c +++ b/trunk/drivers/media/dvb/dvb-usb/umt-010.c @@ -99,21 +99,21 @@ static struct dvb_usb_device_properties umt_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .frontend_attach = umt_mt352_frontend_attach, - .tuner_attach = umt_tuner_attach, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .frontend_attach = umt_mt352_frontend_attach, + .tuner_attach = umt_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 20, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 512, - } - } - }, + .count = 20, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } diff --git a/trunk/drivers/media/dvb/dvb-usb/vp702x.c b/trunk/drivers/media/dvb/dvb-usb/vp702x.c index 16533b31a82d..02bd61aaac66 100644 --- a/trunk/drivers/media/dvb/dvb-usb/vp702x.c +++ b/trunk/drivers/media/dvb/dvb-usb/vp702x.c @@ -275,22 +275,22 @@ static struct dvb_usb_device_properties vp702x_properties = { .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, .streaming_ctrl = vp702x_streaming_ctrl, - .frontend_attach = vp702x_frontend_attach, + .frontend_attach = vp702x_frontend_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, .count = 10, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, - .size_of_priv = sizeof(struct vp702x_state), + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } } }, + .size_of_priv = sizeof(struct vp702x_state), + } + }, .read_mac_address = vp702x_read_mac_addr, .rc_key_map = vp702x_rc_keys, diff --git a/trunk/drivers/media/dvb/dvb-usb/vp7045.c b/trunk/drivers/media/dvb/dvb-usb/vp7045.c index 69a46b3607a2..b4cf002703a7 100644 --- a/trunk/drivers/media/dvb/dvb-usb/vp7045.c +++ b/trunk/drivers/media/dvb/dvb-usb/vp7045.c @@ -125,25 +125,7 @@ static struct dvb_usb_rc_key vp7045_rc_keys[] = { { 0x00, 0x00, KEY_TAB }, /* Tab */ { 0x00, 0x48, KEY_INFO }, /* Preview */ { 0x00, 0x04, KEY_LIST }, /* RecordList */ - { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ - { 0x00, 0x41, KEY_PREVIOUSSONG }, - { 0x00, 0x42, KEY_NEXTSONG }, - { 0x00, 0x4b, KEY_UP }, - { 0x00, 0x51, KEY_DOWN }, - { 0x00, 0x4e, KEY_LEFT }, - { 0x00, 0x52, KEY_RIGHT }, - { 0x00, 0x4f, KEY_ENTER }, - { 0x00, 0x13, KEY_CANCEL }, - { 0x00, 0x4a, KEY_CLEAR }, - { 0x00, 0x54, KEY_PRINT }, /* Capture */ - { 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */ - { 0x00, 0x08, KEY_VIDEO }, /* A/V */ - { 0x00, 0x07, KEY_SLEEP }, /* Hibernate */ - { 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */ - { 0x00, 0x18, KEY_RED}, - { 0x00, 0x53, KEY_GREEN}, - { 0x00, 0x5e, KEY_YELLOW}, - { 0x00, 0x5f, KEY_BLUE} + { 0x00, 0x0f, KEY_TEXT } /* Teletext */ }; static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) @@ -235,18 +217,18 @@ static struct dvb_usb_device_properties vp7045_properties = { .num_adapters = 1, .adapter = { { - .frontend_attach = vp7045_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .frontend_attach = vp7045_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .power_ctrl = vp7045_power_ctrl, diff --git a/trunk/drivers/media/dvb/frontends/Kconfig b/trunk/drivers/media/dvb/frontends/Kconfig index af314bb1dcac..aebb8d6f26f8 100644 --- a/trunk/drivers/media/dvb/frontends/Kconfig +++ b/trunk/drivers/media/dvb/frontends/Kconfig @@ -172,22 +172,6 @@ config DVB_DIB3000MC A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. -config DVB_DIB7000M - tristate "DiBcom 7000MA/MB/PA/PB/MC" - depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE - help - A DVB-T tuner module. Designed for mobile usage. Say Y when you want - to support this frontend. - -config DVB_DIB7000P - tristate "DiBcom 7000PC" - depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE - help - A DVB-T tuner module. Designed for mobile usage. Say Y when you want - to support this frontend. - comment "DVB-C (cable) frontends" depends on DVB_CORE @@ -297,14 +281,6 @@ config DVB_TUNER_MT2060 help A driver for the silicon IF tuner MT2060 from Microtune. -config DVB_TUNER_LGH06XF - tristate "LG TDVS-H06xF ATSC tuner" - depends on DVB_CORE && I2C - select DVB_PLL - default m if DVB_FE_CUSTOMISE - help - A driver for the LG TDVS-H06xF ATSC tuner family. - comment "Miscellaneous devices" depends on DVB_CORE diff --git a/trunk/drivers/media/dvb/frontends/Makefile b/trunk/drivers/media/dvb/frontends/Makefile index 3fa6e5d32a9c..dce9cf0c75c0 100644 --- a/trunk/drivers/media/dvb/frontends/Makefile +++ b/trunk/drivers/media/dvb/frontends/Makefile @@ -13,8 +13,6 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o obj-$(CONFIG_DVB_L64781) += l64781.o obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o -obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o -obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o obj-$(CONFIG_DVB_VES1X93) += ves1x93.o @@ -39,4 +37,3 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o -obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o diff --git a/trunk/drivers/media/dvb/frontends/dib3000mc.c b/trunk/drivers/media/dvb/frontends/dib3000mc.c index 5da66178006c..3561a777568c 100644 --- a/trunk/drivers/media/dvb/frontends/dib3000mc.c +++ b/trunk/drivers/media/dvb/frontends/dib3000mc.c @@ -511,11 +511,16 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000 /* a channel for autosearch */ + reg = 0; + if (chan->nfft == -1 && chan->guard == -1) reg = 7; + if (chan->nfft == -1 && chan->guard != -1) reg = 2; + if (chan->nfft != -1 && chan->guard == -1) reg = 3; + fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; fchan.vit_hrch = 0; fchan.vit_select_hp = 1; - dib3000mc_set_channel_cfg(state, &fchan, 7); + dib3000mc_set_channel_cfg(state, &fchan, reg); reg = dib3000mc_read_word(state, 0); dib3000mc_write_word(state, 0, reg | (1 << 8)); diff --git a/trunk/drivers/media/dvb/frontends/dib7000m.c b/trunk/drivers/media/dvb/frontends/dib7000m.c deleted file mode 100644 index f5d40aa3d27f..000000000000 --- a/trunk/drivers/media/dvb/frontends/dib7000m.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* - * Linux-DVB Driver for DiBcom's DiB7000M and - * first generation DiB7000P-demodulator-family. - * - * Copyright (C) 2005-6 DiBcom (http://www.dibcom.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, version 2. - */ -#include -#include - -#include "dvb_frontend.h" - -#include "dib7000m.h" - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); - -#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0) - -struct dib7000m_state { - struct dvb_frontend demod; - struct dib7000m_config cfg; - - u8 i2c_addr; - struct i2c_adapter *i2c_adap; - - struct dibx000_i2c_master i2c_master; - -/* offset is 1 in case of the 7000MC */ - u8 reg_offs; - - u16 wbd_ref; - - u8 current_band; - fe_bandwidth_t current_bandwidth; - struct dibx000_agc_config *current_agc; - u32 timf; - - u16 revision; -}; - -enum dib7000m_power_mode { - DIB7000M_POWER_ALL = 0, - - DIB7000M_POWER_NO, - DIB7000M_POWER_INTERF_ANALOG_AGC, - DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD, - DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD, - DIB7000M_POWER_INTERFACE_ONLY, -}; - -static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) -{ - u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; - u8 rb[2]; - struct i2c_msg msg[2] = { - { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, - { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, - }; - - if (i2c_transfer(state->i2c_adap, msg, 2) != 2) - dprintk("i2c read error on %d\n",reg); - - return (rb[0] << 8) | rb[1]; -} - -static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) -{ - u8 b[4] = { - (reg >> 8) & 0xff, reg & 0xff, - (val >> 8) & 0xff, val & 0xff, - }; - struct i2c_msg msg = { - .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 - }; - return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; -} -static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) -{ - int ret = 0; - u16 outreg, fifo_threshold, smo_mode, - sram = 0x0005; /* by default SRAM output is disabled */ - - outreg = 0; - fifo_threshold = 1792; - smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); - - dprintk("-I- Setting output mode for demod %p to %d\n", - &state->demod, mode); - - switch (mode) { - case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock - outreg = (1 << 10); /* 0x0400 */ - break; - case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock - outreg = (1 << 10) | (1 << 6); /* 0x0440 */ - break; - case OUTMODE_MPEG2_SERIAL: // STBs with serial input - outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ - break; - case OUTMODE_DIVERSITY: - if (state->cfg.hostbus_diversity) - outreg = (1 << 10) | (4 << 6); /* 0x0500 */ - else - sram |= 0x0c00; - break; - case OUTMODE_MPEG2_FIFO: // e.g. USB feeding - smo_mode |= (3 << 1); - fifo_threshold = 512; - outreg = (1 << 10) | (5 << 6); - break; - case OUTMODE_HIGH_Z: // disable - outreg = 0; - break; - default: - dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); - break; - } - - if (state->cfg.output_mpeg2_in_188_bytes) - smo_mode |= (1 << 5) ; - - ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode); - ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */ - ret |= dib7000m_write_word(state, 1795, outreg); - ret |= dib7000m_write_word(state, 1805, sram); - - return ret; -} - -static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) -{ - /* by default everything is going to be powered off */ - u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; - - /* now, depending on the requested mode, we power on */ - switch (mode) { - /* power up everything in the demod */ - case DIB7000M_POWER_ALL: - reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000; - break; - - /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */ - case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */ - reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2)); - break; - - case DIB7000M_POWER_INTERF_ANALOG_AGC: - reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10)); - reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2)); - reg_906 &= ~((1 << 0)); - break; - - case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD: - reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000; - break; - - case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD: - reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000; - break; - case DIB7000M_POWER_NO: - break; - } - - /* always power down unused parts */ - if (!state->cfg.mobile_mode) - reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); - - /* P_sdio_select_clk = 0 on MC */ - if (state->revision != 0x4000) - reg_906 <<= 1; - - dib7000m_write_word(state, 903, reg_903); - dib7000m_write_word(state, 904, reg_904); - dib7000m_write_word(state, 905, reg_905); - dib7000m_write_word(state, 906, reg_906); - - return 0; -} - -static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) -{ - int ret = 0; - u16 reg_913 = dib7000m_read_word(state, 913), - reg_914 = dib7000m_read_word(state, 914); - - switch (no) { - case DIBX000_SLOW_ADC_ON: - reg_914 |= (1 << 1) | (1 << 0); - ret |= dib7000m_write_word(state, 914, reg_914); - reg_914 &= ~(1 << 1); - break; - - case DIBX000_SLOW_ADC_OFF: - reg_914 |= (1 << 1) | (1 << 0); - break; - - case DIBX000_ADC_ON: - if (state->revision == 0x4000) { // workaround for PA/MA - // power-up ADC - dib7000m_write_word(state, 913, 0); - dib7000m_write_word(state, 914, reg_914 & 0x3); - // power-down bandgag - dib7000m_write_word(state, 913, (1 << 15)); - dib7000m_write_word(state, 914, reg_914 & 0x3); - } - - reg_913 &= 0x0fff; - reg_914 &= 0x0003; - break; - - case DIBX000_ADC_OFF: // leave the VBG voltage on - reg_913 |= (1 << 14) | (1 << 13) | (1 << 12); - reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); - break; - - case DIBX000_VBG_ENABLE: - reg_913 &= ~(1 << 15); - break; - - case DIBX000_VBG_DISABLE: - reg_913 |= (1 << 15); - break; - - default: - break; - } - -// dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914); - - ret |= dib7000m_write_word(state, 913, reg_913); - ret |= dib7000m_write_word(state, 914, reg_914); - - return ret; -} - -static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx) -{ - struct dib7000m_state *state = demod->demodulator_priv; - u32 timf; - - // store the current bandwidth for later use - state->current_bandwidth = bw_idx; - - if (state->timf == 0) { - dprintk("-D- Using default timf\n"); - timf = state->cfg.bw->timf; - } else { - dprintk("-D- Using updated timf\n"); - timf = state->timf; - } - - timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80; - - dib7000m_write_word(state, 23, (timf >> 16) & 0xffff); - dib7000m_write_word(state, 24, (timf ) & 0xffff); - - return 0; -} - -static int dib7000m_sad_calib(struct dib7000m_state *state) -{ - -/* internal */ -// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth - dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); - dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 - - /* do the calibration */ - dib7000m_write_word(state, 929, (1 << 0)); - dib7000m_write_word(state, 929, (0 << 0)); - - msleep(1); - - return 0; -} - -static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) -{ - dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); - dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff); - dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); - dib7000m_write_word(state, 22, bw->ifreq & 0xffff); - - dib7000m_write_word(state, 928, bw->sad_cfg); -} - -static void dib7000m_reset_pll(struct dib7000m_state *state) -{ - const struct dibx000_bandwidth_config *bw = state->cfg.bw; - u16 reg_907,reg_910; - - /* default */ - reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) | - (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | - (bw->enable_refdiv << 1) | (0 << 0); - reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset; - - // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value) - // this is only working only for 30 MHz crystals - if (!state->cfg.quartz_direct) { - reg_910 |= (1 << 5); // forcing the predivider to 1 - - // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2) - if(state->cfg.input_clk_is_div_2) - reg_907 |= (16 << 9); - else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary - reg_907 |= (8 << 9); - } else { - reg_907 |= (bw->pll_ratio & 0x3f) << 9; - reg_910 |= (bw->pll_prediv << 5); - } - - dib7000m_write_word(state, 910, reg_910); // pll cfg - dib7000m_write_word(state, 907, reg_907); // clk cfg0 - dib7000m_write_word(state, 908, 0x0006); // clk_cfg1 - - dib7000m_reset_pll_common(state, bw); -} - -static void dib7000mc_reset_pll(struct dib7000m_state *state) -{ - const struct dibx000_bandwidth_config *bw = state->cfg.bw; - - // clk_cfg0 - dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); - - // clk_cfg1 - //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | - dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) | - (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | - (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0)); - - // smpl_cfg - dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); - - dib7000m_reset_pll_common(state, bw); -} - -static int dib7000m_reset_gpio(struct dib7000m_state *st) -{ - /* reset the GPIOs */ - dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n", - st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos); - - dib7000m_write_word(st, 773, st->cfg.gpio_dir); - dib7000m_write_word(st, 774, st->cfg.gpio_val); - - /* TODO 782 is P_gpio_od */ - - dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos); - - dib7000m_write_word(st, 780, st->cfg.pwm_freq_div); - return 0; -} - -static int dib7000m_demod_reset(struct dib7000m_state *state) -{ - dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); - - /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ - dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE); - - /* restart all parts */ - dib7000m_write_word(state, 898, 0xffff); - dib7000m_write_word(state, 899, 0xffff); - dib7000m_write_word(state, 900, 0xff0f); - dib7000m_write_word(state, 901, 0xfffc); - - dib7000m_write_word(state, 898, 0); - dib7000m_write_word(state, 899, 0); - dib7000m_write_word(state, 900, 0); - dib7000m_write_word(state, 901, 0); - - if (state->revision == 0x4000) - dib7000m_reset_pll(state); - else - dib7000mc_reset_pll(state); - - if (dib7000m_reset_gpio(state) != 0) - dprintk("-E- GPIO reset was not successful.\n"); - - if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) - dprintk("-E- OUTPUT_MODE could not be resetted.\n"); - - /* unforce divstr regardless whether i2c enumeration was done or not */ - dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); - - dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); - - dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); - dib7000m_sad_calib(state); - dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); - - dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); - - return 0; -} - -static void dib7000m_restart_agc(struct dib7000m_state *state) -{ - // P_restart_iqc & P_restart_agc - dib7000m_write_word(state, 898, 0x0c00); - dib7000m_write_word(state, 898, 0x0000); -} - -static int dib7000m_agc_soft_split(struct dib7000m_state *state) -{ - u16 agc,split_offset; - - if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) - return 0; - - // n_agc_global - agc = dib7000m_read_word(state, 390); - - if (agc > state->current_agc->split.min_thres) - split_offset = state->current_agc->split.min; - else if (agc < state->current_agc->split.max_thres) - split_offset = state->current_agc->split.max; - else - split_offset = state->current_agc->split.max * - (agc - state->current_agc->split.min_thres) / - (state->current_agc->split.max_thres - state->current_agc->split.min_thres); - - dprintk("AGC split_offset: %d\n",split_offset); - - // P_agc_force_split and P_agc_split_offset - return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); -} - -static int dib7000m_update_lna(struct dib7000m_state *state) -{ - int i; - u16 dyn_gain; - - // when there is no LNA to program return immediatly - if (state->cfg.update_lna == NULL) - return 0; - - msleep(60); - for (i = 0; i < 20; i++) { - // read dyn_gain here (because it is demod-dependent and not tuner) - dyn_gain = dib7000m_read_word(state, 390); - - dprintk("agc global: %d\n", dyn_gain); - - if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed - dib7000m_restart_agc(state); - msleep(60); - } else - break; - } - return 0; -} - -static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) -{ - struct dibx000_agc_config *agc = NULL; - int i; - if (state->current_band == band) - return; - state->current_band = band; - - for (i = 0; i < state->cfg.agc_config_count; i++) - if (state->cfg.agc[i].band_caps & band) { - agc = &state->cfg.agc[i]; - break; - } - - if (agc == NULL) { - dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band); - return; - } - - state->current_agc = agc; - - /* AGC */ - dib7000m_write_word(state, 72 , agc->setup); - dib7000m_write_word(state, 73 , agc->inv_gain); - dib7000m_write_word(state, 74 , agc->time_stabiliz); - dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock); - - // Demod AGC loop configuration - dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); - dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); - - dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", - state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); - - /* AGC continued */ - if (state->wbd_ref != 0) - dib7000m_write_word(state, 102, state->wbd_ref); - else // use default - dib7000m_write_word(state, 102, agc->wbd_ref); - - dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); - dib7000m_write_word(state, 104, agc->agc1_max); - dib7000m_write_word(state, 105, agc->agc1_min); - dib7000m_write_word(state, 106, agc->agc2_max); - dib7000m_write_word(state, 107, agc->agc2_min); - dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); - dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2); - dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2); - dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2); - - if (state->revision > 0x4000) { // settings for the MC - dib7000m_write_word(state, 71, agc->agc1_pt3); -// dprintk("-D- 929: %x %d %d\n", -// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); - dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); - } else { - // wrong default values - u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 }; - for (i = 0; i < 9; i++) - dib7000m_write_word(state, 88 + i, b[i]); - } -} - -static void dib7000m_update_timf_freq(struct dib7000m_state *state) -{ - u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); - state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); - dib7000m_write_word(state, 23, (u16) (timf >> 16)); - dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); - dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); -} - -static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq) -{ - u16 value, est[4]; - - dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz)); - - /* nfft, guard, qam, alpha */ - dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); - dib7000m_write_word(state, 5, (seq << 4)); - - /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ - value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); - if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) - value |= (ch->vit_code_rate_hp << 1); - else - value |= (ch->vit_code_rate_lp << 1); - dib7000m_write_word(state, 267 + state->reg_offs, value); - - /* offset loop parameters */ - - /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */ - dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80); - - /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ - dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3)); - - /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */ - dib7000m_write_word(state, 32, (0 << 4) | 0x3); - - /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */ - dib7000m_write_word(state, 33, (0 << 4) | 0x5); - - /* P_dvsy_sync_wait */ - switch (ch->nfft) { - case 1: value = 256; break; - case 2: value = 128; break; - case 0: - default: value = 64; break; - } - value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin - value <<= 4; - - /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */ - /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ - if (ch->intlv_native || state->revision > 0x4000) - value |= (1 << 2) | (2 << 0); - else - value |= 0; - dib7000m_write_word(state, 266 + state->reg_offs, value); - - /* channel estimation fine configuration */ - switch (ch->nqam) { - case 2: - est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ - est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ - est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ - est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ - break; - case 1: - est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ - est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ - est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ - est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ - break; - default: - est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ - est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ - est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ - est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ - break; - } - for (value = 0; value < 4; value++) - dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); - - // set power-up level: interf+analog+AGC - dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); - dib7000m_set_adc_state(state, DIBX000_ADC_ON); - - msleep(7); - - //AGC initialization - if (state->cfg.agc_control) - state->cfg.agc_control(&state->demod, 1); - - dib7000m_restart_agc(state); - - // wait AGC rough lock time - msleep(5); - - dib7000m_update_lna(state); - dib7000m_agc_soft_split(state); - - // wait AGC accurate lock time - msleep(7); - - if (state->cfg.agc_control) - state->cfg.agc_control(&state->demod, 0); - - // set power-up level: autosearch - dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); -} - -static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) -{ - struct dib7000m_state *state = demod->demodulator_priv; - struct dibx000_ofdm_channel auto_ch; - int ret = 0; - u32 value; - - INIT_OFDM_CHANNEL(&auto_ch); - auto_ch.RF_kHz = ch->RF_kHz; - auto_ch.Bw = ch->Bw; - auto_ch.nqam = 2; - auto_ch.guard = 0; - auto_ch.nfft = 1; - auto_ch.vit_alpha = 1; - auto_ch.vit_select_hp = 1; - auto_ch.vit_code_rate_hp = 2; - auto_ch.vit_code_rate_lp = 3; - auto_ch.vit_hrch = 0; - auto_ch.intlv_native = 1; - - dib7000m_set_channel(state, &auto_ch, 7); - - // always use the setting for 8MHz here lock_time for 7,6 MHz are longer - value = 30 * state->cfg.bw->internal; - ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time - ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time - value = 100 * state->cfg.bw->internal; - ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time - ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time - value = 500 * state->cfg.bw->internal; - ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time - ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time - - // start search - value = dib7000m_read_word(state, 0); - ret |= dib7000m_write_word(state, 0, value | (1 << 9)); - - /* clear n_irq_pending */ - if (state->revision == 0x4000) - dib7000m_write_word(state, 1793, 0); - else - dib7000m_read_word(state, 537); - - ret |= dib7000m_write_word(state, 0, (u16) value); - - return ret; -} - -static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg) -{ - u16 irq_pending = dib7000m_read_word(state, reg); - - if (irq_pending & 0x1) { // failed - dprintk("#\n"); - return 1; - } - - if (irq_pending & 0x2) { // succeeded - dprintk("!\n"); - return 2; - } - return 0; // still pending -} - -static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod) -{ - struct dib7000m_state *state = demod->demodulator_priv; - if (state->revision == 0x4000) - return dib7000m_autosearch_irq(state, 1793); - else - return dib7000m_autosearch_irq(state, 537); -} - -static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) -{ - struct dib7000m_state *state = demod->demodulator_priv; - int ret = 0; - u16 value; - - // we are already tuned - just resuming from suspend - if (ch != NULL) - dib7000m_set_channel(state, ch, 0); - else - return -EINVAL; - - // restart demod - ret |= dib7000m_write_word(state, 898, 0x4000); - ret |= dib7000m_write_word(state, 898, 0x0000); - msleep(45); - - ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); - /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ - ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); - - // never achieved a lock with that bandwidth so far - wait for timfreq to update - if (state->timf == 0) - msleep(200); - - //dump_reg(state); - /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ - value = (6 << 8) | 0x80; - switch (ch->nfft) { - case 0: value |= (7 << 12); break; - case 1: value |= (9 << 12); break; - case 2: value |= (8 << 12); break; - } - ret |= dib7000m_write_word(state, 26, value); - - /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ - value = (0 << 4); - switch (ch->nfft) { - case 0: value |= 0x6; break; - case 1: value |= 0x8; break; - case 2: value |= 0x7; break; - } - ret |= dib7000m_write_word(state, 32, value); - - /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ - value = (0 << 4); - switch (ch->nfft) { - case 0: value |= 0x6; break; - case 1: value |= 0x8; break; - case 2: value |= 0x7; break; - } - ret |= dib7000m_write_word(state, 33, value); - - // we achieved a lock - it's time to update the osc freq - if ((dib7000m_read_word(state, 535) >> 6) & 0x1) - dib7000m_update_timf_freq(state); - - return ret; -} - -static int dib7000m_init(struct dvb_frontend *demod) -{ - struct dib7000m_state *state = demod->demodulator_priv; - int ret = 0; - u8 o = state->reg_offs; - - dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); - - if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) - dprintk("-E- could not start Slow ADC\n"); - - if (state->cfg.dvbt_mode) - dib7000m_write_word(state, 1796, 0x0); // select DVB-T output - - if (state->cfg.mobile_mode) - ret |= dib7000m_write_word(state, 261 + o, 2); - else - ret |= dib7000m_write_word(state, 224 + o, 1); - - ret |= dib7000m_write_word(state, 173 + o, 0); - ret |= dib7000m_write_word(state, 174 + o, 0); - ret |= dib7000m_write_word(state, 175 + o, 0); - ret |= dib7000m_write_word(state, 176 + o, 0); - ret |= dib7000m_write_word(state, 177 + o, 0); - ret |= dib7000m_write_word(state, 178 + o, 0); - ret |= dib7000m_write_word(state, 179 + o, 0); - ret |= dib7000m_write_word(state, 180 + o, 0); - - // P_corm_thres Lock algorithms configuration - ret |= dib7000m_write_word(state, 26, 0x6680); - - // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on - ret |= dib7000m_write_word(state, 170 + o, 0x0410); - // P_fft_nb_to_cut - ret |= dib7000m_write_word(state, 182 + o, 8192); - // P_pha3_thres - ret |= dib7000m_write_word(state, 195 + o, 0x0ccd); - // P_cti_use_cpe, P_cti_use_prog - ret |= dib7000m_write_word(state, 196 + o, 0); - // P_cspu_regul, P_cspu_win_cut - ret |= dib7000m_write_word(state, 205 + o, 0x200f); - // P_adp_regul_cnt - ret |= dib7000m_write_word(state, 214 + o, 0x023d); - // P_adp_noise_cnt - ret |= dib7000m_write_word(state, 215 + o, 0x00a4); - // P_adp_regul_ext - ret |= dib7000m_write_word(state, 216 + o, 0x00a4); - // P_adp_noise_ext - ret |= dib7000m_write_word(state, 217 + o, 0x7ff0); - // P_adp_fil - ret |= dib7000m_write_word(state, 218 + o, 0x3ccc); - - // P_2d_byp_ti_num - ret |= dib7000m_write_word(state, 226 + o, 0); - - // P_fec_* - ret |= dib7000m_write_word(state, 281 + o, 0x0010); - // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard - ret |= dib7000m_write_word(state, 294 + o,0x0062); - - // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... - if(state->cfg.tuner_is_baseband) - ret |= dib7000m_write_word(state, 36, 0x0755); - else - ret |= dib7000m_write_word(state, 36, 0x1f55); - - // auto search configuration - ret |= dib7000m_write_word(state, 2, 0x0004); - ret |= dib7000m_write_word(state, 3, 0x1000); - ret |= dib7000m_write_word(state, 4, 0x0814); - ret |= dib7000m_write_word(state, 6, 0x001b); - ret |= dib7000m_write_word(state, 7, 0x7740); - ret |= dib7000m_write_word(state, 8, 0x005b); - ret |= dib7000m_write_word(state, 9, 0x8d80); - ret |= dib7000m_write_word(state, 10, 0x01c9); - ret |= dib7000m_write_word(state, 11, 0xc380); - ret |= dib7000m_write_word(state, 12, 0x0000); - ret |= dib7000m_write_word(state, 13, 0x0080); - ret |= dib7000m_write_word(state, 14, 0x0000); - ret |= dib7000m_write_word(state, 15, 0x0090); - ret |= dib7000m_write_word(state, 16, 0x0001); - ret |= dib7000m_write_word(state, 17, 0xd4c0); - ret |= dib7000m_write_word(state, 263 + o,0x0001); - - // P_divclksel=3 P_divbitsel=1 - if (state->revision == 0x4000) - dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); - else - dib7000m_write_word(state, 909, (3 << 4) | 1); - - // Tuner IO bank: max drive (14mA) - ret |= dib7000m_write_word(state, 912 ,0x2c8a); - - ret |= dib7000m_write_word(state, 1817, 1); - - return ret; -} - -static int dib7000m_sleep(struct dvb_frontend *demod) -{ - struct dib7000m_state *st = demod->demodulator_priv; - dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); - return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) | - dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | - dib7000m_set_adc_state(st, DIBX000_ADC_OFF); -} - -static int dib7000m_identify(struct dib7000m_state *state) -{ - u16 value; - if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { - dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value); - return -EREMOTEIO; - } - - state->revision = dib7000m_read_word(state, 897); - if (state->revision != 0x4000 && - state->revision != 0x4001 && - state->revision != 0x4002) { - dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value); - return -EREMOTEIO; - } - - /* protect this driver to be used with 7000PC */ - if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { - dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n"); - return -EREMOTEIO; - } - - switch (state->revision) { - case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break; - case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break; - case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break; - } - - return 0; -} - - -static int dib7000m_get_frontend(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) -{ - struct dib7000m_state *state = fe->demodulator_priv; - u16 tps = dib7000m_read_word(state,480); - - fep->inversion = INVERSION_AUTO; - - fep->u.ofdm.bandwidth = state->current_bandwidth; - - switch ((tps >> 8) & 0x3) { - case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; - case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; - /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ - } - - switch (tps & 0x3) { - case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; - case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; - case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; - case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; - } - - switch ((tps >> 14) & 0x3) { - case 0: fep->u.ofdm.constellation = QPSK; break; - case 1: fep->u.ofdm.constellation = QAM_16; break; - case 2: - default: fep->u.ofdm.constellation = QAM_64; break; - } - - /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ - /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ - - fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; - switch ((tps >> 5) & 0x7) { - case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; - case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; - case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; - case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; - case 7: - default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; - - } - - switch ((tps >> 2) & 0x7) { - case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; - case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; - case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; - case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; - case 7: - default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; - } - - /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */ - - return 0; -} - -static int dib7000m_set_frontend(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) -{ - struct dib7000m_state *state = fe->demodulator_priv; - struct dibx000_ofdm_channel ch; - - INIT_OFDM_CHANNEL(&ch); - FEP2DIB(fep,&ch); - - state->current_bandwidth = fep->u.ofdm.bandwidth; - dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth); - - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe, fep); - - if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || - fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || - fep->u.ofdm.constellation == QAM_AUTO || - fep->u.ofdm.code_rate_HP == FEC_AUTO) { - int i = 800, found; - - dib7000m_autosearch_start(fe, &ch); - do { - msleep(1); - found = dib7000m_autosearch_is_irq(fe); - } while (found == 0 && i--); - - dprintk("autosearch returns: %d\n",found); - if (found == 0 || found == 1) - return 0; // no channel found - - dib7000m_get_frontend(fe, fep); - FEP2DIB(fep, &ch); - } - - /* make this a config parameter */ - dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); - - return dib7000m_tune(fe, &ch); -} - -static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) -{ - struct dib7000m_state *state = fe->demodulator_priv; - u16 lock = dib7000m_read_word(state, 535); - - *stat = 0; - - if (lock & 0x8000) - *stat |= FE_HAS_SIGNAL; - if (lock & 0x3000) - *stat |= FE_HAS_CARRIER; - if (lock & 0x0100) - *stat |= FE_HAS_VITERBI; - if (lock & 0x0010) - *stat |= FE_HAS_SYNC; - if (lock & 0x0008) - *stat |= FE_HAS_LOCK; - - return 0; -} - -static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber) -{ - struct dib7000m_state *state = fe->demodulator_priv; - *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527); - return 0; -} - -static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) -{ - struct dib7000m_state *state = fe->demodulator_priv; - *unc = dib7000m_read_word(state, 534); - return 0; -} - -static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -{ - struct dib7000m_state *state = fe->demodulator_priv; - u16 val = dib7000m_read_word(state, 390); - *strength = 65535 - val; - return 0; -} - -static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr) -{ - *snr = 0x0000; - return 0; -} - -static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) -{ - tune->min_delay_ms = 1000; - return 0; -} - -static void dib7000m_release(struct dvb_frontend *demod) -{ - struct dib7000m_state *st = demod->demodulator_priv; - dibx000_exit_i2c_master(&st->i2c_master); - kfree(st); -} - -struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) -{ - struct dib7000m_state *st = demod->demodulator_priv; - return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); -} -EXPORT_SYMBOL(dib7000m_get_i2c_master); - -int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) -{ - struct dib7000m_state st = { .i2c_adap = i2c }; - int k = 0; - u8 new_addr = 0; - - for (k = no_of_demods-1; k >= 0; k--) { - st.cfg = cfg[k]; - - /* designated i2c address */ - new_addr = (0x40 + k) << 1; - st.i2c_addr = new_addr; - if (dib7000m_identify(&st) != 0) { - st.i2c_addr = default_addr; - if (dib7000m_identify(&st) != 0) { - dprintk("DiB7000M #%d: not identified\n", k); - return -EIO; - } - } - - /* start diversity to pull_down div_str - just for i2c-enumeration */ - dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY); - - dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output - - /* set new i2c address and force divstart */ - dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); - - dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); - } - - for (k = 0; k < no_of_demods; k++) { - st.cfg = cfg[k]; - st.i2c_addr = (0x40 + k) << 1; - - // unforce divstr - dib7000m_write_word(&st,1794, st.i2c_addr << 2); - - /* deactivate div - it was just for i2c-enumeration */ - dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z); - } - - return 0; -} -EXPORT_SYMBOL(dib7000m_i2c_enumeration); - -static struct dvb_frontend_ops dib7000m_ops; -struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) -{ - struct dvb_frontend *demod; - struct dib7000m_state *st; - st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL); - if (st == NULL) - return NULL; - - memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config)); - st->i2c_adap = i2c_adap; - st->i2c_addr = i2c_addr; - - demod = &st->demod; - demod->demodulator_priv = st; - memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); - - if (dib7000m_identify(st) != 0) - goto error; - - if (st->revision == 0x4000) - dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr); - else - dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr); - - dib7000m_demod_reset(st); - - return demod; - -error: - kfree(st); - return NULL; -} -EXPORT_SYMBOL(dib7000m_attach); - -static struct dvb_frontend_ops dib7000m_ops = { - .info = { - .name = "DiBcom 7000MA/MB/PA/PB/MC", - .type = FE_OFDM, - .frequency_min = 44250000, - .frequency_max = 867250000, - .frequency_stepsize = 62500, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_RECOVER | - FE_CAN_HIERARCHY_AUTO, - }, - - .release = dib7000m_release, - - .init = dib7000m_init, - .sleep = dib7000m_sleep, - - .set_frontend = dib7000m_set_frontend, - .get_tune_settings = dib7000m_fe_get_tune_settings, - .get_frontend = dib7000m_get_frontend, - - .read_status = dib7000m_read_status, - .read_ber = dib7000m_read_ber, - .read_signal_strength = dib7000m_read_signal_strength, - .read_snr = dib7000m_read_snr, - .read_ucblocks = dib7000m_read_unc_blocks, -}; - -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/media/dvb/frontends/dib7000m.h b/trunk/drivers/media/dvb/frontends/dib7000m.h deleted file mode 100644 index 597e9cc2da62..000000000000 --- a/trunk/drivers/media/dvb/frontends/dib7000m.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef DIB7000M_H -#define DIB7000M_H - -#include "dibx000_common.h" - -struct dib7000m_config { - u8 dvbt_mode; - u8 output_mpeg2_in_188_bytes; - u8 hostbus_diversity; - u8 tuner_is_baseband; - u8 mobile_mode; - int (*update_lna) (struct dvb_frontend *, u16 agc_global); - - u8 agc_config_count; - struct dibx000_agc_config *agc; - - struct dibx000_bandwidth_config *bw; - -#define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff - u16 gpio_dir; -#define DIB7000M_GPIO_DEFAULT_VALUES 0x0000 - u16 gpio_val; -#define DIB7000M_GPIO_PWM_POS0(v) ((v & 0xf) << 12) -#define DIB7000M_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) -#define DIB7000M_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) -#define DIB7000M_GPIO_PWM_POS3(v) (v & 0xf) -#define DIB7000M_GPIO_DEFAULT_PWM_POS 0xffff - u16 gpio_pwm_pos; - - u16 pwm_freq_div; - - u8 quartz_direct; - - u8 input_clk_is_div_2; - - int (*agc_control) (struct dvb_frontend *, u8 before); -}; - -#define DEFAULT_DIB7000M_I2C_ADDRESS 18 - -extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); -extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); - -/* TODO -extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); -extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod); -extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); -extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod); -*/ - -#endif diff --git a/trunk/drivers/media/dvb/frontends/dib7000p.c b/trunk/drivers/media/dvb/frontends/dib7000p.c deleted file mode 100644 index 0349a4b5da3f..000000000000 --- a/trunk/drivers/media/dvb/frontends/dib7000p.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* - * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC). - * - * Copyright (C) 2005-6 DiBcom (http://www.dibcom.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, version 2. - */ -#include -#include - -#include "dvb_frontend.h" - -#include "dib7000p.h" - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); - -#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0) - -struct dib7000p_state { - struct dvb_frontend demod; - struct dib7000p_config cfg; - - u8 i2c_addr; - struct i2c_adapter *i2c_adap; - - struct dibx000_i2c_master i2c_master; - - u16 wbd_ref; - - u8 current_band; - fe_bandwidth_t current_bandwidth; - struct dibx000_agc_config *current_agc; - u32 timf; - - u16 gpio_dir; - u16 gpio_val; -}; - -enum dib7000p_power_mode { - DIB7000P_POWER_ALL = 0, - DIB7000P_POWER_INTERFACE_ONLY, -}; - -static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) -{ - u8 wb[2] = { reg >> 8, reg & 0xff }; - u8 rb[2]; - struct i2c_msg msg[2] = { - { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, - { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, - }; - - if (i2c_transfer(state->i2c_adap, msg, 2) != 2) - dprintk("i2c read error on %d\n",reg); - - return (rb[0] << 8) | rb[1]; -} - -static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) -{ - u8 b[4] = { - (reg >> 8) & 0xff, reg & 0xff, - (val >> 8) & 0xff, val & 0xff, - }; - struct i2c_msg msg = { - .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 - }; - return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; -} -static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) -{ - int ret = 0; - u16 outreg, fifo_threshold, smo_mode; - - outreg = 0; - fifo_threshold = 1792; - smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1); - - dprintk("-I- Setting output mode for demod %p to %d\n", - &state->demod, mode); - - switch (mode) { - case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock - outreg = (1 << 10); /* 0x0400 */ - break; - case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock - outreg = (1 << 10) | (1 << 6); /* 0x0440 */ - break; - case OUTMODE_MPEG2_SERIAL: // STBs with serial input - outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */ - break; - case OUTMODE_DIVERSITY: - if (state->cfg.hostbus_diversity) - outreg = (1 << 10) | (4 << 6); /* 0x0500 */ - else - outreg = (1 << 11); - break; - case OUTMODE_MPEG2_FIFO: // e.g. USB feeding - smo_mode |= (3 << 1); - fifo_threshold = 512; - outreg = (1 << 10) | (5 << 6); - break; - case OUTMODE_HIGH_Z: // disable - outreg = 0; - break; - default: - dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); - break; - } - - if (state->cfg.output_mpeg2_in_188_bytes) - smo_mode |= (1 << 5) ; - - ret |= dib7000p_write_word(state, 235, smo_mode); - ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */ - ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */ - - return ret; -} - -static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode) -{ - /* by default everything is powered off */ - u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, - reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff); - - /* now, depending on the requested mode, we power on */ - switch (mode) { - /* power up everything in the demod */ - case DIB7000P_POWER_ALL: - reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff; - break; - /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ - case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */ - reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10)); - break; -/* TODO following stuff is just converted from the dib7000-driver - check when is used what */ - } - - dib7000p_write_word(state, 774, reg_774); - dib7000p_write_word(state, 775, reg_775); - dib7000p_write_word(state, 776, reg_776); - dib7000p_write_word(state, 899, reg_899); - dib7000p_write_word(state, 1280, reg_1280); - - return 0; -} - -static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no) -{ - u16 reg_908 = dib7000p_read_word(state, 908), - reg_909 = dib7000p_read_word(state, 909); - - switch (no) { - case DIBX000_SLOW_ADC_ON: - reg_909 |= (1 << 1) | (1 << 0); - dib7000p_write_word(state, 909, reg_909); - reg_909 &= ~(1 << 1); - break; - - case DIBX000_SLOW_ADC_OFF: - reg_909 |= (1 << 1) | (1 << 0); - break; - - case DIBX000_ADC_ON: - reg_908 &= 0x0fff; - reg_909 &= 0x0003; - break; - - case DIBX000_ADC_OFF: // leave the VBG voltage on - reg_908 |= (1 << 14) | (1 << 13) | (1 << 12); - reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); - break; - - case DIBX000_VBG_ENABLE: - reg_908 &= ~(1 << 15); - break; - - case DIBX000_VBG_DISABLE: - reg_908 |= (1 << 15); - break; - - default: - break; - } - -// dprintk("908: %x, 909: %x\n", reg_908, reg_909); - - dib7000p_write_word(state, 908, reg_908); - dib7000p_write_word(state, 909, reg_909); -} - -static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) -{ - struct dib7000p_state *state = demod->demodulator_priv; - u32 timf; - - // store the current bandwidth for later use - state->current_bandwidth = BW_Idx; - - if (state->timf == 0) { - dprintk("-D- Using default timf\n"); - timf = state->cfg.bw->timf; - } else { - dprintk("-D- Using updated timf\n"); - timf = state->timf; - } - - timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80; - - dprintk("timf: %d\n",timf); - - dib7000p_write_word(state, 23, (timf >> 16) & 0xffff); - dib7000p_write_word(state, 24, (timf ) & 0xffff); - - return 0; -} - -static int dib7000p_sad_calib(struct dib7000p_state *state) -{ -/* internal */ -// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth - dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); - dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 - - /* do the calibration */ - dib7000p_write_word(state, 73, (1 << 0)); - dib7000p_write_word(state, 73, (0 << 0)); - - msleep(1); - - return 0; -} - -static void dib7000p_reset_pll(struct dib7000p_state *state) -{ - struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; - - dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset); - dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) | - (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0)); - - dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); - dib7000p_write_word(state, 19, (bw->internal*1000 ) & 0xffff); - dib7000p_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); - dib7000p_write_word(state, 22, (bw->ifreq ) & 0xffff); - - dib7000p_write_word(state, 72, bw->sad_cfg); -} - -static int dib7000p_reset_gpio(struct dib7000p_state *st) -{ - /* reset the GPIOs */ - dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos); - - dib7000p_write_word(st, 1029, st->gpio_dir); - dib7000p_write_word(st, 1030, st->gpio_val); - - /* TODO 1031 is P_gpio_od */ - - dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos); - - dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div); - return 0; -} - -static int dib7000p_demod_reset(struct dib7000p_state *state) -{ - dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); - - dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE); - - /* restart all parts */ - dib7000p_write_word(state, 770, 0xffff); - dib7000p_write_word(state, 771, 0xffff); - dib7000p_write_word(state, 772, 0x001f); - dib7000p_write_word(state, 898, 0x0003); - /* except i2c, sdio, gpio - control interfaces */ - dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) ); - - dib7000p_write_word(state, 770, 0); - dib7000p_write_word(state, 771, 0); - dib7000p_write_word(state, 772, 0); - dib7000p_write_word(state, 898, 0); - dib7000p_write_word(state, 1280, 0); - - /* default */ - dib7000p_reset_pll(state); - - if (dib7000p_reset_gpio(state) != 0) - dprintk("-E- GPIO reset was not successful.\n"); - - if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) - dprintk("-E- OUTPUT_MODE could not be resetted.\n"); - - /* unforce divstr regardless whether i2c enumeration was done or not */ - dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) ); - - dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); - - return 0; -} - -static void dib7000p_restart_agc(struct dib7000p_state *state) -{ - // P_restart_iqc & P_restart_agc - dib7000p_write_word(state, 770, 0x0c00); - dib7000p_write_word(state, 770, 0x0000); -} - -static void dib7000p_update_lna(struct dib7000p_state *state) -{ - int i; - u16 dyn_gain; - - // when there is no LNA to program return immediatly - if (state->cfg.update_lna == NULL) - return; - - for (i = 0; i < 5; i++) { - // read dyn_gain here (because it is demod-dependent and not tuner) - dyn_gain = dib7000p_read_word(state, 394); - - if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed - dib7000p_restart_agc(state); - msleep(5); - } else - break; - } -} - -static void dib7000p_pll_clk_cfg(struct dib7000p_state *state) -{ - u16 tmp = 0; - tmp = dib7000p_read_word(state, 903); - dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll - tmp = dib7000p_read_word(state, 900); - dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock -} - -static void dib7000p_update_timf_freq(struct dib7000p_state *state) -{ - u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428); - state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); - dib7000p_write_word(state, 23, (u16) (timf >> 16)); - dib7000p_write_word(state, 24, (u16) (timf & 0xffff)); - dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); -} - -static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq) -{ - u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208; - - /* nfft, guard, qam, alpha */ - dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); - dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */ - - /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ - tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); - if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) - tmp |= (ch->vit_code_rate_hp << 1); - else - tmp |= (ch->vit_code_rate_lp << 1); - dib7000p_write_word(state, 208, tmp); - - /* P_dvsy_sync_wait */ - switch (ch->nfft) { - case 1: tmp = 256; break; - case 2: tmp = 128; break; - case 0: - default: tmp = 64; break; - } - tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin - tmp <<= 4; - - /* deactive the possibility of diversity reception if extended interleave */ - /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ - if (ch->intlv_native || ch->nfft == 1) - tmp |= (1 << 2) | (2 << 0); - dib7000p_write_word(state, 207, tmp); - - dib7000p_write_word(state, 26, 0x6680); // timf(6xxx) - dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073 - dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3) - dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5) - - /* channel estimation fine configuration */ - switch (ch->nqam) { - case 2: - est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ - est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ - est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ - est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ - break; - case 1: - est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ - est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ - est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ - est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ - break; - default: - est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ - est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ - est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ - est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ - break; - } - for (tmp = 0; tmp < 4; tmp++) - dib7000p_write_word(state, 187 + tmp, est[tmp]); - - // set power-up level: interf+analog+AGC - dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); - dib7000p_set_adc_state(state, DIBX000_ADC_ON); - dib7000p_pll_clk_cfg(state); - msleep(7); - - // AGC initialization - if (state->cfg.agc_control) - state->cfg.agc_control(&state->demod, 1); - - dib7000p_restart_agc(state); - - // wait AGC rough lock time - msleep(5); - - dib7000p_update_lna(state); - - // wait AGC accurate lock time - msleep(7); - if (state->cfg.agc_control) - state->cfg.agc_control(&state->demod, 0); -} - -static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) -{ - struct dib7000p_state *state = demod->demodulator_priv; - struct dibx000_ofdm_channel auto_ch; - u32 value; - - INIT_OFDM_CHANNEL(&auto_ch); - auto_ch.RF_kHz = ch->RF_kHz; - auto_ch.Bw = ch->Bw; - auto_ch.nqam = 2; - auto_ch.guard = 0; - auto_ch.nfft = 1; - auto_ch.vit_alpha = 1; - auto_ch.vit_select_hp = 1; - auto_ch.vit_code_rate_hp = 2; - auto_ch.vit_code_rate_lp = 3; - auto_ch.vit_hrch = 0; - auto_ch.intlv_native = 1; - - dib7000p_set_channel(state, &auto_ch, 7); - - // always use the setting for 8MHz here lock_time for 7,6 MHz are longer - value = 30 * state->cfg.bw->internal; - dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time - dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time - value = 100 * state->cfg.bw->internal; - dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time - dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time - value = 500 * state->cfg.bw->internal; - dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time - dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time - - value = dib7000p_read_word(state, 0); - dib7000p_write_word(state, 0, (1 << 9) | value); - dib7000p_read_word(state, 1284); - dib7000p_write_word(state, 0, (u16) value); - - return 0; -} - -static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod) -{ - struct dib7000p_state *state = demod->demodulator_priv; - u16 irq_pending = dib7000p_read_word(state, 1284); - - if (irq_pending & 0x1) // failed - return 1; - - if (irq_pending & 0x2) // succeeded - return 2; - - return 0; // still pending -} - -static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) -{ - struct dib7000p_state *state = demod->demodulator_priv; - u16 tmp = 0; - - if (ch != NULL) - dib7000p_set_channel(state, ch, 0); - else - return -EINVAL; - - // restart demod - dib7000p_write_word(state, 770, 0x4000); - dib7000p_write_word(state, 770, 0x0000); - msleep(45); - - /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ - dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); - - // never achieved a lock with that bandwidth so far - wait for osc-freq to update - if (state->timf == 0) - msleep(200); - - /* offset loop parameters */ - - /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ - tmp = (6 << 8) | 0x80; - switch (ch->nfft) { - case 0: tmp |= (7 << 12); break; - case 1: tmp |= (9 << 12); break; - case 2: tmp |= (8 << 12); break; - } - dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */ - - /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ - tmp = (0 << 4); - switch (ch->nfft) { - case 0: tmp |= 0x6; break; - case 1: tmp |= 0x8; break; - case 2: tmp |= 0x7; break; - } - dib7000p_write_word(state, 32, tmp); - - /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ - tmp = (0 << 4); - switch (ch->nfft) { - case 0: tmp |= 0x6; break; - case 1: tmp |= 0x8; break; - case 2: tmp |= 0x7; break; - } - dib7000p_write_word(state, 33, tmp); - - tmp = dib7000p_read_word(state,509); - if (!((tmp >> 6) & 0x1)) { - /* restart the fec */ - tmp = dib7000p_read_word(state,771); - dib7000p_write_word(state, 771, tmp | (1 << 1)); - dib7000p_write_word(state, 771, tmp); - msleep(10); - tmp = dib7000p_read_word(state,509); - } - - // we achieved a lock - it's time to update the osc freq - if ((tmp >> 6) & 0x1) - dib7000p_update_timf_freq(state); - - return 0; -} - -static int dib7000p_init(struct dvb_frontend *demod) -{ - struct dibx000_agc_config *agc; - struct dib7000p_state *state = demod->demodulator_priv; - int ret = 0; - - // Demodulator default configuration - agc = state->cfg.agc; - - dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); - dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); - - /* AGC */ - ret |= dib7000p_write_word(state, 75 , agc->setup ); - ret |= dib7000p_write_word(state, 76 , agc->inv_gain ); - ret |= dib7000p_write_word(state, 77 , agc->time_stabiliz ); - ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock); - - // Demod AGC loop configuration - ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp); - ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp); - - /* AGC continued */ - dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", - state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); - - if (state->wbd_ref != 0) - ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref); - else - ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref); - - ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); - - ret |= dib7000p_write_word(state, 107, agc->agc1_max); - ret |= dib7000p_write_word(state, 108, agc->agc1_min); - ret |= dib7000p_write_word(state, 109, agc->agc2_max); - ret |= dib7000p_write_word(state, 110, agc->agc2_min); - ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); - ret |= dib7000p_write_word(state, 112, agc->agc1_pt3); - ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); - ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); - ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); - - /* disable power smoothing */ - ret |= dib7000p_write_word(state, 145, 0); - ret |= dib7000p_write_word(state, 146, 0); - ret |= dib7000p_write_word(state, 147, 0); - ret |= dib7000p_write_word(state, 148, 0); - ret |= dib7000p_write_word(state, 149, 0); - ret |= dib7000p_write_word(state, 150, 0); - ret |= dib7000p_write_word(state, 151, 0); - ret |= dib7000p_write_word(state, 152, 0); - - // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26 - ret |= dib7000p_write_word(state, 26 ,0x6680); - - // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16 - ret |= dib7000p_write_word(state, 142,0x0410); - // P_fft_freq_dir=1, P_fft_nb_to_cut=0 - ret |= dib7000p_write_word(state, 154,1 << 13); - // P_pha3_thres, default 0x3000 - ret |= dib7000p_write_word(state, 168,0x0ccd); - // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010 - //ret |= dib7000p_write_word(state, 169,0x0010); - // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005 - ret |= dib7000p_write_word(state, 183,0x200f); - // P_adp_regul_cnt=573, default: 410 - ret |= dib7000p_write_word(state, 187,0x023d); - // P_adp_noise_cnt= - ret |= dib7000p_write_word(state, 188,0x00a4); - // P_adp_regul_ext - ret |= dib7000p_write_word(state, 189,0x00a4); - // P_adp_noise_ext - ret |= dib7000p_write_word(state, 190,0x7ff0); - // P_adp_fil - ret |= dib7000p_write_word(state, 191,0x3ccc); - - ret |= dib7000p_write_word(state, 222,0x0010); - // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard - ret |= dib7000p_write_word(state, 235,0x0062); - - // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ... - if(state->cfg.tuner_is_baseband) - ret |= dib7000p_write_word(state, 36,0x0755); - else - ret |= dib7000p_write_word(state, 36,0x1f55); - - // auto search configuration - ret |= dib7000p_write_word(state, 2 ,0x0004); - ret |= dib7000p_write_word(state, 3 ,0x1000); - - /* Equal Lock */ - ret |= dib7000p_write_word(state, 4 ,0x0814); - - ret |= dib7000p_write_word(state, 6 ,0x001b); - ret |= dib7000p_write_word(state, 7 ,0x7740); - ret |= dib7000p_write_word(state, 8 ,0x005b); - ret |= dib7000p_write_word(state, 9 ,0x8d80); - ret |= dib7000p_write_word(state, 10 ,0x01c9); - ret |= dib7000p_write_word(state, 11 ,0xc380); - ret |= dib7000p_write_word(state, 12 ,0x0000); - ret |= dib7000p_write_word(state, 13 ,0x0080); - ret |= dib7000p_write_word(state, 14 ,0x0000); - ret |= dib7000p_write_word(state, 15 ,0x0090); - ret |= dib7000p_write_word(state, 16 ,0x0001); - ret |= dib7000p_write_word(state, 17 ,0xd4c0); - - // P_clk_cfg1 - ret |= dib7000p_write_word(state, 901, 0x0006); - - // P_divclksel=3 P_divbitsel=1 - ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6)); - - // Tuner IO bank: max drive (14mA) + divout pads max drive - ret |= dib7000p_write_word(state, 905, 0x2c8e); - - ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); - dib7000p_sad_calib(state); - - return ret; -} - -static int dib7000p_sleep(struct dvb_frontend *demod) -{ - struct dib7000p_state *state = demod->demodulator_priv; - return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); -} - -static int dib7000p_identify(struct dib7000p_state *st) -{ - u16 value; - dprintk("-I- DiB7000PC: checking demod on I2C address: %d (%x)\n", - st->i2c_addr, st->i2c_addr); - - if ((value = dib7000p_read_word(st, 768)) != 0x01b3) { - dprintk("-E- DiB7000PC: wrong Vendor ID (read=0x%x)\n",value); - return -EREMOTEIO; - } - - if ((value = dib7000p_read_word(st, 769)) != 0x4000) { - dprintk("-E- DiB7000PC: wrong Device ID (%x)\n",value); - return -EREMOTEIO; - } - - return 0; -} - - -static int dib7000p_get_frontend(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) -{ - struct dib7000p_state *state = fe->demodulator_priv; - u16 tps = dib7000p_read_word(state,463); - - fep->inversion = INVERSION_AUTO; - - fep->u.ofdm.bandwidth = state->current_bandwidth; - - switch ((tps >> 8) & 0x3) { - case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; - case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; - /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ - } - - switch (tps & 0x3) { - case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; - case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; - case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; - case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; - } - - switch ((tps >> 14) & 0x3) { - case 0: fep->u.ofdm.constellation = QPSK; break; - case 1: fep->u.ofdm.constellation = QAM_16; break; - case 2: - default: fep->u.ofdm.constellation = QAM_64; break; - } - - /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ - /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ - - fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; - switch ((tps >> 5) & 0x7) { - case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; - case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; - case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; - case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; - case 7: - default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; - - } - - switch ((tps >> 2) & 0x7) { - case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; - case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; - case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; - case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; - case 7: - default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; - } - - /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */ - - return 0; -} - -static int dib7000p_set_frontend(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) -{ - struct dib7000p_state *state = fe->demodulator_priv; - struct dibx000_ofdm_channel ch; - - INIT_OFDM_CHANNEL(&ch); - FEP2DIB(fep,&ch); - - state->current_bandwidth = fep->u.ofdm.bandwidth; - dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth); - - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe, fep); - - if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || - fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || - fep->u.ofdm.constellation == QAM_AUTO || - fep->u.ofdm.code_rate_HP == FEC_AUTO) { - int i = 800, found; - - dib7000p_autosearch_start(fe, &ch); - do { - msleep(1); - found = dib7000p_autosearch_is_irq(fe); - } while (found == 0 && i--); - - dprintk("autosearch returns: %d\n",found); - if (found == 0 || found == 1) - return 0; // no channel found - - dib7000p_get_frontend(fe, fep); - FEP2DIB(fep, &ch); - } - - /* make this a config parameter */ - dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO); - - return dib7000p_tune(fe, &ch); -} - -static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat) -{ - struct dib7000p_state *state = fe->demodulator_priv; - u16 lock = dib7000p_read_word(state, 509); - - *stat = 0; - - if (lock & 0x8000) - *stat |= FE_HAS_SIGNAL; - if (lock & 0x3000) - *stat |= FE_HAS_CARRIER; - if (lock & 0x0100) - *stat |= FE_HAS_VITERBI; - if (lock & 0x0010) - *stat |= FE_HAS_SYNC; - if (lock & 0x0008) - *stat |= FE_HAS_LOCK; - - return 0; -} - -static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber) -{ - struct dib7000p_state *state = fe->demodulator_priv; - *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501); - return 0; -} - -static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) -{ - struct dib7000p_state *state = fe->demodulator_priv; - *unc = dib7000p_read_word(state, 506); - return 0; -} - -static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -{ - struct dib7000p_state *state = fe->demodulator_priv; - u16 val = dib7000p_read_word(state, 394); - *strength = 65535 - val; - return 0; -} - -static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) -{ - *snr = 0x0000; - return 0; -} - -static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) -{ - tune->min_delay_ms = 1000; - return 0; -} - -static void dib7000p_release(struct dvb_frontend *demod) -{ - struct dib7000p_state *st = demod->demodulator_priv; - dibx000_exit_i2c_master(&st->i2c_master); - kfree(st); -} - -int dib7000pc_detection(struct i2c_adapter *i2c_adap) -{ - u8 tx[2], rx[2]; - struct i2c_msg msg[2] = { - { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 }, - { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 }, - }; - - tx[0] = 0x03; - tx[1] = 0x00; - - if (i2c_transfer(i2c_adap, msg, 2) == 2) - if (rx[0] == 0x01 && rx[1] == 0xb3) { - dprintk("-D- DiB7000PC detected\n"); - return 1; - } - - msg[0].addr = msg[1].addr = 0x40; - - if (i2c_transfer(i2c_adap, msg, 2) == 2) - if (rx[0] == 0x01 && rx[1] == 0xb3) { - dprintk("-D- DiB7000PC detected\n"); - return 1; - } - - dprintk("-D- DiB7000PC not detected\n"); - return 0; -} -EXPORT_SYMBOL(dib7000pc_detection); - -struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) -{ - struct dib7000p_state *st = demod->demodulator_priv; - return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); -} -EXPORT_SYMBOL(dib7000p_get_i2c_master); - -int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) -{ - struct dib7000p_state st = { .i2c_adap = i2c }; - int k = 0; - u8 new_addr = 0; - - for (k = no_of_demods-1; k >= 0; k--) { - st.cfg = cfg[k]; - - /* designated i2c address */ - new_addr = (0x40 + k) << 1; - st.i2c_addr = new_addr; - if (dib7000p_identify(&st) != 0) { - st.i2c_addr = default_addr; - if (dib7000p_identify(&st) != 0) { - dprintk("DiB7000P #%d: not identified\n", k); - return -EIO; - } - } - - /* start diversity to pull_down div_str - just for i2c-enumeration */ - dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY); - - /* set new i2c address and force divstart */ - dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2); - - dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); - } - - for (k = 0; k < no_of_demods; k++) { - st.cfg = cfg[k]; - st.i2c_addr = (0x40 + k) << 1; - - // unforce divstr - dib7000p_write_word(&st, 1285, st.i2c_addr << 2); - - /* deactivate div - it was just for i2c-enumeration */ - dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z); - } - - return 0; -} -EXPORT_SYMBOL(dib7000p_i2c_enumeration); - -static struct dvb_frontend_ops dib7000p_ops; -struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) -{ - struct dvb_frontend *demod; - struct dib7000p_state *st; - st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL); - if (st == NULL) - return NULL; - - memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config)); - st->i2c_adap = i2c_adap; - st->i2c_addr = i2c_addr; - st->gpio_val = cfg->gpio_val; - st->gpio_dir = cfg->gpio_dir; - - demod = &st->demod; - demod->demodulator_priv = st; - memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); - - if (dib7000p_identify(st) != 0) - goto error; - - dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); - - dib7000p_demod_reset(st); - - return demod; - -error: - kfree(st); - return NULL; -} -EXPORT_SYMBOL(dib7000p_attach); - -static struct dvb_frontend_ops dib7000p_ops = { - .info = { - .name = "DiBcom 7000PC", - .type = FE_OFDM, - .frequency_min = 44250000, - .frequency_max = 867250000, - .frequency_stepsize = 62500, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_RECOVER | - FE_CAN_HIERARCHY_AUTO, - }, - - .release = dib7000p_release, - - .init = dib7000p_init, - .sleep = dib7000p_sleep, - - .set_frontend = dib7000p_set_frontend, - .get_tune_settings = dib7000p_fe_get_tune_settings, - .get_frontend = dib7000p_get_frontend, - - .read_status = dib7000p_read_status, - .read_ber = dib7000p_read_ber, - .read_signal_strength = dib7000p_read_signal_strength, - .read_snr = dib7000p_read_snr, - .read_ucblocks = dib7000p_read_unc_blocks, -}; - -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/media/dvb/frontends/dib7000p.h b/trunk/drivers/media/dvb/frontends/dib7000p.h deleted file mode 100644 index 79465cf1aced..000000000000 --- a/trunk/drivers/media/dvb/frontends/dib7000p.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef DIB7000P_H -#define DIB7000P_H - -#include "dibx000_common.h" - -struct dib7000p_config { - u8 output_mpeg2_in_188_bytes; - u8 hostbus_diversity; - u8 tuner_is_baseband; - int (*update_lna) (struct dvb_frontend *, u16 agc_global); - - struct dibx000_agc_config *agc; - struct dibx000_bandwidth_config *bw; - -#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff - u16 gpio_dir; -#define DIB7000P_GPIO_DEFAULT_VALUES 0x0000 - u16 gpio_val; -#define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12) -#define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) -#define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) -#define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf) -#define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff - u16 gpio_pwm_pos; - - u16 pwm_freq_div; - - u8 quartz_direct; - - int (*agc_control) (struct dvb_frontend *, u8 before); -}; - -#define DEFAULT_DIB7000P_I2C_ADDRESS 18 - -extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); -extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); -extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); - -/* TODO -extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); -extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod); -extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); -extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod); -*/ - -#endif diff --git a/trunk/drivers/media/dvb/frontends/dibx000_common.h b/trunk/drivers/media/dvb/frontends/dibx000_common.h index a1df604366c3..bb0c65f8aee8 100644 --- a/trunk/drivers/media/dvb/frontends/dibx000_common.h +++ b/trunk/drivers/media/dvb/frontends/dibx000_common.h @@ -32,13 +32,6 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); #define BAND_LBAND 0x01 #define BAND_UHF 0x02 #define BAND_VHF 0x04 -#define BAND_SBAND 0x08 -#define BAND_FM 0x10 - -#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ - (freq_kHz) <= 250000 ? BAND_VHF : \ - (freq_kHz) <= 863000 ? BAND_UHF : \ - (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) struct dibx000_agc_config { /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ @@ -136,7 +129,6 @@ enum dibx000_adc_states { /* I hope I can get rid of the following kludge in the near future */ struct dibx000_ofdm_channel { - u32 RF_kHz; u8 Bw; s16 nfft; s16 guard; @@ -146,11 +138,9 @@ struct dibx000_ofdm_channel { s16 vit_alpha; s16 vit_code_rate_hp; s16 vit_code_rate_lp; - u8 intlv_native; }; #define FEP2DIB(fep,ch) \ - (ch)->RF_kHz = (fep)->frequency / 1000; \ (ch)->Bw = (fep)->u.ofdm.bandwidth; \ (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ @@ -159,8 +149,7 @@ struct dibx000_ofdm_channel { (ch)->vit_select_hp = 1; \ (ch)->vit_alpha = 1; \ (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ - (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \ - (ch)->intlv_native = 1; + (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; #define INIT_OFDM_CHANNEL(ch) do {\ (ch)->Bw = 0; \ diff --git a/trunk/drivers/media/dvb/frontends/dvb-pll.c b/trunk/drivers/media/dvb/frontends/dvb-pll.c index 62de760c844f..b7e7108ee5b3 100644 --- a/trunk/drivers/media/dvb/frontends/dvb-pll.c +++ b/trunk/drivers/media/dvb/frontends/dvb-pll.c @@ -472,14 +472,14 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", desc->name, div, buf[0], buf[1], buf[2], buf[3]); - // calculate the frequency we set it to - return (div * desc->entries[i].stepsize) - desc->entries[i].offset; + return 0; } EXPORT_SYMBOL(dvb_pll_configure); static int dvb_pll_release(struct dvb_frontend *fe) { - kfree(fe->tuner_priv); + if (fe->tuner_priv) + kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; } @@ -489,8 +489,7 @@ static int dvb_pll_sleep(struct dvb_frontend *fe) struct dvb_pll_priv *priv = fe->tuner_priv; u8 buf[4]; struct i2c_msg msg = - { .addr = priv->pll_i2c_address, .flags = 0, - .buf = buf, .len = sizeof(buf) }; + { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; int i; int result; @@ -518,16 +517,16 @@ static int dvb_pll_sleep(struct dvb_frontend *fe) return 0; } -static int dvb_pll_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) +static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct dvb_pll_priv *priv = fe->tuner_priv; u8 buf[4]; struct i2c_msg msg = - { .addr = priv->pll_i2c_address, .flags = 0, - .buf = buf, .len = sizeof(buf) }; + { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; int result; - u32 bandwidth = 0, frequency = 0; + u32 div; + int i; + u32 bandwidth = 0; if (priv->i2c == NULL) return -EINVAL; @@ -537,11 +536,8 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, bandwidth = params->u.ofdm.bandwidth; } - if ((result = dvb_pll_configure(priv->pll_desc, buf, - params->frequency, bandwidth)) < 0) + if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0) return result; - else - frequency = result; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -549,19 +545,26 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, return result; } - priv->frequency = frequency; + // calculate the frequency we set it to + for (i = 0; i < priv->pll_desc->count; i++) { + if (params->frequency > priv->pll_desc->entries[i].limit) + continue; + break; + } + div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; + priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; priv->bandwidth = bandwidth; return 0; } -static int dvb_pll_calc_regs(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params, - u8 *buf, int buf_len) +static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) { struct dvb_pll_priv *priv = fe->tuner_priv; int result; - u32 bandwidth = 0, frequency = 0; + u32 div; + int i; + u32 bandwidth = 0; if (buf_len < 5) return -EINVAL; @@ -571,15 +574,18 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, bandwidth = params->u.ofdm.bandwidth; } - if ((result = dvb_pll_configure(priv->pll_desc, buf+1, - params->frequency, bandwidth)) < 0) + if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0) return result; - else - frequency = result; - buf[0] = priv->pll_i2c_address; - priv->frequency = frequency; + // calculate the frequency we set it to + for (i = 0; i < priv->pll_desc->count; i++) { + if (params->frequency > priv->pll_desc->entries[i].limit) + continue; + break; + } + div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; + priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; priv->bandwidth = bandwidth; return 5; @@ -608,13 +614,10 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = { .get_bandwidth = dvb_pll_get_bandwidth, }; -struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, - struct i2c_adapter *i2c, - struct dvb_pll_desc *desc) +struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) { u8 b1 [] = { 0 }; - struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, - .buf = b1, .len = 1 }; + struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }; struct dvb_pll_priv *priv = NULL; int ret; @@ -637,9 +640,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, priv->i2c = i2c; priv->pll_desc = desc; - memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, - sizeof(struct dvb_tuner_ops)); - + memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops)); strncpy(fe->ops.tuner_ops.info.name, desc->name, 128); fe->ops.tuner_ops.info.frequency_min = desc->min; fe->ops.tuner_ops.info.frequency_min = desc->max; diff --git a/trunk/drivers/media/dvb/frontends/dvb-pll.h b/trunk/drivers/media/dvb/frontends/dvb-pll.h index 681186a5e5eb..ed5ac5a361ae 100644 --- a/trunk/drivers/media/dvb/frontends/dvb-pll.h +++ b/trunk/drivers/media/dvb/frontends/dvb-pll.h @@ -48,7 +48,7 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316; extern struct dvb_pll_desc dvb_pll_thomson_fe6600; extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, - u32 freq, int bandwidth); + u32 freq, int bandwidth); /** * Attach a dvb-pll to the supplied frontend structure. @@ -59,9 +59,6 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, * @param desc dvb_pll_desc to use. * @return Frontend pointer on success, NULL on failure */ -extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, - int pll_addr, - struct i2c_adapter *i2c, - struct dvb_pll_desc *desc); +extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc); #endif diff --git a/trunk/drivers/media/dvb/frontends/lg_h06xf.h b/trunk/drivers/media/dvb/frontends/lg_h06xf.h new file mode 100644 index 000000000000..754d51d11120 --- /dev/null +++ b/trunk/drivers/media/dvb/frontends/lg_h06xf.h @@ -0,0 +1,64 @@ +/* + * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _LG_H06XF_H_ +#define _LG_H06XF_H_ +#include "dvb-pll.h" + +static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap, + struct dvb_frontend_parameters* params) +{ + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + int err; + + dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lg_h06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + /* Set the Auxiliary Byte. */ + buf[0] = buf[2]; + buf[0] &= ~0x20; + buf[0] |= 0x18; + buf[1] = 0x50; + msg.len = 2; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lg_h06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} +#endif diff --git a/trunk/drivers/media/dvb/frontends/lgdt330x.c b/trunk/drivers/media/dvb/frontends/lgdt330x.c index 68aad0f6519f..9a354708bd20 100644 --- a/trunk/drivers/media/dvb/frontends/lgdt330x.c +++ b/trunk/drivers/media/dvb/frontends/lgdt330x.c @@ -31,6 +31,9 @@ * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) * pcHDTV HD5500 * + * TODO: + * signal strength always returns 0. + * */ #include @@ -43,13 +46,9 @@ #include #include "dvb_frontend.h" -#include "dvb_math.h" #include "lgdt330x_priv.h" #include "lgdt330x.h" -/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */ -/* #define USE_EQMSE */ - static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); @@ -69,7 +68,6 @@ struct lgdt330x_state /* Demodulator private data */ fe_modulation_t current_modulation; - u32 snr; /* Result of last SNR calculation */ /* Tuner private data */ u32 current_frequency; @@ -304,10 +302,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, static u8 lgdt3303_8vsb_44_data[] = { 0x04, 0x00, 0x0d, 0x40, - 0x0e, 0x87, - 0x0f, 0x8e, - 0x10, 0x01, - 0x47, 0x8b }; + 0x0e, 0x87, + 0x0f, 0x8e, + 0x10, 0x01, + 0x47, 0x8b }; /* * Array of byte pairs @@ -437,6 +435,9 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) /* Test signal does not exist flag */ /* as well as the AGC lock flag. */ *status |= FE_HAS_SIGNAL; + } else { + /* Without a signal all other status bits are meaningless */ + return 0; } /* @@ -499,6 +500,9 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) /* Test input signal does not exist flag */ /* as well as the AGC lock flag. */ *status |= FE_HAS_SIGNAL; + } else { + /* Without a signal all other status bits are meaningless */ + return 0; } /* Carrier Recovery Lock Status Register */ @@ -539,150 +543,151 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } -/* Calculate SNR estimation (scaled by 2^24) - - 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM - equations from LGDT3303 datasheet. VSB is the same between the '02 - and '03, so maybe QAM is too? Perhaps someone with a newer datasheet - that has QAM information could verify? - - For 8-VSB: (two ways, take your pick) - LGDT3302: - SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE) - LGDT3303: - SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE) - LGDT3302 & LGDT3303: - SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one) - For 64-QAM: - SNR = 10 * log10( 688128 / MSEQAM) - For 256-QAM: - SNR = 10 * log10( 696320 / MSEQAM) - - We re-write the snr equation as: - SNR * 2^24 = 10*(c - intlog10(MSE)) - Where for 256-QAM, c = log10(696320) * 2^24, and so on. */ - -static u32 calculate_snr(u32 mse, u32 c) +static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - if (mse == 0) /* No signal */ - return 0; - - mse = intlog10(mse); - if (mse > c) { - /* Negative SNR, which is possible, but realisticly the - demod will lose lock before the signal gets this bad. The - API only allows for unsigned values, so just return 0 */ - return 0; - } - return 10*(c - mse); + /* not directly available. */ + *strength = 0; + return 0; } static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) { +#ifdef SNR_IN_DB + /* + * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise) + * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker + * respectively. The following tables are built on these formulas. + * The usual definition is SNR = 20 log10(signal/noise) + * If the specification is wrong the value retuned is 1/2 the actual SNR in db. + * + * This table is a an ordered list of noise values computed by the + * formula from the spec sheet such that the index into the table + * starting at 43 or 45 is the SNR value in db. There are duplicate noise + * value entries at the beginning because the SNR varies more than + * 1 db for a change of 1 digit in noise at very small values of noise. + * + * Examples from SNR_EQ table: + * noise SNR + * 0 43 + * 1 42 + * 2 39 + * 3 37 + * 4 36 + * 5 35 + * 6 34 + * 7 33 + * 8 33 + * 9 32 + * 10 32 + * 11 31 + * 12 31 + * 13 30 + */ + + static const u32 SNR_EQ[] = + { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7, + 9, 11, 13, 17, 21, 26, 33, 41, 52, 65, + 81, 102, 129, 162, 204, 257, 323, 406, 511, 644, + 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433, + 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323, + 80978, 101945, 128341, 161571, 203406, 256073, 0x40000 + }; + + static const u32 SNR_PH[] = + { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8, + 10, 12, 15, 19, 23, 29, 37, 46, 58, 73, + 91, 115, 144, 182, 229, 288, 362, 456, 574, 722, + 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216, + 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151, + 90833, 114351, 143960, 181235, 228161, 0x080000 + }; + + static u8 buf[5];/* read data buffer */ + static u32 noise; /* noise value */ + static u32 snr_db; /* index into SNR_EQ[] */ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; - u8 buf[5]; /* read data buffer */ - u32 noise; /* noise value */ - u32 c; /* per-modulation SNR calculation constant */ - switch(state->current_modulation) { - case VSB_8: - i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5); -#ifdef USE_EQMSE - /* Use Equalizer Mean-Square Error Register */ - /* SNR for ranges from -15.61 to +41.58 */ + /* read both equalizer and phase tracker noise data */ + i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); + + if (state->current_modulation == VSB_8) { + /* Equalizer Mean-Square Error Register for VSB */ noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; - c = 69765745; /* log10(25*24^2)*2^24 */ + + /* + * Look up noise value in table. + * A better search algorithm could be used... + * watch out there are duplicate entries. + */ + for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) { + if (noise < SNR_EQ[snr_db]) { + *snr = 43 - snr_db; + break; + } + } + } else { + /* Phase Tracker Mean-Square Error Register for QAM */ + noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; + + /* Look up noise value in table. */ + for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) { + if (noise < SNR_PH[snr_db]) { + *snr = 45 - snr_db; + break; + } + } + } #else - /* Use Phase Tracker Mean-Square Error Register */ - /* SNR for ranges from -13.11 to +44.08 */ + /* Return the raw noise value */ + static u8 buf[5];/* read data buffer */ + static u32 noise; /* noise value */ + struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + + /* read both equalizer and pase tracker noise data */ + i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); + + if (state->current_modulation == VSB_8) { + /* Phase Tracker Mean-Square Error Register for VSB */ noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; - c = 73957994; /* log10(25*32^2)*2^24 */ -#endif - break; - case QAM_64: - case QAM_256: - i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2); + } else { + + /* Carrier Recovery Mean-Square Error for QAM */ + i2c_read_demod_bytes(state, 0x1a, buf, 2); noise = ((buf[0] & 3) << 8) | buf[1]; - c = state->current_modulation == QAM_64 ? 97939837 : 98026066; - /* log10(688128)*2^24 and log10(696320)*2^24 */ - break; - default: - printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", - __FUNCTION__); - return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ } - state->snr = calculate_snr(noise, c); - *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ + /* Small values for noise mean signal is better so invert noise */ + *snr = ~noise; +#endif - dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, - state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); + dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); return 0; } static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) { + /* Return the raw noise value */ + static u8 buf[5];/* read data buffer */ + static u32 noise; /* noise value */ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; - u8 buf[5]; /* read data buffer */ - u32 noise; /* noise value */ - u32 c; /* per-modulation SNR calculation constant */ - switch(state->current_modulation) { - case VSB_8: - i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5); -#ifdef USE_EQMSE - /* Use Equalizer Mean-Square Error Register */ - /* SNR for ranges from -16.12 to +44.08 */ - noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2]; - c = 73957994; /* log10(25*32^2)*2^24 */ -#else - /* Use Phase Tracker Mean-Square Error Register */ - /* SNR for ranges from -13.11 to +44.08 */ + if (state->current_modulation == VSB_8) { + + i2c_read_demod_bytes(state, 0x6e, buf, 5); + /* Phase Tracker Mean-Square Error Register for VSB */ noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; - c = 73957994; /* log10(25*32^2)*2^24 */ -#endif - break; - case QAM_64: - case QAM_256: - i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2); + } else { + + /* Carrier Recovery Mean-Square Error for QAM */ + i2c_read_demod_bytes(state, 0x1a, buf, 2); noise = (buf[0] << 8) | buf[1]; - c = state->current_modulation == QAM_64 ? 97939837 : 98026066; - /* log10(688128)*2^24 and log10(696320)*2^24 */ - break; - default: - printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", - __FUNCTION__); - return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ } - state->snr = calculate_snr(noise, c); - *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ - - dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, - state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16); - - return 0; -} - -static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) -{ - /* Calculate Strength from SNR up to 35dB */ - /* Even though the SNR can go higher than 35dB, there is some comfort */ - /* factor in having a range of strong signals that can show at 100% */ - struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; - u16 snr; - int ret; + /* Small values for noise mean signal is better so invert noise */ + *snr = ~noise; - ret = fe->ops.read_snr(fe, &snr); - if (ret != 0) - return ret; - /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ - /* scale the range 0 - 35*2^24 into 0 - 65535 */ - if (state->snr >= 8960 * 0x10000) - *strength = 0xffff; - else - *strength = state->snr / 8960; + dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); return 0; } diff --git a/trunk/drivers/media/dvb/frontends/lgdt330x_priv.h b/trunk/drivers/media/dvb/frontends/lgdt330x_priv.h index 38c76695abfe..59b7c5b9012d 100644 --- a/trunk/drivers/media/dvb/frontends/lgdt330x_priv.h +++ b/trunk/drivers/media/dvb/frontends/lgdt330x_priv.h @@ -51,19 +51,14 @@ enum I2C_REG { AGC_RFIF_ACC2= 0x3b, AGC_STATUS= 0x3f, SYNC_STATUS_VSB= 0x43, + EQPH_ERR0= 0x47, + EQ_ERR1= 0x48, + EQ_ERR2= 0x49, + PH_ERR1= 0x4a, + PH_ERR2= 0x4b, DEMUX_CONTROL= 0x66, - LGDT3302_EQPH_ERR0= 0x47, - LGDT3302_EQ_ERR1= 0x48, - LGDT3302_EQ_ERR2= 0x49, - LGDT3302_PH_ERR1= 0x4a, - LGDT3302_PH_ERR2= 0x4b, LGDT3302_PACKET_ERR_COUNTER1= 0x6a, LGDT3302_PACKET_ERR_COUNTER2= 0x6b, - LGDT3303_EQPH_ERR0= 0x6e, - LGDT3303_EQ_ERR1= 0x6f, - LGDT3303_EQ_ERR2= 0x70, - LGDT3303_PH_ERR1= 0x71, - LGDT3303_PH_ERR2= 0x72, LGDT3303_PACKET_ERR_COUNTER1= 0x8b, LGDT3303_PACKET_ERR_COUNTER2= 0x8c, }; diff --git a/trunk/drivers/media/dvb/frontends/lgh06xf.c b/trunk/drivers/media/dvb/frontends/lgh06xf.c deleted file mode 100644 index 2202d0cc878b..000000000000 --- a/trunk/drivers/media/dvb/frontends/lgh06xf.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * lgh06xf.c - ATSC Tuner support for LG TDVS-H06xF - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "dvb-pll.h" -#include "lgh06xf.h" - -#define LG_H06XF_PLL_I2C_ADDR 0x61 - -struct lgh06xf_priv { - struct i2c_adapter *i2c; - u32 frequency; -}; - -static int lgh06xf_release(struct dvb_frontend *fe) -{ - kfree(fe->tuner_priv); - fe->tuner_priv = NULL; - return 0; -} - -static int lgh06xf_set_params(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) -{ - struct lgh06xf_priv *priv = fe->tuner_priv; - u8 buf[4]; - struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0, - .buf = buf, .len = sizeof(buf) }; - u32 frequency; - int result; - - if ((result = dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, - params->frequency, 0)) < 0) - return result; - else - frequency = result; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgh06xf: %s error " - "(addr %02x <- %02x, result = %i)\n", - __FUNCTION__, buf[0], buf[1], result); - if (result < 0) - return result; - else - return -EREMOTEIO; - } - - /* Set the Auxiliary Byte. */ - buf[0] = buf[2]; - buf[0] &= ~0x20; - buf[0] |= 0x18; - buf[1] = 0x50; - msg.len = 2; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgh06xf: %s error " - "(addr %02x <- %02x, result = %i)\n", - __FUNCTION__, buf[0], buf[1], result); - if (result < 0) - return result; - else - return -EREMOTEIO; - } - - priv->frequency = frequency; - - return 0; -} - -static int lgh06xf_get_frequency(struct dvb_frontend *fe, u32 *frequency) -{ - struct lgh06xf_priv *priv = fe->tuner_priv; - *frequency = priv->frequency; - return 0; -} - -static struct dvb_tuner_ops lgh06xf_tuner_ops = { - .release = lgh06xf_release, - .set_params = lgh06xf_set_params, - .get_frequency = lgh06xf_get_frequency, -}; - -struct dvb_frontend* lgh06xf_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c) -{ - struct lgh06xf_priv *priv = NULL; - - priv = kzalloc(sizeof(struct lgh06xf_priv), GFP_KERNEL); - if (priv == NULL) - return NULL; - - priv->i2c = i2c; - - memcpy(&fe->ops.tuner_ops, &lgh06xf_tuner_ops, - sizeof(struct dvb_tuner_ops)); - - strlcpy(fe->ops.tuner_ops.info.name, dvb_pll_lg_tdvs_h06xf.name, - sizeof(fe->ops.tuner_ops.info.name)); - - fe->ops.tuner_ops.info.frequency_min = dvb_pll_lg_tdvs_h06xf.min; - fe->ops.tuner_ops.info.frequency_max = dvb_pll_lg_tdvs_h06xf.max; - - fe->tuner_priv = priv; - return fe; -} - -EXPORT_SYMBOL(lgh06xf_attach); - -MODULE_DESCRIPTION("LG TDVS-H06xF ATSC Tuner support"); -MODULE_AUTHOR("Michael Krufky"); -MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/trunk/drivers/media/dvb/frontends/lgh06xf.h b/trunk/drivers/media/dvb/frontends/lgh06xf.h deleted file mode 100644 index 510b4bedfb24..000000000000 --- a/trunk/drivers/media/dvb/frontends/lgh06xf.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * lgh06xf.h - ATSC Tuner support for LG TDVS-H06xF - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _LGH06XF_H_ -#define _LGH06XF_H_ -#include "dvb_frontend.h" - -#if defined(CONFIG_DVB_TUNER_LGH06XF) || (defined(CONFIG_DVB_TUNER_LGH06XF_MODULE) && defined(MODULE)) -extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, - struct i2c_adapter *i2c); -#else -static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, - struct i2c_adapter *i2c) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); - return NULL; -} -#endif /* CONFIG_DVB_TUNER_LGH06XF */ - -#endif /* _LGH06XF_H_ */ diff --git a/trunk/drivers/media/dvb/frontends/or51132.c b/trunk/drivers/media/dvb/frontends/or51132.c index 5a3a6e53cda2..d20ab30c1e83 100644 --- a/trunk/drivers/media/dvb/frontends/or51132.c +++ b/trunk/drivers/media/dvb/frontends/or51132.c @@ -40,7 +40,6 @@ #include #include -#include "dvb_math.h" #include "dvb_frontend.h" #include "dvb-pll.h" #include "or51132.h" @@ -63,7 +62,6 @@ struct or51132_state /* Demodulator private data */ fe_modulation_t current_modulation; - u32 snr; /* Result of last SNR calculation */ /* Tuner private data */ u32 current_frequency; @@ -467,128 +465,124 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } -/* Calculate SNR estimation (scaled by 2^24) - - 8-VSB SNR and QAM equations from Oren datasheets - - For 8-VSB: - SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K +/* log10-1 table at .5 increments from 1 to 100.5 */ +static unsigned int i100x20log10[] = { + 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, + 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, + 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, + 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, + 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, + 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, + 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, + 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, + 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, + 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, + 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, + 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, + 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, + 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, + 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, + 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, + 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, + 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, + 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, + 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, +}; - Where K = 0 if NTSC rejection filter is OFF; and - K = 3 if NTSC rejection filter is ON +static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; - For QAM64: - SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) +static unsigned int i20Log10(unsigned short val) +{ + unsigned int rntval = 100; + unsigned int tmp = val; + unsigned int exp = 1; - For QAM256: - SNR[dB] = 10 * log10(907832426.314266 / MSE^2 ) + while(tmp > 100) {tmp /= 100; exp++;} - We re-write the snr equation as: - SNR * 2^24 = 10*(c - 2*intlog10(MSE)) - Where for QAM256, c = log10(907832426.314266) * 2^24 - and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */ + val = (2 * val)/denom[exp]; + if (exp > 1) rntval = 2000*exp; -static u32 calculate_snr(u32 mse, u32 c) -{ - if (mse == 0) /* No signal */ - return 0; - - mse = 2*intlog10(mse); - if (mse > c) { - /* Negative SNR, which is possible, but realisticly the - demod will lose lock before the signal gets this bad. The - API only allows for unsigned values, so just return 0 */ - return 0; - } - return 10*(c - mse); + rntval += i100x20log10[val]; + return rntval; } -static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) +static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) { struct or51132_state* state = fe->demodulator_priv; - u8 rec_buf[2]; - u8 snd_buf[2]; - u32 noise; - u32 c; - u32 usK; + unsigned char rec_buf[2]; + unsigned char snd_buf[2]; + u8 rcvr_stat; + u16 snr_equ; + u32 signal_strength; + int usK; - /* Register is same for VSB or QAM firmware */ snd_buf[0]=0x04; snd_buf[1]=0x02; /* SNR after Equalizer */ msleep(30); /* 30ms */ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { - printk(KERN_WARNING "or51132: snr write error\n"); - return -EREMOTEIO; + printk(KERN_WARNING "or51132: read_status write error\n"); + return -1; } msleep(30); /* 30ms */ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "or51132: snr read error\n"); - return -EREMOTEIO; + printk(KERN_WARNING "or51132: read_status read error\n"); + return -1; } - noise = rec_buf[0] | (rec_buf[1] << 8); - dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise); + snr_equ = rec_buf[0] | (rec_buf[1] << 8); + dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); - /* Read status, contains modulation type for QAM_AUTO and - NTSC filter for VSB */ + /* Receiver Status */ snd_buf[0]=0x04; - snd_buf[1]=0x00; /* Status register */ + snd_buf[1]=0x00; msleep(30); /* 30ms */ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { - printk(KERN_WARNING "or51132: status write error\n"); - return -EREMOTEIO; + printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n"); + return -1; } msleep(30); /* 30ms */ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "or51132: status read error\n"); - return -EREMOTEIO; - } - - usK = 0; - switch (rec_buf[0]) { - case 0x06: - usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0; - /* Fall through to QAM64 case */ - case 0x43: - c = 150204167; - break; - case 0x45: - c = 150290396; - break; - default: - printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]); - return -EREMOTEIO; + printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n"); + return -1; } - dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__, - rec_buf[0], rec_buf[1]&0x10?"n":"ff"); + dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]); + rcvr_stat = rec_buf[1]; + usK = (rcvr_stat & 0x10) ? 3 : 0; - /* Calculate SNR using noise, c, and NTSC rejection correction */ - state->snr = calculate_snr(noise, c) - usK; - *snr = (state->snr) >> 16; - - dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, - state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); + /* The value reported back from the frontend will be FFFF=100% 0000=0% */ + signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000; + if (signal_strength > 0xffff) + *strength = 0xffff; + else + *strength = signal_strength; + dprintk("read_signal_strength %i\n",*strength); return 0; } -static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) +static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) { - /* Calculate Strength from SNR up to 35dB */ - /* Even though the SNR can go higher than 35dB, there is some comfort */ - /* factor in having a range of strong signals that can show at 100% */ - struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; - u16 snr; - int ret; + struct or51132_state* state = fe->demodulator_priv; + unsigned char rec_buf[2]; + unsigned char snd_buf[2]; + u16 snr_equ; - ret = fe->ops.read_snr(fe, &snr); - if (ret != 0) - return ret; - /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ - /* scale the range 0 - 35*2^24 into 0 - 65535 */ - if (state->snr >= 8960 * 0x10000) - *strength = 0xffff; - else - *strength = state->snr / 8960; + snd_buf[0]=0x04; + snd_buf[1]=0x02; /* SNR after Equalizer */ + msleep(30); /* 30ms */ + if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { + printk(KERN_WARNING "or51132: read_snr write error\n"); + return -1; + } + msleep(30); /* 30ms */ + if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { + printk(KERN_WARNING "or51132: read_snr dvr read error\n"); + return -1; + } + snr_equ = rec_buf[0] | (rec_buf[1] << 8); + dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); + + *snr = 0xFFFF - snr_equ; + dprintk("read_snr %i\n",*snr); return 0; } diff --git a/trunk/drivers/media/dvb/frontends/or51211.c b/trunk/drivers/media/dvb/frontends/or51211.c index 048d7cfe12d3..2bf124b53689 100644 --- a/trunk/drivers/media/dvb/frontends/or51211.c +++ b/trunk/drivers/media/dvb/frontends/or51211.c @@ -39,7 +39,6 @@ #include #include -#include "dvb_math.h" #include "dvb_frontend.h" #include "or51211.h" @@ -64,7 +63,6 @@ struct or51211_state { /* Demodulator private data */ u8 initialized:1; - u32 snr; /* Result of last SNR claculation */ /* Tuner private data */ u32 current_frequency; @@ -294,81 +292,107 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } -/* Calculate SNR estimation (scaled by 2^24) +/* log10-1 table at .5 increments from 1 to 100.5 */ +static unsigned int i100x20log10[] = { + 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, + 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, + 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, + 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, + 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, + 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, + 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, + 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, + 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, + 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, + 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, + 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, + 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, + 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, + 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, + 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, + 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, + 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, + 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, + 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, +}; - 8-VSB SNR equation from Oren datasheets +static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; - For 8-VSB: - SNR[dB] = 10 * log10(219037.9454 / MSE^2 ) +static unsigned int i20Log10(unsigned short val) +{ + unsigned int rntval = 100; + unsigned int tmp = val; + unsigned int exp = 1; - We re-write the snr equation as: - SNR * 2^24 = 10*(c - 2*intlog10(MSE)) - Where for 8-VSB, c = log10(219037.9454) * 2^24 */ + while(tmp > 100) {tmp /= 100; exp++;} -static u32 calculate_snr(u32 mse, u32 c) -{ - if (mse == 0) /* No signal */ - return 0; - - mse = 2*intlog10(mse); - if (mse > c) { - /* Negative SNR, which is possible, but realisticly the - demod will lose lock before the signal gets this bad. The - API only allows for unsigned values, so just return 0 */ - return 0; - } - return 10*(c - mse); + val = (2 * val)/denom[exp]; + if (exp > 1) rntval = 2000*exp; + + rntval += i100x20log10[val]; + return rntval; } -static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) +static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) { struct or51211_state* state = fe->demodulator_priv; u8 rec_buf[2]; - u8 snd_buf[3]; + u8 snd_buf[4]; + u8 snr_equ; + u32 signal_strength; /* SNR after Equalizer */ snd_buf[0] = 0x04; snd_buf[1] = 0x00; snd_buf[2] = 0x04; + snd_buf[3] = 0x00; if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { - printk(KERN_WARNING "%s: error writing snr reg\n", - __FUNCTION__); + printk(KERN_WARNING "or51211: read_status write error\n"); return -1; } + msleep(3); if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { - printk(KERN_WARNING "%s: read_status read error\n", - __FUNCTION__); + printk(KERN_WARNING "or51211: read_status read error\n"); return -1; } + snr_equ = rec_buf[0] & 0xff; - state->snr = calculate_snr(rec_buf[0], 89599047); - *snr = (state->snr) >> 16; - - dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0], - state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); + /* The value reported back from the frontend will be FFFF=100% 0000=0% */ + signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000; + if (signal_strength > 0xffff) + *strength = 0xffff; + else + *strength = signal_strength; + dprintk("read_signal_strength %i\n",*strength); return 0; } -static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) +static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) { - /* Calculate Strength from SNR up to 35dB */ - /* Even though the SNR can go higher than 35dB, there is some comfort */ - /* factor in having a range of strong signals that can show at 100% */ - struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv; - u16 snr; - int ret; - - ret = fe->ops.read_snr(fe, &snr); - if (ret != 0) - return ret; - /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ - /* scale the range 0 - 35*2^24 into 0 - 65535 */ - if (state->snr >= 8960 * 0x10000) - *strength = 0xffff; - else - *strength = state->snr / 8960; + struct or51211_state* state = fe->demodulator_priv; + u8 rec_buf[2]; + u8 snd_buf[4]; + + /* SNR after Equalizer */ + snd_buf[0] = 0x04; + snd_buf[1] = 0x00; + snd_buf[2] = 0x04; + snd_buf[3] = 0x00; + + if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { + printk(KERN_WARNING "or51211: read_status write error\n"); + return -1; + } + msleep(3); + if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { + printk(KERN_WARNING "or51211: read_status read error\n"); + return -1; + } + *snr = rec_buf[0] & 0xff; + + dprintk("read_snr %i\n",*snr); return 0; } diff --git a/trunk/drivers/media/dvb/frontends/tda1004x.c b/trunk/drivers/media/dvb/frontends/tda1004x.c index 00e4bcd9f1a4..11e0dca9a2d7 100644 --- a/trunk/drivers/media/dvb/frontends/tda1004x.c +++ b/trunk/drivers/media/dvb/frontends/tda1004x.c @@ -648,24 +648,18 @@ static int tda10046_init(struct dvb_frontend* fe) tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities break; - case TDA10046_AGC_TDA827X_GP11: + case TDA10046_AGC_TDA827X: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities break; - case TDA10046_AGC_TDA827X_GP00: + case TDA10046_AGC_TDA827X_GPL: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities break; - case TDA10046_AGC_TDA827X_GP01: - tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup - tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold - tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize - tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities - break; } tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on diff --git a/trunk/drivers/media/dvb/frontends/tda1004x.h b/trunk/drivers/media/dvb/frontends/tda1004x.h index ec502d71b83c..605ad2dfc09d 100644 --- a/trunk/drivers/media/dvb/frontends/tda1004x.h +++ b/trunk/drivers/media/dvb/frontends/tda1004x.h @@ -35,9 +35,8 @@ enum tda10046_agc { TDA10046_AGC_DEFAULT, /* original configuration */ TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ - TDA10046_AGC_TDA827X_GP11, /* IF AGC only, special setup for tda827x */ - TDA10046_AGC_TDA827X_GP00, /* same as above, but GPIOs 0 */ - TDA10046_AGC_TDA827X_GP01, /* same as above, but GPIO3=0 GPIO1=1*/ + TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ + TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */ }; enum tda10046_if { diff --git a/trunk/drivers/media/dvb/frontends/tda8083.c b/trunk/drivers/media/dvb/frontends/tda8083.c index 67415c9db6f7..3aa45ebbac3d 100644 --- a/trunk/drivers/media/dvb/frontends/tda8083.c +++ b/trunk/drivers/media/dvb/frontends/tda8083.c @@ -262,29 +262,12 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status) if (sync & 0x10) *status |= FE_HAS_SYNC; - if (sync & 0x20) /* frontend can not lock */ - *status |= FE_TIMEDOUT; - if ((sync & 0x1f) == 0x1f) *status |= FE_HAS_LOCK; return 0; } -static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber) -{ - struct tda8083_state* state = fe->demodulator_priv; - int ret; - u8 buf[3]; - - if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf)))) - return ret; - - *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2]; - - return 0; -} - static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength) { struct tda8083_state* state = fe->demodulator_priv; @@ -305,17 +288,6 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr) return 0; } -static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) -{ - struct tda8083_state* state = fe->demodulator_priv; - - *ucblocks = tda8083_readreg(state, 0x0f); - if (*ucblocks == 0xff) - *ucblocks = 0xffffffff; - - return 0; -} - static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { struct tda8083_state* state = fe->demodulator_priv; @@ -468,8 +440,6 @@ static struct dvb_frontend_ops tda8083_ops = { .read_status = tda8083_read_status, .read_signal_strength = tda8083_read_signal_strength, .read_snr = tda8083_read_snr, - .read_ber = tda8083_read_ber, - .read_ucblocks = tda8083_read_ucblocks, .diseqc_send_master_cmd = tda8083_send_diseqc_msg, .diseqc_send_burst = tda8083_diseqc_send_burst, diff --git a/trunk/drivers/media/dvb/frontends/tda826x.c b/trunk/drivers/media/dvb/frontends/tda826x.c index 79f971dc52b6..34815b0b97e4 100644 --- a/trunk/drivers/media/dvb/frontends/tda826x.c +++ b/trunk/drivers/media/dvb/frontends/tda826x.c @@ -42,7 +42,8 @@ struct tda826x_priv { static int tda826x_release(struct dvb_frontend *fe) { - kfree(fe->tuner_priv); + if (fe->tuner_priv) + kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; } @@ -132,21 +133,18 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2 { struct tda826x_priv *priv = NULL; u8 b1 [] = { 0, 0 }; - struct i2c_msg msg[2] = { - { .addr = addr, .flags = 0, .buf = NULL, .len = 0 }, - { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } - }; + struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }; int ret; dprintk("%s:\n", __FUNCTION__); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - ret = i2c_transfer (i2c, msg, 2); + ret = i2c_transfer (i2c, &msg, 1); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); - if (ret != 2) + if (ret != 1) return NULL; if (!(b1[1] & 0x80)) return NULL; diff --git a/trunk/drivers/media/dvb/frontends/tua6100.c b/trunk/drivers/media/dvb/frontends/tua6100.c index 6ba0029dcf2e..88554393a9bf 100644 --- a/trunk/drivers/media/dvb/frontends/tua6100.c +++ b/trunk/drivers/media/dvb/frontends/tua6100.c @@ -43,7 +43,8 @@ struct tua6100_priv { static int tua6100_release(struct dvb_frontend *fe) { - kfree(fe->tuner_priv); + if (fe->tuner_priv) + kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; } diff --git a/trunk/drivers/media/dvb/pluto2/pluto2.c b/trunk/drivers/media/dvb/pluto2/pluto2.c index ffda71dfdd65..8e4ce101eb22 100644 --- a/trunk/drivers/media/dvb/pluto2/pluto2.c +++ b/trunk/drivers/media/dvb/pluto2/pluto2.c @@ -650,7 +650,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, /* dvb */ ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev); if (ret < 0) - goto err_i2c_del_adapter; + goto err_i2c_bit_del_bus; dvb_adapter = &pluto->dvb_adapter; @@ -712,8 +712,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, dvb_dmx_release(dvbdemux); err_dvb_unregister_adapter: dvb_unregister_adapter(dvb_adapter); -err_i2c_del_adapter: - i2c_del_adapter(&pluto->i2c_adap); +err_i2c_bit_del_bus: + i2c_bit_del_bus(&pluto->i2c_adap); err_pluto_hw_exit: pluto_hw_exit(pluto); err_free_irq: @@ -748,7 +748,7 @@ static void __devexit pluto2_remove(struct pci_dev *pdev) dvb_dmxdev_release(&pluto->dmxdev); dvb_dmx_release(dvbdemux); dvb_unregister_adapter(dvb_adapter); - i2c_del_adapter(&pluto->i2c_adap); + i2c_bit_del_bus(&pluto->i2c_adap); pluto_hw_exit(pluto); free_irq(pdev->irq, pluto); pci_iounmap(pdev, pluto->io_mem); diff --git a/trunk/drivers/media/dvb/ttpci/Kconfig b/trunk/drivers/media/dvb/ttpci/Kconfig index eec7ccf41f8b..95531a624991 100644 --- a/trunk/drivers/media/dvb/ttpci/Kconfig +++ b/trunk/drivers/media/dvb/ttpci/Kconfig @@ -92,7 +92,6 @@ config DVB_BUDGET_CI select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select VIDEO_IR help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard diff --git a/trunk/drivers/media/dvb/ttpci/av7110.c b/trunk/drivers/media/dvb/ttpci/av7110.c index 366c1371ee97..bba23bcd1b11 100644 --- a/trunk/drivers/media/dvb/ttpci/av7110.c +++ b/trunk/drivers/media/dvb/ttpci/av7110.c @@ -2828,7 +2828,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension av7110_extension = { .name = "dvb", - .flags = SAA7146_USE_I2C_IRQ, + .flags = SAA7146_I2C_SHORT_DELAY, .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], diff --git a/trunk/drivers/media/dvb/ttpci/av7110_ir.c b/trunk/drivers/media/dvb/ttpci/av7110_ir.c index e4544ea2b89b..d54bbcdde2cc 100644 --- a/trunk/drivers/media/dvb/ttpci/av7110_ir.c +++ b/trunk/drivers/media/dvb/ttpci/av7110_ir.c @@ -48,8 +48,7 @@ static void av7110_emit_keyup(unsigned long data) if (!data || !test_bit(data, input_dev->key)) return; - input_report_key(input_dev, data, 0); - input_sync(input_dev); + input_event(input_dev, EV_KEY, data, !!0); } @@ -116,17 +115,14 @@ static void av7110_emit_key(unsigned long parm) del_timer(&keyup_timer); if (keyup_timer.data != keycode || new_toggle != old_toggle) { delay_timer_finished = 0; - input_event(input_dev, EV_KEY, keyup_timer.data, 0); - input_event(input_dev, EV_KEY, keycode, 1); - input_sync(input_dev); - } else if (delay_timer_finished) { - input_event(input_dev, EV_KEY, keycode, 2); - input_sync(input_dev); - } + input_event(input_dev, EV_KEY, keyup_timer.data, !!0); + input_event(input_dev, EV_KEY, keycode, !0); + } else + if (delay_timer_finished) + input_event(input_dev, EV_KEY, keycode, 2); } else { delay_timer_finished = 0; - input_event(input_dev, EV_KEY, keycode, 1); - input_sync(input_dev); + input_event(input_dev, EV_KEY, keycode, !0); } keyup_timer.expires = jiffies + UP_TIMEOUT; @@ -215,7 +211,6 @@ static void ir_handler(struct av7110 *av7110, u32 ircom) int __devinit av7110_ir_init(struct av7110 *av7110) { static struct proc_dir_entry *e; - int err; if (av_cnt >= sizeof av_list/sizeof av_list[0]) return -ENOSPC; @@ -236,11 +231,7 @@ int __devinit av7110_ir_init(struct av7110 *av7110) set_bit(EV_KEY, input_dev->evbit); set_bit(EV_REP, input_dev->evbit); input_register_keys(); - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } + input_register_device(input_dev); input_dev->timer.function = input_repeat_key; e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL); diff --git a/trunk/drivers/media/dvb/ttpci/budget-av.c b/trunk/drivers/media/dvb/ttpci/budget-av.c index 89ab4b59155c..2235ff8b8a1d 100644 --- a/trunk/drivers/media/dvb/ttpci/budget-av.c +++ b/trunk/drivers/media/dvb/ttpci/budget-av.c @@ -360,7 +360,7 @@ static int ciintf_init(struct budget_av *budget_av) saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); /* Enable DEBI pins */ - saa7146_write(saa, MC1, MASK_27 | MASK_11); + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); /* register CI interface */ budget_av->ca.owner = THIS_MODULE; @@ -386,7 +386,7 @@ static int ciintf_init(struct budget_av *budget_av) return 0; error: - saa7146_write(saa, MC1, MASK_27); + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); return result; } @@ -403,7 +403,7 @@ static void ciintf_deinit(struct budget_av *budget_av) dvb_ca_en50221_release(&budget_av->ca); /* disable DEBI pins */ - saa7146_write(saa, MC1, MASK_27); + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); } @@ -655,10 +655,6 @@ static struct tda10021_config philips_cu1216_config = { .demod_address = 0x0c, }; -static struct tda10021_config philips_cu1216_config_altaddress = { - .demod_address = 0x0d, -}; - @@ -835,7 +831,7 @@ static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe, return -EINVAL; rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf, - params->frequency, 0); + params->frequency, 0); if(rc < 0) return rc; if (fe->ops.i2c_gate_ctrl) @@ -918,7 +914,6 @@ static u8 read_pwm(struct budget_av *budget_av) #define SUBID_DVBS_TV_STAR_CI 0x0016 #define SUBID_DVBS_EASYWATCH_1 0x001a #define SUBID_DVBS_EASYWATCH 0x001e -#define SUBID_DVBC_EASYWATCH 0x002a #define SUBID_DVBC_KNC1 0x0020 #define SUBID_DVBC_KNC1_PLUS 0x0021 #define SUBID_DVBC_CINERGY1200 0x1156 @@ -952,15 +947,11 @@ static void frontend_init(struct budget_av *budget_av) /* Enable / PowerON Frontend */ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); - /* Wait for PowerON */ - msleep(100); - /* additional setup necessary for the PLUS cards */ switch (saa->pci->subsystem_device) { case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBT_KNC1_PLUS: - case SUBID_DVBC_EASYWATCH: saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); break; } @@ -1015,15 +1006,10 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBC_KNC1: case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBC_CINERGY1200: - case SUBID_DVBC_EASYWATCH: budget_av->reinitialise_demod = 1; fe = dvb_attach(tda10021_attach, &philips_cu1216_config, &budget_av->budget.i2c_adap, read_pwm(budget_av)); - if (fe == NULL) - fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress, - &budget_av->budget.i2c_adap, - read_pwm(budget_av)); if (fe) { budget_av->tda10021_poclkp = 1; budget_av->tda10021_set_frontend = fe->ops.set_frontend; @@ -1256,7 +1242,6 @@ MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR); MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR); MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S); -MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP); MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); @@ -1275,7 +1260,6 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), - MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a), MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), @@ -1293,7 +1277,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension budget_extension = { .name = "budget_av", - .flags = SAA7146_USE_I2C_IRQ, + .flags = SAA7146_I2C_SHORT_DELAY, .pci_tbl = pci_tbl, diff --git a/trunk/drivers/media/dvb/ttpci/budget-ci.c b/trunk/drivers/media/dvb/ttpci/budget-ci.c index f2066b47baee..cd5ec489af1c 100644 --- a/trunk/drivers/media/dvb/ttpci/budget-ci.c +++ b/trunk/drivers/media/dvb/ttpci/budget-ci.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "dvb_ca_en50221.h" #include "stv0299.h" @@ -73,218 +72,162 @@ #define SLOTSTATUS_READY 8 #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) -/* Milliseconds during which key presses are regarded as key repeat and during - * which the debounce logic is active - */ -#define IR_REPEAT_TIMEOUT 350 - -/* RC5 device wildcard */ -#define IR_DEVICE_ANY 255 - -/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), - * this setting allows the superflous sequences to be ignored - */ -static int debounce = 0; -module_param(debounce, int, 0644); -MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); - -static int rc5_device = -1; -module_param(rc5_device, int, 0644); -MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); - -static int ir_debug = 0; -module_param(ir_debug, int, 0644); -MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); - -struct budget_ci_ir { - struct input_dev *dev; - struct tasklet_struct msp430_irq_tasklet; - char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ - char phys[32]; - struct ir_input_state state; - int rc5_device; -}; - struct budget_ci { struct budget budget; + struct input_dev *input_dev; + struct tasklet_struct msp430_irq_tasklet; struct tasklet_struct ciintf_irq_tasklet; int slot_status; int ci_irq; struct dvb_ca_en50221 ca; - struct budget_ci_ir ir; + char ir_dev_name[50]; u8 tuner_pll_address; /* used for philips_tdm1316l configs */ }; -static void msp430_ir_keyup(unsigned long data) -{ - struct budget_ci_ir *ir = (struct budget_ci_ir *) data; - ir_input_nokey(ir->dev, &ir->state); -} +/* from reading the following remotes: + Zenith Universal 7 / TV Mode 807 / VCR Mode 837 + Hauppauge (from NOVA-CI-s box product) + i've taken a "middle of the road" approach and note the differences +*/ +static u16 key_map[64] = { + /* 0x0X */ + KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, + KEY_9, + KEY_ENTER, + KEY_RED, + KEY_POWER, /* RADIO on Hauppauge */ + KEY_MUTE, + 0, + KEY_A, /* TV on Hauppauge */ + /* 0x1X */ + KEY_VOLUMEUP, KEY_VOLUMEDOWN, + 0, 0, + KEY_B, + 0, 0, 0, 0, 0, 0, 0, + KEY_UP, KEY_DOWN, + KEY_OPTION, /* RESERVED on Hauppauge */ + KEY_BREAK, + /* 0x2X */ + KEY_CHANNELUP, KEY_CHANNELDOWN, + KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ + 0, KEY_RESTART, KEY_OK, + KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ + 0, + KEY_ENTER, /* VCR mode on Zenith */ + KEY_PAUSE, + 0, + KEY_RIGHT, KEY_LEFT, + 0, + KEY_MENU, /* FULL SCREEN on Hauppauge */ + 0, + /* 0x3X */ + KEY_SLOW, + KEY_PREVIOUS, /* VCR mode on Zenith */ + KEY_REWIND, + 0, + KEY_FASTFORWARD, + KEY_PLAY, KEY_STOP, + KEY_RECORD, + KEY_TUNER, /* TV/VCR on Zenith */ + 0, + KEY_C, + 0, + KEY_EXIT, + KEY_POWER2, + KEY_TUNER, /* VCR mode on Zenith */ + 0, +}; -static void msp430_ir_interrupt(unsigned long data) +static void msp430_ir_debounce(unsigned long data) { - struct budget_ci *budget_ci = (struct budget_ci *) data; - struct input_dev *dev = budget_ci->ir.dev; - static int bounces = 0; - int device; - int toggle; - static int prev_toggle = -1; - static u32 ir_key; - u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; - - /* - * The msp430 chip can generate two different bytes, command and device - * - * type1: X1CCCCCC, C = command bits (0 - 63) - * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit - * - * More than one command byte may be generated before the device byte - * Only when we have both, a correct keypress is generated - */ - - /* Is this a RC5 command byte? */ - if (command & 0x40) { - if (ir_debug) - printk("budget_ci: received command byte 0x%02x\n", command); - ir_key = command & 0x3f; + struct input_dev *dev = (struct input_dev *) data; + + if (dev->rep[0] == 0 || dev->rep[0] == ~0) { + input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); return; } - /* It's a RC5 device byte */ - if (ir_debug) - printk("budget_ci: received device byte 0x%02x\n", command); - device = command & 0x1f; - toggle = command & 0x20; + dev->rep[0] = 0; + dev->timer.expires = jiffies + HZ * 350 / 1000; + add_timer(&dev->timer); + input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */ +} - if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device) - return; +static void msp430_ir_interrupt(unsigned long data) +{ + struct budget_ci *budget_ci = (struct budget_ci *) data; + struct input_dev *dev = budget_ci->input_dev; + unsigned int code = + ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; - /* Ignore repeated key sequences if requested */ - if (toggle == prev_toggle && ir_key == dev->repeat_key && - bounces > 0 && timer_pending(&dev->timer)) { - if (ir_debug) - printk("budget_ci: debounce logic ignored IR command\n"); - bounces--; - return; - } - prev_toggle = toggle; + if (code & 0x40) { + code &= 0x3f; - /* Are we still waiting for a keyup event? */ - if (del_timer(&dev->timer)) - ir_input_nokey(dev, &budget_ci->ir.state); + if (timer_pending(&dev->timer)) { + if (code == dev->repeat_key) { + ++dev->rep[0]; + return; + } + del_timer(&dev->timer); + input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); + } - /* Generate keypress */ - if (ir_debug) - printk("budget_ci: generating keypress 0x%02x\n", ir_key); - ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8))); + if (!key_map[code]) { + printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code); + return; + } - /* Do we want to delay the keyup event? */ - if (debounce) { - bounces = debounce; - mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); - } else { - ir_input_nokey(dev, &budget_ci->ir.state); + /* initialize debounce and repeat */ + dev->repeat_key = code; + /* Zenith remote _always_ sends 2 sequences */ + dev->rep[0] = ~0; + /* 350 milliseconds */ + dev->timer.expires = jiffies + HZ * 350 / 1000; + /* MAKE */ + input_event(dev, EV_KEY, key_map[code], !0); + add_timer(&dev->timer); } } static int msp430_ir_init(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; - struct input_dev *input_dev = budget_ci->ir.dev; - int error; - - budget_ci->ir.dev = input_dev = input_allocate_device(); - if (!input_dev) { - printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); - error = -ENOMEM; - goto out1; - } - - snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), - "Budget-CI dvb ir receiver %s", saa->name); - snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys), - "pci-%s/ir0", pci_name(saa->pci)); + struct input_dev *input_dev; + int i; - input_dev->name = budget_ci->ir.name; + budget_ci->input_dev = input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; - input_dev->phys = budget_ci->ir.phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; - if (saa->pci->subsystem_vendor) { - input_dev->id.vendor = saa->pci->subsystem_vendor; - input_dev->id.product = saa->pci->subsystem_device; - } else { - input_dev->id.vendor = saa->pci->vendor; - input_dev->id.product = saa->pci->device; - } - input_dev->cdev.dev = &saa->pci->dev; + sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name); - /* Select keymap and address */ - switch (budget_ci->budget.dev->pci->subsystem_device) { - case 0x100c: - case 0x100f: - case 0x1010: - case 0x1011: - case 0x1012: - case 0x1017: - /* The hauppauge keymap is a superset of these remotes */ - ir_input_init(input_dev, &budget_ci->ir.state, - IR_TYPE_RC5, ir_codes_hauppauge_new); - - if (rc5_device < 0) - budget_ci->ir.rc5_device = 0x1f; - else - budget_ci->ir.rc5_device = rc5_device; - break; - default: - /* unknown remote */ - ir_input_init(input_dev, &budget_ci->ir.state, - IR_TYPE_RC5, ir_codes_budget_ci_old); - - if (rc5_device < 0) - budget_ci->ir.rc5_device = IR_DEVICE_ANY; - else - budget_ci->ir.rc5_device = rc5_device; - break; - } + input_dev->name = budget_ci->ir_dev_name; - /* initialise the key-up debounce timeout handler */ - input_dev->timer.function = msp430_ir_keyup; - input_dev->timer.data = (unsigned long) &budget_ci->ir; + set_bit(EV_KEY, input_dev->evbit); + for (i = 0; i < ARRAY_SIZE(key_map); i++) + if (key_map[i]) + set_bit(key_map[i], input_dev->keybit); - error = input_register_device(input_dev); - if (error) { - printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); - goto out2; - } + input_register_device(budget_ci->input_dev); - tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, - (unsigned long) budget_ci); + input_dev->timer.function = msp430_ir_debounce; - SAA7146_IER_ENABLE(saa, MASK_06); + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); return 0; - -out2: - input_free_device(input_dev); -out1: - return error; } static void msp430_ir_deinit(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; - struct input_dev *dev = budget_ci->ir.dev; + struct input_dev *dev = budget_ci->input_dev; - SAA7146_IER_DISABLE(saa, MASK_06); + saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); - tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); - if (del_timer(&dev->timer)) { - ir_input_nokey(dev, &budget_ci->ir.state); - input_sync(dev); - } + if (del_timer(&dev->timer)) + input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); input_unregister_device(dev); } @@ -485,7 +428,7 @@ static int ciintf_init(struct budget_ci *budget_ci) memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); // enable DEBI pins - saa7146_write(saa, MC1, MASK_27 | MASK_11); + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); // test if it is there ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); @@ -537,7 +480,7 @@ static int ciintf_init(struct budget_ci *budget_ci) } else { saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); } - SAA7146_IER_ENABLE(saa, MASK_03); + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); } // enable interface @@ -559,7 +502,7 @@ static int ciintf_init(struct budget_ci *budget_ci) return 0; error: - saa7146_write(saa, MC1, MASK_27); + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); return result; } @@ -569,7 +512,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) // disable CI interrupts if (budget_ci->ci_irq) { - SAA7146_IER_DISABLE(saa, MASK_03); + saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); tasklet_kill(&budget_ci->ciintf_irq_tasklet); } @@ -587,7 +530,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) dvb_ca_en50221_release(&budget_ci->ca); // disable DEBI pins - saa7146_write(saa, MC1, MASK_27); + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); } static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) @@ -597,7 +540,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci); if (*isr & MASK_06) - tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet); + tasklet_schedule(&budget_ci->msp430_irq_tasklet); if (*isr & MASK_10) ttpci_budget_irq10_handler(dev, isr); @@ -892,7 +835,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc band = 1; } else if (tuner_frequency < 200000000) { cp = 6; - band = 2; + band = 1; } else if (tuner_frequency < 290000000) { cp = 3; band = 2; @@ -1140,23 +1083,24 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio struct budget_ci *budget_ci; int err; - budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL); - if (!budget_ci) { - err = -ENOMEM; - goto out1; - } + if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL))) + return -ENOMEM; dprintk(2, "budget_ci: %p\n", budget_ci); + budget_ci->budget.ci_present = 0; + dev->ext_priv = budget_ci; - err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE); - if (err) - goto out2; + if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) { + kfree(budget_ci); + return err; + } + + tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt, + (unsigned long) budget_ci); - err = msp430_ir_init(budget_ci); - if (err) - goto out3; + msp430_ir_init(budget_ci); ciintf_init(budget_ci); @@ -1166,13 +1110,6 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio ttpci_budget_init_hooks(&budget_ci->budget); return 0; - -out3: - ttpci_budget_deinit(&budget_ci->budget); -out2: - kfree(budget_ci); -out1: - return err; } static int budget_ci_detach(struct saa7146_dev *dev) @@ -1183,13 +1120,16 @@ static int budget_ci_detach(struct saa7146_dev *dev) if (budget_ci->budget.ci_present) ciintf_deinit(budget_ci); - msp430_ir_deinit(budget_ci); if (budget_ci->budget.dvb_frontend) { dvb_unregister_frontend(budget_ci->budget.dvb_frontend); dvb_frontend_detach(budget_ci->budget.dvb_frontend); } err = ttpci_budget_deinit(&budget_ci->budget); + tasklet_kill(&budget_ci->msp430_irq_tasklet); + + msp430_ir_deinit(budget_ci); + // disable frontend and CI interface saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); @@ -1222,7 +1162,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension budget_extension = { .name = "budget_ci dvb", - .flags = SAA7146_USE_I2C_IRQ, + .flags = SAA7146_I2C_SHORT_DELAY, .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], diff --git a/trunk/drivers/media/dvb/ttpci/budget.c b/trunk/drivers/media/dvb/ttpci/budget.c index 9268a82bada6..56f1c80defc6 100644 --- a/trunk/drivers/media/dvb/ttpci/budget.c +++ b/trunk/drivers/media/dvb/ttpci/budget.c @@ -555,7 +555,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_extension budget_extension = { .name = "budget dvb", - .flags = SAA7146_USE_I2C_IRQ, + .flags = SAA7146_I2C_SHORT_DELAY, .module = THIS_MODULE, .pci_tbl = pci_tbl, diff --git a/trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c index bd6e7baae2ec..10b121ada833 100644 --- a/trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -238,7 +238,6 @@ static void ttusb_dec_handle_irq( struct urb *urb) * for now lets report each signal as a key down and up*/ dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]); input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1); - input_sync(dec->rc_input_dev); input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0); input_sync(dec->rc_input_dev); } @@ -1188,12 +1187,11 @@ static int ttusb_init_rc( struct ttusb_dec *dec) struct input_dev *input_dev; u8 b[] = { 0x00, 0x01 }; int i; - int err; usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys)); strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); - input_dev = input_allocate_device(); + dec->rc_input_dev = input_dev = input_allocate_device(); if (!input_dev) return -ENOMEM; @@ -1207,13 +1205,8 @@ static int ttusb_init_rc( struct ttusb_dec *dec) for (i = 0; i < ARRAY_SIZE(rc_keys); i++) set_bit(rc_keys[i], input_dev->keybit); - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } + input_register_device(input_dev); - dec->rc_input_dev = input_dev; if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) printk("%s: usb_submit_urb failed\n",__FUNCTION__); /* enable irq pipe */ diff --git a/trunk/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/trunk/drivers/media/dvb/ttusb-dec/ttusbdecfe.c index a6fb1d6a7b5d..42f39a89bc4d 100644 --- a/trunk/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/trunk/drivers/media/dvb/ttusb-dec/ttusbdecfe.c @@ -195,7 +195,7 @@ struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* conf struct ttusbdecfe_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL); + state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL); if (state == NULL) return NULL; @@ -215,7 +215,7 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf struct ttusbdecfe_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL); + state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL); if (state == NULL) return NULL; diff --git a/trunk/drivers/media/video/Kconfig b/trunk/drivers/media/video/Kconfig index 29a11c1db1b7..b8fde5cf4735 100644 --- a/trunk/drivers/media/video/Kconfig +++ b/trunk/drivers/media/video/Kconfig @@ -184,14 +184,6 @@ config VIDEO_KS0127 To compile this driver as a module, choose M here: the module will be called ks0127. -config VIDEO_OV7670 - tristate "OmniVision OV7670 sensor support" - depends on I2C && VIDEO_V4L2 - ---help--- - This is a Video4Linux2 sensor-level driver for the OmniVision - OV7670 VGA camera. It currently only works with the M88ALP01 - controller. - config VIDEO_SAA7110 tristate "Philips SAA7110 video decoder" depends on VIDEO_V4L1 && I2C @@ -575,6 +567,18 @@ config VIDEO_ZORAN_AVS6EYES help Support for the AverMedia 6 Eyes video surveillance card. +config VIDEO_ZR36120 + tristate "Zoran ZR36120/36125 Video For Linux" + depends on PCI && I2C && VIDEO_V4L1 && BROKEN + help + Support for ZR36120/ZR36125 based frame grabber/overlay boards. + This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV, + and Buster boards. Please read the material in + for more information. + + To compile this driver as a module, choose M here: the + module will be called zr36120. + config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" depends on PCI && SONYPI && VIDEO_V4L1 @@ -666,15 +670,6 @@ config VIDEO_M32R_AR_M64278 To compile this driver as a module, choose M here: the module will be called arv. -config VIDEO_CAFE_CCIC - tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support" - depends on I2C && VIDEO_V4L2 - select VIDEO_OV7670 - ---help--- - This is a video4linux2 driver for the Marvell 88ALP01 integrated - CMOS camera controller. This is the controller found on first- - generation OLPC systems. - # # USB Multimedia device configuration # @@ -686,8 +681,6 @@ source "drivers/media/video/pvrusb2/Kconfig" source "drivers/media/video/em28xx/Kconfig" -source "drivers/media/video/usbvision/Kconfig" - source "drivers/media/video/usbvideo/Kconfig" source "drivers/media/video/et61x251/Kconfig" diff --git a/trunk/drivers/media/video/Makefile b/trunk/drivers/media/video/Makefile index 9b1f3f06bb7c..af57abce8a6e 100644 --- a/trunk/drivers/media/video/Makefile +++ b/trunk/drivers/media/video/Makefile @@ -2,6 +2,7 @@ # Makefile for the video capture/playback device drivers. # +zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ @@ -22,6 +23,7 @@ obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o +obj-$(CONFIG_VIDEO_ZR36120) += zoran.o obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o @@ -62,7 +64,6 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ -obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o @@ -91,9 +92,6 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o -obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o -obj-$(CONFIG_VIDEO_OV7670) += ov7670.o - obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_OV511) += ov511.o obj-$(CONFIG_USB_SE401) += se401.o diff --git a/trunk/drivers/media/video/bt8xx/bttv-driver.c b/trunk/drivers/media/video/bt8xx/bttv-driver.c index 3c8e4742dccc..6e1ddad9f0c1 100644 --- a/trunk/drivers/media/video/bt8xx/bttv-driver.c +++ b/trunk/drivers/media/video/bt8xx/bttv-driver.c @@ -1793,7 +1793,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) memset(i,0,sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; - i->audioset = 1; + i->audioset = 0; if (i->index == bttv_tvcards[btv->c.type].tuner) { sprintf(i->name, "Television"); i->type = V4L2_INPUT_TYPE_TUNER; diff --git a/trunk/drivers/media/video/bt8xx/bttv-i2c.c b/trunk/drivers/media/video/bt8xx/bttv-i2c.c index 62b873076e09..70de6c96e201 100644 --- a/trunk/drivers/media/video/bt8xx/bttv-i2c.c +++ b/trunk/drivers/media/video/bt8xx/bttv-i2c.c @@ -479,7 +479,11 @@ int __devexit fini_bttv_i2c(struct bttv *btv) if (0 != btv->i2c_rc) return 0; - return i2c_del_adapter(&btv->c.i2c_adap); + if (btv->use_i2c_hw) { + return i2c_del_adapter(&btv->c.i2c_adap); + } else { + return i2c_bit_del_bus(&btv->c.i2c_adap); + } } /* diff --git a/trunk/drivers/media/video/bt8xx/bttv-input.c b/trunk/drivers/media/video/bt8xx/bttv-input.c index cbc012f71f52..933d6db09acb 100644 --- a/trunk/drivers/media/video/bt8xx/bttv-input.c +++ b/trunk/drivers/media/video/bt8xx/bttv-input.c @@ -259,59 +259,24 @@ static void bttv_rc5_timer_keyup(unsigned long data) /* ---------------------------------------------------------------------- */ -static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) -{ - if (ir->polling) { - init_timer(&ir->timer); - ir->timer.function = bttv_input_timer; - ir->timer.data = (unsigned long)btv; - ir->timer.expires = jiffies + HZ; - add_timer(&ir->timer); - } else if (ir->rc5_gpio) { - /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = bttv_rc5_timer_end; - ir->timer_end.data = (unsigned long)ir; - - init_timer(&ir->timer_keyup); - ir->timer_keyup.function = bttv_rc5_timer_keyup; - ir->timer_keyup.data = (unsigned long)ir; - } -} - -static void bttv_ir_stop(struct bttv *btv) -{ - if (btv->remote->polling) { - del_timer_sync(&btv->remote->timer); - flush_scheduled_work(); - } - - if (btv->remote->rc5_gpio) { - u32 gpio; - - del_timer_sync(&btv->remote->timer_end); - flush_scheduled_work(); - - gpio = bttv_gpio_read(&btv->c); - bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); - } -} - int bttv_input_init(struct bttv *btv) { struct bttv_ir *ir; IR_KEYTAB_TYPE *ir_codes = NULL; struct input_dev *input_dev; int ir_type = IR_TYPE_OTHER; - int err = -ENOMEM; if (!btv->has_remote) return -ENODEV; ir = kzalloc(sizeof(*ir),GFP_KERNEL); input_dev = input_allocate_device(); - if (!ir || !input_dev) - goto err_out_free; + if (!ir || !input_dev) { + kfree(ir); + input_free_device(input_dev); + return -ENOMEM; + } + memset(ir,0,sizeof(*ir)); /* detect & configure */ switch (btv->c.type) { @@ -383,9 +348,10 @@ int bttv_input_init(struct bttv *btv) break; } if (NULL == ir_codes) { - dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); - err = -ENODEV; - goto err_out_free; + dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type); + kfree(ir); + input_free_device(input_dev); + return -ENODEV; } if (ir->rc5_gpio) { @@ -423,26 +389,32 @@ int bttv_input_init(struct bttv *btv) input_dev->cdev.dev = &btv->c.pci->dev; btv->remote = ir; - bttv_ir_start(btv, ir); + if (ir->polling) { + init_timer(&ir->timer); + ir->timer.function = bttv_input_timer; + ir->timer.data = (unsigned long)btv; + ir->timer.expires = jiffies + HZ; + add_timer(&ir->timer); + } else if (ir->rc5_gpio) { + /* set timer_end for code completion */ + init_timer(&ir->timer_end); + ir->timer_end.function = bttv_rc5_timer_end; + ir->timer_end.data = (unsigned long)ir; + + init_timer(&ir->timer_keyup); + ir->timer_keyup.function = bttv_rc5_timer_keyup; + ir->timer_keyup.data = (unsigned long)ir; + } /* all done */ - err = input_register_device(btv->remote->dev); - if (err) - goto err_out_stop; + input_register_device(btv->remote->dev); + printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); /* the remote isn't as bouncy as a keyboard */ ir->dev->rep[REP_DELAY] = repeat_delay; ir->dev->rep[REP_PERIOD] = repeat_period; return 0; - - err_out_stop: - bttv_ir_stop(btv); - btv->remote = NULL; - err_out_free: - input_free_device(input_dev); - kfree(ir); - return err; } void bttv_input_fini(struct bttv *btv) @@ -450,7 +422,22 @@ void bttv_input_fini(struct bttv *btv) if (btv->remote == NULL) return; - bttv_ir_stop(btv); + if (btv->remote->polling) { + del_timer_sync(&btv->remote->timer); + flush_scheduled_work(); + } + + + if (btv->remote->rc5_gpio) { + u32 gpio; + + del_timer_sync(&btv->remote->timer_end); + flush_scheduled_work(); + + gpio = bttv_gpio_read(&btv->c); + bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); + } + input_unregister_device(btv->remote->dev); kfree(btv->remote); btv->remote = NULL; diff --git a/trunk/drivers/media/video/cafe_ccic-regs.h b/trunk/drivers/media/video/cafe_ccic-regs.h deleted file mode 100644 index b2c22a0d6643..000000000000 --- a/trunk/drivers/media/video/cafe_ccic-regs.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Register definitions for the m88alp01 camera interface. Offsets in bytes - * as given in the spec. - * - * Copyright 2006 One Laptop Per Child Association, Inc. - * - * Written by Jonathan Corbet, corbet@lwn.net. - * - * This file may be distributed under the terms of the GNU General - * Public License, version 2. - */ -#define REG_Y0BAR 0x00 -#define REG_Y1BAR 0x04 -#define REG_Y2BAR 0x08 -/* ... */ - -#define REG_IMGPITCH 0x24 /* Image pitch register */ -#define IMGP_YP_SHFT 2 /* Y pitch params */ -#define IMGP_YP_MASK 0x00003ffc /* Y pitch field */ -#define IMGP_UVP_SHFT 18 /* UV pitch (planar) */ -#define IMGP_UVP_MASK 0x3ffc0000 -#define REG_IRQSTATRAW 0x28 /* RAW IRQ Status */ -#define IRQ_EOF0 0x00000001 /* End of frame 0 */ -#define IRQ_EOF1 0x00000002 /* End of frame 1 */ -#define IRQ_EOF2 0x00000004 /* End of frame 2 */ -#define IRQ_SOF0 0x00000008 /* Start of frame 0 */ -#define IRQ_SOF1 0x00000010 /* Start of frame 1 */ -#define IRQ_SOF2 0x00000020 /* Start of frame 2 */ -#define IRQ_OVERFLOW 0x00000040 /* FIFO overflow */ -#define IRQ_TWSIW 0x00010000 /* TWSI (smbus) write */ -#define IRQ_TWSIR 0x00020000 /* TWSI read */ -#define IRQ_TWSIE 0x00040000 /* TWSI error */ -#define TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE) -#define FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2) -#define ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW) -#define REG_IRQMASK 0x2c /* IRQ mask - same bits as IRQSTAT */ -#define REG_IRQSTAT 0x30 /* IRQ status / clear */ - -#define REG_IMGSIZE 0x34 /* Image size */ -#define IMGSZ_V_MASK 0x1fff0000 -#define IMGSZ_V_SHIFT 16 -#define IMGSZ_H_MASK 0x00003fff -#define REG_IMGOFFSET 0x38 /* IMage offset */ - -#define REG_CTRL0 0x3c /* Control 0 */ -#define C0_ENABLE 0x00000001 /* Makes the whole thing go */ - -/* Mask for all the format bits */ -#define C0_DF_MASK 0x00fffffc /* Bits 2-23 */ - -/* RGB ordering */ -#define C0_RGB4_RGBX 0x00000000 -#define C0_RGB4_XRGB 0x00000004 -#define C0_RGB4_BGRX 0x00000008 -#define C0_RGB4_XBGR 0x0000000c -#define C0_RGB5_RGGB 0x00000000 -#define C0_RGB5_GRBG 0x00000004 -#define C0_RGB5_GBRG 0x00000008 -#define C0_RGB5_BGGR 0x0000000c - -/* Spec has two fields for DIN and DOUT, but they must match, so - combine them here. */ -#define C0_DF_YUV 0x00000000 /* Data is YUV */ -#define C0_DF_RGB 0x000000a0 /* ... RGB */ -#define C0_DF_BAYER 0x00000140 /* ... Bayer */ -/* 8-8-8 must be missing from the below - ask */ -#define C0_RGBF_565 0x00000000 -#define C0_RGBF_444 0x00000800 -#define C0_RGB_BGR 0x00001000 /* Blue comes first */ -#define C0_YUV_PLANAR 0x00000000 /* YUV 422 planar format */ -#define C0_YUV_PACKED 0x00008000 /* YUV 422 packed */ -#define C0_YUV_420PL 0x0000a000 /* YUV 420 planar */ -/* Think that 420 packed must be 111 - ask */ -#define C0_YUVE_YUYV 0x00000000 /* Y1CbY0Cr */ -#define C0_YUVE_YVYU 0x00010000 /* Y1CrY0Cb */ -#define C0_YUVE_VYUY 0x00020000 /* CrY1CbY0 */ -#define C0_YUVE_UYVY 0x00030000 /* CbY1CrY0 */ -#define C0_YUVE_XYUV 0x00000000 /* 420: .YUV */ -#define C0_YUVE_XYVU 0x00010000 /* 420: .YVU */ -#define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ -#define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ -/* Bayer bits 18,19 if needed */ -#define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ -#define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ -#define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ -#define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ -#define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ -#define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ -#define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ - - -#define REG_CTRL1 0x40 /* Control 1 */ -#define C1_444ALPHA 0x00f00000 /* Alpha field in RGB444 */ -#define C1_ALPHA_SHFT 20 -#define C1_DMAB32 0x00000000 /* 32-byte DMA burst */ -#define C1_DMAB16 0x02000000 /* 16-byte DMA burst */ -#define C1_DMAB64 0x04000000 /* 64-byte DMA burst */ -#define C1_DMAB_MASK 0x06000000 -#define C1_TWOBUFS 0x08000000 /* Use only two DMA buffers */ -#define C1_PWRDWN 0x10000000 /* Power down */ - -#define REG_CLKCTRL 0x88 /* Clock control */ -#define CLK_DIV_MASK 0x0000ffff /* Upper bits RW "reserved" */ - -#define REG_GPR 0xb4 /* General purpose register. This - controls inputs to the power and reset - pins on the OV7670 used with OLPC; - other deployments could differ. */ -#define GPR_C1EN 0x00000020 /* Pad 1 (power down) enable */ -#define GPR_C0EN 0x00000010 /* Pad 0 (reset) enable */ -#define GPR_C1 0x00000002 /* Control 1 value */ -/* - * Control 0 is wired to reset on OLPC machines. For ov7x sensors, - * it is active low, for 0v6x, instead, it's active high. What - * fun. - */ -#define GPR_C0 0x00000001 /* Control 0 value */ - -#define REG_TWSIC0 0xb8 /* TWSI (smbus) control 0 */ -#define TWSIC0_EN 0x00000001 /* TWSI enable */ -#define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */ -#define TWSIC0_SID 0x000003fc /* Slave ID */ -#define TWSIC0_SID_SHIFT 2 -#define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */ -#define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */ -#define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */ - -#define REG_TWSIC1 0xbc /* TWSI control 1 */ -#define TWSIC1_DATA 0x0000ffff /* Data to/from camchip */ -#define TWSIC1_ADDR 0x00ff0000 /* Address (register) */ -#define TWSIC1_ADDR_SHIFT 16 -#define TWSIC1_READ 0x01000000 /* Set for read op */ -#define TWSIC1_WSTAT 0x02000000 /* Write status */ -#define TWSIC1_RVALID 0x04000000 /* Read data valid */ -#define TWSIC1_ERROR 0x08000000 /* Something screwed up */ - - -#define REG_UBAR 0xc4 /* Upper base address register */ - -/* - * Here's the weird global control registers which are said to live - * way up here. - */ -#define REG_GL_CSR 0x3004 /* Control/status register */ -#define GCSR_SRS 0x00000001 /* SW Reset set */ -#define GCSR_SRC 0x00000002 /* SW Reset clear */ -#define GCSR_MRS 0x00000004 /* Master reset set */ -#define GCSR_MRC 0x00000008 /* HW Reset clear */ -#define GCSR_CCIC_EN 0x00004000 /* CCIC Clock enable */ -#define REG_GL_IMASK 0x300c /* Interrupt mask register */ -#define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ - -#define REG_LEN REG_GL_IMASK + 4 - - -/* - * Useful stuff that probably belongs somewhere global. - */ -#define VGA_WIDTH 640 -#define VGA_HEIGHT 480 diff --git a/trunk/drivers/media/video/cafe_ccic.c b/trunk/drivers/media/video/cafe_ccic.c deleted file mode 100644 index e347c7ebc984..000000000000 --- a/trunk/drivers/media/video/cafe_ccic.c +++ /dev/null @@ -1,2228 +0,0 @@ -/* - * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe" - * multifunction chip. Currently works with the Omnivision OV7670 - * sensor. - * - * Copyright 2006 One Laptop Per Child Association, Inc. - * - * Written by Jonathan Corbet, corbet@lwn.net. - * - * This file may be distributed under the terms of the GNU General - * Public License, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "cafe_ccic-regs.h" - -#define CAFE_VERSION 0x000001 - - -/* - * Parameters. - */ -MODULE_AUTHOR("Jonathan Corbet "); -MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("Video"); - -/* - * Internal DMA buffer management. Since the controller cannot do S/G I/O, - * we must have physically contiguous buffers to bring frames into. - * These parameters control how many buffers we use, whether we - * allocate them at load time (better chance of success, but nails down - * memory) or when somebody tries to use the camera (riskier), and, - * for load-time allocation, how big they should be. - * - * The controller can cycle through three buffers. We could use - * more by flipping pointers around, but it probably makes little - * sense. - */ - -#define MAX_DMA_BUFS 3 -static int alloc_bufs_at_load = 0; -module_param(alloc_bufs_at_load, bool, 0444); -MODULE_PARM_DESC(alloc_bufs_at_load, - "Non-zero value causes DMA buffers to be allocated at module " - "load time. This increases the chances of successfully getting " - "those buffers, but at the cost of nailing down the memory from " - "the outset."); - -static int n_dma_bufs = 3; -module_param(n_dma_bufs, uint, 0644); -MODULE_PARM_DESC(n_dma_bufs, - "The number of DMA buffers to allocate. Can be either two " - "(saves memory, makes timing tighter) or three."); - -static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2; /* Worst case */ -module_param(dma_buf_size, uint, 0444); -MODULE_PARM_DESC(dma_buf_size, - "The size of the allocated DMA buffers. If actual operating " - "parameters require larger buffers, an attempt to reallocate " - "will be made."); - -static int min_buffers = 1; -module_param(min_buffers, uint, 0644); -MODULE_PARM_DESC(min_buffers, - "The minimum number of streaming I/O buffers we are willing " - "to work with."); - -static int max_buffers = 10; -module_param(max_buffers, uint, 0644); -MODULE_PARM_DESC(max_buffers, - "The maximum number of streaming I/O buffers an application " - "will be allowed to allocate. These buffers are big and live " - "in vmalloc space."); - -static int flip = 0; -module_param(flip, bool, 0444); -MODULE_PARM_DESC(flip, - "If set, the sensor will be instructed to flip the image " - "vertically."); - - -enum cafe_state { - S_NOTREADY, /* Not yet initialized */ - S_IDLE, /* Just hanging around */ - S_FLAKED, /* Some sort of problem */ - S_SINGLEREAD, /* In read() */ - S_SPECREAD, /* Speculative read (for future read()) */ - S_STREAMING /* Streaming data */ -}; - -/* - * Tracking of streaming I/O buffers. - */ -struct cafe_sio_buffer { - struct list_head list; - struct v4l2_buffer v4lbuf; - char *buffer; /* Where it lives in kernel space */ - int mapcount; - struct cafe_camera *cam; -}; - -/* - * A description of one of our devices. - * Locking: controlled by s_mutex. Certain fields, however, require - * the dev_lock spinlock; they are marked as such by comments. - * dev_lock is also required for access to device registers. - */ -struct cafe_camera -{ - enum cafe_state state; - unsigned long flags; /* Buffer status, mainly (dev_lock) */ - int users; /* How many open FDs */ - struct file *owner; /* Who has data access (v4l2) */ - - /* - * Subsystem structures. - */ - struct pci_dev *pdev; - struct video_device v4ldev; - struct i2c_adapter i2c_adapter; - struct i2c_client *sensor; - - unsigned char __iomem *regs; - struct list_head dev_list; /* link to other devices */ - - /* DMA buffers */ - unsigned int nbufs; /* How many are alloc'd */ - int next_buf; /* Next to consume (dev_lock) */ - unsigned int dma_buf_size; /* allocated size */ - void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ - dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ - unsigned int specframes; /* Unconsumed spec frames (dev_lock) */ - unsigned int sequence; /* Frame sequence number */ - unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */ - - /* Streaming buffers */ - unsigned int n_sbufs; /* How many we have */ - struct cafe_sio_buffer *sb_bufs; /* The array of housekeeping structs */ - struct list_head sb_avail; /* Available for data (we own) (dev_lock) */ - struct list_head sb_full; /* With data (user space owns) (dev_lock) */ - struct tasklet_struct s_tasklet; - - /* Current operating parameters */ - enum v4l2_chip_ident sensor_type; /* Currently ov7670 only */ - struct v4l2_pix_format pix_format; - - /* Locks */ - struct mutex s_mutex; /* Access to this structure */ - spinlock_t dev_lock; /* Access to device */ - - /* Misc */ - wait_queue_head_t smbus_wait; /* Waiting on i2c events */ - wait_queue_head_t iowait; /* Waiting on frame data */ -#ifdef CONFIG_VIDEO_ADV_DEBUG - struct dentry *dfs_regs; - struct dentry *dfs_cam_regs; -#endif -}; - -/* - * Status flags. Always manipulated with bit operations. - */ -#define CF_BUF0_VALID 0 /* Buffers valid - first three */ -#define CF_BUF1_VALID 1 -#define CF_BUF2_VALID 2 -#define CF_DMA_ACTIVE 3 /* A frame is incoming */ -#define CF_CONFIG_NEEDED 4 /* Must configure hardware */ - - - -/* - * Start over with DMA buffers - dev_lock needed. - */ -static void cafe_reset_buffers(struct cafe_camera *cam) -{ - int i; - - cam->next_buf = -1; - for (i = 0; i < cam->nbufs; i++) - clear_bit(i, &cam->flags); - cam->specframes = 0; -} - -static inline int cafe_needs_config(struct cafe_camera *cam) -{ - return test_bit(CF_CONFIG_NEEDED, &cam->flags); -} - -static void cafe_set_config_needed(struct cafe_camera *cam, int needed) -{ - if (needed) - set_bit(CF_CONFIG_NEEDED, &cam->flags); - else - clear_bit(CF_CONFIG_NEEDED, &cam->flags); -} - - - - -/* - * Debugging and related. - */ -#define cam_err(cam, fmt, arg...) \ - dev_err(&(cam)->pdev->dev, fmt, ##arg); -#define cam_warn(cam, fmt, arg...) \ - dev_warn(&(cam)->pdev->dev, fmt, ##arg); -#define cam_dbg(cam, fmt, arg...) \ - dev_dbg(&(cam)->pdev->dev, fmt, ##arg); - - -/* ---------------------------------------------------------------------*/ -/* - * We keep a simple list of known devices to search at open time. - */ -static LIST_HEAD(cafe_dev_list); -static DEFINE_MUTEX(cafe_dev_list_lock); - -static void cafe_add_dev(struct cafe_camera *cam) -{ - mutex_lock(&cafe_dev_list_lock); - list_add_tail(&cam->dev_list, &cafe_dev_list); - mutex_unlock(&cafe_dev_list_lock); -} - -static void cafe_remove_dev(struct cafe_camera *cam) -{ - mutex_lock(&cafe_dev_list_lock); - list_del(&cam->dev_list); - mutex_unlock(&cafe_dev_list_lock); -} - -static struct cafe_camera *cafe_find_dev(int minor) -{ - struct cafe_camera *cam; - - mutex_lock(&cafe_dev_list_lock); - list_for_each_entry(cam, &cafe_dev_list, dev_list) { - if (cam->v4ldev.minor == minor) - goto done; - } - cam = NULL; - done: - mutex_unlock(&cafe_dev_list_lock); - return cam; -} - - -static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev) -{ - struct cafe_camera *cam; - - mutex_lock(&cafe_dev_list_lock); - list_for_each_entry(cam, &cafe_dev_list, dev_list) { - if (cam->pdev == pdev) - goto done; - } - cam = NULL; - done: - mutex_unlock(&cafe_dev_list_lock); - return cam; -} - - -/* ------------------------------------------------------------------------ */ -/* - * Device register I/O - */ -static inline void cafe_reg_write(struct cafe_camera *cam, unsigned int reg, - unsigned int val) -{ - iowrite32(val, cam->regs + reg); -} - -static inline unsigned int cafe_reg_read(struct cafe_camera *cam, - unsigned int reg) -{ - return ioread32(cam->regs + reg); -} - - -static inline void cafe_reg_write_mask(struct cafe_camera *cam, unsigned int reg, - unsigned int val, unsigned int mask) -{ - unsigned int v = cafe_reg_read(cam, reg); - - v = (v & ~mask) | (val & mask); - cafe_reg_write(cam, reg, v); -} - -static inline void cafe_reg_clear_bit(struct cafe_camera *cam, - unsigned int reg, unsigned int val) -{ - cafe_reg_write_mask(cam, reg, 0, val); -} - -static inline void cafe_reg_set_bit(struct cafe_camera *cam, - unsigned int reg, unsigned int val) -{ - cafe_reg_write_mask(cam, reg, val, val); -} - - - -/* -------------------------------------------------------------------- */ -/* - * The I2C/SMBUS interface to the camera itself starts here. The - * controller handles SMBUS itself, presenting a relatively simple register - * interface; all we have to do is to tell it where to route the data. - */ -#define CAFE_SMBUS_TIMEOUT (HZ) /* generous */ - -static int cafe_smbus_write_done(struct cafe_camera *cam) -{ - unsigned long flags; - int c1; - - /* - * We must delay after the interrupt, or the controller gets confused - * and never does give us good status. Fortunately, we don't do this - * often. - */ - udelay(20); - spin_lock_irqsave(&cam->dev_lock, flags); - c1 = cafe_reg_read(cam, REG_TWSIC1); - spin_unlock_irqrestore(&cam->dev_lock, flags); - return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT; -} - -static int cafe_smbus_write_data(struct cafe_camera *cam, - u16 addr, u8 command, u8 value) -{ - unsigned int rval; - unsigned long flags; - - spin_lock_irqsave(&cam->dev_lock, flags); - rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); - rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ - /* - * Marvell sez set clkdiv to all 1's for now. - */ - rval |= TWSIC0_CLKDIV; - cafe_reg_write(cam, REG_TWSIC0, rval); - (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ - rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); - cafe_reg_write(cam, REG_TWSIC1, rval); - spin_unlock_irqrestore(&cam->dev_lock, flags); - msleep(2); /* Required or things flake */ - - wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), - CAFE_SMBUS_TIMEOUT); - spin_lock_irqsave(&cam->dev_lock, flags); - rval = cafe_reg_read(cam, REG_TWSIC1); - spin_unlock_irqrestore(&cam->dev_lock, flags); - - if (rval & TWSIC1_WSTAT) { - cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr, - command, value); - return -EIO; - } - if (rval & TWSIC1_ERROR) { - cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr, - command, value); - return -EIO; - } - return 0; -} - - - -static int cafe_smbus_read_done(struct cafe_camera *cam) -{ - unsigned long flags; - int c1; - - /* - * We must delay after the interrupt, or the controller gets confused - * and never does give us good status. Fortunately, we don't do this - * often. - */ - udelay(20); - spin_lock_irqsave(&cam->dev_lock, flags); - c1 = cafe_reg_read(cam, REG_TWSIC1); - spin_unlock_irqrestore(&cam->dev_lock, flags); - return c1 & (TWSIC1_RVALID|TWSIC1_ERROR); -} - - - -static int cafe_smbus_read_data(struct cafe_camera *cam, - u16 addr, u8 command, u8 *value) -{ - unsigned int rval; - unsigned long flags; - - spin_lock_irqsave(&cam->dev_lock, flags); - rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); - rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ - /* - * Marvel sez set clkdiv to all 1's for now. - */ - rval |= TWSIC0_CLKDIV; - cafe_reg_write(cam, REG_TWSIC0, rval); - (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ - rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); - cafe_reg_write(cam, REG_TWSIC1, rval); - spin_unlock_irqrestore(&cam->dev_lock, flags); - - wait_event_timeout(cam->smbus_wait, - cafe_smbus_read_done(cam), CAFE_SMBUS_TIMEOUT); - spin_lock_irqsave(&cam->dev_lock, flags); - rval = cafe_reg_read(cam, REG_TWSIC1); - spin_unlock_irqrestore(&cam->dev_lock, flags); - - if (rval & TWSIC1_ERROR) { - cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command); - return -EIO; - } - if (! (rval & TWSIC1_RVALID)) { - cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr, - command); - return -EIO; - } - *value = rval & 0xff; - return 0; -} - -/* - * Perform a transfer over SMBUS. This thing is called under - * the i2c bus lock, so we shouldn't race with ourselves... - */ -static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - unsigned short flags, char rw, u8 command, - int size, union i2c_smbus_data *data) -{ - struct cafe_camera *cam = i2c_get_adapdata(adapter); - int ret = -EINVAL; - - /* - * Refuse to talk to anything but OV cam chips. We should - * never even see an attempt to do so, but one never knows. - */ - if (cam->sensor && addr != cam->sensor->addr) { - cam_err(cam, "funky smbus addr %d\n", addr); - return -EINVAL; - } - /* - * This interface would appear to only do byte data ops. OK - * it can do word too, but the cam chip has no use for that. - */ - if (size != I2C_SMBUS_BYTE_DATA) { - cam_err(cam, "funky xfer size %d\n", size); - return -EINVAL; - } - - if (rw == I2C_SMBUS_WRITE) - ret = cafe_smbus_write_data(cam, addr, command, data->byte); - else if (rw == I2C_SMBUS_READ) - ret = cafe_smbus_read_data(cam, addr, command, &data->byte); - return ret; -} - - -static void cafe_smbus_enable_irq(struct cafe_camera *cam) -{ - unsigned long flags; - - spin_lock_irqsave(&cam->dev_lock, flags); - cafe_reg_set_bit(cam, REG_IRQMASK, TWSIIRQS); - spin_unlock_irqrestore(&cam->dev_lock, flags); -} - -static u32 cafe_smbus_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_READ_BYTE_DATA | - I2C_FUNC_SMBUS_WRITE_BYTE_DATA; -} - -static struct i2c_algorithm cafe_smbus_algo = { - .smbus_xfer = cafe_smbus_xfer, - .functionality = cafe_smbus_func -}; - -/* Somebody is on the bus */ -static int cafe_cam_init(struct cafe_camera *cam); -static void cafe_ctlr_stop_dma(struct cafe_camera *cam); -static void cafe_ctlr_power_down(struct cafe_camera *cam); - -static int cafe_smbus_attach(struct i2c_client *client) -{ - struct cafe_camera *cam = i2c_get_adapdata(client->adapter); - - /* - * Don't talk to chips we don't recognize. - */ - if (client->driver->id == I2C_DRIVERID_OV7670) { - cam->sensor = client; - return cafe_cam_init(cam); - } - return -EINVAL; -} - -static int cafe_smbus_detach(struct i2c_client *client) -{ - struct cafe_camera *cam = i2c_get_adapdata(client->adapter); - - if (cam->sensor == client) { - cafe_ctlr_stop_dma(cam); - cafe_ctlr_power_down(cam); - cam_err(cam, "lost the sensor!\n"); - cam->sensor = NULL; /* Bummer, no camera */ - cam->state = S_NOTREADY; - } - return 0; -} - -static int cafe_smbus_setup(struct cafe_camera *cam) -{ - struct i2c_adapter *adap = &cam->i2c_adapter; - int ret; - - cafe_smbus_enable_irq(cam); - adap->id = I2C_HW_SMBUS_CAFE; - adap->class = I2C_CLASS_CAM_DIGITAL; - adap->owner = THIS_MODULE; - adap->client_register = cafe_smbus_attach; - adap->client_unregister = cafe_smbus_detach; - adap->algo = &cafe_smbus_algo; - strcpy(adap->name, "cafe_ccic"); - i2c_set_adapdata(adap, cam); - ret = i2c_add_adapter(adap); - if (ret) - printk(KERN_ERR "Unable to register cafe i2c adapter\n"); - return ret; -} - -static void cafe_smbus_shutdown(struct cafe_camera *cam) -{ - i2c_del_adapter(&cam->i2c_adapter); -} - - -/* ------------------------------------------------------------------- */ -/* - * Deal with the controller. - */ - -/* - * Do everything we think we need to have the interface operating - * according to the desired format. - */ -static void cafe_ctlr_dma(struct cafe_camera *cam) -{ - /* - * Store the first two Y buffers (we aren't supporting - * planar formats for now, so no UV bufs). Then either - * set the third if it exists, or tell the controller - * to just use two. - */ - cafe_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]); - cafe_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]); - if (cam->nbufs > 2) { - cafe_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]); - cafe_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS); - } - else - cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); - cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */ -} - -static void cafe_ctlr_image(struct cafe_camera *cam) -{ - int imgsz; - struct v4l2_pix_format *fmt = &cam->pix_format; - - imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) | - (fmt->bytesperline & IMGSZ_H_MASK); - cafe_reg_write(cam, REG_IMGSIZE, imgsz); - cafe_reg_write(cam, REG_IMGOFFSET, 0); - /* YPITCH just drops the last two bits */ - cafe_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline, - IMGP_YP_MASK); - /* - * Tell the controller about the image format we are using. - */ - switch (cam->pix_format.pixelformat) { - case V4L2_PIX_FMT_YUYV: - cafe_reg_write_mask(cam, REG_CTRL0, - C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV, - C0_DF_MASK); - break; - - case V4L2_PIX_FMT_RGB444: - cafe_reg_write_mask(cam, REG_CTRL0, - C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB, - C0_DF_MASK); - /* Alpha value? */ - break; - - case V4L2_PIX_FMT_RGB565: - cafe_reg_write_mask(cam, REG_CTRL0, - C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR, - C0_DF_MASK); - break; - - default: - cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat); - break; - } - /* - * Make sure it knows we want to use hsync/vsync. - */ - cafe_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, - C0_SIFM_MASK); -} - - -/* - * Configure the controller for operation; caller holds the - * device mutex. - */ -static int cafe_ctlr_configure(struct cafe_camera *cam) -{ - unsigned long flags; - - spin_lock_irqsave(&cam->dev_lock, flags); - cafe_ctlr_dma(cam); - cafe_ctlr_image(cam); - cafe_set_config_needed(cam, 0); - spin_unlock_irqrestore(&cam->dev_lock, flags); - return 0; -} - -static void cafe_ctlr_irq_enable(struct cafe_camera *cam) -{ - /* - * Clear any pending interrupts, since we do not - * expect to have I/O active prior to enabling. - */ - cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); - cafe_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS); -} - -static void cafe_ctlr_irq_disable(struct cafe_camera *cam) -{ - cafe_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS); -} - -/* - * Make the controller start grabbing images. Everything must - * be set up before doing this. - */ -static void cafe_ctlr_start(struct cafe_camera *cam) -{ - /* set_bit performs a read, so no other barrier should be - needed here */ - cafe_reg_set_bit(cam, REG_CTRL0, C0_ENABLE); -} - -static void cafe_ctlr_stop(struct cafe_camera *cam) -{ - cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); -} - -static void cafe_ctlr_init(struct cafe_camera *cam) -{ - unsigned long flags; - - spin_lock_irqsave(&cam->dev_lock, flags); - /* - * Added magic to bring up the hardware on the B-Test board - */ - cafe_reg_write(cam, 0x3038, 0x8); - cafe_reg_write(cam, 0x315c, 0x80008); - /* - * Go through the dance needed to wake the device up. - * Note that these registers are global and shared - * with the NAND and SD devices. Interaction between the - * three still needs to be examined. - */ - cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */ - cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC); - cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS); - mdelay(5); /* FIXME revisit this */ - cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); - cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN); - /* - * Make sure it's not powered down. - */ - cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); - /* - * Turn off the enable bit. It sure should be off anyway, - * but it's good to be sure. - */ - cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); - /* - * Mask all interrupts. - */ - cafe_reg_write(cam, REG_IRQMASK, 0); - /* - * Clock the sensor appropriately. Controller clock should - * be 48MHz, sensor "typical" value is half that. - */ - cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK); - spin_unlock_irqrestore(&cam->dev_lock, flags); -} - - -/* - * Stop the controller, and don't return until we're really sure that no - * further DMA is going on. - */ -static void cafe_ctlr_stop_dma(struct cafe_camera *cam) -{ - unsigned long flags; - - /* - * Theory: stop the camera controller (whether it is operating - * or not). Delay briefly just in case we race with the SOF - * interrupt, then wait until no DMA is active. - */ - spin_lock_irqsave(&cam->dev_lock, flags); - cafe_ctlr_stop(cam); - spin_unlock_irqrestore(&cam->dev_lock, flags); - mdelay(1); - wait_event_timeout(cam->iowait, - !test_bit(CF_DMA_ACTIVE, &cam->flags), HZ); - if (test_bit(CF_DMA_ACTIVE, &cam->flags)) - cam_err(cam, "Timeout waiting for DMA to end\n"); - /* This would be bad news - what now? */ - spin_lock_irqsave(&cam->dev_lock, flags); - cam->state = S_IDLE; - cafe_ctlr_irq_disable(cam); - spin_unlock_irqrestore(&cam->dev_lock, flags); -} - -/* - * Power up and down. - */ -static void cafe_ctlr_power_up(struct cafe_camera *cam) -{ - unsigned long flags; - - spin_lock_irqsave(&cam->dev_lock, flags); - cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); - /* - * Put the sensor into operational mode (assumes OLPC-style - * wiring). Control 0 is reset - set to 1 to operate. - * Control 1 is power down, set to 0 to operate. - */ - cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ - mdelay(1); /* Marvell says 1ms will do it */ - cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); - mdelay(1); /* Enough? */ - spin_unlock_irqrestore(&cam->dev_lock, flags); -} - -static void cafe_ctlr_power_down(struct cafe_camera *cam) -{ - unsigned long flags; - - spin_lock_irqsave(&cam->dev_lock, flags); - cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); - cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); - spin_unlock_irqrestore(&cam->dev_lock, flags); -} - -/* -------------------------------------------------------------------- */ -/* - * Communications with the sensor. - */ - -static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg) -{ - struct i2c_client *sc = cam->sensor; - int ret; - - if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL) - return -EINVAL; - ret = sc->driver->command(sc, cmd, arg); - if (ret == -EPERM) /* Unsupported command */ - return 0; - return ret; -} - -static int __cafe_cam_reset(struct cafe_camera *cam) -{ - int zero = 0; - return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero); -} - -/* - * We have found the sensor on the i2c. Let's try to have a - * conversation. - */ -static int cafe_cam_init(struct cafe_camera *cam) -{ - int ret; - - mutex_lock(&cam->s_mutex); - if (cam->state != S_NOTREADY) - cam_warn(cam, "Cam init with device in funky state %d", - cam->state); - ret = __cafe_cam_reset(cam); - if (ret) - goto out; - ret = __cafe_cam_cmd(cam, VIDIOC_INT_G_CHIP_IDENT, &cam->sensor_type); - if (ret) - goto out; -// if (cam->sensor->addr != OV7xx0_SID) { - if (cam->sensor_type != V4L2_IDENT_OV7670) { - cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr); - ret = -EINVAL; - goto out; - } -/* Get/set parameters? */ - ret = 0; - cam->state = S_IDLE; - out: - mutex_unlock(&cam->s_mutex); - return ret; -} - -/* - * Configure the sensor to match the parameters we have. Caller should - * hold s_mutex - */ -static int cafe_cam_set_flip(struct cafe_camera *cam) -{ - struct v4l2_control ctrl; - - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.id = V4L2_CID_VFLIP; - ctrl.value = flip; - return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl); -} - - -static int cafe_cam_configure(struct cafe_camera *cam) -{ - struct v4l2_format fmt; - int ret, zero = 0; - - if (cam->state != S_IDLE) - return -EINVAL; - fmt.fmt.pix = cam->pix_format; - ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero); - if (ret == 0) - ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt); - /* - * OV7670 does weird things if flip is set *before* format... - */ - ret += cafe_cam_set_flip(cam); - return ret; -} - -/* -------------------------------------------------------------------- */ -/* - * DMA buffer management. These functions need s_mutex held. - */ - -/* FIXME: this is inefficient as hell, since dma_alloc_coherent just - * does a get_free_pages() call, and we waste a good chunk of an orderN - * allocation. Should try to allocate the whole set in one chunk. - */ -static int cafe_alloc_dma_bufs(struct cafe_camera *cam, int loadtime) -{ - int i; - - cafe_set_config_needed(cam, 1); - if (loadtime) - cam->dma_buf_size = dma_buf_size; - else - cam->dma_buf_size = cam->pix_format.sizeimage; - if (n_dma_bufs > 3) - n_dma_bufs = 3; - - cam->nbufs = 0; - for (i = 0; i < n_dma_bufs; i++) { - cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev, - cam->dma_buf_size, cam->dma_handles + i, - GFP_KERNEL); - if (cam->dma_bufs[i] == NULL) { - cam_warn(cam, "Failed to allocate DMA buffer\n"); - break; - } - /* For debug, remove eventually */ - memset(cam->dma_bufs[i], 0xcc, cam->dma_buf_size); - (cam->nbufs)++; - } - - switch (cam->nbufs) { - case 1: - dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, - cam->dma_bufs[0], cam->dma_handles[0]); - cam->nbufs = 0; - case 0: - cam_err(cam, "Insufficient DMA buffers, cannot operate\n"); - return -ENOMEM; - - case 2: - if (n_dma_bufs > 2) - cam_warn(cam, "Will limp along with only 2 buffers\n"); - break; - } - return 0; -} - -static void cafe_free_dma_bufs(struct cafe_camera *cam) -{ - int i; - - for (i = 0; i < cam->nbufs; i++) { - dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, - cam->dma_bufs[i], cam->dma_handles[i]); - cam->dma_bufs[i] = NULL; - } - cam->nbufs = 0; -} - - - - - -/* ----------------------------------------------------------------------- */ -/* - * Here starts the V4L2 interface code. - */ - -/* - * Read an image from the device. - */ -static ssize_t cafe_deliver_buffer(struct cafe_camera *cam, - char __user *buffer, size_t len, loff_t *pos) -{ - int bufno; - unsigned long flags; - - spin_lock_irqsave(&cam->dev_lock, flags); - if (cam->next_buf < 0) { - cam_err(cam, "deliver_buffer: No next buffer\n"); - spin_unlock_irqrestore(&cam->dev_lock, flags); - return -EIO; - } - bufno = cam->next_buf; - clear_bit(bufno, &cam->flags); - if (++(cam->next_buf) >= cam->nbufs) - cam->next_buf = 0; - if (! test_bit(cam->next_buf, &cam->flags)) - cam->next_buf = -1; - cam->specframes = 0; - spin_unlock_irqrestore(&cam->dev_lock, flags); - - if (len > cam->pix_format.sizeimage) - len = cam->pix_format.sizeimage; - if (copy_to_user(buffer, cam->dma_bufs[bufno], len)) - return -EFAULT; - (*pos) += len; - return len; -} - -/* - * Get everything ready, and start grabbing frames. - */ -static int cafe_read_setup(struct cafe_camera *cam, enum cafe_state state) -{ - int ret; - unsigned long flags; - - /* - * Configuration. If we still don't have DMA buffers, - * make one last, desperate attempt. - */ - if (cam->nbufs == 0) - if (cafe_alloc_dma_bufs(cam, 0)) - return -ENOMEM; - - if (cafe_needs_config(cam)) { - cafe_cam_configure(cam); - ret = cafe_ctlr_configure(cam); - if (ret) - return ret; - } - - /* - * Turn it loose. - */ - spin_lock_irqsave(&cam->dev_lock, flags); - cafe_reset_buffers(cam); - cafe_ctlr_irq_enable(cam); - cam->state = state; - cafe_ctlr_start(cam); - spin_unlock_irqrestore(&cam->dev_lock, flags); - return 0; -} - - -static ssize_t cafe_v4l_read(struct file *filp, - char __user *buffer, size_t len, loff_t *pos) -{ - struct cafe_camera *cam = filp->private_data; - int ret; - - /* - * Perhaps we're in speculative read mode and already - * have data? - */ - mutex_lock(&cam->s_mutex); - if (cam->state == S_SPECREAD) { - if (cam->next_buf >= 0) { - ret = cafe_deliver_buffer(cam, buffer, len, pos); - if (ret != 0) - goto out_unlock; - } - } else if (cam->state == S_FLAKED || cam->state == S_NOTREADY) { - ret = -EIO; - goto out_unlock; - } else if (cam->state != S_IDLE) { - ret = -EBUSY; - goto out_unlock; - } - - /* - * v4l2: multiple processes can open the device, but only - * one gets to grab data from it. - */ - if (cam->owner && cam->owner != filp) { - ret = -EBUSY; - goto out_unlock; - } - cam->owner = filp; - - /* - * Do setup if need be. - */ - if (cam->state != S_SPECREAD) { - ret = cafe_read_setup(cam, S_SINGLEREAD); - if (ret) - goto out_unlock; - } - /* - * Wait for something to happen. This should probably - * be interruptible (FIXME). - */ - wait_event_timeout(cam->iowait, cam->next_buf >= 0, HZ); - if (cam->next_buf < 0) { - cam_err(cam, "read() operation timed out\n"); - cafe_ctlr_stop_dma(cam); - ret = -EIO; - goto out_unlock; - } - /* - * Give them their data and we should be done. - */ - ret = cafe_deliver_buffer(cam, buffer, len, pos); - - out_unlock: - mutex_unlock(&cam->s_mutex); - return ret; -} - - - - - - - - -/* - * Streaming I/O support. - */ - - - -static int cafe_vidioc_streamon(struct file *filp, void *priv, - enum v4l2_buf_type type) -{ - struct cafe_camera *cam = filp->private_data; - int ret = -EINVAL; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out; - mutex_lock(&cam->s_mutex); - if (cam->state != S_IDLE || cam->n_sbufs == 0) - goto out_unlock; - - cam->sequence = 0; - ret = cafe_read_setup(cam, S_STREAMING); - - out_unlock: - mutex_unlock(&cam->s_mutex); - out: - return ret; -} - - -static int cafe_vidioc_streamoff(struct file *filp, void *priv, - enum v4l2_buf_type type) -{ - struct cafe_camera *cam = filp->private_data; - int ret = -EINVAL; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out; - mutex_lock(&cam->s_mutex); - if (cam->state != S_STREAMING) - goto out_unlock; - - cafe_ctlr_stop_dma(cam); - ret = 0; - - out_unlock: - mutex_unlock(&cam->s_mutex); - out: - return ret; -} - - - -static int cafe_setup_siobuf(struct cafe_camera *cam, int index) -{ - struct cafe_sio_buffer *buf = cam->sb_bufs + index; - - INIT_LIST_HEAD(&buf->list); - buf->v4lbuf.length = PAGE_ALIGN(cam->pix_format.sizeimage); - buf->buffer = vmalloc_user(buf->v4lbuf.length); - if (buf->buffer == NULL) - return -ENOMEM; - buf->mapcount = 0; - buf->cam = cam; - - buf->v4lbuf.index = index; - buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf->v4lbuf.field = V4L2_FIELD_NONE; - buf->v4lbuf.memory = V4L2_MEMORY_MMAP; - /* - * Offset: must be 32-bit even on a 64-bit system. video-buf - * just uses the length times the index, but the spec warns - * against doing just that - vma merging problems. So we - * leave a gap between each pair of buffers. - */ - buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length; - return 0; -} - -static int cafe_free_sio_buffers(struct cafe_camera *cam) -{ - int i; - - /* - * If any buffers are mapped, we cannot free them at all. - */ - for (i = 0; i < cam->n_sbufs; i++) - if (cam->sb_bufs[i].mapcount > 0) - return -EBUSY; - /* - * OK, let's do it. - */ - for (i = 0; i < cam->n_sbufs; i++) - vfree(cam->sb_bufs[i].buffer); - cam->n_sbufs = 0; - kfree(cam->sb_bufs); - cam->sb_bufs = NULL; - INIT_LIST_HEAD(&cam->sb_avail); - INIT_LIST_HEAD(&cam->sb_full); - return 0; -} - - - -static int cafe_vidioc_reqbufs(struct file *filp, void *priv, - struct v4l2_requestbuffers *req) -{ - struct cafe_camera *cam = filp->private_data; - int ret; - - /* - * Make sure it's something we can do. User pointers could be - * implemented without great pain, but that's not been done yet. - */ - if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (req->memory != V4L2_MEMORY_MMAP) - return -EINVAL; - /* - * If they ask for zero buffers, they really want us to stop streaming - * (if it's happening) and free everything. Should we check owner? - */ - mutex_lock(&cam->s_mutex); - if (req->count == 0) { - if (cam->state == S_STREAMING) - cafe_ctlr_stop_dma(cam); - ret = cafe_free_sio_buffers (cam); - goto out; - } - /* - * Device needs to be idle and working. We *could* try to do the - * right thing in S_SPECREAD by shutting things down, but it - * probably doesn't matter. - */ - if (cam->state != S_IDLE || (cam->owner && cam->owner != filp)) { - ret = -EBUSY; - goto out; - } - cam->owner = filp; - - if (req->count < min_buffers) - req->count = min_buffers; - else if (req->count > max_buffers) - req->count = max_buffers; - if (cam->n_sbufs > 0) { - ret = cafe_free_sio_buffers(cam); - if (ret) - goto out; - } - - cam->sb_bufs = kzalloc(req->count*sizeof(struct cafe_sio_buffer), - GFP_KERNEL); - if (cam->sb_bufs == NULL) { - ret = -ENOMEM; - goto out; - } - for (cam->n_sbufs = 0; cam->n_sbufs < req->count; (cam->n_sbufs++)) { - ret = cafe_setup_siobuf(cam, cam->n_sbufs); - if (ret) - break; - } - - if (cam->n_sbufs == 0) /* no luck at all - ret already set */ - kfree(cam->sb_bufs); - else - ret = 0; - req->count = cam->n_sbufs; /* In case of partial success */ - - out: - mutex_unlock(&cam->s_mutex); - return ret; -} - - -static int cafe_vidioc_querybuf(struct file *filp, void *priv, - struct v4l2_buffer *buf) -{ - struct cafe_camera *cam = filp->private_data; - int ret = -EINVAL; - - mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out; - if (buf->index < 0 || buf->index >= cam->n_sbufs) - goto out; - *buf = cam->sb_bufs[buf->index].v4lbuf; - ret = 0; - out: - mutex_unlock(&cam->s_mutex); - return ret; -} - -static int cafe_vidioc_qbuf(struct file *filp, void *priv, - struct v4l2_buffer *buf) -{ - struct cafe_camera *cam = filp->private_data; - struct cafe_sio_buffer *sbuf; - int ret = -EINVAL; - unsigned long flags; - - mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out; - if (buf->index < 0 || buf->index >= cam->n_sbufs) - goto out; - sbuf = cam->sb_bufs + buf->index; - if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) { - ret = 0; /* Already queued?? */ - goto out; - } - if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_DONE) { - /* Spec doesn't say anything, seems appropriate tho */ - ret = -EBUSY; - goto out; - } - sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED; - spin_lock_irqsave(&cam->dev_lock, flags); - list_add(&sbuf->list, &cam->sb_avail); - spin_unlock_irqrestore(&cam->dev_lock, flags); - ret = 0; - out: - mutex_unlock(&cam->s_mutex); - return ret; -} - -static int cafe_vidioc_dqbuf(struct file *filp, void *priv, - struct v4l2_buffer *buf) -{ - struct cafe_camera *cam = filp->private_data; - struct cafe_sio_buffer *sbuf; - int ret = -EINVAL; - unsigned long flags; - - mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out_unlock; - if (cam->state != S_STREAMING) - goto out_unlock; - if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - goto out_unlock; - } - - while (list_empty(&cam->sb_full) && cam->state == S_STREAMING) { - mutex_unlock(&cam->s_mutex); - if (wait_event_interruptible(cam->iowait, - !list_empty(&cam->sb_full))) { - ret = -ERESTARTSYS; - goto out; - } - mutex_lock(&cam->s_mutex); - } - - if (cam->state != S_STREAMING) - ret = -EINTR; - else { - spin_lock_irqsave(&cam->dev_lock, flags); - /* Should probably recheck !list_empty() here */ - sbuf = list_entry(cam->sb_full.next, - struct cafe_sio_buffer, list); - list_del_init(&sbuf->list); - spin_unlock_irqrestore(&cam->dev_lock, flags); - sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE; - *buf = sbuf->v4lbuf; - ret = 0; - } - - out_unlock: - mutex_unlock(&cam->s_mutex); - out: - return ret; -} - - - -static void cafe_v4l_vm_open(struct vm_area_struct *vma) -{ - struct cafe_sio_buffer *sbuf = vma->vm_private_data; - /* - * Locking: done under mmap_sem, so we don't need to - * go back to the camera lock here. - */ - sbuf->mapcount++; -} - - -static void cafe_v4l_vm_close(struct vm_area_struct *vma) -{ - struct cafe_sio_buffer *sbuf = vma->vm_private_data; - - mutex_lock(&sbuf->cam->s_mutex); - sbuf->mapcount--; - /* Docs say we should stop I/O too... */ - if (sbuf->mapcount == 0) - sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED; - mutex_unlock(&sbuf->cam->s_mutex); -} - -static struct vm_operations_struct cafe_v4l_vm_ops = { - .open = cafe_v4l_vm_open, - .close = cafe_v4l_vm_close -}; - - -static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct cafe_camera *cam = filp->private_data; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - int ret = -EINVAL; - int i; - struct cafe_sio_buffer *sbuf = NULL; - - if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED)) - return -EINVAL; - /* - * Find the buffer they are looking for. - */ - mutex_lock(&cam->s_mutex); - for (i = 0; i < cam->n_sbufs; i++) - if (cam->sb_bufs[i].v4lbuf.m.offset == offset) { - sbuf = cam->sb_bufs + i; - break; - } - if (sbuf == NULL) - goto out; - - ret = remap_vmalloc_range(vma, sbuf->buffer, 0); - if (ret) - goto out; - vma->vm_flags |= VM_DONTEXPAND; - vma->vm_private_data = sbuf; - vma->vm_ops = &cafe_v4l_vm_ops; - sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED; - cafe_v4l_vm_open(vma); - ret = 0; - out: - mutex_unlock(&cam->s_mutex); - return ret; -} - - - -static int cafe_v4l_open(struct inode *inode, struct file *filp) -{ - struct cafe_camera *cam; - - cam = cafe_find_dev(iminor(inode)); - if (cam == NULL) - return -ENODEV; - filp->private_data = cam; - - mutex_lock(&cam->s_mutex); - if (cam->users == 0) { - cafe_ctlr_power_up(cam); - __cafe_cam_reset(cam); - cafe_set_config_needed(cam, 1); - /* FIXME make sure this is complete */ - } - (cam->users)++; - mutex_unlock(&cam->s_mutex); - return 0; -} - - -static int cafe_v4l_release(struct inode *inode, struct file *filp) -{ - struct cafe_camera *cam = filp->private_data; - - mutex_lock(&cam->s_mutex); - (cam->users)--; - if (filp == cam->owner) { - cafe_ctlr_stop_dma(cam); - cafe_free_sio_buffers(cam); - cam->owner = NULL; - } - if (cam->users == 0) { - cafe_ctlr_power_down(cam); - if (! alloc_bufs_at_load) - cafe_free_dma_bufs(cam); - } - mutex_unlock(&cam->s_mutex); - return 0; -} - - - -static unsigned int cafe_v4l_poll(struct file *filp, - struct poll_table_struct *pt) -{ - struct cafe_camera *cam = filp->private_data; - - poll_wait(filp, &cam->iowait, pt); - if (cam->next_buf >= 0) - return POLLIN | POLLRDNORM; - return 0; -} - - - -static int cafe_vidioc_queryctrl(struct file *filp, void *priv, - struct v4l2_queryctrl *qc) -{ - struct cafe_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc); - mutex_unlock(&cam->s_mutex); - return ret; -} - - -static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, - struct v4l2_control *ctrl) -{ - struct cafe_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl); - mutex_unlock(&cam->s_mutex); - return ret; -} - - -static int cafe_vidioc_s_ctrl(struct file *filp, void *priv, - struct v4l2_control *ctrl) -{ - struct cafe_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl); - mutex_unlock(&cam->s_mutex); - return ret; -} - - - - - -static int cafe_vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - strcpy(cap->driver, "cafe_ccic"); - strcpy(cap->card, "cafe_ccic"); - cap->version = CAFE_VERSION; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - return 0; -} - - -/* - * The default format we use until somebody says otherwise. - */ -static struct v4l2_pix_format cafe_def_pix_format = { - .width = VGA_WIDTH, - .height = VGA_HEIGHT, - .pixelformat = V4L2_PIX_FMT_YUYV, - .field = V4L2_FIELD_NONE, - .bytesperline = VGA_WIDTH*2, - .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, -}; - -static int cafe_vidioc_enum_fmt_cap(struct file *filp, - void *priv, struct v4l2_fmtdesc *fmt) -{ - struct cafe_camera *cam = priv; - int ret; - - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt); - mutex_unlock(&cam->s_mutex); - return ret; -} - - -static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv, - struct v4l2_format *fmt) -{ - struct cafe_camera *cam = priv; - int ret; - - mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt); - mutex_unlock(&cam->s_mutex); - return ret; -} - -static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv, - struct v4l2_format *fmt) -{ - struct cafe_camera *cam = priv; - int ret; - - /* - * Can't do anything if the device is not idle - * Also can't if there are streaming buffers in place. - */ - if (cam->state != S_IDLE || cam->n_sbufs > 0) - return -EBUSY; - /* - * See if the formatting works in principle. - */ - ret = cafe_vidioc_try_fmt_cap(filp, priv, fmt); - if (ret) - return ret; - /* - * Now we start to change things for real, so let's do it - * under lock. - */ - mutex_lock(&cam->s_mutex); - cam->pix_format = fmt->fmt.pix; - /* - * Make sure we have appropriate DMA buffers. - */ - ret = -ENOMEM; - if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage) - cafe_free_dma_bufs(cam); - if (cam->nbufs == 0) { - if (cafe_alloc_dma_bufs(cam, 0)) - goto out; - } - /* - * It looks like this might work, so let's program the sensor. - */ - ret = cafe_cam_configure(cam); - if (! ret) - ret = cafe_ctlr_configure(cam); - out: - mutex_unlock(&cam->s_mutex); - return ret; -} - -/* - * Return our stored notion of how the camera is/should be configured. - * The V4l2 spec wants us to be smarter, and actually get this from - * the camera (and not mess with it at open time). Someday. - */ -static int cafe_vidioc_g_fmt_cap(struct file *filp, void *priv, - struct v4l2_format *f) -{ - struct cafe_camera *cam = priv; - - f->fmt.pix = cam->pix_format; - return 0; -} - -/* - * We only have one input - the sensor - so minimize the nonsense here. - */ -static int cafe_vidioc_enum_input(struct file *filp, void *priv, - struct v4l2_input *input) -{ - if (input->index != 0) - return -EINVAL; - - input->type = V4L2_INPUT_TYPE_CAMERA; - input->std = V4L2_STD_ALL; /* Not sure what should go here */ - strcpy(input->name, "Camera"); - return 0; -} - -static int cafe_vidioc_g_input(struct file *filp, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i) -{ - if (i != 0) - return -EINVAL; - return 0; -} - -/* from vivi.c */ -static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a) -{ - return 0; -} - -/* - * G/S_PARM. Most of this is done by the sensor, but we are - * the level which controls the number of read buffers. - */ -static int cafe_vidioc_g_parm(struct file *filp, void *priv, - struct v4l2_streamparm *parms) -{ - struct cafe_camera *cam = priv; - int ret; - - mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms); - mutex_unlock(&cam->s_mutex); - parms->parm.capture.readbuffers = n_dma_bufs; - return ret; -} - -static int cafe_vidioc_s_parm(struct file *filp, void *priv, - struct v4l2_streamparm *parms) -{ - struct cafe_camera *cam = priv; - int ret; - - mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms); - mutex_unlock(&cam->s_mutex); - parms->parm.capture.readbuffers = n_dma_bufs; - return ret; -} - - -static void cafe_v4l_dev_release(struct video_device *vd) -{ - struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); - - kfree(cam); -} - - -/* - * This template device holds all of those v4l2 methods; we - * clone it for specific real devices. - */ - -static struct file_operations cafe_v4l_fops = { - .owner = THIS_MODULE, - .open = cafe_v4l_open, - .release = cafe_v4l_release, - .read = cafe_v4l_read, - .poll = cafe_v4l_poll, - .mmap = cafe_v4l_mmap, - .ioctl = video_ioctl2, - .llseek = no_llseek, -}; - -static struct video_device cafe_v4l_template = { - .name = "cafe", - .type = VFL_TYPE_GRABBER, - .type2 = VID_TYPE_CAPTURE, - .minor = -1, /* Get one dynamically */ - .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ - - .fops = &cafe_v4l_fops, - .release = cafe_v4l_dev_release, - - .vidioc_querycap = cafe_vidioc_querycap, - .vidioc_enum_fmt_cap = cafe_vidioc_enum_fmt_cap, - .vidioc_try_fmt_cap = cafe_vidioc_try_fmt_cap, - .vidioc_s_fmt_cap = cafe_vidioc_s_fmt_cap, - .vidioc_g_fmt_cap = cafe_vidioc_g_fmt_cap, - .vidioc_enum_input = cafe_vidioc_enum_input, - .vidioc_g_input = cafe_vidioc_g_input, - .vidioc_s_input = cafe_vidioc_s_input, - .vidioc_s_std = cafe_vidioc_s_std, - .vidioc_reqbufs = cafe_vidioc_reqbufs, - .vidioc_querybuf = cafe_vidioc_querybuf, - .vidioc_qbuf = cafe_vidioc_qbuf, - .vidioc_dqbuf = cafe_vidioc_dqbuf, - .vidioc_streamon = cafe_vidioc_streamon, - .vidioc_streamoff = cafe_vidioc_streamoff, - .vidioc_queryctrl = cafe_vidioc_queryctrl, - .vidioc_g_ctrl = cafe_vidioc_g_ctrl, - .vidioc_s_ctrl = cafe_vidioc_s_ctrl, - .vidioc_g_parm = cafe_vidioc_g_parm, - .vidioc_s_parm = cafe_vidioc_s_parm, -}; - - - - - - - -/* ---------------------------------------------------------------------- */ -/* - * Interrupt handler stuff - */ - - - -static void cafe_frame_tasklet(unsigned long data) -{ - struct cafe_camera *cam = (struct cafe_camera *) data; - int i; - unsigned long flags; - struct cafe_sio_buffer *sbuf; - - spin_lock_irqsave(&cam->dev_lock, flags); - for (i = 0; i < cam->nbufs; i++) { - int bufno = cam->next_buf; - if (bufno < 0) { /* "will never happen" */ - cam_err(cam, "No valid bufs in tasklet!\n"); - break; - } - if (++(cam->next_buf) >= cam->nbufs) - cam->next_buf = 0; - if (! test_bit(bufno, &cam->flags)) - continue; - if (list_empty(&cam->sb_avail)) - break; /* Leave it valid, hope for better later */ - clear_bit(bufno, &cam->flags); - /* - * We could perhaps drop the spinlock during this - * big copy. Something to consider. - */ - sbuf = list_entry(cam->sb_avail.next, - struct cafe_sio_buffer, list); - memcpy(sbuf->buffer, cam->dma_bufs[bufno], - cam->pix_format.sizeimage); - sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage; - sbuf->v4lbuf.sequence = cam->buf_seq[bufno]; - sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; - sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; - list_move_tail(&sbuf->list, &cam->sb_full); - } - if (! list_empty(&cam->sb_full)) - wake_up(&cam->iowait); - spin_unlock_irqrestore(&cam->dev_lock, flags); -} - - - -static void cafe_frame_complete(struct cafe_camera *cam, int frame) -{ - /* - * Basic frame housekeeping. - */ - if (test_bit(frame, &cam->flags) && printk_ratelimit()) - cam_err(cam, "Frame overrun on %d, frames lost\n", frame); - set_bit(frame, &cam->flags); - clear_bit(CF_DMA_ACTIVE, &cam->flags); - if (cam->next_buf < 0) - cam->next_buf = frame; - cam->buf_seq[frame] = ++(cam->sequence); - - switch (cam->state) { - /* - * If in single read mode, try going speculative. - */ - case S_SINGLEREAD: - cam->state = S_SPECREAD; - cam->specframes = 0; - wake_up(&cam->iowait); - break; - - /* - * If we are already doing speculative reads, and nobody is - * reading them, just stop. - */ - case S_SPECREAD: - if (++(cam->specframes) >= cam->nbufs) { - cafe_ctlr_stop(cam); - cafe_ctlr_irq_disable(cam); - cam->state = S_IDLE; - } - wake_up(&cam->iowait); - break; - /* - * For the streaming case, we defer the real work to the - * camera tasklet. - * - * FIXME: if the application is not consuming the buffers, - * we should eventually put things on hold and restart in - * vidioc_dqbuf(). - */ - case S_STREAMING: - tasklet_schedule(&cam->s_tasklet); - break; - - default: - cam_err(cam, "Frame interrupt in non-operational state\n"); - break; - } -} - - - - -static void cafe_frame_irq(struct cafe_camera *cam, unsigned int irqs) -{ - unsigned int frame; - - cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */ - /* - * Handle any frame completions. There really should - * not be more than one of these, or we have fallen - * far behind. - */ - for (frame = 0; frame < cam->nbufs; frame++) - if (irqs & (IRQ_EOF0 << frame)) - cafe_frame_complete(cam, frame); - /* - * If a frame starts, note that we have DMA active. This - * code assumes that we won't get multiple frame interrupts - * at once; may want to rethink that. - */ - if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) - set_bit(CF_DMA_ACTIVE, &cam->flags); -} - - - -static irqreturn_t cafe_irq(int irq, void *data) -{ - struct cafe_camera *cam = data; - unsigned int irqs; - - spin_lock(&cam->dev_lock); - irqs = cafe_reg_read(cam, REG_IRQSTAT); - if ((irqs & ALLIRQS) == 0) { - spin_unlock(&cam->dev_lock); - return IRQ_NONE; - } - if (irqs & FRAMEIRQS) - cafe_frame_irq(cam, irqs); - if (irqs & TWSIIRQS) { - cafe_reg_write(cam, REG_IRQSTAT, TWSIIRQS); - wake_up(&cam->smbus_wait); - } - spin_unlock(&cam->dev_lock); - return IRQ_HANDLED; -} - - -/* -------------------------------------------------------------------------- */ -#ifdef CONFIG_VIDEO_ADV_DEBUG -/* - * Debugfs stuff. - */ - -static char cafe_debug_buf[1024]; -static struct dentry *cafe_dfs_root; - -static void cafe_dfs_setup(void) -{ - cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL); - if (IS_ERR(cafe_dfs_root)) { - cafe_dfs_root = NULL; /* Never mind */ - printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n"); - } -} - -static void cafe_dfs_shutdown(void) -{ - if (cafe_dfs_root) - debugfs_remove(cafe_dfs_root); -} - -static int cafe_dfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t cafe_dfs_read_regs(struct file *file, - char __user *buf, size_t count, loff_t *ppos) -{ - struct cafe_camera *cam = file->private_data; - char *s = cafe_debug_buf; - int offset; - - for (offset = 0; offset < 0x44; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0x88; offset <= 0x90; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0xb4; offset <= 0xbc; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0x3000; offset <= 0x300c; offset += 4) - s += sprintf(s, "%04x: %08x\n", offset, - cafe_reg_read(cam, offset)); - return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, - s - cafe_debug_buf); -} - -static struct file_operations cafe_dfs_reg_ops = { - .owner = THIS_MODULE, - .read = cafe_dfs_read_regs, - .open = cafe_dfs_open -}; - -static ssize_t cafe_dfs_read_cam(struct file *file, - char __user *buf, size_t count, loff_t *ppos) -{ - struct cafe_camera *cam = file->private_data; - char *s = cafe_debug_buf; - int offset; - - if (! cam->sensor) - return -EINVAL; - for (offset = 0x0; offset < 0x8a; offset++) - { - u8 v; - - cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v); - s += sprintf(s, "%02x: %02x\n", offset, v); - } - return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, - s - cafe_debug_buf); -} - -static struct file_operations cafe_dfs_cam_ops = { - .owner = THIS_MODULE, - .read = cafe_dfs_read_cam, - .open = cafe_dfs_open -}; - - - -static void cafe_dfs_cam_setup(struct cafe_camera *cam) -{ - char fname[40]; - - if (!cafe_dfs_root) - return; - sprintf(fname, "regs-%d", cam->v4ldev.minor); - cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, - cam, &cafe_dfs_reg_ops); - sprintf(fname, "cam-%d", cam->v4ldev.minor); - cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, - cam, &cafe_dfs_cam_ops); -} - - -static void cafe_dfs_cam_shutdown(struct cafe_camera *cam) -{ - if (! IS_ERR(cam->dfs_regs)) - debugfs_remove(cam->dfs_regs); - if (! IS_ERR(cam->dfs_cam_regs)) - debugfs_remove(cam->dfs_cam_regs); -} - -#else - -#define cafe_dfs_setup() -#define cafe_dfs_shutdown() -#define cafe_dfs_cam_setup(cam) -#define cafe_dfs_cam_shutdown(cam) -#endif /* CONFIG_VIDEO_ADV_DEBUG */ - - - - -/* ------------------------------------------------------------------------*/ -/* - * PCI interface stuff. - */ - -static int cafe_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int ret; - u16 classword; - struct cafe_camera *cam; - /* - * Make sure we have a camera here - we'll get calls for - * the other cafe devices as well. - */ - pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword); - if (classword != PCI_CLASS_MULTIMEDIA_VIDEO) - return -ENODEV; - /* - * Start putting together one of our big camera structures. - */ - ret = -ENOMEM; - cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL); - if (cam == NULL) - goto out; - mutex_init(&cam->s_mutex); - mutex_lock(&cam->s_mutex); - spin_lock_init(&cam->dev_lock); - cam->state = S_NOTREADY; - cafe_set_config_needed(cam, 1); - init_waitqueue_head(&cam->smbus_wait); - init_waitqueue_head(&cam->iowait); - cam->pdev = pdev; - cam->pix_format = cafe_def_pix_format; - INIT_LIST_HEAD(&cam->dev_list); - INIT_LIST_HEAD(&cam->sb_avail); - INIT_LIST_HEAD(&cam->sb_full); - tasklet_init(&cam->s_tasklet, cafe_frame_tasklet, (unsigned long) cam); - /* - * Get set up on the PCI bus. - */ - ret = pci_enable_device(pdev); - if (ret) - goto out_free; - pci_set_master(pdev); - - ret = -EIO; - cam->regs = pci_iomap(pdev, 0, 0); - if (! cam->regs) { - printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); - goto out_free; - } - ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); - if (ret) - goto out_iounmap; - cafe_ctlr_init(cam); - cafe_ctlr_power_up(cam); - /* - * Set up I2C/SMBUS communications - */ - mutex_unlock(&cam->s_mutex); /* attach can deadlock */ - ret = cafe_smbus_setup(cam); - if (ret) - goto out_freeirq; - /* - * Get the v4l2 setup done. - */ - mutex_lock(&cam->s_mutex); - cam->v4ldev = cafe_v4l_template; - cam->v4ldev.debug = 0; -// cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG; - ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1); - if (ret) - goto out_smbus; - /* - * If so requested, try to get our DMA buffers now. - */ - if (alloc_bufs_at_load) { - if (cafe_alloc_dma_bufs(cam, 1)) - cam_warn(cam, "Unable to alloc DMA buffers at load" - " will try again later."); - } - - cafe_dfs_cam_setup(cam); - mutex_unlock(&cam->s_mutex); - cafe_add_dev(cam); - return 0; - - out_smbus: - cafe_smbus_shutdown(cam); - out_freeirq: - cafe_ctlr_power_down(cam); - free_irq(pdev->irq, cam); - out_iounmap: - pci_iounmap(pdev, cam->regs); - out_free: - kfree(cam); - out: - return ret; -} - - -/* - * Shut down an initialized device - */ -static void cafe_shutdown(struct cafe_camera *cam) -{ -/* FIXME: Make sure we take care of everything here */ - cafe_dfs_cam_shutdown(cam); - if (cam->n_sbufs > 0) - /* What if they are still mapped? Shouldn't be, but... */ - cafe_free_sio_buffers(cam); - cafe_remove_dev(cam); - cafe_ctlr_stop_dma(cam); - cafe_ctlr_power_down(cam); - cafe_smbus_shutdown(cam); - cafe_free_dma_bufs(cam); - free_irq(cam->pdev->irq, cam); - pci_iounmap(cam->pdev, cam->regs); - video_unregister_device(&cam->v4ldev); - /* kfree(cam); done in v4l_release () */ -} - - -static void cafe_pci_remove(struct pci_dev *pdev) -{ - struct cafe_camera *cam = cafe_find_by_pdev(pdev); - - if (cam == NULL) { - cam_warn(cam, "pci_remove on unknown pdev %p\n", pdev); - return; - } - mutex_lock(&cam->s_mutex); - if (cam->users > 0) - cam_warn(cam, "Removing a device with users!\n"); - cafe_shutdown(cam); -/* No unlock - it no longer exists */ -} - - - - -static struct pci_device_id cafe_ids[] = { - { PCI_DEVICE(0x1148, 0x4340) }, /* Temporary ID on devel board */ - { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */ - { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, cafe_ids); - -static struct pci_driver cafe_pci_driver = { - .name = "cafe1000-ccic", - .id_table = cafe_ids, - .probe = cafe_pci_probe, - .remove = cafe_pci_remove, -}; - - - - -static int __init cafe_init(void) -{ - int ret; - - printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", - CAFE_VERSION); - cafe_dfs_setup(); - ret = pci_register_driver(&cafe_pci_driver); - if (ret) { - printk(KERN_ERR "Unable to register cafe_ccic driver\n"); - goto out; - } - request_module("ov7670"); /* FIXME want something more general */ - ret = 0; - - out: - return ret; -} - - -static void __exit cafe_exit(void) -{ - pci_unregister_driver(&cafe_pci_driver); - cafe_dfs_shutdown(); -} - -module_init(cafe_init); -module_exit(cafe_exit); diff --git a/trunk/drivers/media/video/cx88/Kconfig b/trunk/drivers/media/video/cx88/Kconfig index b2a66ba625f9..0f9d96963618 100644 --- a/trunk/drivers/media/video/cx88/Kconfig +++ b/trunk/drivers/media/video/cx88/Kconfig @@ -53,7 +53,6 @@ config VIDEO_CX88_DVB select DVB_OR51132 if !DVB_FE_CUSTOMISE select DVB_CX22702 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE diff --git a/trunk/drivers/media/video/cx88/cx88-blackbird.c b/trunk/drivers/media/video/cx88/cx88-blackbird.c index 0cf0360588e6..46738321adaf 100644 --- a/trunk/drivers/media/video/cx88/cx88-blackbird.c +++ b/trunk/drivers/media/video/cx88/cx88-blackbird.c @@ -50,6 +50,7 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); #define dprintk(level,fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) +static LIST_HEAD(cx8802_devlist); /* ------------------------------------------------------------------ */ @@ -881,7 +882,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE); - cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); + cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); blackbird_initialize_codec(dev); cx88_set_scale(dev->core, dev->width, dev->height, @@ -913,15 +914,11 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, } default: - return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); + return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); } return 0; } -int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg); -unsigned int (*cx88_ioctl_translator)(unsigned int cmd); - static unsigned int mpeg_translate_ioctl(unsigned int cmd) { return cmd; @@ -930,49 +927,33 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd) static int mpeg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - cmd = cx88_ioctl_translator( cmd ); - return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook); + cmd = mpeg_translate_ioctl( cmd ); + return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl); } static int mpeg_open(struct inode *inode, struct file *file) { int minor = iminor(inode); - struct cx8802_dev *dev = NULL; + struct cx8802_dev *h,*dev = NULL; struct cx8802_fh *fh; - struct cx8802_driver *drv = NULL; - int err; - - dev = cx8802_get_device(inode); - - dprintk( 1, "%s\n", __FUNCTION__); + struct list_head *list; - if (dev == NULL) - return -ENODEV; - - /* Make sure we can acquire the hardware */ - drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); - if (drv) { - err = drv->request_acquire(drv); - if(err != 0) { - dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err); - return err; - } + list_for_each(list,&cx8802_devlist) { + h = list_entry(list, struct cx8802_dev, devlist); + if (h->mpeg_dev->minor == minor) + dev = h; } + if (NULL == dev) + return -ENODEV; - if (blackbird_initialize_codec(dev) < 0) { - if (drv) - drv->request_release(drv); + if (blackbird_initialize_codec(dev) < 0) return -EINVAL; - } dprintk(1,"open minor=%d\n",minor); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) { - if (drv) - drv->request_release(drv); + if (NULL == fh) return -ENOMEM; - } file->private_data = fh; fh->dev = dev; @@ -993,8 +974,6 @@ static int mpeg_open(struct inode *inode, struct file *file) static int mpeg_release(struct inode *inode, struct file *file) { struct cx8802_fh *fh = file->private_data; - struct cx8802_dev *dev = NULL; - struct cx8802_driver *drv = NULL; /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, @@ -1013,16 +992,6 @@ static int mpeg_release(struct inode *inode, struct file *file) videobuf_mmap_free(&fh->mpegq); file->private_data = NULL; kfree(fh); - - /* Make sure we release the hardware */ - dev = cx8802_get_device(inode); - if (dev == NULL) - return -ENODEV; - - drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); - if (drv) - drv->request_release(drv); - return 0; } @@ -1074,44 +1043,6 @@ static struct video_device cx8802_mpeg_template = /* ------------------------------------------------------------------ */ -/* The CX8802 MPEG API will call this when we can use the hardware */ -static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - int err = 0; - - switch (core->board) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* By default, core setup will leave the cx22702 out of reset, on the bus. - * We left the hardware on power up with the cx22702 active. - * We're being given access to re-arrange the GPIOs. - * Take the bus off the cx22702 and put the cx23416 on it. - */ - cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */ - cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */ - break; - default: - err = -ENODEV; - } - return err; -} - -/* The CX8802 MPEG API will call this when we need to release the hardware */ -static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - int err = 0; - - switch (core->board) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* Exit leaving the cx23416 on the bus */ - break; - default: - err = -ENODEV; - } - return err; -} - static void blackbird_unregister_video(struct cx8802_dev *dev) { if (dev->mpeg_dev) { @@ -1142,23 +1073,28 @@ static int blackbird_register_video(struct cx8802_dev *dev) /* ----------------------------------------------------------- */ -static int cx8802_blackbird_probe(struct cx8802_driver *drv) +static int __devinit blackbird_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) { - struct cx88_core *core = drv->core; - struct cx8802_dev *dev = core->dvbdev; + struct cx8802_dev *dev; + struct cx88_core *core; int err; - dprintk( 1, "%s\n", __FUNCTION__); - dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", - core->board, - core->name, - core->pci_bus, - core->pci_slot); + /* general setup */ + core = cx88_core_get(pci_dev); + if (NULL == core) + return -EINVAL; err = -ENODEV; if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) goto fail_core; + err = -ENOMEM; + dev = kzalloc(sizeof(*dev),GFP_KERNEL); + if (NULL == dev) + goto fail_core; + dev->pci = pci_dev; + dev->core = core; dev->width = 720; dev->height = 576; cx2341x_fill_defaults(&dev->params); @@ -1170,36 +1106,64 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) dev->height = 576; } + err = cx8802_init_common(dev); + if (0 != err) + goto fail_free; + /* blackbird stuff */ printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", core->name); host_setup(dev->core); + list_add_tail(&dev->devlist,&cx8802_devlist); blackbird_register_video(dev); /* initial device configuration: needed ? */ return 0; + fail_free: + kfree(dev); fail_core: + cx88_core_put(core,pci_dev); return err; } -static int cx8802_blackbird_remove(struct cx8802_driver *drv) +static void __devexit blackbird_remove(struct pci_dev *pci_dev) { + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + /* blackbird */ - blackbird_unregister_video(drv->core->dvbdev); + blackbird_unregister_video(dev); + list_del(&dev->devlist); - return 0; + /* common */ + cx8802_fini_common(dev); + cx88_core_put(dev->core,dev->pci); + kfree(dev); } -static struct cx8802_driver cx8802_blackbird_driver = { - .type_id = CX88_MPEG_BLACKBIRD, - .hw_access = CX8802_DRVCTL_SHARED, - .probe = cx8802_blackbird_probe, - .remove = cx8802_blackbird_remove, - .advise_acquire = cx8802_blackbird_advise_acquire, - .advise_release = cx8802_blackbird_advise_release, +static struct pci_device_id cx8802_pci_tbl[] = { + { + .vendor = 0x14f1, + .device = 0x8802, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + },{ + /* --- end of list --- */ + } +}; +MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); + +static struct pci_driver blackbird_pci_driver = { + .name = "cx88-blackbird", + .id_table = cx8802_pci_tbl, + .probe = blackbird_probe, + .remove = __devexit_p(blackbird_remove), +#ifdef CONFIG_PM + .suspend = cx8802_suspend_common, + .resume = cx8802_resume_common, +#endif }; static int blackbird_init(void) @@ -1212,22 +1176,17 @@ static int blackbird_init(void) printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif - cx88_ioctl_hook = mpeg_do_ioctl; - cx88_ioctl_translator = mpeg_translate_ioctl; - return cx8802_register_driver(&cx8802_blackbird_driver); + return pci_register_driver(&blackbird_pci_driver); } static void blackbird_fini(void) { - cx8802_unregister_driver(&cx8802_blackbird_driver); + pci_unregister_driver(&blackbird_pci_driver); } module_init(blackbird_init); module_exit(blackbird_fini); -EXPORT_SYMBOL(cx88_ioctl_hook); -EXPORT_SYMBOL(cx88_ioctl_translator); - /* ----------------------------------------------------------- */ /* * Local variables: diff --git a/trunk/drivers/media/video/cx88/cx88-cards.c b/trunk/drivers/media/video/cx88/cx88-cards.c index c791708b1336..f764a57c56be 100644 --- a/trunk/drivers/media/video/cx88/cx88-cards.c +++ b/trunk/drivers/media/video/cx88/cx88-cards.c @@ -281,22 +281,18 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x0000bde2, - .extadc = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x0000bde6, - .extadc = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000bde6, - .extadc = 1, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x0000bd62, - .extadc = 1, }, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -357,7 +353,6 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? - .extadc = 1, }}, .radio = { .type = CX88_RADIO, @@ -528,7 +523,6 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .extadc = 1, }}, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -652,22 +646,18 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x00009d80, - .extadc = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x00009d76, - .extadc = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x00009d76, - .extadc = 1, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x00009d00, - .extadc = 1, }, .mpeg = CX88_MPEG_BLACKBIRD, }, @@ -796,29 +786,25 @@ struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .mpeg = CX88_MPEG_BLACKBIRD, .input = {{ .type = CX88_VMUX_COMPOSITE1, .vmux = 0, .gpio0 = 0x0000cd73, - .extadc = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 1, .gpio0 = 0x0000cd73, - .extadc = 1, },{ .type = CX88_VMUX_TELEVISION, .vmux = 3, .gpio0 = 0x0000cdb3, - .extadc = 1, }}, .radio = { .type = CX88_RADIO, .vmux = 2, .gpio0 = 0x0000cdf3, - .extadc = 1, }, - .mpeg = CX88_MPEG_BLACKBIRD, }, [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { /* Alexander Wold */ @@ -1064,6 +1050,7 @@ struct cx88_board cx88_boards[] = { .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { + /* FIXME: Audio not working for s-video / composite inputs. */ .name = "KWorld HardwareMpegTV XPert", .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -1078,12 +1065,10 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x3de6, - .extadc = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x3de6, - .extadc = 1, }}, .radio = { .type = CX88_RADIO, @@ -1267,35 +1252,35 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0x070b, }}, }, - [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { - .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x003fffff, - .gpio1 = 0x00e00000, - .gpio2 = 0x003fffff, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x003fffff, - .gpio1 = 0x00e00000, - .gpio2 = 0x003fffff, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x003fffff, - .gpio1 = 0x00e00000, - .gpio2 = 0x003fffff, - .gpio3 = 0x02000000, - }}, - }, + [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { + .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x003fffff, + .gpio1 = 0x00e00000, + .gpio2 = 0x003fffff, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x003fffff, + .gpio1 = 0x00e00000, + .gpio2 = 0x003fffff, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x003fffff, + .gpio1 = 0x00e00000, + .gpio2 = 0x003fffff, + .gpio3 = 0x02000000, + }}, + }, [CX88_BOARD_HAUPPAUGE_HVR1300] = { .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, @@ -1308,20 +1293,17 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0xe780, - .extadc = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0xe780, - .extadc = 1, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0xe780, - .extadc = 1, }}, /* fixme: Add radio support */ - .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, + .mpeg = CX88_MPEG_DVB, }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1531,10 +1513,6 @@ struct cx88_subid cx88_subids[] = { },{ .subvendor = 0x17de, .subdevice = 0x0840, - .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, - },{ - .subvendor = 0x1421, - .subdevice = 0x0305, .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, },{ .subvendor = 0x18ac, diff --git a/trunk/drivers/media/video/cx88/cx88-core.c b/trunk/drivers/media/video/cx88/cx88-core.c index 453af5e943ff..4b655f2ef278 100644 --- a/trunk/drivers/media/video/cx88/cx88-core.c +++ b/trunk/drivers/media/video/cx88/cx88-core.c @@ -1153,7 +1153,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) mutex_lock(&devlist); cx88_ir_fini(core); if (0 == core->i2c_rc) - i2c_del_adapter(&core->i2c_adap); + i2c_bit_del_bus(&core->i2c_adap); list_del(&core->devlist); iounmap(core->lmmio); cx88_devcount--; diff --git a/trunk/drivers/media/video/cx88/cx88-dvb.c b/trunk/drivers/media/video/cx88/cx88-dvb.c index 8b203354fccd..0ef13e7efa2e 100644 --- a/trunk/drivers/media/video/cx88/cx88-dvb.c +++ b/trunk/drivers/media/video/cx88/cx88-dvb.c @@ -42,7 +42,7 @@ #include "cx22702.h" #include "or51132.h" #include "lgdt330x.h" -#include "lgh06xf.h" +#include "lg_h06xf.h" #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" @@ -57,7 +57,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); #define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) + printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg) /* ------------------------------------------------------------------ */ @@ -74,8 +74,8 @@ static int dvb_buf_setup(struct videobuf_queue *q, return 0; } -static int dvb_buf_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, enum v4l2_field field) +static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field) { struct cx8802_dev *dev = q->priv_data; return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); @@ -87,8 +87,7 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) cx8802_buf_queue(dev, (struct cx88_buffer*)vb); } -static void dvb_buf_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { cx88_free_buffer(q, (struct cx88_buffer*)vb); } @@ -101,26 +100,6 @@ static struct videobuf_queue_ops dvb_qops = { }; /* ------------------------------------------------------------------ */ - -static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) -{ - struct cx8802_dev *dev= fe->dvb->priv; - struct cx8802_driver *drv = NULL; - int ret = 0; - - drv = cx8802_get_driver(dev, CX88_MPEG_DVB); - if (drv) { - if (acquire) - ret = drv->request_acquire(drv); - else - ret = drv->request_release(drv); - } - - return ret; -} - -/* ------------------------------------------------------------------ */ - static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) { static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; @@ -289,6 +268,35 @@ static struct mt352_config dntv_live_dvbt_pro_config = { }; #endif +static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 pllbuf[4]; + struct cx8802_dev *dev= fe->dvb->priv; + struct i2c_msg msg = + { .addr = dev->core->pll_addr, .flags = 0, + .buf = pllbuf, .len = 4 }; + int err; + + dvb_pll_configure(dev->core->pll_desc, pllbuf, + params->frequency, + params->u.ofdm.bandwidth); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "cx88-dvb: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, pllbuf[0], pllbuf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} + static struct zl10353_config dvico_fusionhdtv_hybrid = { .demod_address = 0x0f, .no_tuner = 1, @@ -303,12 +311,28 @@ static struct cx22702_config connexant_refboard_config = { .output_mode = CX22702_SERIAL_OUTPUT, }; -static struct cx22702_config hauppauge_hvr_config = { +static struct cx22702_config hauppauge_novat_config = { + .demod_address = 0x43, + .output_mode = CX22702_SERIAL_OUTPUT, +}; + +static struct cx22702_config hauppauge_hvr1100_config = { .demod_address = 0x63, .output_mode = CX22702_SERIAL_OUTPUT, }; -static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) +static struct cx22702_config hauppauge_hvr1300_config = { + .demod_address = 0x63, + .output_mode = CX22702_SERIAL_OUTPUT, +}; + +static struct cx22702_config hauppauge_hvr3000_config = { + .demod_address = 0x63, + .output_mode = CX22702_SERIAL_OUTPUT, +}; + +static int or51132_set_ts_param(struct dvb_frontend* fe, + int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; @@ -320,6 +344,50 @@ static struct or51132_config pchdtv_hd3000 = { .set_ts_params = or51132_set_ts_param, }; +static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + /* FIXME make this routine use the tuner-simple code. + * It could probably be shared with a number of ATSC + * frontends. Many share the same tuner with analog TV. */ + + struct cx8802_dev *dev= fe->dvb->priv; + struct cx88_core *core = dev->core; + u8 buf[4]; + struct i2c_msg msg = + { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; + int err; + + dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); + dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", + __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "cx88-dvb: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + return 0; +} + +static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct cx88_core *core = dev->core; + + /* Put the analog decoder in standby to keep it quiet */ + cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + + return lg_h06xf_pll_set(fe, &core->i2c_adap, params); +} + static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) { struct cx8802_dev *dev= fe->dvb->priv; @@ -364,7 +432,8 @@ static struct lgdt330x_config pchdtv_hd5500 = { .set_ts_params = lgdt330x_set_ts_param, }; -static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) +static int nxt200x_set_ts_param(struct dvb_frontend* fe, + int is_punctured) { struct cx8802_dev *dev= fe->dvb->priv; dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; @@ -400,10 +469,11 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; - if (voltage == SEC_VOLTAGE_OFF) + if (voltage == SEC_VOLTAGE_OFF) { cx_write(MO_GP0_IO, 0x000006fb); - else + } else { cx_write(MO_GP0_IO, 0x000006f9); + } if (core->prev_set_voltage) return core->prev_set_voltage(fe, voltage); @@ -452,7 +522,7 @@ static int dvb_register(struct cx8802_dev *dev) switch (dev->core->board) { case CX88_BOARD_HAUPPAUGE_DVB_T1: dev->dvb.frontend = dvb_attach(cx22702_attach, - &connexant_refboard_config, + &hauppauge_novat_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, @@ -477,11 +547,32 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: dev->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, + &hauppauge_hvr1100_config, + &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_fmd1216me); + } + break; + case CX88_BOARD_HAUPPAUGE_HVR1300: + dev->dvb.frontend = dvb_attach(cx22702_attach, + &hauppauge_hvr1300_config, + &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_fmd1216me); + } + break; + case CX88_BOARD_HAUPPAUGE_HVR3000: + dev->dvb.frontend = dvb_attach(cx22702_attach, + &hauppauge_hvr3000_config, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, &dvb_pll_fmd1216me); + &dev->core->i2c_adap, + &dvb_pll_fmd1216me); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: @@ -556,17 +647,18 @@ static int dvb_register(struct cx8802_dev *dev) #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_thomson_fe6600; dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - &dvb_pll_thomson_fe6600); + dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; } break; case CX88_BOARD_PCHDTV_HD3000: - dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, + dev->dvb.frontend = dvb_attach(or51132_attach, + &pchdtv_hd3000, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, @@ -587,13 +679,13 @@ static int dvb_register(struct cx8802_dev *dev) /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_microtune_4042; dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - &dvb_pll_microtune_4042); + dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; } } break; @@ -607,13 +699,13 @@ static int dvb_register(struct cx8802_dev *dev) mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_thomson_dtt761x; dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - &dvb_pll_thomson_dtt761x); + dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; } } break; @@ -631,8 +723,7 @@ static int dvb_register(struct cx8802_dev *dev) &fusionhdtv_5_gold, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(lgh06xf_attach, dev->dvb.frontend, - &dev->core->i2c_adap); + dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; } } break; @@ -650,8 +741,7 @@ static int dvb_register(struct cx8802_dev *dev) &pchdtv_hd5500, &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(lgh06xf_attach, dev->dvb.frontend, - &dev->core->i2c_adap); + dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; } } break; @@ -692,24 +782,6 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; - case CX88_BOARD_HAUPPAUGE_HVR1300: - dev->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, - &dev->core->i2c_adap); - if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, &dvb_pll_fmd1216me); - } - break; - case CX88_BOARD_HAUPPAUGE_HVR3000: - dev->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, - &dev->core->i2c_adap); - if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, &dvb_pll_fmd1216me); - } - break; default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); @@ -724,8 +796,6 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; } - /* Ensure all frontends negotiate bus access */ - dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); @@ -736,67 +806,37 @@ static int dvb_register(struct cx8802_dev *dev) /* ----------------------------------------------------------- */ -/* CX8802 MPEG -> mini driver - We have been given the hardware */ -static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) +static int __devinit dvb_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) { - struct cx88_core *core = drv->core; - int err = 0; - dprintk( 1, "%s\n", __FUNCTION__); - - switch (core->board) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* We arrive here with either the cx23416 or the cx22702 - * on the bus. Take the bus from the cx23416 and enable the - * cx22702 demod - */ - cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */ - cx_clear(MO_GP0_IO, 0x00000004); - udelay(1000); - break; - default: - err = -ENODEV; - } - return err; -} - -/* CX8802 MPEG -> mini driver - We no longer have the hardware */ -static int cx8802_dvb_advise_release(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - int err = 0; - dprintk( 1, "%s\n", __FUNCTION__); - - switch (core->board) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* Do Nothing, leave the cx22702 on the bus. */ - break; - default: - err = -ENODEV; - } - return err; -} - -static int cx8802_dvb_probe(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - struct cx8802_dev *dev = drv->core->dvbdev; + struct cx8802_dev *dev; + struct cx88_core *core; int err; - dprintk( 1, "%s\n", __FUNCTION__); - dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", - core->board, - core->name, - core->pci_bus, - core->pci_slot); + /* general setup */ + core = cx88_core_get(pci_dev); + if (NULL == core) + return -EINVAL; err = -ENODEV; if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) goto fail_core; + err = -ENOMEM; + dev = kzalloc(sizeof(*dev),GFP_KERNEL); + if (NULL == dev) + goto fail_core; + dev->pci = pci_dev; + dev->core = core; + + err = cx8802_init_common(dev); + if (0 != err) + goto fail_free; + #ifdef HAVE_VP3054_I2C err = vp3054_i2c_probe(dev); if (0 != err) - goto fail_core; + goto fail_free; #endif /* dvb stuff */ @@ -808,16 +848,28 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) sizeof(struct cx88_buffer), dev); err = dvb_register(dev); - if (err != 0) - printk("%s dvb_register failed err = %d\n", __FUNCTION__, err); + if (0 != err) + goto fail_fini; + /* Maintain a reference to cx88-video can query the 8802 device. */ + core->dvbdev = dev; + return 0; + + fail_fini: + cx8802_fini_common(dev); + fail_free: + kfree(dev); fail_core: + cx88_core_put(core,pci_dev); return err; } -static int cx8802_dvb_remove(struct cx8802_driver *drv) +static void __devexit dvb_remove(struct pci_dev *pci_dev) { - struct cx8802_dev *dev = drv->core->dvbdev; + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + + /* Destroy any 8802 reference. */ + dev->core->dvbdev = NULL; /* dvb */ videobuf_dvb_unregister(&dev->dvb); @@ -826,16 +878,33 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) vp3054_i2c_remove(dev); #endif - return 0; + /* common */ + cx8802_fini_common(dev); + cx88_core_put(dev->core,dev->pci); + kfree(dev); } -static struct cx8802_driver cx8802_dvb_driver = { - .type_id = CX88_MPEG_DVB, - .hw_access = CX8802_DRVCTL_SHARED, - .probe = cx8802_dvb_probe, - .remove = cx8802_dvb_remove, - .advise_acquire = cx8802_dvb_advise_acquire, - .advise_release = cx8802_dvb_advise_release, +static struct pci_device_id cx8802_pci_tbl[] = { + { + .vendor = 0x14f1, + .device = 0x8802, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + },{ + /* --- end of list --- */ + } +}; +MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); + +static struct pci_driver dvb_pci_driver = { + .name = "cx88-dvb", + .id_table = cx8802_pci_tbl, + .probe = dvb_probe, + .remove = __devexit_p(dvb_remove), +#ifdef CONFIG_PM + .suspend = cx8802_suspend_common, + .resume = cx8802_resume_common, +#endif }; static int dvb_init(void) @@ -848,12 +917,12 @@ static int dvb_init(void) printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif - return cx8802_register_driver(&cx8802_dvb_driver); + return pci_register_driver(&dvb_pci_driver); } static void dvb_fini(void) { - cx8802_unregister_driver(&cx8802_dvb_driver); + pci_unregister_driver(&dvb_pci_driver); } module_init(dvb_init); diff --git a/trunk/drivers/media/video/cx88/cx88-input.c b/trunk/drivers/media/video/cx88/cx88-input.c index 8136673fe9e8..e60a0a52e4b2 100644 --- a/trunk/drivers/media/video/cx88/cx88-input.c +++ b/trunk/drivers/media/video/cx88/cx88-input.c @@ -155,35 +155,6 @@ static void cx88_ir_work(struct work_struct *work) mod_timer(&ir->timer, timeout); } -static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) -{ - if (ir->polling) { - INIT_WORK(&ir->work, cx88_ir_work); - init_timer(&ir->timer); - ir->timer.function = ir_timer; - ir->timer.data = (unsigned long)ir; - schedule_work(&ir->work); - } - if (ir->sampling) { - core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ - cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ - cx_write(MO_DDSCFG_IO, 0x5); /* enable */ - } -} - -static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) -{ - if (ir->sampling) { - cx_write(MO_DDSCFG_IO, 0x0); - core->pci_irqmask &= ~(1 << 18); - } - - if (ir->polling) { - del_timer_sync(&ir->timer); - flush_scheduled_work(); - } -} - /* ---------------------------------------------------------------------- */ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) @@ -192,12 +163,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) struct input_dev *input_dev; IR_KEYTAB_TYPE *ir_codes = NULL; int ir_type = IR_TYPE_OTHER; - int err = -ENOMEM; ir = kzalloc(sizeof(*ir), GFP_KERNEL); input_dev = input_allocate_device(); - if (!ir || !input_dev) - goto err_out_free; + if (!ir || !input_dev) { + kfree(ir); + input_free_device(input_dev); + return -ENOMEM; + } ir->input = input_dev; @@ -307,8 +280,9 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) } if (NULL == ir_codes) { - err = -ENODEV; - goto err_out_free; + kfree(ir); + input_free_device(input_dev); + return -ENODEV; } /* init input device */ @@ -333,22 +307,23 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->core = core; core->ir = ir; - cx88_ir_start(core, ir); + if (ir->polling) { + INIT_WORK(&ir->work, cx88_ir_work); + init_timer(&ir->timer); + ir->timer.function = ir_timer; + ir->timer.data = (unsigned long)ir; + schedule_work(&ir->work); + } + if (ir->sampling) { + core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ + cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ + cx_write(MO_DDSCFG_IO, 0x5); /* enable */ + } /* all done */ - err = input_register_device(ir->input); - if (err) - goto err_out_stop; + input_register_device(ir->input); return 0; - - err_out_stop: - cx88_ir_stop(core, ir); - core->ir = NULL; - err_out_free: - input_free_device(input_dev); - kfree(ir); - return err; } int cx88_ir_fini(struct cx88_core *core) @@ -359,7 +334,15 @@ int cx88_ir_fini(struct cx88_core *core) if (NULL == ir) return 0; - cx88_ir_stop(core, ir); + if (ir->sampling) { + cx_write(MO_DDSCFG_IO, 0x0); + core->pci_irqmask &= ~(1 << 18); + } + if (ir->polling) { + del_timer(&ir->timer); + flush_scheduled_work(); + } + input_unregister_device(ir->input); kfree(ir); diff --git a/trunk/drivers/media/video/cx88/cx88-mpeg.c b/trunk/drivers/media/video/cx88/cx88-mpeg.c index 1fe1a833c7c7..6b23a4e6f66d 100644 --- a/trunk/drivers/media/video/cx88/cx88-mpeg.c +++ b/trunk/drivers/media/video/cx88/cx88-mpeg.c @@ -44,12 +44,8 @@ module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); #define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg) + printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg) -#define mpeg_dbg(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg) - -static LIST_HEAD(cx8802_devlist); /* ------------------------------------------------------------------ */ static int cx8802_start_dma(struct cx8802_dev *dev, @@ -69,13 +65,17 @@ static int cx8802_start_dma(struct cx8802_dev *dev, /* FIXME: this needs a review. * also: move to cx88-blackbird + cx88-dvb source files? */ + if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) { + /* Report a warning until the mini driver patch is applied, + * else the following conditions will set the dma registers incorrectly. + * This will be removed in the next major patch and changes to the conditions + * will be made. + */ + printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__); + return -EINVAL; + } - dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); - - if ( (core->active_type_id == CX88_MPEG_DVB) && - (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) { - - dprintk( 1, "cx8802_start_dma doing .dvb\n"); + if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) { /* negedge driven & software reset */ cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); udelay(100); @@ -93,17 +93,15 @@ static int cx8802_start_dma(struct cx8802_dev *dev, cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ udelay(100); break; - case CX88_BOARD_HAUPPAUGE_HVR1300: - break; default: cx_write(TS_SOP_STAT, 0x00); break; } cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); udelay(100); - } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) && - (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) { - dprintk( 1, "cx8802_start_dma doing .blackbird\n"); + } + + if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ @@ -114,10 +112,6 @@ static int cx8802_start_dma(struct cx8802_dev *dev, cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ udelay(100); - } else { - printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__, - cx88_boards[core->board].mpeg ); - return -EINVAL; } /* reset counter */ @@ -548,315 +542,8 @@ int cx8802_resume_common(struct pci_dev *pci_dev) return 0; } -struct cx8802_dev * cx8802_get_device(struct inode *inode) -{ - int minor = iminor(inode); - struct cx8802_dev *h = NULL; - struct list_head *list; - - list_for_each(list,&cx8802_devlist) { - h = list_entry(list, struct cx8802_dev, devlist); - if (h->mpeg_dev->minor == minor) - return h; - } - - return NULL; -} - -struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) -{ - struct cx8802_dev *h = NULL; - struct cx8802_driver *d = NULL; - struct list_head *list; - struct list_head *list2; - - list_for_each(list,&cx8802_devlist) { - h = list_entry(list, struct cx8802_dev, devlist); - if (h != dev) - continue; - - list_for_each(list2, &h->drvlist.devlist) { - d = list_entry(list2, struct cx8802_driver, devlist); - - /* only unregister the correct driver type */ - if (d->type_id == btype) { - return d; - } - } - } - - return NULL; -} - -/* Driver asked for hardware access. */ -int cx8802_request_acquire(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - - /* Fail a request for hardware if the device is busy. */ - if (core->active_type_id != CX88_BOARD_NONE) - return -EBUSY; - - if (drv->advise_acquire) - { - core->active_type_id = drv->type_id; - drv->advise_acquire(drv); - - mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); - } - - return 0; -} - -/* Driver asked to release hardware. */ -int cx8802_request_release(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - - if (drv->advise_release) - { - drv->advise_release(drv); - core->active_type_id = CX88_BOARD_NONE; - mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); - } - - return 0; -} - -static int cx8802_check_driver(struct cx8802_driver *drv) -{ - if (drv == NULL) - return -ENODEV; - - if ((drv->type_id != CX88_MPEG_DVB) && - (drv->type_id != CX88_MPEG_BLACKBIRD)) - return -EINVAL; - - if ((drv->hw_access != CX8802_DRVCTL_SHARED) && - (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE)) - return -EINVAL; - - if ((drv->probe == NULL) || - (drv->remove == NULL) || - (drv->advise_acquire == NULL) || - (drv->advise_release == NULL)) - return -EINVAL; - - return 0; -} - -int cx8802_register_driver(struct cx8802_driver *drv) -{ - struct cx8802_dev *h; - struct cx8802_driver *driver; - struct list_head *list; - int err = 0, i = 0; - - printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ , - drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", - drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); - - if ((err = cx8802_check_driver(drv)) != 0) { - printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ ); - return err; - } - - list_for_each(list,&cx8802_devlist) { - h = list_entry(list, struct cx8802_dev, devlist); - - printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", - h->core->name,h->pci->subsystem_vendor, - h->pci->subsystem_device,cx88_boards[h->core->board].name, - h->core->board); - - /* Bring up a new struct for each driver instance */ - driver = kzalloc(sizeof(*drv),GFP_KERNEL); - if (driver == NULL) - return -ENOMEM; - - /* Snapshot of the driver registration data */ - drv->core = h->core; - drv->suspend = cx8802_suspend_common; - drv->resume = cx8802_resume_common; - drv->request_acquire = cx8802_request_acquire; - drv->request_release = cx8802_request_release; - memcpy(driver, drv, sizeof(*driver)); - - err = drv->probe(driver); - if (err == 0) { - i++; - mutex_lock(&drv->core->lock); - list_add_tail(&driver->devlist,&h->drvlist.devlist); - mutex_unlock(&drv->core->lock); - } else { - printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err); - } - - } - if (i == 0) - err = -ENODEV; - else - err = 0; - - return err; -} - -int cx8802_unregister_driver(struct cx8802_driver *drv) -{ - struct cx8802_dev *h; - struct cx8802_driver *d; - struct list_head *list; - struct list_head *list2, *q; - int err = 0, i = 0; - - printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ , - drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird"); - - list_for_each(list,&cx8802_devlist) { - i++; - h = list_entry(list, struct cx8802_dev, devlist); - - printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", - h->core->name,h->pci->subsystem_vendor, - h->pci->subsystem_device,cx88_boards[h->core->board].name, - h->core->board); - - list_for_each_safe(list2, q, &h->drvlist.devlist) { - d = list_entry(list2, struct cx8802_driver, devlist); - - /* only unregister the correct driver type */ - if (d->type_id != drv->type_id) - continue; - - err = d->remove(d); - if (err == 0) { - mutex_lock(&drv->core->lock); - list_del(list2); - mutex_unlock(&drv->core->lock); - } else - printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err); - - } - - } - - return err; -} - /* ----------------------------------------------------------- */ -static int __devinit cx8802_probe(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) -{ - struct cx8802_dev *dev; - struct cx88_core *core; - int err; - - /* general setup */ - core = cx88_core_get(pci_dev); - if (NULL == core) - return -EINVAL; - printk("%s/2: cx2388x 8802 Driver Manager\n", core->name); - - err = -ENODEV; - if (!cx88_boards[core->board].mpeg) - goto fail_core; - - err = -ENOMEM; - dev = kzalloc(sizeof(*dev),GFP_KERNEL); - if (NULL == dev) - goto fail_core; - dev->pci = pci_dev; - dev->core = core; - - err = cx8802_init_common(dev); - if (err != 0) - goto fail_free; - - INIT_LIST_HEAD(&dev->drvlist.devlist); - list_add_tail(&dev->devlist,&cx8802_devlist); - - /* Maintain a reference so cx88-video can query the 8802 device. */ - core->dvbdev = dev; - return 0; - - fail_free: - kfree(dev); - fail_core: - cx88_core_put(core,pci_dev); - return err; -} - -static void __devexit cx8802_remove(struct pci_dev *pci_dev) -{ - struct cx8802_dev *dev; - struct cx8802_driver *h; - struct list_head *list; - - dev = pci_get_drvdata(pci_dev); - - dprintk( 1, "%s\n", __FUNCTION__); - - list_for_each(list,&dev->drvlist.devlist) { - h = list_entry(list, struct cx8802_driver, devlist); - dprintk( 1, " ->driver\n"); - if (h->remove == NULL) { - printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__); - continue; - } - printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id); - cx8802_unregister_driver(h); - list_del(&dev->drvlist.devlist); - } - - /* Destroy any 8802 reference. */ - dev->core->dvbdev = NULL; - - /* common */ - cx8802_fini_common(dev); - cx88_core_put(dev->core,dev->pci); - kfree(dev); -} - -static struct pci_device_id cx8802_pci_tbl[] = { - { - .vendor = 0x14f1, - .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - },{ - /* --- end of list --- */ - } -}; -MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); - -static struct pci_driver cx8802_pci_driver = { - .name = "cx88-mpeg driver manager", - .id_table = cx8802_pci_tbl, - .probe = cx8802_probe, - .remove = __devexit_p(cx8802_remove), -}; - -static int cx8802_init(void) -{ - printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n", - (CX88_VERSION_CODE >> 16) & 0xff, - (CX88_VERSION_CODE >> 8) & 0xff, - CX88_VERSION_CODE & 0xff); -#ifdef SNAPSHOT - printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", - SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); -#endif - return pci_register_driver(&cx8802_pci_driver); -} - -static void cx8802_fini(void) -{ - pci_unregister_driver(&cx8802_pci_driver); -} - -module_init(cx8802_init); -module_exit(cx8802_fini); EXPORT_SYMBOL(cx8802_buf_prepare); EXPORT_SYMBOL(cx8802_buf_queue); EXPORT_SYMBOL(cx8802_cancel_buffers); @@ -864,10 +551,9 @@ EXPORT_SYMBOL(cx8802_cancel_buffers); EXPORT_SYMBOL(cx8802_init_common); EXPORT_SYMBOL(cx8802_fini_common); -EXPORT_SYMBOL(cx8802_register_driver); -EXPORT_SYMBOL(cx8802_unregister_driver); -EXPORT_SYMBOL(cx8802_get_device); -EXPORT_SYMBOL(cx8802_get_driver); +EXPORT_SYMBOL(cx8802_suspend_common); +EXPORT_SYMBOL(cx8802_resume_common); + /* ----------------------------------------------------------- */ /* * Local variables: diff --git a/trunk/drivers/media/video/cx88/cx88-tvaudio.c b/trunk/drivers/media/video/cx88/cx88-tvaudio.c index 3482e0114d43..58ba9f773524 100644 --- a/trunk/drivers/media/video/cx88/cx88-tvaudio.c +++ b/trunk/drivers/media/video/cx88/cx88-tvaudio.c @@ -143,6 +143,19 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) cx88_start_audio_dma(core); if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { + /* sets sound input from external adc */ + switch (core->board) { + case CX88_BOARD_HAUPPAUGE_ROSLYN: + case CX88_BOARD_KWORLD_MCE200_DELUXE: + case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT: + case CX88_BOARD_PIXELVIEW_PLAYTV_P7000: + case CX88_BOARD_ASUS_PVR_416: + cx_clear(AUD_CTL, EN_I2SIN_ENABLE); + break; + default: + cx_set(AUD_CTL, EN_I2SIN_ENABLE); + } + cx_write(AUD_I2SINPUTCNTL, 4); cx_write(AUD_BAUDRATE, 1); /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ diff --git a/trunk/drivers/media/video/cx88/cx88-video.c b/trunk/drivers/media/video/cx88/cx88-video.c index 8613378428fd..90e298d074d1 100644 --- a/trunk/drivers/media/video/cx88/cx88-video.c +++ b/trunk/drivers/media/video/cx88/cx88-video.c @@ -454,14 +454,6 @@ static int video_mux(struct cx88_core *core, unsigned int input) cx_clear(MO_FILTER_ODD, 0x00002020); break; } - - if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { - /* sets sound input from external adc */ - if (INPUT(input)->extadc) - cx_set(AUD_CTL, EN_I2SIN_ENABLE); - else - cx_clear(AUD_CTL, EN_I2SIN_ENABLE); - } return 0; } @@ -1498,30 +1490,6 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, mutex_unlock(&core->lock); return 0; } -#ifdef CONFIG_VIDEO_ADV_DEBUG - /* ioctls to allow direct acces to the cx2388x registers */ - case VIDIOC_INT_G_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != 0) - return -EINVAL; - /* cx2388x has a 24-bit register space */ - reg->val = cx_read(reg->reg&0xffffff); - return 0; - } - case VIDIOC_INT_S_REGISTER: - { - struct v4l2_register *reg = arg; - - if (reg->i2c_id != 0) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - cx_write(reg->reg&0xffffff, reg->val); - return 0; - } -#endif default: return v4l_compat_translate_ioctl(inode,file,cmd,arg, diff --git a/trunk/drivers/media/video/cx88/cx88-vp3054-i2c.c b/trunk/drivers/media/video/cx88/cx88-vp3054-i2c.c index 6068c9bf82cd..2b4f1970c7df 100644 --- a/trunk/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/trunk/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -168,7 +168,7 @@ void vp3054_i2c_remove(struct cx8802_dev *dev) dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) return; - i2c_del_adapter(&vp3054_i2c->adap); + i2c_bit_del_bus(&vp3054_i2c->adap); kfree(vp3054_i2c); } diff --git a/trunk/drivers/media/video/cx88/cx88.h b/trunk/drivers/media/video/cx88/cx88.h index 7054e941f1d7..3bc91aad4fe5 100644 --- a/trunk/drivers/media/video/cx88/cx88.h +++ b/trunk/drivers/media/video/cx88/cx88.h @@ -74,11 +74,6 @@ enum cx88_board_type { CX88_MPEG_BLACKBIRD }; -enum cx8802_board_access { - CX8802_DRVCTL_SHARED = 1, - CX8802_DRVCTL_EXCLUSIVE = 2, -}; - /* ----------------------------------------------------------- */ /* tv norms */ @@ -225,7 +220,6 @@ struct cx88_input { enum cx88_itype type; unsigned int vmux; u32 gpio0, gpio1, gpio2, gpio3; - unsigned int extadc:1; }; struct cx88_board { @@ -336,7 +330,6 @@ struct cx88_core { /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ struct cx8802_dev *dvbdev; - enum cx88_board_type active_type_id; }; struct cx8800_dev; @@ -412,31 +405,6 @@ struct cx8802_suspend_state { int disabled; }; -struct cx8802_driver { - struct cx88_core *core; - struct list_head devlist; - - /* Type of driver and access required */ - enum cx88_board_type type_id; - enum cx8802_board_access hw_access; - - /* MPEG 8802 internal only */ - int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); - int (*resume)(struct pci_dev *pci_dev); - - /* MPEG 8802 -> mini driver - Driver probe and configuration */ - int (*probe)(struct cx8802_driver *drv); - int (*remove)(struct cx8802_driver *drv); - - /* MPEG 8802 -> mini driver - Access for hardware control */ - int (*advise_acquire)(struct cx8802_driver *drv); - int (*advise_release)(struct cx8802_driver *drv); - - /* MPEG 8802 <- mini driver - Access for hardware control */ - int (*request_acquire)(struct cx8802_driver *drv); - int (*request_release)(struct cx8802_driver *drv); -}; - struct cx8802_dev { struct cx88_core *core; spinlock_t slock; @@ -471,9 +439,6 @@ struct cx8802_dev { /* mpeg params */ struct cx2341x_mpeg_params params; - - /* List of attached drivers */ - struct cx8802_driver drvlist; }; /* ----------------------------------------------------------- */ @@ -606,11 +571,6 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); int cx88_audio_thread(void *data); -int cx8802_register_driver(struct cx8802_driver *drv); -int cx8802_unregister_driver(struct cx8802_driver *drv); -struct cx8802_dev * cx8802_get_device(struct inode *inode); -struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); - /* ----------------------------------------------------------- */ /* cx88-input.c */ @@ -640,13 +600,6 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, extern const u32 cx88_user_ctrls[]; extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); -/* ----------------------------------------------------------- */ -/* cx88-blackbird.c */ -/* used by cx88-ivtv ioctl emulation layer */ -extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg); -extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); - /* * Local variables: * c-basic-offset: 8 diff --git a/trunk/drivers/media/video/dabusb.c b/trunk/drivers/media/video/dabusb.c index 917021fc2993..b1012e92ee04 100644 --- a/trunk/drivers/media/video/dabusb.c +++ b/trunk/drivers/media/video/dabusb.c @@ -218,7 +218,7 @@ static int dabusb_alloc_buffers (pdabusb_t s) pipesize, packets, transfer_buffer_length); while (buffers < (s->total_buffer_size << 10)) { - b = kzalloc(sizeof (buff_t), GFP_KERNEL); + b = (pbuff_t) kzalloc (sizeof (buff_t), GFP_KERNEL); if (!b) { err("kzalloc(sizeof(buff_t))==NULL"); goto err; @@ -659,7 +659,7 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm switch (cmd) { case IOCTL_DAB_BULK: - pbulk = kmalloc(sizeof (bulk_transfer_t), GFP_KERNEL); + pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); if (!pbulk) { ret = -ENOMEM; diff --git a/trunk/drivers/media/video/ir-kbd-i2c.c b/trunk/drivers/media/video/ir-kbd-i2c.c index 59edf58204de..ab87e7bfe84f 100644 --- a/trunk/drivers/media/video/ir-kbd-i2c.c +++ b/trunk/drivers/media/video/ir-kbd-i2c.c @@ -305,14 +305,15 @@ static int ir_attach(struct i2c_adapter *adap, int addr, int ir_type; struct IR_i2c *ir; struct input_dev *input_dev; - int err; ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); input_dev = input_allocate_device(); if (!ir || !input_dev) { - err = -ENOMEM; - goto err_out_free; + input_free_device(input_dev); + kfree(ir); + return -ENOMEM; } + memset(ir,0,sizeof(*ir)); ir->c = client_template; ir->input = input_dev; @@ -354,34 +355,32 @@ static int ir_attach(struct i2c_adapter *adap, int addr, break; case 0x7a: case 0x47: - case 0x71: /* Handled by saa7134-input */ name = "SAA713x remote"; ir_type = IR_TYPE_OTHER; break; default: /* shouldn't happen */ - printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr); - err = -ENODEV; - goto err_out_free; + printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr); + kfree(ir); + return -1; } /* Sets name */ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); - ir->ir_codes = ir_codes; + ir->ir_codes=ir_codes; /* register i2c device * At device register, IR codes may be changed to be * board dependent. */ - err = i2c_attach_client(&ir->c); - if (err) - goto err_out_free; + i2c_attach_client(&ir->c); /* If IR not supported or disabled, unregisters driver */ if (ir->get_key == NULL) { - err = -ENODEV; - goto err_out_detach; + i2c_detach_client(&ir->c); + kfree(ir); + return -1; } /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */ @@ -390,17 +389,15 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->c.dev.bus_id); /* init + register input device */ - ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); + ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes); input_dev->id.bustype = BUS_I2C; input_dev->name = ir->c.name; input_dev->phys = ir->phys; - err = input_register_device(ir->input); - if (err) - goto err_out_detach; - + /* register event device */ + input_register_device(ir->input); printk(DEVNAME ": %s detected at %s [%s]\n", - ir->input->name, ir->input->phys, adap->name); + ir->input->name,ir->input->phys,adap->name); /* start polling via eventd */ INIT_WORK(&ir->work, ir_work); @@ -410,13 +407,6 @@ static int ir_attach(struct i2c_adapter *adap, int addr, schedule_work(&ir->work); return 0; - - err_out_detach: - i2c_detach_client(&ir->c); - err_out_free: - input_free_device(input_dev); - kfree(ir); - return err; } static int ir_detach(struct i2c_client *client) @@ -424,7 +414,7 @@ static int ir_detach(struct i2c_client *client) struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ - del_timer_sync(&ir->timer); + del_timer(&ir->timer); flush_scheduled_work(); /* unregister devices */ @@ -449,7 +439,7 @@ static int ir_probe(struct i2c_adapter *adap) */ static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; - static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 }; + static const int probe_saa7134[] = { 0x7a, 0x47, -1 }; static const int probe_em28XX[] = { 0x30, 0x47, -1 }; const int *probe = NULL; struct i2c_client c; diff --git a/trunk/drivers/media/video/mxb.c b/trunk/drivers/media/video/mxb.c index 152cc6b3e152..b0aea4002d11 100644 --- a/trunk/drivers/media/video/mxb.c +++ b/trunk/drivers/media/video/mxb.c @@ -160,6 +160,10 @@ static int mxb_probe(struct saa7146_dev* dev) printk("mxb: saa7111 i2c module not available.\n"); return -ENODEV; } + if ((result = request_module("tuner")) < 0) { + printk("mxb: tuner i2c module not available.\n"); + return -ENODEV; + } if ((result = request_module("tea6420")) < 0) { printk("mxb: tea6420 i2c module not available.\n"); return -ENODEV; @@ -172,10 +176,6 @@ static int mxb_probe(struct saa7146_dev* dev) printk("mxb: tda9840 i2c module not available.\n"); return -ENODEV; } - if ((result = request_module("tuner")) < 0) { - printk("mxb: tuner i2c module not available.\n"); - return -ENODEV; - } mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); if( NULL == mxb ) { diff --git a/trunk/drivers/media/video/ov7670.c b/trunk/drivers/media/video/ov7670.c deleted file mode 100644 index 5ed0adc4ca26..000000000000 --- a/trunk/drivers/media/video/ov7670.c +++ /dev/null @@ -1,1333 +0,0 @@ -/* - * A V4L2 driver for OmniVision OV7670 cameras. - * - * Copyright 2006 One Laptop Per Child Association, Inc. Written - * by Jonathan Corbet with substantial inspiration from Mark - * McClelland's ovcamchip code. - * - * This file may be distributed under the terms of the GNU General - * Public License, version 2. - */ -#include -#include -#include -#include -#include -#include -#include -#include - - -MODULE_AUTHOR("Jonathan Corbet "); -MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); -MODULE_LICENSE("GPL"); - -/* - * Basic window sizes. These probably belong somewhere more globally - * useful. - */ -#define VGA_WIDTH 640 -#define VGA_HEIGHT 480 -#define QVGA_WIDTH 320 -#define QVGA_HEIGHT 240 -#define CIF_WIDTH 352 -#define CIF_HEIGHT 288 -#define QCIF_WIDTH 176 -#define QCIF_HEIGHT 144 - -/* - * Our nominal (default) frame rate. - */ -#define OV7670_FRAME_RATE 30 - -/* - * The 7670 sits on i2c with ID 0x42 - */ -#define OV7670_I2C_ADDR 0x42 - -/* Registers */ -#define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ -#define REG_BLUE 0x01 /* blue gain */ -#define REG_RED 0x02 /* red gain */ -#define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ -#define REG_COM1 0x04 /* Control 1 */ -#define COM1_CCIR656 0x40 /* CCIR656 enable */ -#define REG_BAVE 0x05 /* U/B Average level */ -#define REG_GbAVE 0x06 /* Y/Gb Average level */ -#define REG_AECHH 0x07 /* AEC MS 5 bits */ -#define REG_RAVE 0x08 /* V/R Average level */ -#define REG_COM2 0x09 /* Control 2 */ -#define COM2_SSLEEP 0x10 /* Soft sleep mode */ -#define REG_PID 0x0a /* Product ID MSB */ -#define REG_VER 0x0b /* Product ID LSB */ -#define REG_COM3 0x0c /* Control 3 */ -#define COM3_SWAP 0x40 /* Byte swap */ -#define COM3_SCALEEN 0x08 /* Enable scaling */ -#define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */ -#define REG_COM4 0x0d /* Control 4 */ -#define REG_COM5 0x0e /* All "reserved" */ -#define REG_COM6 0x0f /* Control 6 */ -#define REG_AECH 0x10 /* More bits of AEC value */ -#define REG_CLKRC 0x11 /* Clocl control */ -#define CLK_EXT 0x40 /* Use external clock directly */ -#define CLK_SCALE 0x3f /* Mask for internal clock scale */ -#define REG_COM7 0x12 /* Control 7 */ -#define COM7_RESET 0x80 /* Register reset */ -#define COM7_FMT_MASK 0x38 -#define COM7_FMT_VGA 0x00 -#define COM7_FMT_CIF 0x20 /* CIF format */ -#define COM7_FMT_QVGA 0x10 /* QVGA format */ -#define COM7_FMT_QCIF 0x08 /* QCIF format */ -#define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ -#define COM7_YUV 0x00 /* YUV */ -#define COM7_BAYER 0x01 /* Bayer format */ -#define COM7_PBAYER 0x05 /* "Processed bayer" */ -#define REG_COM8 0x13 /* Control 8 */ -#define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ -#define COM8_AECSTEP 0x40 /* Unlimited AEC step size */ -#define COM8_BFILT 0x20 /* Band filter enable */ -#define COM8_AGC 0x04 /* Auto gain enable */ -#define COM8_AWB 0x02 /* White balance enable */ -#define COM8_AEC 0x01 /* Auto exposure enable */ -#define REG_COM9 0x14 /* Control 9 - gain ceiling */ -#define REG_COM10 0x15 /* Control 10 */ -#define COM10_HSYNC 0x40 /* HSYNC instead of HREF */ -#define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */ -#define COM10_HREF_REV 0x08 /* Reverse HREF */ -#define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ -#define COM10_VS_NEG 0x02 /* VSYNC negative */ -#define COM10_HS_NEG 0x01 /* HSYNC negative */ -#define REG_HSTART 0x17 /* Horiz start high bits */ -#define REG_HSTOP 0x18 /* Horiz stop high bits */ -#define REG_VSTART 0x19 /* Vert start high bits */ -#define REG_VSTOP 0x1a /* Vert stop high bits */ -#define REG_PSHFT 0x1b /* Pixel delay after HREF */ -#define REG_MIDH 0x1c /* Manuf. ID high */ -#define REG_MIDL 0x1d /* Manuf. ID low */ -#define REG_MVFP 0x1e /* Mirror / vflip */ -#define MVFP_MIRROR 0x20 /* Mirror image */ -#define MVFP_FLIP 0x10 /* Vertical flip */ - -#define REG_AEW 0x24 /* AGC upper limit */ -#define REG_AEB 0x25 /* AGC lower limit */ -#define REG_VPT 0x26 /* AGC/AEC fast mode op region */ -#define REG_HSYST 0x30 /* HSYNC rising edge delay */ -#define REG_HSYEN 0x31 /* HSYNC falling edge delay */ -#define REG_HREF 0x32 /* HREF pieces */ -#define REG_TSLB 0x3a /* lots of stuff */ -#define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */ -#define REG_COM11 0x3b /* Control 11 */ -#define COM11_NIGHT 0x80 /* NIght mode enable */ -#define COM11_NMFR 0x60 /* Two bit NM frame rate */ -#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ -#define COM11_50HZ 0x08 /* Manual 50Hz select */ -#define COM11_EXP 0x02 -#define REG_COM12 0x3c /* Control 12 */ -#define COM12_HREF 0x80 /* HREF always */ -#define REG_COM13 0x3d /* Control 13 */ -#define COM13_GAMMA 0x80 /* Gamma enable */ -#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ -#define COM13_UVSWAP 0x01 /* V before U - w/TSLB */ -#define REG_COM14 0x3e /* Control 14 */ -#define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */ -#define REG_EDGE 0x3f /* Edge enhancement factor */ -#define REG_COM15 0x40 /* Control 15 */ -#define COM15_R10F0 0x00 /* Data range 10 to F0 */ -#define COM15_R01FE 0x80 /* 01 to FE */ -#define COM15_R00FF 0xc0 /* 00 to FF */ -#define COM15_RGB565 0x10 /* RGB565 output */ -#define COM15_RGB555 0x30 /* RGB555 output */ -#define REG_COM16 0x41 /* Control 16 */ -#define COM16_AWBGAIN 0x08 /* AWB gain enable */ -#define REG_COM17 0x42 /* Control 17 */ -#define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */ -#define COM17_CBAR 0x08 /* DSP Color bar */ - -/* - * This matrix defines how the colors are generated, must be - * tweaked to adjust hue and saturation. - * - * Order: v-red, v-green, v-blue, u-red, u-green, u-blue - * - * They are nine-bit signed quantities, with the sign bit - * stored in 0x58. Sign for v-red is bit 0, and up from there. - */ -#define REG_CMATRIX_BASE 0x4f -#define CMATRIX_LEN 6 -#define REG_CMATRIX_SIGN 0x58 - - -#define REG_BRIGHT 0x55 /* Brightness */ -#define REG_CONTRAS 0x56 /* Contrast control */ - -#define REG_GFIX 0x69 /* Fix gain control */ - -#define REG_RGB444 0x8c /* RGB 444 control */ -#define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ -#define R444_RGBX 0x01 /* Empty nibble at end */ - -#define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ -#define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ - -#define REG_BD50MAX 0xa5 /* 50hz banding step limit */ -#define REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ -#define REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ -#define REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ -#define REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ -#define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ -#define REG_BD60MAX 0xab /* 60hz banding step limit */ - - -/* - * Information we maintain about a known sensor. - */ -struct ov7670_format_struct; /* coming later */ -struct ov7670_info { - struct ov7670_format_struct *fmt; /* Current format */ - unsigned char sat; /* Saturation value */ - int hue; /* Hue value */ -}; - - - - -/* - * The default register settings, as obtained from OmniVision. There - * is really no making sense of most of these - lots of "reserved" values - * and such. - * - * These settings give VGA YUYV. - */ - -struct regval_list { - unsigned char reg_num; - unsigned char value; -}; - -static struct regval_list ov7670_default_regs[] = { - { REG_COM7, COM7_RESET }, -/* - * Clock scale: 3 = 15fps - * 2 = 20fps - * 1 = 30fps - */ - { REG_CLKRC, 0x1 }, /* OV: clock scale (30 fps) */ - { REG_TSLB, 0x04 }, /* OV */ - { REG_COM7, 0 }, /* VGA */ - /* - * Set the hardware window. These values from OV don't entirely - * make sense - hstop is less than hstart. But they work... - */ - { REG_HSTART, 0x13 }, { REG_HSTOP, 0x01 }, - { REG_HREF, 0xb6 }, { REG_VSTART, 0x02 }, - { REG_VSTOP, 0x7a }, { REG_VREF, 0x0a }, - - { REG_COM3, 0 }, { REG_COM14, 0 }, - /* Mystery scaling numbers */ - { 0x70, 0x3a }, { 0x71, 0x35 }, - { 0x72, 0x11 }, { 0x73, 0xf0 }, - { 0xa2, 0x02 }, { 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. */ - { REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT }, - { REG_GAIN, 0 }, { REG_AECH, 0 }, - { REG_COM4, 0x40 }, /* magic reserved bit */ - { REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ - { REG_BD50MAX, 0x05 }, { REG_BD60MAX, 0x07 }, - { REG_AEW, 0x95 }, { REG_AEB, 0x33 }, - { REG_VPT, 0xe3 }, { REG_HAECC1, 0x78 }, - { REG_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */ - { REG_HAECC3, 0xd8 }, { REG_HAECC4, 0xd8 }, - { REG_HAECC5, 0xf0 }, { REG_HAECC6, 0x90 }, - { REG_HAECC7, 0x94 }, - { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC }, - - /* Almost all of these are magic "reserved" values. */ - { REG_COM5, 0x61 }, { REG_COM6, 0x4b }, - { 0x16, 0x02 }, { REG_MVFP, 0x07|MVFP_MIRROR }, - { 0x21, 0x02 }, { 0x22, 0x91 }, - { 0x29, 0x07 }, { 0x33, 0x0b }, - { 0x35, 0x0b }, { 0x37, 0x1d }, - { 0x38, 0x71 }, { 0x39, 0x2a }, - { REG_COM12, 0x78 }, { 0x4d, 0x40 }, - { 0x4e, 0x20 }, { 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 }, { REG_BLUE, 0x40 }, - { REG_RED, 0x60 }, - { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB }, - - /* Matrix coefficients */ - { 0x4f, 0x80 }, { 0x50, 0x80 }, - { 0x51, 0 }, { 0x52, 0x22 }, - { 0x53, 0x5e }, { 0x54, 0x80 }, - { 0x58, 0x9e }, - - { REG_COM16, COM16_AWBGAIN }, { REG_EDGE, 0 }, - { 0x75, 0x05 }, { 0x76, 0xe1 }, - { 0x4c, 0 }, { 0x77, 0x01 }, - { REG_COM13, 0xc3 }, { 0x4b, 0x09 }, - { 0xc9, 0x60 }, { REG_COM16, 0x38 }, - { 0x56, 0x40 }, - - { 0x34, 0x11 }, { REG_COM11, COM11_EXP|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 }, - - { 0xff, 0xff }, /* END MARKER */ -}; - - -/* - * Here we'll try to encapsulate the changes for just the output - * video format. - * - * RGB656 and YUV422 come from OV; RGB444 is homebrewed. - * - * IMPORTANT RULE: the first entry must be for COM7, see ov7670_s_fmt for why. - */ - - -static struct regval_list ov7670_fmt_yuv422[] = { - { REG_COM7, 0x0 }, /* Selects YUV mode */ - { REG_RGB444, 0 }, /* No RGB444 please */ - { REG_COM1, 0 }, - { REG_COM15, COM15_R00FF }, - { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */ - { 0x4f, 0x80 }, /* "matrix coefficient 1" */ - { 0x50, 0x80 }, /* "matrix coefficient 2" */ - { 0x51, 0 }, /* vb */ - { 0x52, 0x22 }, /* "matrix coefficient 4" */ - { 0x53, 0x5e }, /* "matrix coefficient 5" */ - { 0x54, 0x80 }, /* "matrix coefficient 6" */ - { REG_COM13, COM13_GAMMA|COM13_UVSAT }, - { 0xff, 0xff }, -}; - -static struct regval_list ov7670_fmt_rgb565[] = { - { REG_COM7, COM7_RGB }, /* Selects RGB mode */ - { REG_RGB444, 0 }, /* No RGB444 please */ - { REG_COM1, 0x0 }, - { REG_COM15, COM15_RGB565 }, - { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ - { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ - { 0x50, 0xb3 }, /* "matrix coefficient 2" */ - { 0x51, 0 }, /* vb */ - { 0x52, 0x3d }, /* "matrix coefficient 4" */ - { 0x53, 0xa7 }, /* "matrix coefficient 5" */ - { 0x54, 0xe4 }, /* "matrix coefficient 6" */ - { REG_COM13, COM13_GAMMA|COM13_UVSAT }, - { 0xff, 0xff }, -}; - -static struct regval_list ov7670_fmt_rgb444[] = { - { REG_COM7, COM7_RGB }, /* Selects RGB mode */ - { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */ - { REG_COM1, 0x40 }, /* Magic reserved bit */ - { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */ - { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ - { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ - { 0x50, 0xb3 }, /* "matrix coefficient 2" */ - { 0x51, 0 }, /* vb */ - { 0x52, 0x3d }, /* "matrix coefficient 4" */ - { 0x53, 0xa7 }, /* "matrix coefficient 5" */ - { 0x54, 0xe4 }, /* "matrix coefficient 6" */ - { REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2 }, /* Magic rsvd bit */ - { 0xff, 0xff }, -}; - - - - -/* - * Low-level register I/O. - */ - -static int ov7670_read(struct i2c_client *c, unsigned char reg, - unsigned char *value) -{ - int ret; - - ret = i2c_smbus_read_byte_data(c, reg); - if (ret >= 0) - *value = (unsigned char) ret; - return ret; -} - - -static int ov7670_write(struct i2c_client *c, unsigned char reg, - unsigned char value) -{ - return i2c_smbus_write_byte_data(c, reg, value); -} - - -/* - * Write a list of register settings; ff/ff stops the process. - */ -static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) -{ - while (vals->reg_num != 0xff || vals->value != 0xff) { - int ret = ov7670_write(c, vals->reg_num, vals->value); - if (ret < 0) - return ret; - vals++; - } - return 0; -} - - -/* - * Stuff that knows about the sensor. - */ -static void ov7670_reset(struct i2c_client *client) -{ - ov7670_write(client, REG_COM7, COM7_RESET); - msleep(1); -} - - -static int ov7670_init(struct i2c_client *client) -{ - return ov7670_write_array(client, ov7670_default_regs); -} - - - -static int ov7670_detect(struct i2c_client *client) -{ - unsigned char v; - int ret; - - ret = ov7670_init(client); - if (ret < 0) - return ret; - ret = ov7670_read(client, REG_MIDH, &v); - if (ret < 0) - return ret; - if (v != 0x7f) /* OV manuf. id. */ - return -ENODEV; - ret = ov7670_read(client, REG_MIDL, &v); - if (ret < 0) - return ret; - if (v != 0xa2) - return -ENODEV; - /* - * OK, we know we have an OmniVision chip...but which one? - */ - ret = ov7670_read(client, REG_PID, &v); - if (ret < 0) - return ret; - if (v != 0x76) /* PID + VER = 0x76 / 0x73 */ - return -ENODEV; - ret = ov7670_read(client, REG_VER, &v); - if (ret < 0) - return ret; - if (v != 0x73) /* PID + VER = 0x76 / 0x73 */ - return -ENODEV; - return 0; -} - - -/* - * Store information about the video data format. The color matrix - * is deeply tied into the format, so keep the relevant values here. - * The magic matrix nubmers come from OmniVision. - */ -static struct ov7670_format_struct { - __u8 *desc; - __u32 pixelformat; - struct regval_list *regs; - int cmatrix[CMATRIX_LEN]; -} ov7670_formats[] = { - { - .desc = "YUYV 4:2:2", - .pixelformat = V4L2_PIX_FMT_YUYV, - .regs = ov7670_fmt_yuv422, - .cmatrix = { 128, -128, 0, -34, -94, 128 }, - }, - { - .desc = "RGB 444", - .pixelformat = V4L2_PIX_FMT_RGB444, - .regs = ov7670_fmt_rgb444, - .cmatrix = { 179, -179, 0, -61, -176, 228 }, - }, - { - .desc = "RGB 565", - .pixelformat = V4L2_PIX_FMT_RGB565, - .regs = ov7670_fmt_rgb565, - .cmatrix = { 179, -179, 0, -61, -176, 228 }, - }, -}; -#define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0])) - -/* - * All formats we support are 2 bytes/pixel. - */ -#define BYTES_PER_PIXEL 2 - -/* - * Then there is the issue of window sizes. Try to capture the info here. - */ - -/* - * QCIF mode is done (by OV) in a very strange way - it actually looks like - * VGA with weird scaling options - they do *not* use the canned QCIF mode - * which is allegedly provided by the sensor. So here's the weird register - * settings. - */ -static struct regval_list ov7670_qcif_regs[] = { - { REG_COM3, COM3_SCALEEN|COM3_DCWEN }, - { REG_COM3, COM3_DCWEN }, - { REG_COM14, COM14_DCWEN | 0x01}, - { 0x73, 0xf1 }, - { 0xa2, 0x52 }, - { 0x7b, 0x1c }, - { 0x7c, 0x28 }, - { 0x7d, 0x3c }, - { 0x7f, 0x69 }, - { REG_COM9, 0x38 }, - { 0xa1, 0x0b }, - { 0x74, 0x19 }, - { 0x9a, 0x80 }, - { 0x43, 0x14 }, - { REG_COM13, 0xc0 }, - { 0xff, 0xff }, -}; - -static struct ov7670_win_size { - int width; - int height; - unsigned char com7_bit; - int hstart; /* Start/stop values for the camera. Note */ - int hstop; /* that they do not always make complete */ - int vstart; /* sense to humans, but evidently the sensor */ - int vstop; /* will do the right thing... */ - struct regval_list *regs; /* Regs to tweak */ -/* h/vref stuff */ -} ov7670_win_sizes[] = { - /* VGA */ - { - .width = VGA_WIDTH, - .height = VGA_HEIGHT, - .com7_bit = COM7_FMT_VGA, - .hstart = 158, /* These values from */ - .hstop = 14, /* Omnivision */ - .vstart = 10, - .vstop = 490, - .regs = NULL, - }, - /* CIF */ - { - .width = CIF_WIDTH, - .height = CIF_HEIGHT, - .com7_bit = COM7_FMT_CIF, - .hstart = 170, /* Empirically determined */ - .hstop = 90, - .vstart = 14, - .vstop = 494, - .regs = NULL, - }, - /* QVGA */ - { - .width = QVGA_WIDTH, - .height = QVGA_HEIGHT, - .com7_bit = COM7_FMT_QVGA, - .hstart = 164, /* Empirically determined */ - .hstop = 20, - .vstart = 14, - .vstop = 494, - .regs = NULL, - }, - /* QCIF */ - { - .width = QCIF_WIDTH, - .height = QCIF_HEIGHT, - .com7_bit = COM7_FMT_VGA, /* see comment above */ - .hstart = 456, /* Empirically determined */ - .hstop = 24, - .vstart = 14, - .vstop = 494, - .regs = ov7670_qcif_regs, - }, -}; - -#define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0])) - - -/* - * Store a set of start/stop values into the camera. - */ -static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, - int vstart, int vstop) -{ - int ret; - unsigned char v; -/* - * Horizontal: 11 bits, top 8 live in hstart and hstop. Bottom 3 of - * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is - * a mystery "edge offset" value in the top two bits of href. - */ - ret = ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff); - ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff); - ret += ov7670_read(client, REG_HREF, &v); - v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7); - msleep(10); - ret += ov7670_write(client, REG_HREF, v); -/* - * Vertical: similar arrangement, but only 10 bits. - */ - ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff); - ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff); - ret += ov7670_read(client, REG_VREF, &v); - v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3); - msleep(10); - ret += ov7670_write(client, REG_VREF, v); - return ret; -} - - -static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) -{ - struct ov7670_format_struct *ofmt; - - if (fmt->index >= N_OV7670_FMTS) - return -EINVAL; - - ofmt = ov7670_formats + fmt->index; - fmt->flags = 0; - strcpy(fmt->description, ofmt->desc); - fmt->pixelformat = ofmt->pixelformat; - return 0; -} - - -static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, - struct ov7670_format_struct **ret_fmt, - struct ov7670_win_size **ret_wsize) -{ - int index; - struct ov7670_win_size *wsize; - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - for (index = 0; index < N_OV7670_FMTS; index++) - if (ov7670_formats[index].pixelformat == pix->pixelformat) - break; - if (index >= N_OV7670_FMTS) - return -EINVAL; - if (ret_fmt != NULL) - *ret_fmt = ov7670_formats + index; - /* - * Fields: the OV devices claim to be progressive. - */ - if (pix->field == V4L2_FIELD_ANY) - pix->field = V4L2_FIELD_NONE; - else if (pix->field != V4L2_FIELD_NONE) - return -EINVAL; - /* - * Round requested image size down to the nearest - * we support, but not below the smallest. - */ - for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; - wsize++) - if (pix->width >= wsize->width && pix->height >= wsize->height) - break; - if (wsize >= ov7670_win_sizes + N_WIN_SIZES) - wsize--; /* Take the smallest one */ - if (ret_wsize != NULL) - *ret_wsize = wsize; - /* - * Note the size we'll actually handle. - */ - pix->width = wsize->width; - pix->height = wsize->height; - pix->bytesperline = pix->width*BYTES_PER_PIXEL; - pix->sizeimage = pix->height*pix->bytesperline; - return 0; -} - -/* - * Set a format. - */ -static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) -{ - int ret; - struct ov7670_format_struct *ovfmt; - struct ov7670_win_size *wsize; - struct ov7670_info *info = i2c_get_clientdata(c); - unsigned char com7; - - ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize); - if (ret) - return ret; - /* - * COM7 is a pain in the ass, it doesn't like to be read then - * quickly written afterward. But we have everything we need - * to set it absolutely here, as long as the format-specific - * register sets list it first. - */ - com7 = ovfmt->regs[0].value; - com7 |= wsize->com7_bit; - ov7670_write(c, REG_COM7, com7); - /* - * Now write the rest of the array. Also store start/stops - */ - ov7670_write_array(c, ovfmt->regs + 1); - ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart, - wsize->vstop); - ret = 0; - if (wsize->regs) - ret = ov7670_write_array(c, wsize->regs); - info->fmt = ovfmt; - return 0; -} - -/* - * Implement G/S_PARM. There is a "high quality" mode we could try - * to do someday; for now, we just do the frame rate tweak. - */ -static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) -{ - struct v4l2_captureparm *cp = &parms->parm.capture; - unsigned char clkrc; - int ret; - - if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - ret = ov7670_read(c, REG_CLKRC, &clkrc); - if (ret < 0) - return ret; - memset(cp, 0, sizeof(struct v4l2_captureparm)); - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->timeperframe.numerator = 1; - cp->timeperframe.denominator = OV7670_FRAME_RATE; - if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) - cp->timeperframe.denominator /= (clkrc & CLK_SCALE); - return 0; -} - -static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) -{ - struct v4l2_captureparm *cp = &parms->parm.capture; - struct v4l2_fract *tpf = &cp->timeperframe; - unsigned char clkrc; - int ret, div; - - if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (cp->extendedmode != 0) - return -EINVAL; - /* - * CLKRC has a reserved bit, so let's preserve it. - */ - ret = ov7670_read(c, REG_CLKRC, &clkrc); - if (ret < 0) - return ret; - if (tpf->numerator == 0 || tpf->denominator == 0) - div = 1; /* Reset to full rate */ - else - div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator; - if (div == 0) - div = 1; - else if (div > CLK_SCALE) - div = CLK_SCALE; - clkrc = (clkrc & 0x80) | div; - tpf->numerator = 1; - tpf->denominator = OV7670_FRAME_RATE/div; - return ov7670_write(c, REG_CLKRC, clkrc); -} - - - -/* - * Code for dealing with controls. - */ - - - - - -static int ov7670_store_cmatrix(struct i2c_client *client, - int matrix[CMATRIX_LEN]) -{ - int i, ret; - unsigned char signbits; - - /* - * Weird crap seems to exist in the upper part of - * the sign bits register, so let's preserve it. - */ - ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits); - signbits &= 0xc0; - - for (i = 0; i < CMATRIX_LEN; i++) { - unsigned char raw; - - if (matrix[i] < 0) { - signbits |= (1 << i); - if (matrix[i] < -255) - raw = 0xff; - else - raw = (-1 * matrix[i]) & 0xff; - } - else { - if (matrix[i] > 255) - raw = 0xff; - else - raw = matrix[i] & 0xff; - } - ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw); - } - ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits); - return ret; -} - - -/* - * Hue also requires messing with the color matrix. It also requires - * trig functions, which tend not to be well supported in the kernel. - * So here is a simple table of sine values, 0-90 degrees, in steps - * of five degrees. Values are multiplied by 1000. - * - * The following naive approximate trig functions require an argument - * carefully limited to -180 <= theta <= 180. - */ -#define SIN_STEP 5 -static const int ov7670_sin_table[] = { - 0, 87, 173, 258, 342, 422, - 499, 573, 642, 707, 766, 819, - 866, 906, 939, 965, 984, 996, - 1000 -}; - -static int ov7670_sine(int theta) -{ - int chs = 1; - int sine; - - if (theta < 0) { - theta = -theta; - chs = -1; - } - if (theta <= 90) - sine = ov7670_sin_table[theta/SIN_STEP]; - else { - theta -= 90; - sine = 1000 - ov7670_sin_table[theta/SIN_STEP]; - } - return sine*chs; -} - -static int ov7670_cosine(int theta) -{ - theta = 90 - theta; - if (theta > 180) - theta -= 360; - else if (theta < -180) - theta += 360; - return ov7670_sine(theta); -} - - - - -static void ov7670_calc_cmatrix(struct ov7670_info *info, - int matrix[CMATRIX_LEN]) -{ - int i; - /* - * Apply the current saturation setting first. - */ - for (i = 0; i < CMATRIX_LEN; i++) - matrix[i] = (info->fmt->cmatrix[i]*info->sat) >> 7; - /* - * Then, if need be, rotate the hue value. - */ - if (info->hue != 0) { - int sinth, costh, tmpmatrix[CMATRIX_LEN]; - - memcpy(tmpmatrix, matrix, CMATRIX_LEN*sizeof(int)); - sinth = ov7670_sine(info->hue); - costh = ov7670_cosine(info->hue); - - matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000; - matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000; - matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000; - matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000; - matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000; - matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000; - } -} - - - -static int ov7670_t_sat(struct i2c_client *client, int value) -{ - struct ov7670_info *info = i2c_get_clientdata(client); - int matrix[CMATRIX_LEN]; - int ret; - - info->sat = value; - ov7670_calc_cmatrix(info, matrix); - ret = ov7670_store_cmatrix(client, matrix); - return ret; -} - -static int ov7670_q_sat(struct i2c_client *client, __s32 *value) -{ - struct ov7670_info *info = i2c_get_clientdata(client); - - *value = info->sat; - return 0; -} - -static int ov7670_t_hue(struct i2c_client *client, int value) -{ - struct ov7670_info *info = i2c_get_clientdata(client); - int matrix[CMATRIX_LEN]; - int ret; - - if (value < -180 || value > 180) - return -EINVAL; - info->hue = value; - ov7670_calc_cmatrix(info, matrix); - ret = ov7670_store_cmatrix(client, matrix); - return ret; -} - - -static int ov7670_q_hue(struct i2c_client *client, __s32 *value) -{ - struct ov7670_info *info = i2c_get_clientdata(client); - - *value = info->hue; - return 0; -} - - -/* - * Some weird registers seem to store values in a sign/magnitude format! - */ -static unsigned char ov7670_sm_to_abs(unsigned char v) -{ - if ((v & 0x80) == 0) - return v + 128; - else - return 128 - (v & 0x7f); -} - - -static unsigned char ov7670_abs_to_sm(unsigned char v) -{ - if (v > 127) - return v & 0x7f; - else - return (128 - v) | 0x80; -} - -static int ov7670_t_brightness(struct i2c_client *client, int value) -{ - unsigned char com8, v; - int ret; - - ov7670_read(client, REG_COM8, &com8); - com8 &= ~COM8_AEC; - ov7670_write(client, REG_COM8, com8); - v = ov7670_abs_to_sm(value); - ret = ov7670_write(client, REG_BRIGHT, v); - return ret; -} - -static int ov7670_q_brightness(struct i2c_client *client, __s32 *value) -{ - unsigned char v; - int ret = ov7670_read(client, REG_BRIGHT, &v); - - *value = ov7670_sm_to_abs(v); - return ret; -} - -static int ov7670_t_contrast(struct i2c_client *client, int value) -{ - return ov7670_write(client, REG_CONTRAS, (unsigned char) value); -} - -static int ov7670_q_contrast(struct i2c_client *client, __s32 *value) -{ - unsigned char v; - int ret = ov7670_read(client, REG_CONTRAS, &v); - - *value = v; - return ret; -} - -static int ov7670_q_hflip(struct i2c_client *client, __s32 *value) -{ - int ret; - unsigned char v; - - ret = ov7670_read(client, REG_MVFP, &v); - *value = (v & MVFP_MIRROR) == MVFP_MIRROR; - return ret; -} - - -static int ov7670_t_hflip(struct i2c_client *client, int value) -{ - unsigned char v; - int ret; - - ret = ov7670_read(client, REG_MVFP, &v); - if (value) - v |= MVFP_MIRROR; - else - v &= ~MVFP_MIRROR; - msleep(10); /* FIXME */ - ret += ov7670_write(client, REG_MVFP, v); - return ret; -} - - - -static int ov7670_q_vflip(struct i2c_client *client, __s32 *value) -{ - int ret; - unsigned char v; - - ret = ov7670_read(client, REG_MVFP, &v); - *value = (v & MVFP_FLIP) == MVFP_FLIP; - return ret; -} - - -static int ov7670_t_vflip(struct i2c_client *client, int value) -{ - unsigned char v; - int ret; - - ret = ov7670_read(client, REG_MVFP, &v); - if (value) - v |= MVFP_FLIP; - else - v &= ~MVFP_FLIP; - msleep(10); /* FIXME */ - ret += ov7670_write(client, REG_MVFP, v); - return ret; -} - - -static struct ov7670_control { - struct v4l2_queryctrl qc; - int (*query)(struct i2c_client *c, __s32 *value); - int (*tweak)(struct i2c_client *c, int value); -} ov7670_controls[] = -{ - { - .qc = { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 0x80, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_brightness, - .query = ov7670_q_brightness, - }, - { - .qc = { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 0x40, /* XXX ov7670 spec */ - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_contrast, - .query = ov7670_q_contrast, - }, - { - .qc = { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 256, - .step = 1, - .default_value = 0x80, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_sat, - .query = ov7670_q_sat, - }, - { - .qc = { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "HUE", - .minimum = -180, - .maximum = 180, - .step = 5, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_hue, - .query = ov7670_q_hue, - }, - { - .qc = { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .tweak = ov7670_t_vflip, - .query = ov7670_q_vflip, - }, - { - .qc = { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Horizontal mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .tweak = ov7670_t_hflip, - .query = ov7670_q_hflip, - }, -}; -#define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0])) - -static struct ov7670_control *ov7670_find_control(__u32 id) -{ - int i; - - for (i = 0; i < N_CONTROLS; i++) - if (ov7670_controls[i].qc.id == id) - return ov7670_controls + i; - return NULL; -} - - -static int ov7670_queryctrl(struct i2c_client *client, - struct v4l2_queryctrl *qc) -{ - struct ov7670_control *ctrl = ov7670_find_control(qc->id); - - if (ctrl == NULL) - return -EINVAL; - *qc = ctrl->qc; - return 0; -} - -static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) -{ - struct ov7670_control *octrl = ov7670_find_control(ctrl->id); - int ret; - - if (octrl == NULL) - return -EINVAL; - ret = octrl->query(client, &ctrl->value); - if (ret >= 0) - return 0; - return ret; -} - -static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) -{ - struct ov7670_control *octrl = ov7670_find_control(ctrl->id); - int ret; - - if (octrl == NULL) - return -EINVAL; - ret = octrl->tweak(client, ctrl->value); - if (ret >= 0) - return 0; - return ret; -} - - - - - - -/* - * Basic i2c stuff. - */ -static struct i2c_driver ov7670_driver; - -static int ov7670_attach(struct i2c_adapter *adapter) -{ - int ret; - struct i2c_client *client; - struct ov7670_info *info; - - /* - * For now: only deal with adapters we recognize. - */ - if (adapter->id != I2C_HW_SMBUS_CAFE) - return -ENODEV; - - client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL); - if (! client) - return -ENOMEM; - client->adapter = adapter; - client->addr = OV7670_I2C_ADDR; - client->driver = &ov7670_driver, - strcpy(client->name, "OV7670"); - /* - * Set up our info structure. - */ - info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL); - if (! info) { - ret = -ENOMEM; - goto out_free; - } - info->fmt = &ov7670_formats[0]; - info->sat = 128; /* Review this */ - i2c_set_clientdata(client, info); - - /* - * Make sure it's an ov7670 - */ - ret = ov7670_detect(client); - if (ret) - goto out_free_info; - i2c_attach_client(client); - return 0; - - out_free_info: - kfree(info); - out_free: - kfree(client); - return ret; -} - - -static int ov7670_detach(struct i2c_client *client) -{ - i2c_detach_client(client); - kfree(i2c_get_clientdata(client)); - kfree(client); - return 0; -} - - -static int ov7670_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - switch (cmd) { - case VIDIOC_INT_G_CHIP_IDENT: - * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670; - return 0; - - case VIDIOC_INT_RESET: - ov7670_reset(client); - return 0; - - case VIDIOC_INT_INIT: - return ov7670_init(client); - - case VIDIOC_ENUM_FMT: - return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg); - case VIDIOC_TRY_FMT: - return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL); - case VIDIOC_S_FMT: - return ov7670_s_fmt(client, (struct v4l2_format *) arg); - case VIDIOC_QUERYCTRL: - return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg); - case VIDIOC_S_CTRL: - return ov7670_s_ctrl(client, (struct v4l2_control *) arg); - case VIDIOC_G_CTRL: - return ov7670_g_ctrl(client, (struct v4l2_control *) arg); - case VIDIOC_S_PARM: - return ov7670_s_parm(client, (struct v4l2_streamparm *) arg); - case VIDIOC_G_PARM: - return ov7670_g_parm(client, (struct v4l2_streamparm *) arg); - } - return -EINVAL; -} - - - -static struct i2c_driver ov7670_driver = { - .driver = { - .name = "ov7670", - }, - .id = I2C_DRIVERID_OV7670, - .class = I2C_CLASS_CAM_DIGITAL, - .attach_adapter = ov7670_attach, - .detach_client = ov7670_detach, - .command = ov7670_command, -}; - - -/* - * Module initialization - */ -static int __init ov7670_mod_init(void) -{ - printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n"); - return i2c_add_driver(&ov7670_driver); -} - -static void __exit ov7670_mod_exit(void) -{ - i2c_del_driver(&ov7670_driver); -} - -module_init(ov7670_mod_init); -module_exit(ov7670_mod_exit); diff --git a/trunk/drivers/media/video/planb.c b/trunk/drivers/media/video/planb.c index 86d2884e16c6..368d6e219fa4 100644 --- a/trunk/drivers/media/video/planb.c +++ b/trunk/drivers/media/video/planb.c @@ -138,7 +138,7 @@ static int grabbuf_alloc(struct planb *pb) + MAX_LNUM #endif /* PLANB_GSCANLINE */ ); - if ((pb->rawbuf = kmalloc(npage + if ((pb->rawbuf = (unsigned char**) kmalloc (npage * sizeof(unsigned long), GFP_KERNEL)) == 0) return -ENOMEM; for (i = 0; i < npage; i++) { diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/trunk/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 848fb233d808..c80c26be6e4d 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -260,22 +260,6 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, sizeof(decoder_ops[0]))) - 1; hdw->decoder_ctrl = &ctxt->ctrl; cp->handler = &ctxt->handler; - { - /* - Mike Isely 19-Nov-2006 - This bit - of nuttiness for cx25840 causes that module to - correctly set up its video scaling. This is really - a problem in the cx25840 module itself, but we work - around it here. The problem has not been seen in - ivtv because there VBI is supported and set up. We - don't do VBI here (at least not yet) and thus we - never attempted to even set it up. - */ - struct v4l2_format fmt; - memset(&fmt,0,sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt); - } pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", cp->client->addr); return !0; diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c index d2004965187b..1f787333d18c 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -356,6 +356,28 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) return 0; } +static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp) +{ + /* If we're dealing with a 24xxx device, force the horizontal + maximum to be 720 no matter what, since we can't get the device + to work properly with any other value. Otherwise just return + the normal value. */ + *vp = cptr->info->def.type_int.max_value; + if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; + return 0; +} + +static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp) +{ + /* If we're dealing with a 24xxx device, force the horizontal + minimum to be 720 no matter what, since we can't get the device + to work properly with any other value. Otherwise just return + the normal value. */ + *vp = cptr->info->def.type_int.min_value; + if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; + return 0; +} + static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) { /* Actual maximum depends on the video standard in effect. */ @@ -736,6 +758,10 @@ static const struct pvr2_ctl_info control_defs[] = { .default_value = 720, DEFREF(res_hor), DEFINT(19,720), + /* Hook in check for clamp on horizontal resolution in + order to avoid unsolved problem involving cx25840. */ + .get_max_value = ctrl_hres_max_get, + .get_min_value = ctrl_hres_min_get, },{ .desc = "Vertical capture resolution", .name = "resolution_ver", diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/trunk/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index f9bb41d8f4f3..3b9012f8e380 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -185,79 +185,6 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw, } } - -/* This is a special entry point for cases of I2C transaction attempts to - the IR receiver. The implementation here simulates the IR receiver by - issuing a command to the FX2 firmware and using that response to return - what the real I2C receiver would have returned. We use this for 24xxx - devices, where the IR receiver chip has been removed and replaced with - FX2 related logic. */ -static int i2c_24xxx_ir(struct pvr2_hdw *hdw, - u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) -{ - u8 dat[4]; - unsigned int stat; - - if (!(rlen || wlen)) { - /* This is a probe attempt. Just let it succeed. */ - return 0; - } - - /* We don't understand this kind of transaction */ - if ((wlen != 0) || (rlen == 0)) return -EIO; - - if (rlen < 3) { - /* Mike Isely Appears to be a probe - attempt from lirc. Just fill in zeroes and return. If - we try instead to do the full transaction here, then bad - things seem to happen within the lirc driver module - (version 0.8.0-7 sources from Debian, when run under - vanilla 2.6.17.6 kernel) - and I don't have the patience - to chase it down. */ - if (rlen > 0) rdata[0] = 0; - if (rlen > 1) rdata[1] = 0; - return 0; - } - - /* Issue a command to the FX2 to read the IR receiver. */ - LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = 0xec; - stat = pvr2_send_request(hdw, - hdw->cmd_buffer,1, - hdw->cmd_buffer,4); - dat[0] = hdw->cmd_buffer[0]; - dat[1] = hdw->cmd_buffer[1]; - dat[2] = hdw->cmd_buffer[2]; - dat[3] = hdw->cmd_buffer[3]; - } while (0); LOCK_GIVE(hdw->ctl_lock); - - /* Give up if that operation failed. */ - if (stat != 0) return stat; - - /* Mangle the results into something that looks like the real IR - receiver. */ - rdata[2] = 0xc1; - if (dat[0] != 1) { - /* No code received. */ - rdata[0] = 0; - rdata[1] = 0; - } else { - u16 val; - /* Mash the FX2 firmware-provided IR code into something - that the normal i2c chip-level driver expects. */ - val = dat[1]; - val <<= 8; - val |= dat[2]; - val >>= 1; - val &= ~0x0003; - val |= 0x8000; - rdata[0] = (val >> 8) & 0xffu; - rdata[1] = val & 0xffu; - } - - return 0; -} - /* This is a special entry point that is entered if an I2C operation is attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this part doesn't work, but we know it is really there. So let's look for @@ -960,17 +887,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) { unsigned int idx; - /* The default action for all possible I2C addresses is just to do - the transfer normally. */ + // The default action for all possible I2C addresses is just to do + // the transfer normally. for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { hdw->i2c_func[idx] = pvr2_i2c_basic_op; } - /* However, deal with various special cases for 24xxx hardware. */ + // If however we're dealing with new hardware, insert some hacks in + // the I2C transfer stack to let things work better. if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { hdw->i2c_func[0x1b] = i2c_hack_wm8775; hdw->i2c_func[0x44] = i2c_hack_cx25840; - hdw->i2c_func[0x18] = i2c_24xxx_ir; } // Configure the adapter and set up everything else related to it. diff --git a/trunk/drivers/media/video/saa7115.c b/trunk/drivers/media/video/saa7115.c index c2374ed7ba9f..f28398dd9d93 100644 --- a/trunk/drivers/media/video/saa7115.c +++ b/trunk/drivers/media/video/saa7115.c @@ -851,7 +851,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) /* On 60Hz, it is using a higher Vertical Output Size */ if (!is_50hz) - res += (VRES_60HZ - 480) >> 1; + res+=(VRES_60HZ-480)>>1; /* height */ saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, @@ -907,7 +907,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) /* Activates task "B" */ saa711x_write(client, R_80_GLOBAL_CNTL_1, - saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20); + saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20); return 0; } @@ -932,11 +932,11 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) if (std & V4L2_STD_525_60) { v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); saa711x_writeregs(client, saa7115_cfg_60hz_video); - saa711x_set_size(client, 720, 480); + saa711x_set_size(client,720,480); } else { v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); saa711x_writeregs(client, saa7115_cfg_50hz_video); - saa711x_set_size(client, 720, 576); + saa711x_set_size(client,720,576); } /* Register 0E - Bits D6-D4 on NO-AUTO mode @@ -1464,13 +1464,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) client->driver = &i2c_driver_saa711x; snprintf(client->name, sizeof(client->name) - 1, "saa7115"); - for (i = 0; i < 0x0f; i++) { + for (i=0;i<0x0f;i++) { saa711x_write(client, 0, i); - name[i] = (saa711x_read(client, 0) & 0x0f) + '0'; - if (name[i] > '9') - name[i] += 'a' - '9' - 1; + name[i] = (saa711x_read(client, 0) &0x0f) +'0'; + if (name[i]>'9') + name[i]+='a'-'9'-1; } - name[i] = '\0'; + name[i]='\0'; saa711x_write(client, 0, 5); chip_id = saa711x_read(client, 0) & 0x0f; diff --git a/trunk/drivers/media/video/saa7134/saa7134-alsa.c b/trunk/drivers/media/video/saa7134/saa7134-alsa.c index ffb0f647a86d..4abf5c03a740 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-alsa.c +++ b/trunk/drivers/media/video/saa7134/saa7134-alsa.c @@ -1,6 +1,10 @@ /* * SAA713x ALSA support for V4L * + * + * Caveats: + * - Volume doesn't work (it's always at max) + * * 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, version 2 @@ -610,18 +614,13 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) snd_card_saa7134_pcm_t *pcm; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev = saa7134->dev; - int amux, err; + int err; mutex_lock(&dev->dmasound.lock); dev->dmasound.read_count = 0; dev->dmasound.read_offset = 0; - amux = dev->input->amux; - if ((amux < 1) || (amux > 3)) - amux = 1; - dev->dmasound.input = amux - 1; - mutex_unlock(&dev->dmasound.lock); pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); @@ -714,8 +713,6 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); - struct saa7134_dev *dev = chip->dev; - int change, addr = kcontrol->private_value; int left, right; @@ -730,52 +727,10 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, if (right > 20) right = 20; spin_lock_irq(&chip->mixer_lock); - change = 0; - if (chip->mixer_volume[addr][0] != left) { - change = 1; - right = left; - } - if (chip->mixer_volume[addr][1] != right) { - change = 1; - left = right; - } - if (change) { - switch (dev->pci->device) { - case PCI_DEVICE_ID_PHILIPS_SAA7134: - switch (addr) { - case MIXER_ADDR_TVTUNER: - left = 20; - break; - case MIXER_ADDR_LINE1: - saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10, - (left > 10) ? 0x00 : 0x10); - break; - case MIXER_ADDR_LINE2: - saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20, - (left > 10) ? 0x00 : 0x20); - break; - } - break; - case PCI_DEVICE_ID_PHILIPS_SAA7133: - case PCI_DEVICE_ID_PHILIPS_SAA7135: - switch (addr) { - case MIXER_ADDR_TVTUNER: - left = 20; - break; - case MIXER_ADDR_LINE1: - saa_andorb(0x0594, 0x10, - (left > 10) ? 0x00 : 0x10); - break; - case MIXER_ADDR_LINE2: - saa_andorb(0x0594, 0x20, - (left > 10) ? 0x00 : 0x20); - break; - } - break; - } - chip->mixer_volume[addr][0] = left; - chip->mixer_volume[addr][1] = right; - } + change = chip->mixer_volume[addr][0] != left || + chip->mixer_volume[addr][1] != right; + chip->mixer_volume[addr][0] = left; + chip->mixer_volume[addr][1] = right; spin_unlock_irq(&chip->mixer_lock); return change; } diff --git a/trunk/drivers/media/video/saa7134/saa7134-cards.c b/trunk/drivers/media/video/saa7134/saa7134-cards.c index 4dead84aff46..51f0cfdcb680 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-cards.c +++ b/trunk/drivers/media/video/saa7134/saa7134-cards.c @@ -2462,17 +2462,14 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .tv = 1, - .gpio = 0x0000000, },{ .name = name_comp1, .vmux = 3, .amux = LINE2, - .gpio = 0x0200000, },{ .name = name_svideo, .vmux = 8, .amux = LINE2, - .gpio = 0x0200000, }}, .radio = { .name = name_radio, @@ -3025,158 +3022,6 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, - [SAA7134_BOARD_PINNACLE_PCTV_310i] = { - .name = "Pinnacle PCTV 310i", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_TDA8290, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .mpeg = SAA7134_MPEG_DVB, - .gpiomask = 0x000200000, - .inputs = {{ - .name = name_tv, - .vmux = 4, - .amux = TV, - .tv = 1, - },{ - .name = name_comp1, - .vmux = 1, - .amux = LINE2, - },{ - .name = name_comp2, - .vmux = 0, - .amux = LINE2, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, - }}, - .radio = { - .name = name_radio, - .amux = TV, - .gpio = 0x0200000, - }, - }, - [SAA7134_BOARD_AVERMEDIA_STUDIO_507] = { - /* Mikhail Fedotov */ - .name = "Avermedia AVerTV Studio 507", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FM1256_IH3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0x03, - .inputs = {{ - .name = name_tv, - .vmux = 1, - .amux = TV, - .tv = 1, - .gpio = 0x00, - },{ - .name = name_comp1, - .vmux = 0, - .amux = LINE2, - .gpio = 0x00, - },{ - .name = name_comp2, - .vmux = 3, - .amux = LINE2, - .gpio = 0x00, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, - .gpio = 0x00, - }}, - .radio = { - .name = name_radio, - .amux = LINE2, - .gpio = 0x01, - }, - .mute = { - .name = name_mute, - .amux = LINE1, - .gpio = 0x00, - }, - }, - [SAA7134_BOARD_VIDEOMATE_DVBT_200A] = { - /* Francis Barber */ - .name = "Compro Videomate DVB-T200A", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, - .mpeg = SAA7134_MPEG_DVB, - .inputs = {{ - .name = name_tv, - .vmux = 3, - .amux = TV, - .tv = 1, - },{ - .name = name_comp1, - .vmux = 1, - .amux = LINE2, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, - }}, - }, - [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { - /* Thomas Genty */ - .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_TDA8290, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .mpeg = SAA7134_MPEG_DVB, - .inputs = {{ - .name = name_tv, - .vmux = 1, - .amux = TV, - .tv = 1, - },{ - .name = name_comp1, - .vmux = 3, - .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ - }}, - .radio = { - .name = name_radio, - .amux = TV, - }, - }, - [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { - .name = "Terratec Cinergy HT PCMCIA", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_TDA8290, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .mpeg = SAA7134_MPEG_DVB, - .inputs = {{ - .name = name_tv, - .vmux = 1, - .amux = TV, - .tv = 1, - },{ - .name = name_comp1, - .vmux = 0, - .amux = LINE1, - },{ - .name = name_svideo, - .vmux = 6, - .amux = LINE1, - }}, - }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3785,36 +3630,6 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1043, .subdevice = 0x4860, .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x11bd, - .subdevice = 0x002f, - .driver_data = SAA7134_BOARD_PINNACLE_PCTV_310i, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x9715, - .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1043, - .subdevice = 0x4876, - .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6701, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x153b, - .subdevice = 0x1172, - .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3902,7 +3717,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_307: - case SAA7134_BOARD_AVERMEDIA_STUDIO_507: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: case SAA7134_BOARD_AVERMEDIA_777: /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ @@ -3911,7 +3725,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: - case SAA7134_BOARD_VIDEOMATE_DVBT_200A: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: @@ -3980,9 +3793,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) break; /* i2c remotes */ case SAA7134_BOARD_PINNACLE_PCTV_110i: - case SAA7134_BOARD_PINNACLE_PCTV_310i: case SAA7134_BOARD_UPMOST_PURPLE_TV: - case SAA7134_BOARD_HAUPPAUGE_HVR1110: dev->has_remote = SAA7134_REMOTE_I2C; break; case SAA7134_BOARD_AVERMEDIA_A169_B: @@ -4113,11 +3924,9 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PHILIPS_TIGER: - case SAA7134_BOARD_PINNACLE_PCTV_310i: case SAA7134_BOARD_TEVION_DVBT_220RF: case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_MEDION_MD8800_QUADRO: - case SAA7134_BOARD_HAUPPAUGE_HVR1110: /* this is a hybrid board, initialize to analog mode * and configure firmware eeprom address */ @@ -4143,14 +3952,6 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); } break; - case SAA7134_BOARD_CINERGY_HT_PCMCIA: - /* make the tda10046 find its eeprom */ - { - u8 data[] = { 0x3c, 0x33, 0x60}; - struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; - i2c_transfer(&dev->i2c_adap, &msg, 1); - } - break; case SAA7134_BOARD_KWORLD_ATSC110: { /* enable tuner */ @@ -4163,29 +3964,6 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, i); } break; - case SAA7134_BOARD_VIDEOMATE_DVBT_200: - case SAA7134_BOARD_VIDEOMATE_DVBT_200A: - /* The T200 and the T200A share the same pci id. Consequently, - * we are going to query eeprom to try to find out which one we - * are actually looking at. */ - - /* Don't do this if the board was specifically selected with an - * insmod option or if we have the default configuration T200*/ - if(!dev->autodetected || (dev->eedata[0x41] == 0xd0)) - break; - if(dev->eedata[0x41] == 0x02) { - /* Reconfigure board as T200A */ - dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A; - dev->tuner_type = saa7134_boards[dev->board].tuner_type; - dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; - printk(KERN_INFO "%s: Reconfigured board as %s\n", - dev->name, saa7134_boards[dev->board].name); - } else { - printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n", - dev->name, dev->eedata[0x41]); - break; - } - break; } return 0; } diff --git a/trunk/drivers/media/video/saa7134/saa7134-core.c b/trunk/drivers/media/video/saa7134/saa7134-core.c index ed038fff3b4f..5c9e63dfbea6 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-core.c +++ b/trunk/drivers/media/video/saa7134/saa7134-core.c @@ -889,16 +889,15 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, must_configure_manually(); dev->board = SAA7134_BOARD_UNKNOWN; } - dev->autodetected = card[dev->nr] != dev->board; dev->tuner_type = saa7134_boards[dev->board].tuner_type; dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; if (UNSET != tuner[dev->nr]) dev->tuner_type = tuner[dev->nr]; - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", - dev->name,pci_dev->subsystem_vendor, - pci_dev->subsystem_device,saa7134_boards[dev->board].name, - dev->board, dev->autodetected ? - "autodetected" : "insmod option"); + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + dev->name,pci_dev->subsystem_vendor, + pci_dev->subsystem_device,saa7134_boards[dev->board].name, + dev->board, card[dev->nr] == dev->board ? + "insmod option" : "autodetected"); /* get mmio */ if (!request_mem_region(pci_resource_start(pci_dev,0), diff --git a/trunk/drivers/media/video/saa7134/saa7134-dvb.c b/trunk/drivers/media/video/saa7134/saa7134-dvb.c index fa8339879095..6b61d9b2fcb5 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-dvb.c +++ b/trunk/drivers/media/video/saa7134/saa7134-dvb.c @@ -50,10 +50,6 @@ static unsigned int antenna_pwr = 0; module_param(antenna_pwr, int, 0444); MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); -static int use_frontent = 0; -module_param(use_frontent, int, 0644); -MODULE_PARM_DESC(use_frontent,"for cards with multiple frontends (0: terrestrial, 1: satellite)"); - /* ------------------------------------------------------------------ */ static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) { @@ -297,7 +293,7 @@ static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dv return philips_tda6651_pll_set(0x60, fe, params); } -static int philips_tda1004x_request_firmware(struct dvb_frontend *fe, +static int philips_tu1216_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name) { struct saa7134_dev *dev = fe->dvb->priv; @@ -312,7 +308,7 @@ static struct tda1004x_config philips_tu1216_60_config = { .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .request_firmware = philips_tda1004x_request_firmware, + .request_firmware = philips_tu1216_request_firmware, }; /* ------------------------------------------------------------------ */ @@ -335,12 +331,12 @@ static struct tda1004x_config philips_tu1216_61_config = { .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .request_firmware = philips_tda1004x_request_firmware, + .request_firmware = philips_tu1216_request_firmware, }; /* ------------------------------------------------------------------ */ -static int philips_td1316_tuner_init(struct dvb_frontend *fe) +static int philips_europa_tuner_init(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; @@ -351,8 +347,18 @@ static int philips_td1316_tuner_init(struct dvb_frontend *fe) fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) return -EIO; + msleep(1); + + /* switch the board to dvb mode */ + init_msg.addr = 0x43; + init_msg.len = 0x02; + msg[0] = 0x00; + msg[1] = 0x40; if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) + return -EIO; + return 0; } @@ -361,22 +367,6 @@ static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_f return philips_tda6651_pll_set(0x61, fe, params); } -static int philips_europa_tuner_init(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - static u8 msg[] = { 0x00, 0x40}; - struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) }; - - - if (philips_td1316_tuner_init(fe)) - return -EIO; - msleep(1); - if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) - return -EIO; - - return 0; -} - static int philips_europa_tuner_sleep(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; @@ -681,7 +671,7 @@ static struct tda1004x_config tda827x_lifeview_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, .if_freq = TDA10046_FREQ_045, .request_firmware = NULL, }; @@ -822,40 +812,32 @@ static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe) if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); return 0; } /* ------------------------------------------------------------------ */ -static int tda8290_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { + int ret; struct saa7134_dev *dev = fe->dvb->priv; static u8 tda8290_close[] = { 0x21, 0xc0}; static u8 tda8290_open[] = { 0x21, 0x80}; struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; - if (enable) { - tda8290_msg.buf = tda8290_close; - } else { - tda8290_msg.buf = tda8290_open; - } - if (i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1) != 1) + + /* close tda8290 i2c bridge */ + tda8290_msg.buf = tda8290_close; + ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); + if (ret != 1) return -EIO; msleep(20); - return 0; -} - -/* ------------------------------------------------------------------ */ - -static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) -{ - int ret; - ret = philips_tda827xa_pll_set(0x61, fe, params); if (ret != 0) return ret; - return 0; + /* open tda8290 i2c bridge */ + tda8290_msg.buf = tda8290_open; + i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); + return ret; } static int philips_tiger_tuner_init(struct dvb_frontend *fe) @@ -885,80 +867,13 @@ static struct tda1004x_config philips_tiger_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, - .if_freq = TDA10046_FREQ_045, - .request_firmware = NULL, -}; -/* ------------------------------------------------------------------ */ - -static int cinergy_ht_tuner_init(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - static u8 data[] = { 0x3c, 0x33, 0x62}; - struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; - - if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) - return -EIO; - return 0; -} - -static int cinergy_ht_tuner_sleep(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - static u8 data[] = { 0x3c, 0x33, 0x60}; - struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; - - i2c_transfer(&dev->i2c_adap, &msg, 1); - philips_tda827xa_tuner_sleep( 0x61, fe); - return 0; -} - -static struct tda1004x_config cinergy_ht_config = { - .demod_address = 0x08, - .invert = 1, - .invert_oclk = 0, - .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP01, + .agc_config = TDA10046_AGC_TDA827X, .if_freq = TDA10046_FREQ_045, .request_firmware = NULL, }; /* ------------------------------------------------------------------ */ -static struct tda1004x_config pinnacle_pctv_310i_config = { - .demod_address = 0x08, - .invert = 1, - .invert_oclk = 0, - .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, - .if_freq = TDA10046_FREQ_045, - .request_firmware = philips_tda1004x_request_firmware, -}; - -/* ------------------------------------------------------------------ */ - -static struct tda1004x_config hauppauge_hvr_1110_config = { - .demod_address = 0x08, - .invert = 1, - .invert_oclk = 0, - .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, - .if_freq = TDA10046_FREQ_045, - .request_firmware = philips_tda1004x_request_firmware, -}; - -/* ------------------------------------------------------------------ */ - -static struct tda1004x_config asus_p7131_dual_config = { - .demod_address = 0x08, - .invert = 1, - .invert_oclk = 0, - .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, - .if_freq = TDA10046_FREQ_045, - .request_firmware = philips_tda1004x_request_firmware, -}; - static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; @@ -1006,7 +921,7 @@ static struct tda1004x_config lifeview_trio_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP00, + .agc_config = TDA10046_AGC_TDA827X_GPL, .if_freq = TDA10046_FREQ_045, .request_firmware = NULL, }; @@ -1043,7 +958,7 @@ static struct tda1004x_config ads_tech_duo_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP00, + .agc_config = TDA10046_AGC_TDA827X_GPL, .if_freq = TDA10046_FREQ_045, .request_firmware = NULL, }; @@ -1068,7 +983,7 @@ static struct tda1004x_config tevion_dvbt220rf_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, .if_freq = TDA10046_FREQ_045, .request_firmware = NULL, }; @@ -1113,7 +1028,7 @@ static struct tda1004x_config md8800_dvbt_config = { .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, - .agc_config = TDA10046_AGC_TDA827X_GP11, + .agc_config = TDA10046_AGC_TDA827X, .if_freq = TDA10046_FREQ_045, .request_firmware = NULL, }; @@ -1253,29 +1168,6 @@ static int dvb_init(struct saa7134_dev *dev) &philips_tiger_config, &dev->i2c_adap); if (dev->dvb.frontend) { - dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; - } - break; - case SAA7134_BOARD_PINNACLE_PCTV_310i: - dev->dvb.frontend = dvb_attach(tda10046_attach, - &pinnacle_pctv_310i_config, - &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; - } - break; - case SAA7134_BOARD_HAUPPAUGE_HVR1110: - dev->dvb.frontend = dvb_attach(tda10046_attach, - &hauppauge_hvr_1110_config, - &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; @@ -1283,10 +1175,9 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: dev->dvb.frontend = dvb_attach(tda10046_attach, - &asus_p7131_dual_config, + &philips_tiger_config, &dev->i2c_adap); if (dev->dvb.frontend) { - dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init; dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep; dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; @@ -1303,27 +1194,12 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_FLYDVB_TRIO: - if(! use_frontent) { //terrestrial - dev->dvb.frontend = dvb_attach(tda10046_attach, - &lifeview_trio_config, - &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = - lifeview_trio_tuner_set_params; - } - } else { //satellite - dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, - &dev->i2c_adap, 0) == NULL) { - printk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__); - } - if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, - 0x08, 0, 0) == NULL) { - printk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__); - } - } + dev->dvb.frontend = dvb_attach(tda10046_attach, + &lifeview_trio_config, + &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params; } break; case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: @@ -1405,27 +1281,7 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; } break; - case SAA7134_BOARD_VIDEOMATE_DVBT_200A: - dev->dvb.frontend = dvb_attach(tda10046_attach, - &philips_europa_config, - &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; - } - break; - case SAA7134_BOARD_CINERGY_HT_PCMCIA: - dev->dvb.frontend = dvb_attach(tda10046_attach, - &cinergy_ht_config, - &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; - } - break; default: printk("%s: Huh? unknown DVB card?\n",dev->name); break; diff --git a/trunk/drivers/media/video/saa7134/saa7134-i2c.c b/trunk/drivers/media/video/saa7134/saa7134-i2c.c index 6f9fe86fed98..6162550c4136 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-i2c.c +++ b/trunk/drivers/media/video/saa7134/saa7134-i2c.c @@ -341,7 +341,6 @@ static int attach_inform(struct i2c_client *client) switch (client->addr) { case 0x7a: case 0x47: - case 0x71: { struct IR_i2c *ir = i2c_get_clientdata(client); d1printk("%s i2c IR detected (%s).\n", diff --git a/trunk/drivers/media/video/saa7134/saa7134-input.c b/trunk/drivers/media/video/saa7134/saa7134-input.c index 60b38defd9bc..dee83552e681 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-input.c +++ b/trunk/drivers/media/video/saa7134/saa7134-input.c @@ -112,27 +112,6 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - unsigned char buf[5], cod4, code3, code4; - - /* poll IR chip */ - if (5 != i2c_master_recv(&ir->c,buf,5)) - return -EIO; - - cod4 = buf[4]; - code4 = (cod4 >> 2); - code3 = buf[3]; - if (code3 == 0) - /* no key pressed */ - return 0; - - /* return key */ - *ir_key = code4; - *ir_raw = code4; - return 1; -} - void saa7134_input_irq(struct saa7134_dev *dev) { struct saa7134_ir *ir = dev->remote; @@ -152,23 +131,6 @@ static void saa7134_input_timer(unsigned long data) mod_timer(&ir->timer, timeout); } -static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir) -{ - if (ir->polling) { - init_timer(&ir->timer); - ir->timer.function = saa7134_input_timer; - ir->timer.data = (unsigned long)dev; - ir->timer.expires = jiffies + HZ; - add_timer(&ir->timer); - } -} - -static void saa7134_ir_stop(struct saa7134_dev *dev) -{ - if (dev->remote->polling) - del_timer_sync(&dev->remote->timer); -} - int saa7134_input_init1(struct saa7134_dev *dev) { struct saa7134_ir *ir; @@ -179,7 +141,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) u32 mask_keyup = 0; int polling = 0; int ir_type = IR_TYPE_OTHER; - int err; if (dev->has_remote != SAA7134_REMOTE_GPIO) return -ENODEV; @@ -223,7 +184,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_307: case SAA7134_BOARD_AVERMEDIA_STUDIO_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: - case SAA7134_BOARD_AVERMEDIA_STUDIO_507: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: ir_codes = ir_codes_avermedia; mask_keycode = 0x0007C8; @@ -306,8 +266,9 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir = kzalloc(sizeof(*ir), GFP_KERNEL); input_dev = input_allocate_device(); if (!ir || !input_dev) { - err = -ENOMEM; - goto err_out_free; + kfree(ir); + input_free_device(input_dev); + return -ENOMEM; } ir->dev = input_dev; @@ -338,22 +299,18 @@ int saa7134_input_init1(struct saa7134_dev *dev) } input_dev->cdev.dev = &dev->pci->dev; + /* all done */ dev->remote = ir; - saa7134_ir_start(dev, ir); - - err = input_register_device(ir->dev); - if (err) - goto err_out_stop; + if (ir->polling) { + init_timer(&ir->timer); + ir->timer.function = saa7134_input_timer; + ir->timer.data = (unsigned long)dev; + ir->timer.expires = jiffies + HZ; + add_timer(&ir->timer); + } + input_register_device(ir->dev); return 0; - - err_out_stop: - saa7134_ir_stop(dev); - dev->remote = NULL; - err_out_free: - input_free_device(input_dev); - kfree(ir); - return err; } void saa7134_input_fini(struct saa7134_dev *dev) @@ -361,7 +318,8 @@ void saa7134_input_fini(struct saa7134_dev *dev) if (NULL == dev->remote) return; - saa7134_ir_stop(dev); + if (dev->remote->polling) + del_timer_sync(&dev->remote->timer); input_unregister_device(dev->remote->dev); kfree(dev->remote); dev->remote = NULL; @@ -377,7 +335,6 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: - case SAA7134_BOARD_PINNACLE_PCTV_310i: snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); if (pinnacle_remote == 0) { ir->get_key = get_key_pinnacle_color; @@ -392,11 +349,6 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) ir->get_key = get_key_purpletv; ir->ir_codes = ir_codes_purpletv; break; - case SAA7134_BOARD_HAUPPAUGE_HVR1110: - snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); - ir->get_key = get_key_hvr1110; - ir->ir_codes = ir_codes_hauppauge_new; - break; default: dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); break; diff --git a/trunk/drivers/media/video/saa7134/saa7134.h b/trunk/drivers/media/video/saa7134/saa7134.h index e88ad7b40c47..7cf96b430250 100644 --- a/trunk/drivers/media/video/saa7134/saa7134.h +++ b/trunk/drivers/media/video/saa7134/saa7134.h @@ -227,11 +227,6 @@ struct saa7134_format { #define SAA7134_BOARD_PROTEUS_2309 98 #define SAA7134_BOARD_AVERMEDIA_A16AR 99 #define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100 -#define SAA7134_BOARD_PINNACLE_PCTV_310i 101 -#define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102 -#define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103 -#define SAA7134_BOARD_HAUPPAUGE_HVR1110 104 -#define SAA7134_BOARD_CINERGY_HT_PCMCIA 105 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -451,9 +446,6 @@ struct saa7134_dev { struct v4l2_prio_state prio; #endif - /* insmod option/autodetected */ - int autodetected; - /* various device info */ unsigned int resources; struct video_device *video_dev; diff --git a/trunk/drivers/media/video/stv680.c b/trunk/drivers/media/video/stv680.c index a1ec3aca3f91..6d1ef1e2e8ef 100644 --- a/trunk/drivers/media/video/stv680.c +++ b/trunk/drivers/media/video/stv680.c @@ -687,7 +687,7 @@ static int stv680_start_stream (struct usb_stv *stv680) stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); if (stv680->sbuf[i].data == NULL) { PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); - goto nomem_err; + return -1; } } @@ -698,7 +698,7 @@ static int stv680_start_stream (struct usb_stv *stv680) stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); if (stv680->scratch[i].data == NULL) { PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); - goto nomem_err; + return -1; } stv680->scratch[i].state = BUFFER_UNUSED; } @@ -706,7 +706,7 @@ static int stv680_start_stream (struct usb_stv *stv680) for (i = 0; i < STV680_NUMSBUF; i++) { urb = usb_alloc_urb (0, GFP_KERNEL); if (!urb) - goto nomem_err; + return -ENOMEM; /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ usb_fill_bulk_urb (urb, stv680->udev, @@ -721,21 +721,6 @@ static int stv680_start_stream (struct usb_stv *stv680) stv680->framecount = 0; return 0; - - nomem_err: - for (i = 0; i < STV680_NUMSCRATCH; i++) { - kfree(stv680->scratch[i].data); - stv680->scratch[i].data = NULL; - } - for (i = 0; i < STV680_NUMSBUF; i++) { - usb_kill_urb(stv680->urb[i]); - usb_free_urb(stv680->urb[i]); - stv680->urb[i] = NULL; - kfree(stv680->sbuf[i].data); - stv680->sbuf[i].data = NULL; - } - return -ENOMEM; - } static int stv680_stop_stream (struct usb_stv *stv680) diff --git a/trunk/drivers/media/video/tda9887.c b/trunk/drivers/media/video/tda9887.c index fde576f1101c..87ffb0e84a7a 100644 --- a/trunk/drivers/media/video/tda9887.c +++ b/trunk/drivers/media/video/tda9887.c @@ -482,12 +482,6 @@ static int tda9887_set_config(struct tuner *t, char *buf) buf[1] &= ~cQSS; if (t->tda9887_config & TDA9887_GATING_18) buf[3] &= ~cGating_36; - - if (t->tda9887_config & TDA9887_GAIN_NORMAL) { - radio_stereo.e &= ~cTunerGainLow; - radio_mono.e &= ~cTunerGainLow; - } - return 0; } diff --git a/trunk/drivers/media/video/tuner-core.c b/trunk/drivers/media/video/tuner-core.c index 705daaa2a4ff..40590bae5ff7 100644 --- a/trunk/drivers/media/video/tuner-core.c +++ b/trunk/drivers/media/video/tuner-core.c @@ -443,10 +443,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) printk("%02x ",buffer[i]); printk("\n"); } - /* HACK: This test were added to avoid tuner to probe tda9840 and tea6415c on the MXB card */ - if (adap->id == I2C_HW_SAA7146 && addr < 0x4a) - return -ENODEV; - /* autodetection code based on the i2c addr */ if (!no_autodetect) { switch (addr) { diff --git a/trunk/drivers/media/video/tuner-simple.c b/trunk/drivers/media/video/tuner-simple.c index 1b9b0742f753..63db4e97ae6c 100644 --- a/trunk/drivers/media/video/tuner-simple.c +++ b/trunk/drivers/media/video/tuner-simple.c @@ -108,7 +108,6 @@ static int tuner_stereo(struct i2c_client *c) case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: case TUNER_PHILIPS_FM1256_IH3: - case TUNER_LG_NTSC_TAPE: stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); break; default: @@ -422,7 +421,6 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: case TUNER_PHILIPS_FMD1216ME_MK3: - case TUNER_LG_NTSC_TAPE: buffer[3] = 0x19; break; case TUNER_TNF_5335MF: @@ -467,8 +465,6 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) config |= TDA9887_INTERCARRIER; /* if (params->port1_set_for_fm_mono) config &= ~TDA9887_PORT1_ACTIVE;*/ - if (params->fm_gain_normal) - config |= TDA9887_GAIN_NORMAL; i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); } if (4 != (rc = i2c_master_send(c,buffer,4))) diff --git a/trunk/drivers/media/video/tuner-types.c b/trunk/drivers/media/video/tuner-types.c index 74c3e6f96f1a..781682373b61 100644 --- a/trunk/drivers/media/video/tuner-types.c +++ b/trunk/drivers/media/video/tuner-types.c @@ -651,7 +651,6 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = { .has_tda9887 = 1, .port1_invert_for_secam_lc = 1, .default_pll_gating_18 = 1, - .fm_gain_normal=1, }, }; @@ -673,6 +672,16 @@ static struct tuner_params tuner_panasonic_vp27_params[] = { }, }; +/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ + +static struct tuner_params tuner_lg_ntsc_tape_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_fm1236_mk3_ntsc_ranges, + .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), + }, +}; + /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { @@ -1322,8 +1331,8 @@ struct tunertype tuners[] = { }, [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ .name = "LG NTSC (TAPE series)", - .params = tuner_fm1236_mk3_params, - .count = ARRAY_SIZE(tuner_fm1236_mk3_params), + .params = tuner_lg_ntsc_tape_params, + .count = ARRAY_SIZE(tuner_lg_ntsc_tape_params), }, [TUNER_TNF_8831BGFF] = { /* Philips PAL */ .name = "Tenna TNF 8831 BGFF)", diff --git a/trunk/drivers/media/video/tveeprom.c b/trunk/drivers/media/video/tveeprom.c index 2624e3f7dd29..6b9ef731b83a 100644 --- a/trunk/drivers/media/video/tveeprom.c +++ b/trunk/drivers/media/video/tveeprom.c @@ -430,7 +430,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, tvee->has_radio = eeprom_data[i+len-1]; /* old style tag, don't know how to detect IR presence, mark as unknown. */ - tvee->has_ir = -1; + tvee->has_ir = 2; tvee->model = eeprom_data[i+8] + (eeprom_data[i+9] << 8); @@ -653,14 +653,13 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, STRM(decoderIC, tvee->decoder_processor), tvee->decoder_processor); } - if (tvee->has_ir == -1) + if (tvee->has_ir == 2) tveeprom_info("has %sradio\n", tvee->has_radio ? "" : "no "); else - tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n", + tveeprom_info("has %sradio, has %sIR remote\n", tvee->has_radio ? "" : "no ", - (tvee->has_ir & 1) ? "" : "no ", - (tvee->has_ir & 2) ? "" : "no "); + tvee->has_ir ? "" : "no "); } EXPORT_SYMBOL(tveeprom_hauppauge_analog); diff --git a/trunk/drivers/media/video/usbvideo/quickcam_messenger.c b/trunk/drivers/media/video/usbvideo/quickcam_messenger.c index ec0ff2247f06..bbf2beeeb449 100644 --- a/trunk/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/trunk/drivers/media/video/usbvideo/quickcam_messenger.c @@ -86,7 +86,6 @@ MODULE_DEVICE_TABLE(usb, qcm_table); static void qcm_register_input(struct qcm *cam, struct usb_device *dev) { struct input_dev *input_dev; - int error; usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); @@ -107,13 +106,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) input_dev->private = cam; - error = input_register_device(cam->input); - if (error) { - warn("Failed to register camera's input device, err: %d\n", - error); - input_free_device(cam->input); - cam->input = NULL; - } + input_register_device(cam->input); } static void qcm_unregister_input(struct qcm *cam) diff --git a/trunk/drivers/media/video/usbvideo/usbvideo.c b/trunk/drivers/media/video/usbvideo/usbvideo.c index b560c9d7c516..d8b88024bc2f 100644 --- a/trunk/drivers/media/video/usbvideo/usbvideo.c +++ b/trunk/drivers/media/video/usbvideo/usbvideo.c @@ -690,7 +690,7 @@ int usbvideo_register( } base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); - cams = kzalloc(base_size, GFP_KERNEL); + cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL); if (cams == NULL) { err("Failed to allocate %d. bytes for usbvideo struct", base_size); return -ENOMEM; diff --git a/trunk/drivers/media/video/usbvision/Kconfig b/trunk/drivers/media/video/usbvision/Kconfig deleted file mode 100644 index fc24ef05b3f3..000000000000 --- a/trunk/drivers/media/video/usbvision/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config VIDEO_USBVISION - tristate "USB video devices based on Nogatech NT1003/1004/1005" - depends on I2C && VIDEO_V4L2 - select VIDEO_TUNER - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO - ---help--- - There are more than 50 different USB video devices based on - NT1003/1004/1005 USB Bridges. This driver enables using those - devices. - - To compile this driver as a module, choose M here: the - module will be called usbvision. diff --git a/trunk/drivers/media/video/usbvision/Makefile b/trunk/drivers/media/video/usbvision/Makefile deleted file mode 100644 index 9ac92a80c645..000000000000 --- a/trunk/drivers/media/video/usbvision/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o - -obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o - -EXTRA_CFLAGS += -Idrivers/media/video diff --git a/trunk/drivers/media/video/usbvision/usbvision-cards.c b/trunk/drivers/media/video/usbvision/usbvision-cards.c deleted file mode 100644 index 134eb9865df6..000000000000 --- a/trunk/drivers/media/video/usbvision/usbvision-cards.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * USBVISION.H - * usbvision header file - * - * Copyright (c) 1999-2005 Joerg Heckenbach - * - * This module is part of usbvision driver project. - * Updates to driver completed by Dwaine P. Garden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include -#include -#include -#include -#include "usbvision.h" - -/* Supported Devices: A table for usbvision.c*/ -struct usbvision_device_data_st usbvision_device_data[] = { - {0xFFF0, 0xFFF0, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Custom Dummy USBVision Device"}, - {0x0A6F, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "Xanboo"}, - {0x050D, 0x0208, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Belkin USBView II"}, - {0x0571, 0x0002, 0, CODEC_SAA7111, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, -1, -1, 7, "echoFX InterView Lite"}, - {0x0573, 0x0003, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "USBGear USBG-V1 resp. HAMA USB"}, - {0x0573, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "D-Link V100"}, - {0x0573, 0x2000, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "X10 USB Camera"}, - {0x0573, 0x2d00, -1, CODEC_SAA7111, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, -1, 3, 7, "Osprey 50"}, - {0x0573, 0x2d01, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Hauppauge USB-Live Model 600"}, - {0x0573, 0x2101, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 2, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Zoran Co. PMD (Nogatech) AV-grabber Manhattan"}, - {0x0573, 0x4100, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Nogatech USB-TV (NTSC) FM"}, - {0x0573, 0x4110, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "PNY USB-TV (NTSC) FM"}, - {0x0573, 0x4450, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "PixelView PlayTv-USB PRO (PAL) FM"}, - {0x0573, 0x4550, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "ZTV ZT-721 2.4GHz USB A/V Receiver"}, - {0x0573, 0x4d00, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Hauppauge WinTv-USB USA"}, - {0x0573, 0x4d01, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, - {0x0573, 0x4d02, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC)"}, - {0x0573, 0x4d03, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (SECAM) "}, - {0x0573, 0x4d10, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC) FM"}, - {0x0573, 0x4d11, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"}, - {0x0573, 0x4d12, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"}, - {0x0573, 0x4d2a, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B285"}, - {0x0573, 0x4d2b, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B282"}, - {0x0573, 0x4d2c, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (PAL/SECAM) 40209 Rev E1A5"}, - {0x0573, 0x4d20, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226"}, - {0x0573, 0x4d21, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL)"}, - {0x0573, 0x4d22, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) MODEL 566"}, - {0x0573, 0x4d23, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) 4D23"}, - {0x0573, 0x4d25, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B234"}, - {0x0573, 0x4d26, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B243"}, - {0x0573, 0x4d27, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B281"}, - {0x0573, 0x4d28, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B283"}, - {0x0573, 0x4d29, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40205 Rev B298"}, - {0x0573, 0x4d30, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB FM Model 40211 Rev B123"}, - {0x0573, 0x4d31, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 568"}, - {0x0573, 0x4d32, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 573"}, - {0x0573, 0x4d35, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 40219 Rev B252"}, - {0x0573, 0x4d37, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTV USB device Model 40219 Rev E189"}, - {0x0768, 0x0006, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 5, 5, -1, "Camtel Technology USB TV Genie Pro FM Model TVB330"}, - {0x07d0, 0x0001, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Digital Video Creator I"}, - {0x07d0, 0x0002, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 82, 20, 7, "Global Village GV-007 (NTSC)"}, - {0x07d0, 0x0003, 0, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)"}, - {0x07d0, 0x0004, 0, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-80 Rev 1 (PAL)"}, - {0x07d0, 0x0005, 0, CODEC_SAA7113, 2, V4L2_STD_SECAM, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)"}, - {0x2304, 0x010d, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 0, 1, TUNER_TEMIC_4066FY5_PAL_I, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (PAL)"}, - {0x2304, 0x0109, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (SECAM)"}, - {0x2304, 0x0110, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1,128, 23, -1, "Pinnacle Studio PCTV USB (PAL) FM"}, - {0x2304, 0x0111, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Miro PCTV USB"}, - {0x2304, 0x0112, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (NTSC) FM"}, - {0x2304, 0x0210, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, - {0x2304, 0x0212, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_TEMIC_4039FR5_NTSC, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (NTSC) FM"}, - {0x2304, 0x0214, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, - {0x2304, 0x0300, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (NTSC)"}, - {0x2304, 0x0301, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (PAL)"}, - {0x2304, 0x0419, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle PCTV Bungee USB (PAL) FM"}, - {0x2400, 0x4200, -1, CODEC_SAA7111, 3, VIDEO_MODE_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, - {} /* Terminating entry */ -}; - -/* Supported Devices */ - -struct usb_device_id usbvision_table [] = { - { USB_DEVICE(0xFFF0, 0xFFF0) }, /* Custom Dummy USBVision Device */ - { USB_DEVICE(0x0A6F, 0x0400) }, /* Xanboo */ - { USB_DEVICE(0x050d, 0x0208) }, /* Belkin USBView II */ - { USB_DEVICE(0x0571, 0x0002) }, /* echoFX InterView Lite */ - { USB_DEVICE(0x0573, 0x0003) }, /* USBGear USBG-V1 */ - { USB_DEVICE(0x0573, 0x0400) }, /* D-Link V100 */ - { USB_DEVICE(0x0573, 0x2000) }, /* X10 USB Camera */ - { USB_DEVICE(0x0573, 0x2d00) }, /* Osprey 50 */ - { USB_DEVICE(0x0573, 0x2d01) }, /* Hauppauge USB-Live Model 600 */ - { USB_DEVICE(0x0573, 0x2101) }, /* Zoran Co. PMD (Nogatech) AV-grabber Manhattan */ - { USB_DEVICE(0x0573, 0x4100) }, /* Nogatech USB-TV FM (NTSC) */ - { USB_DEVICE(0x0573, 0x4110) }, /* PNY USB-TV (NTSC) FM */ - { USB_DEVICE(0x0573, 0x4450) }, /* PixelView PlayTv-USB PRO (PAL) FM */ - { USB_DEVICE(0x0573, 0x4550) }, /* ZTV ZT-721 2.4GHz USB A/V Receiver */ - { USB_DEVICE(0x0573, 0x4d00) }, /* Hauppauge WinTv-USB USA */ - { USB_DEVICE(0x0573, 0x4d01) }, /* Hauppauge WinTv-USB */ - { USB_DEVICE(0x0573, 0x4d02) }, /* Hauppauge WinTv-USB UK */ - { USB_DEVICE(0x0573, 0x4d03) }, /* Hauppauge WinTv-USB France */ - { USB_DEVICE(0x0573, 0x4d10) }, /* Hauppauge WinTv-USB with FM USA radio */ - { USB_DEVICE(0x0573, 0x4d11) }, /* Hauppauge WinTv-USB (PAL) with FM radio */ - { USB_DEVICE(0x0573, 0x4d12) }, /* Hauppauge WinTv-USB UK with FM Radio */ - { USB_DEVICE(0x0573, 0x4d2a) }, /* Hauppague WinTv USB Model 602 40201 Rev B285 */ - { USB_DEVICE(0x0573, 0x4d2b) }, /* Hauppague WinTv USB Model 602 40201 Rev B282 */ - { USB_DEVICE(0x0573, 0x4d2c) }, /* Hauppague WinTv USB Model 40209 Rev. E1A5 PAL*/ - { USB_DEVICE(0x0573, 0x4d20) }, /* Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226 */ - { USB_DEVICE(0x0573, 0x4d21) }, /* Hauppauge WinTv-USB II (PAL) with FM radio*/ - { USB_DEVICE(0x0573, 0x4d22) }, /* Hauppauge WinTv-USB II (PAL) Model 566 */ - { USB_DEVICE(0x0573, 0x4d23) }, /* Hauppauge WinTv-USB France 4D23*/ - { USB_DEVICE(0x0573, 0x4d25) }, /* Hauppauge WinTv-USB Model 40209 rev B234 */ - { USB_DEVICE(0x0573, 0x4d26) }, /* Hauppauge WinTv-USB Model 40209 Rev B243 */ - { USB_DEVICE(0x0573, 0x4d27) }, /* Hauppauge WinTv-USB Model 40204 Rev B281 */ - { USB_DEVICE(0x0573, 0x4d28) }, /* Hauppauge WinTv-USB Model 40204 Rev B283 */ - { USB_DEVICE(0x0573, 0x4d29) }, /* Hauppauge WinTv-USB Model 40205 Rev B298 */ - { USB_DEVICE(0x0573, 0x4d30) }, /* Hauppauge WinTv-USB FM Model 40211 Rev B123 */ - { USB_DEVICE(0x0573, 0x4d31) }, /* Hauppauge WinTv-USB III (PAL) with FM radio Model 568 */ - { USB_DEVICE(0x0573, 0x4d32) }, /* Hauppauge WinTv-USB III (PAL) FM Model 573 */ - { USB_DEVICE(0x0573, 0x4d35) }, /* Hauppauge WinTv-USB III (SECAM) FM Model 40219 Rev B252 */ - { USB_DEVICE(0x0573, 0x4d37) }, /* Hauppauge WinTv-USB Model 40219 Rev E189 */ - { USB_DEVICE(0x0768, 0x0006) }, /* Camtel Technology USB TV Genie Pro FM Model TVB330 */ - { USB_DEVICE(0x07d0, 0x0001) }, /* Digital Video Creator I */ - { USB_DEVICE(0x07d0, 0x0002) }, /* Global Village GV-007 (NTSC) */ - { USB_DEVICE(0x07d0, 0x0003) }, /* Dazzle Fusion Model DVC-50 Rev 1 (NTSC) */ - { USB_DEVICE(0x07d0, 0x0004) }, /* Dazzle Fusion Model DVC-80 Rev 1 (PAL) */ - { USB_DEVICE(0x07d0, 0x0005) }, /* Dazzle Fusion Model DVC-90 Rev 1 (SECAM) */ - { USB_DEVICE(0x2304, 0x010d) }, /* Pinnacle Studio PCTV USB (PAL) */ - { USB_DEVICE(0x2304, 0x0109) }, /* Pinnacle Studio PCTV USB (SECAM) */ - { USB_DEVICE(0x2304, 0x0110) }, /* Pinnacle Studio PCTV USB (PAL) */ - { USB_DEVICE(0x2304, 0x0111) }, /* Miro PCTV USB */ - { USB_DEVICE(0x2304, 0x0112) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ - { USB_DEVICE(0x2304, 0x0210) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ - { USB_DEVICE(0x2304, 0x0212) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ - { USB_DEVICE(0x2304, 0x0214) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ - { USB_DEVICE(0x2304, 0x0300) }, /* Pinnacle Studio Linx Video input cable (NTSC) */ - { USB_DEVICE(0x2304, 0x0301) }, /* Pinnacle Studio Linx Video input cable (PAL) */ - { USB_DEVICE(0x2304, 0x0419) }, /* Pinnacle PCTV Bungee USB (PAL) FM */ - - { USB_DEVICE(0x2400, 0x4200) }, /* Hauppauge WinTv-USB2 Model 42012 */ - - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usbvision_table); diff --git a/trunk/drivers/media/video/usbvision/usbvision-core.c b/trunk/drivers/media/video/usbvision/usbvision-core.c deleted file mode 100644 index 797b97baf9ed..000000000000 --- a/trunk/drivers/media/video/usbvision/usbvision-core.c +++ /dev/null @@ -1,2554 +0,0 @@ -/* - * usbvision-core.c - driver for NT100x USB video capture devices - * - * - * Copyright (c) 1999-2005 Joerg Heckenbach - * Dwaine Garden - * - * This module is part of usbvision driver project. - * Updates to driver completed by Dwaine P. Garden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_KMOD -#include -#endif - -#include "usbvision.h" - -static unsigned int core_debug = 0; -module_param(core_debug,int,0644); -MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); - -static unsigned int force_testpattern = 0; -module_param(force_testpattern,int,0644); -MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); - -static int adjustCompression = 1; // Set the compression to be adaptive -module_param(adjustCompression, int, 0444); -MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); - -static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. -module_param(SwitchSVideoInput, int, 0444); -MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); - -#define ENABLE_HEXDUMP 0 /* Enable if you need it */ - - -#ifdef USBVISION_DEBUG - #define PDEBUG(level, fmt, args...) \ - if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) -#else - #define PDEBUG(level, fmt, args...) do {} while(0) -#endif - -#define DBG_HEADER 1<<0 -#define DBG_IRQ 1<<1 -#define DBG_ISOC 1<<2 -#define DBG_PARSE 1<<3 -#define DBG_SCRATCH 1<<4 -#define DBG_FUNC 1<<5 - -static const int max_imgwidth = MAX_FRAME_WIDTH; -static const int max_imgheight = MAX_FRAME_HEIGHT; -static const int min_imgwidth = MIN_FRAME_WIDTH; -static const int min_imgheight = MIN_FRAME_HEIGHT; - -/* The value of 'scratch_buf_size' affects quality of the picture - * in many ways. Shorter buffers may cause loss of data when client - * is too slow. Larger buffers are memory-consuming and take longer - * to work with. This setting can be adjusted, but the default value - * should be OK for most desktop users. - */ -#define DEFAULT_SCRATCH_BUF_SIZE (0x20000) // 128kB memory scratch buffer -static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; - -// Function prototypes -static int usbvision_request_intra (struct usb_usbvision *usbvision); -static int usbvision_unrequest_intra (struct usb_usbvision *usbvision); -static int usbvision_adjust_compression (struct usb_usbvision *usbvision); -static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision); - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -/* - * Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ - -void *usbvision_rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -void usbvision_rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - size = PAGE_ALIGN(size); - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vfree(mem); -} - - - -#if ENABLE_HEXDUMP -static void usbvision_hexdump(const unsigned char *data, int len) -{ - char tmp[80]; - int i, k; - - for (i = k = 0; len > 0; i++, len--) { - if (i > 0 && (i % 16 == 0)) { - printk("%s\n", tmp); - k = 0; - } - k += sprintf(&tmp[k], "%02x ", data[i]); - } - if (k > 0) - printk("%s\n", tmp); -} -#endif - -/******************************** - * scratch ring buffer handling - ********************************/ -int scratch_len(struct usb_usbvision *usbvision) /*This returns the amount of data actually in the buffer */ -{ - int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr; - if (len < 0) { - len += scratch_buf_size; - } - PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len); - - return len; -} - - -/* This returns the free space left in the buffer */ -int scratch_free(struct usb_usbvision *usbvision) -{ - int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr; - if (free <= 0) { - free += scratch_buf_size; - } - if (free) { - free -= 1; /* at least one byte in the buffer must */ - /* left blank, otherwise there is no chance to differ between full and empty */ - } - PDEBUG(DBG_SCRATCH, "return %d\n", free); - - return free; -} - - -/* This puts data into the buffer */ -int scratch_put(struct usb_usbvision *usbvision, unsigned char *data, int len) -{ - int len_part; - - if (usbvision->scratch_write_ptr + len < scratch_buf_size) { - memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len); - usbvision->scratch_write_ptr += len; - } - else { - len_part = scratch_buf_size - usbvision->scratch_write_ptr; - memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part); - if (len == len_part) { - usbvision->scratch_write_ptr = 0; /* just set write_ptr to zero */ - } - else { - memcpy(usbvision->scratch, data + len_part, len - len_part); - usbvision->scratch_write_ptr = len - len_part; - } - } - - PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr); - - return len; -} - -/* This marks the write_ptr as position of new frame header */ -void scratch_mark_header(struct usb_usbvision *usbvision) -{ - PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr); - - usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] = - usbvision->scratch_write_ptr; - usbvision->scratch_headermarker_write_ptr += 1; - usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER; -} - -/* This gets data from the buffer at the given "ptr" position */ -int scratch_get_extra(struct usb_usbvision *usbvision, unsigned char *data, int *ptr, int len) -{ - int len_part; - if (*ptr + len < scratch_buf_size) { - memcpy(data, usbvision->scratch + *ptr, len); - *ptr += len; - } - else { - len_part = scratch_buf_size - *ptr; - memcpy(data, usbvision->scratch + *ptr, len_part); - if (len == len_part) { - *ptr = 0; /* just set the y_ptr to zero */ - } - else { - memcpy(data + len_part, usbvision->scratch, len - len_part); - *ptr = len - len_part; - } - } - - PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr); - - return len; -} - - -/* This sets the scratch extra read pointer */ -void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, int len) -{ - *ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size; - - PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); -} - - -/*This increments the scratch extra read pointer */ -void scratch_inc_extra_ptr(int *ptr, int len) -{ - *ptr = (*ptr + len) % scratch_buf_size; - - PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); -} - - -/* This gets data from the buffer */ -int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, int len) -{ - int len_part; - if (usbvision->scratch_read_ptr + len < scratch_buf_size) { - memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len); - usbvision->scratch_read_ptr += len; - } - else { - len_part = scratch_buf_size - usbvision->scratch_read_ptr; - memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part); - if (len == len_part) { - usbvision->scratch_read_ptr = 0; /* just set the read_ptr to zero */ - } - else { - memcpy(data + len_part, usbvision->scratch, len - len_part); - usbvision->scratch_read_ptr = len - len_part; - } - } - - PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr); - - return len; -} - - -/* This sets read pointer to next header and returns it */ -int scratch_get_header(struct usb_usbvision *usbvision,struct usbvision_frame_header *header) -{ - int errCode = 0; - - PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr); - - while (usbvision->scratch_headermarker_write_ptr - - usbvision->scratch_headermarker_read_ptr != 0) { - usbvision->scratch_read_ptr = - usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr]; - usbvision->scratch_headermarker_read_ptr += 1; - usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER; - scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH); - if ((header->magic_1 == USBVISION_MAGIC_1) - && (header->magic_2 == USBVISION_MAGIC_2) - && (header->headerLength == USBVISION_HEADER_LENGTH)) { - errCode = USBVISION_HEADER_LENGTH; - header->frameWidth = header->frameWidthLo + (header->frameWidthHi << 8); - header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8); - break; - } - } - - return errCode; -} - - -/*This removes len bytes of old data from the buffer */ -void scratch_rm_old(struct usb_usbvision *usbvision, int len) -{ - - usbvision->scratch_read_ptr += len; - usbvision->scratch_read_ptr %= scratch_buf_size; - PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr); -} - - -/*This resets the buffer - kills all data in it too */ -void scratch_reset(struct usb_usbvision *usbvision) -{ - PDEBUG(DBG_SCRATCH, "\n"); - - usbvision->scratch_read_ptr = 0; - usbvision->scratch_write_ptr = 0; - usbvision->scratch_headermarker_read_ptr = 0; - usbvision->scratch_headermarker_write_ptr = 0; - usbvision->isocstate = IsocState_NoFrame; -} - -int usbvision_scratch_alloc(struct usb_usbvision *usbvision) -{ - usbvision->scratch = vmalloc(scratch_buf_size); - scratch_reset(usbvision); - if(usbvision->scratch == NULL) { - err("%s: unable to allocate %d bytes for scratch", - __FUNCTION__, scratch_buf_size); - return -ENOMEM; - } - return 0; -} - -void usbvision_scratch_free(struct usb_usbvision *usbvision) -{ - if (usbvision->scratch != NULL) { - vfree(usbvision->scratch); - usbvision->scratch = NULL; - } -} - -/* - * usbvision_testpattern() - * - * Procedure forms a test pattern (yellow grid on blue background). - * - * Parameters: - * fullframe: if TRUE then entire frame is filled, otherwise the procedure - * continues from the current scanline. - * pmode 0: fill the frame with solid blue color (like on VCR or TV) - * 1: Draw a colored grid - * - */ -void usbvision_testpattern(struct usb_usbvision *usbvision, int fullframe, - int pmode) -{ - static const char proc[] = "usbvision_testpattern"; - struct usbvision_frame *frame; - unsigned char *f; - int num_cell = 0; - int scan_length = 0; - static int num_pass = 0; - - if (usbvision == NULL) { - printk(KERN_ERR "%s: usbvision == NULL\n", proc); - return; - } - if (usbvision->curFrame == NULL) { - printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc); - return; - } - - /* Grab the current frame */ - frame = usbvision->curFrame; - - /* Optionally start at the beginning */ - if (fullframe) { - frame->curline = 0; - frame->scanlength = 0; - } - - /* Form every scan line */ - for (; frame->curline < frame->frmheight; frame->curline++) { - int i; - - f = frame->data + (usbvision->curwidth * 3 * frame->curline); - for (i = 0; i < usbvision->curwidth; i++) { - unsigned char cb = 0x80; - unsigned char cg = 0; - unsigned char cr = 0; - - if (pmode == 1) { - if (frame->curline % 32 == 0) - cb = 0, cg = cr = 0xFF; - else if (i % 32 == 0) { - if (frame->curline % 32 == 1) - num_cell++; - cb = 0, cg = cr = 0xFF; - } else { - cb = - ((num_cell * 7) + - num_pass) & 0xFF; - cg = - ((num_cell * 5) + - num_pass * 2) & 0xFF; - cr = - ((num_cell * 3) + - num_pass * 3) & 0xFF; - } - } else { - /* Just the blue screen */ - } - - *f++ = cb; - *f++ = cg; - *f++ = cr; - scan_length += 3; - } - } - - frame->grabstate = FrameState_Done; - frame->scanlength += scan_length; - ++num_pass; - -} - -/* - * usbvision_decompress_alloc() - * - * allocates intermediate buffer for decompression - */ -int usbvision_decompress_alloc(struct usb_usbvision *usbvision) -{ - int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; - usbvision->IntraFrameBuffer = vmalloc(IFB_size); - if (usbvision->IntraFrameBuffer == NULL) { - err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size); - return -ENOMEM; - } - return 0; -} - -/* - * usbvision_decompress_free() - * - * frees intermediate buffer for decompression - */ -void usbvision_decompress_free(struct usb_usbvision *usbvision) -{ - if (usbvision->IntraFrameBuffer != NULL) { - vfree(usbvision->IntraFrameBuffer); - usbvision->IntraFrameBuffer = NULL; - } -} - -/************************************************************ - * Here comes the data parsing stuff that is run as interrupt - ************************************************************/ -/* - * usbvision_find_header() - * - * Locate one of supported header markers in the scratch buffer. - */ -static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision) -{ - struct usbvision_frame *frame; - int foundHeader = 0; - - frame = usbvision->curFrame; - - while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) { - // found header in scratch - PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u", - frame->isocHeader.magic_2, - frame->isocHeader.magic_1, - frame->isocHeader.headerLength, - frame->isocHeader.frameNum, - frame->isocHeader.framePhase, - frame->isocHeader.frameLatency, - frame->isocHeader.dataFormat, - frame->isocHeader.formatParam, - frame->isocHeader.frameWidth, - frame->isocHeader.frameHeight); - - if (usbvision->requestIntra) { - if (frame->isocHeader.formatParam & 0x80) { - foundHeader = 1; - usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time - usbvision_unrequest_intra(usbvision); - break; - } - } - else { - foundHeader = 1; - break; - } - } - - if (foundHeader) { - frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width; - frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height; - frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; - } - else { // no header found - PDEBUG(DBG_HEADER, "skipping scratch data, no header"); - scratch_reset(usbvision); - return ParseState_EndParse; - } - - // found header - if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) { - //check isocHeader.frameNum for lost frames - if (usbvision->lastIsocFrameNum >= 0) { - if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) { - // unexpected frame drop: need to request new intra frame - PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum); - usbvision_request_intra(usbvision); - return ParseState_NextFrame; - } - } - usbvision->lastIsocFrameNum = frame->isocHeader.frameNum; - } - usbvision->header_count++; - frame->scanstate = ScanState_Lines; - frame->curline = 0; - - if (force_testpattern) { - usbvision_testpattern(usbvision, 1, 1); - return ParseState_NextFrame; - } - return ParseState_Continue; -} - -static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision, - long *pcopylen) -{ - volatile struct usbvision_frame *frame; - unsigned char *f; - int len; - int i; - unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components - unsigned char rv, gv, bv; // RGB components - int clipmask_index, bytes_per_pixel; - int stretch_bytes, clipmask_add; - - frame = usbvision->curFrame; - f = frame->data + (frame->v4l2_linesize * frame->curline); - - /* Make sure there's enough data for the entire line */ - len = (frame->isocHeader.frameWidth * 2)+5; - if (scratch_len(usbvision) < len) { - PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len); - return ParseState_Out; - } - - if ((frame->curline + 1) >= frame->frmheight) { - return ParseState_NextFrame; - } - - bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; - stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; - clipmask_index = frame->curline * MAX_FRAME_WIDTH; - clipmask_add = usbvision->stretch_width; - - for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) { - - scratch_get(usbvision, &yuyv[0], 4); - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = yuyv[0]; // Y - *f++ = yuyv[3]; // U - } - else { - - YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv); - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); - *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = bv; - *f++ = gv; - *f++ = rv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = bv; - *f++ = gv; - *f++ = rv; - f++; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); - *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); - break; - } - } - clipmask_index += clipmask_add; - f += stretch_bytes; - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = yuyv[2]; // Y - *f++ = yuyv[1]; // V - } - else { - - YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv); - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); - *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = bv; - *f++ = gv; - *f++ = rv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = bv; - *f++ = gv; - *f++ = rv; - f++; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); - *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); - break; - } - } - clipmask_index += clipmask_add; - f += stretch_bytes; - } - - frame->curline += usbvision->stretch_height; - *pcopylen += frame->v4l2_linesize * usbvision->stretch_height; - - if (frame->curline >= frame->frmheight) { - return ParseState_NextFrame; - } - else { - return ParseState_Continue; - } -} - -/* The decompression routine */ -static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed, - unsigned char *Decompressed, int *StartPos, - int *BlockTypeStartPos, int Len) -{ - int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen; - unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator; - - Integrator = 0; - Pos = *StartPos; - BlockTypePos = *BlockTypeStartPos; - MaxPos = 396; //Pos + Len; - ExtraPos = Pos; - BlockLen = 0; - BlockByte = 0; - BlockCode = 0; - BlockType = 0; - BlockTypeByte = 0; - BlockTypeLen = 0; - RestPixel = Len; - - for (Idx = 0; Idx < Len; Idx++) { - - if (BlockLen == 0) { - if (BlockTypeLen==0) { - BlockTypeByte = Compressed[BlockTypePos]; - BlockTypePos++; - BlockTypeLen = 4; - } - BlockType = (BlockTypeByte & 0xC0) >> 6; - - //statistic: - usbvision->ComprBlockTypes[BlockType]++; - - Pos = ExtraPos; - if (BlockType == 0) { - if(RestPixel >= 24) { - Idx += 23; - RestPixel -= 24; - Integrator = Decompressed[Idx]; - } else { - Idx += RestPixel - 1; - RestPixel = 0; - } - } else { - BlockCode = Compressed[Pos]; - Pos++; - if (RestPixel >= 24) { - BlockLen = 24; - } else { - BlockLen = RestPixel; - } - RestPixel -= BlockLen; - ExtraPos = Pos + (BlockLen / 4); - } - BlockTypeByte <<= 2; - BlockTypeLen -= 1; - } - if (BlockLen > 0) { - if ((BlockLen%4) == 0) { - BlockByte = Compressed[Pos]; - Pos++; - } - if (BlockType == 1) { //inter Block - Integrator = Decompressed[Idx]; - } - switch (BlockByte & 0xC0) { - case 0x03<<6: - Integrator += Compressed[ExtraPos]; - ExtraPos++; - break; - case 0x02<<6: - Integrator += BlockCode; - break; - case 0x00: - Integrator -= BlockCode; - break; - } - Decompressed[Idx] = Integrator; - BlockByte <<= 2; - BlockLen -= 1; - } - } - *StartPos = ExtraPos; - *BlockTypeStartPos = BlockTypePos; - return Idx; -} - - -/* - * usbvision_parse_compress() - * - * Parse compressed frame from the scratch buffer, put - * decoded RGB value into the current frame buffer and add the written - * number of bytes (RGB) to the *pcopylen. - * - */ -static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, - long *pcopylen) -{ -#define USBVISION_STRIP_MAGIC 0x5A -#define USBVISION_STRIP_LEN_MAX 400 -#define USBVISION_STRIP_HEADER_LEN 3 - - struct usbvision_frame *frame; - unsigned char *f,*u = NULL ,*v = NULL; - unsigned char StripData[USBVISION_STRIP_LEN_MAX]; - unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN]; - int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos; - int clipmask_index, bytes_per_pixel, rc; - int imageSize; - unsigned char rv, gv, bv; - static unsigned char *Y, *U, *V; - - frame = usbvision->curFrame; - imageSize = frame->frmwidth * frame->frmheight; - if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || - (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { // this is a planar format - //... v4l2_linesize not used here. - f = frame->data + (frame->width * frame->curline); - } else - f = frame->data + (frame->v4l2_linesize * frame->curline); - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers - // get base of u and b planes add halfoffset - - u = frame->data - + imageSize - + (frame->frmwidth >>1) * frame->curline ; - v = u + (imageSize >>1 ); - - } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){ - - v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ; - u = v + (imageSize >>2) ; - } - - if (frame->curline == 0) { - usbvision_adjust_compression(usbvision); - } - - if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) { - return ParseState_Out; - } - - //get strip header without changing the scratch_read_ptr - scratch_set_extra_ptr(usbvision, &StripPtr, 0); - scratch_get_extra(usbvision, &StripHeader[0], &StripPtr, - USBVISION_STRIP_HEADER_LEN); - - if (StripHeader[0] != USBVISION_STRIP_MAGIC) { - // wrong strip magic - usbvision->stripMagicErrors++; - return ParseState_NextFrame; - } - - if (frame->curline != (int)StripHeader[2]) { - //line number missmatch error - usbvision->stripLineNumberErrors++; - } - - StripLen = 2 * (unsigned int)StripHeader[1]; - if (StripLen > USBVISION_STRIP_LEN_MAX) { - // strip overrun - // I think this never happens - usbvision_request_intra(usbvision); - } - - if (scratch_len(usbvision) < StripLen) { - //there is not enough data for the strip - return ParseState_Out; - } - - if (usbvision->IntraFrameBuffer) { - Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline; - U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2); - V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); - } - else { - return ParseState_NextFrame; - } - - bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; - clipmask_index = frame->curline * MAX_FRAME_WIDTH; - - scratch_get(usbvision, StripData, StripLen); - - IdxEnd = frame->frmwidth; - BlockTypePos = USBVISION_STRIP_HEADER_LEN; - StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2; - BlockPos = StartBlockPos; - - usbvision->BlockPos = BlockPos; - - if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) { - //return ParseState_Continue; - } - if (StripLen > usbvision->maxStripLen) { - usbvision->maxStripLen = StripLen; - } - - if (frame->curline%2) { - if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { - //return ParseState_Continue; - } - } - else { - if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { - //return ParseState_Continue; - } - } - - if (BlockPos > usbvision->comprBlockPos) { - usbvision->comprBlockPos = BlockPos; - } - if (BlockPos > StripLen) { - usbvision->stripLenErrors++; - } - - for (Idx = 0; Idx < IdxEnd; Idx++) { - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = Y[Idx]; - *f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2]; - } - else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { - *f++ = Y[Idx]; - if ( Idx & 0x01) - *u++ = U[Idx>>1] ; - else - *v++ = V[Idx>>1]; - } - else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { - *f++ = Y [Idx]; - if ( !(( Idx & 0x01 ) | ( frame->curline & 0x01 )) ){ - -/* only need do this for 1 in 4 pixels */ -/* intraframe buffer is YUV420 format */ - - *u++ = U[Idx >>1]; - *v++ = V[Idx >>1]; - } - - } - else { - YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv); - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_GREY: - *f++ = Y[Idx]; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); - *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); - break; - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); - *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = bv; - *f++ = gv; - *f++ = rv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = bv; - *f++ = gv; - *f++ = rv; - f++; - break; - } - } - clipmask_index++; - } - /* Deal with non-integer no. of bytes for YUV420P */ - if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 ) - *pcopylen += frame->v4l2_linesize; - else - *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1; - - frame->curline += 1; - - if (frame->curline >= frame->frmheight) { - return ParseState_NextFrame; - } - else { - return ParseState_Continue; - } - -} - - -/* - * usbvision_parse_lines_420() - * - * Parse two lines from the scratch buffer, put - * decoded RGB value into the current frame buffer and add the written - * number of bytes (RGB) to the *pcopylen. - * - */ -static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision, - long *pcopylen) -{ - struct usbvision_frame *frame; - unsigned char *f_even = NULL, *f_odd = NULL; - unsigned int pixel_per_line, block; - int pixel, block_split; - int y_ptr, u_ptr, v_ptr, y_odd_offset; - const int y_block_size = 128; - const int uv_block_size = 64; - const int sub_block_size = 32; - const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; - const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4; - unsigned char y[2], u, v; /* YUV components */ - int y_, u_, v_, vb, uvg, ur; - int r_, g_, b_; /* RGB components */ - unsigned char g; - int clipmask_even_index, clipmask_odd_index, bytes_per_pixel; - int clipmask_add, stretch_bytes; - - frame = usbvision->curFrame; - f_even = frame->data + (frame->v4l2_linesize * frame->curline); - f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; - - /* Make sure there's enough data for the entire line */ - /* In this mode usbvision transfer 3 bytes for every 2 pixels */ - /* I need two lines to decode the color */ - bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; - stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; - clipmask_even_index = frame->curline * MAX_FRAME_WIDTH; - clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH; - clipmask_add = usbvision->stretch_width; - pixel_per_line = frame->isocHeader.frameWidth; - - if (scratch_len(usbvision) < (int)pixel_per_line * 3) { - //printk(KERN_DEBUG "out of data, need %d\n", len); - return ParseState_Out; - } - - if ((frame->curline + 1) >= frame->frmheight) { - return ParseState_NextFrame; - } - - block_split = (pixel_per_line%y_block_size) ? 1 : 0; //are some blocks splitted into different lines? - - y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size) - + block_split * uv_block_size; - - scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset); - scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size); - scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset - + (4 - block_split) * sub_block_size); - - for (block = 0; block < (pixel_per_line / sub_block_size); - block++) { - - - for (pixel = 0; pixel < sub_block_size; pixel +=2) { - scratch_get(usbvision, &y[0], 2); - scratch_get_extra(usbvision, &u, &u_ptr, 1); - scratch_get_extra(usbvision, &v, &v_ptr, 1); - - //I don't use the YUV_TO_RGB macro for better performance - v_ = v - 128; - u_ = u - 128; - vb = 132252 * v_; - uvg= -53281 * u_ - 25625 * v_; - ur = 104595 * u_; - - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f_even++ = y[0]; - *f_even++ = v; - } - else { - y_ = 76284 * (y[0] - 16); - - b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; - r_ = (y_ + ur) >> 16; - - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); - *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_even++ = LIMIT_RGB(b_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(r_); - break; - case V4L2_PIX_FMT_RGB32: - *f_even++ = LIMIT_RGB(b_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(r_); - f_even++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); - *f_even++ = (0x03 & ( g >> 6)) | - (0x7C & (LIMIT_RGB(r_) >> 1)); - break; - } - } - clipmask_even_index += clipmask_add; - f_even += stretch_bytes; - - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f_even++ = y[1]; - *f_even++ = u; - } - else { - y_ = 76284 * (y[1] - 16); - - b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; - r_ = (y_ + ur) >> 16; - - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); - *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_even++ = LIMIT_RGB(b_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(r_); - break; - case V4L2_PIX_FMT_RGB32: - *f_even++ = LIMIT_RGB(b_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(r_); - f_even++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); - *f_even++ = (0x03 & ( g >> 6)) | - (0x7C & (LIMIT_RGB(r_) >> 1)); - break; - } - } - clipmask_even_index += clipmask_add; - f_even += stretch_bytes; - - scratch_get_extra(usbvision, &y[0], &y_ptr, 2); - - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f_odd++ = y[0]; - *f_odd++ = v; - } - else { - y_ = 76284 * (y[0] - 16); - - b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; - r_ = (y_ + ur) >> 16; - - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); - *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_odd++ = LIMIT_RGB(b_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(r_); - break; - case V4L2_PIX_FMT_RGB32: - *f_odd++ = LIMIT_RGB(b_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(r_); - f_odd++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); - *f_odd++ = (0x03 & ( g >> 6)) | - (0x7C & (LIMIT_RGB(r_) >> 1)); - break; - } - } - clipmask_odd_index += clipmask_add; - f_odd += stretch_bytes; - - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f_odd++ = y[1]; - *f_odd++ = u; - } - else { - y_ = 76284 * (y[1] - 16); - - b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; - r_ = (y_ + ur) >> 16; - - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); - *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_odd++ = LIMIT_RGB(b_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(r_); - break; - case V4L2_PIX_FMT_RGB32: - *f_odd++ = LIMIT_RGB(b_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(r_); - f_odd++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); - *f_odd++ = (0x03 & ( g >> 6)) | - (0x7C & (LIMIT_RGB(r_) >> 1)); - break; - } - } - clipmask_odd_index += clipmask_add; - f_odd += stretch_bytes; - } - - scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size); - scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size] - * sub_block_size); - scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size] - * sub_block_size); - scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size] - * sub_block_size); - } - - scratch_rm_old(usbvision, pixel_per_line * 3 / 2 - + block_split * sub_block_size); - - frame->curline += 2 * usbvision->stretch_height; - *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height; - - if (frame->curline >= frame->frmheight) - return ParseState_NextFrame; - else - return ParseState_Continue; -} - -/* - * usbvision_parse_data() - * - * Generic routine to parse the scratch buffer. It employs either - * usbvision_find_header() or usbvision_parse_lines() to do most - * of work. - * - */ -static void usbvision_parse_data(struct usb_usbvision *usbvision) -{ - struct usbvision_frame *frame; - enum ParseState newstate; - long copylen = 0; - unsigned long lock_flags; - - frame = usbvision->curFrame; - - PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); - - while (1) { - - newstate = ParseState_Out; - if (scratch_len(usbvision)) { - if (frame->scanstate == ScanState_Scanning) { - newstate = usbvision_find_header(usbvision); - } - else if (frame->scanstate == ScanState_Lines) { - if (usbvision->isocMode == ISOC_MODE_YUV420) { - newstate = usbvision_parse_lines_420(usbvision, ©len); - } - else if (usbvision->isocMode == ISOC_MODE_YUV422) { - newstate = usbvision_parse_lines_422(usbvision, ©len); - } - else if (usbvision->isocMode == ISOC_MODE_COMPRESS) { - newstate = usbvision_parse_compress(usbvision, ©len); - } - - } - } - if (newstate == ParseState_Continue) { - continue; - } - else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) { - break; - } - else { - return; /* ParseState_EndParse */ - } - } - - if (newstate == ParseState_NextFrame) { - frame->grabstate = FrameState_Done; - do_gettimeofday(&(frame->timestamp)); - frame->sequence = usbvision->frame_num; - - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - list_move_tail(&(frame->frame), &usbvision->outqueue); - usbvision->curFrame = NULL; - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - - usbvision->frame_num++; - - /* This will cause the process to request another frame. */ - if (waitqueue_active(&usbvision->wait_frame)) { - PDEBUG(DBG_PARSE, "Wake up !"); - wake_up_interruptible(&usbvision->wait_frame); - } - } - else - frame->grabstate = FrameState_Grabbing; - - - /* Update the frame's uncompressed length. */ - frame->scanlength += copylen; -} - - -/* - * Make all of the blocks of data contiguous - */ -static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, - struct urb *urb) -{ - unsigned char *packet_data; - int i, totlen = 0; - - for (i = 0; i < urb->number_of_packets; i++) { - int packet_len = urb->iso_frame_desc[i].actual_length; - int packet_stat = urb->iso_frame_desc[i].status; - - packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* Detect and ignore errored packets */ - if (packet_stat) { // packet_stat != 0 ????????????? - PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat); - usbvision->isocErrCount++; - continue; - } - - /* Detect and ignore empty packets */ - if (packet_len < 0) { - PDEBUG(DBG_ISOC, "error packet [%d]", i); - usbvision->isocSkipCount++; - continue; - } - else if (packet_len == 0) { /* Frame end ????? */ - PDEBUG(DBG_ISOC, "null packet [%d]", i); - usbvision->isocstate=IsocState_NoFrame; - usbvision->isocSkipCount++; - continue; - } - else if (packet_len > usbvision->isocPacketSize) { - PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i); - usbvision->isocSkipCount++; - continue; - } - - PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); - - if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins - usbvision->isocstate=IsocState_InFrame; - scratch_mark_header(usbvision); - usbvision_measure_bandwidth(usbvision); - PDEBUG(DBG_ISOC, "packet with header"); - } - - /* - * If usbvision continues to feed us with data but there is no - * consumption (if, for example, V4L client fell asleep) we - * may overflow the buffer. We have to move old data over to - * free room for new data. This is bad for old data. If we - * just drop new data then it's bad for new data... choose - * your favorite evil here. - */ - if (scratch_free(usbvision) < packet_len) { - - usbvision->scratch_ovf_count++; - PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d", - scratch_len(usbvision), packet_len); - scratch_rm_old(usbvision, packet_len - scratch_free(usbvision)); - } - - /* Now we know that there is enough room in scratch buffer */ - scratch_put(usbvision, packet_data, packet_len); - totlen += packet_len; - usbvision->isocDataCount += packet_len; - usbvision->isocPacketCount++; - } -#if ENABLE_HEXDUMP - if (totlen > 0) { - static int foo = 0; - if (foo < 1) { - printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); - usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); - ++foo; - } - } -#endif - return totlen; -} - -static void usbvision_isocIrq(struct urb *urb) -{ - int errCode = 0; - int len; - struct usb_usbvision *usbvision = urb->context; - int i; - unsigned long startTime = jiffies; - struct usbvision_frame **f; - - /* We don't want to do anything if we are about to be removed! */ - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return; - - f = &usbvision->curFrame; - - /* Manage streaming interruption */ - if (usbvision->streaming == Stream_Interrupt) { - usbvision->streaming = Stream_Idle; - if ((*f)) { - (*f)->grabstate = FrameState_Ready; - (*f)->scanstate = ScanState_Scanning; - } - PDEBUG(DBG_IRQ, "stream interrupted"); - wake_up_interruptible(&usbvision->wait_stream); - } - - /* Copy the data received into our scratch buffer */ - len = usbvision_compress_isochronous(usbvision, urb); - - usbvision->isocUrbCount++; - usbvision->urb_length = len; - - if (usbvision->streaming == Stream_On) { - - /* If we collected enough data let's parse! */ - if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ - /*If we don't have a frame we're current working on, complain */ - if(!list_empty(&(usbvision->inqueue))) { - if (!(*f)) { - (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame); - } - usbvision_parse_data(usbvision); - } - else { - PDEBUG(DBG_IRQ, "received data, but no one needs it"); - scratch_reset(usbvision); - } - } - } - else { - PDEBUG(DBG_IRQ, "received data, but no one needs it"); - scratch_reset(usbvision); - } - - usbvision->timeInIrq += jiffies - startTime; - - for (i = 0; i < USBVISION_URB_FRAMES; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - - urb->status = 0; - urb->dev = usbvision->dev; - errCode = usb_submit_urb (urb, GFP_ATOMIC); - - /* Disable this warning. By design of the driver. */ - // if(errCode) { - // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); - // } - - return; -} - -/*************************************/ -/* Low level usbvision access functions */ -/*************************************/ - -/* - * usbvision_read_reg() - * - * return < 0 -> Error - * >= 0 -> Data - */ - -int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) -{ - int errCode = 0; - unsigned char buffer[1]; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -1; - - errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - 0, (__u16) reg, buffer, 1, HZ); - - if (errCode < 0) { - err("%s: failed: error %d", __FUNCTION__, errCode); - return errCode; - } - return buffer[0]; -} - -/* - * usbvision_write_reg() - * - * return 1 -> Reg written - * 0 -> usbvision is not yet ready - * -1 -> Something went wrong - */ - -int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, - unsigned char value) -{ - int errCode = 0; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); - - if (errCode < 0) { - err("%s: failed: error %d", __FUNCTION__, errCode); - } - return errCode; -} - - -static void usbvision_ctrlUrb_complete(struct urb *urb) -{ - struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context; - - PDEBUG(DBG_IRQ, ""); - usbvision->ctrlUrbBusy = 0; - if (waitqueue_active(&usbvision->ctrlUrb_wq)) { - wake_up_interruptible(&usbvision->ctrlUrb_wq); - } -} - - -static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, - unsigned char *data, int len) -{ - int errCode = 0; - - PDEBUG(DBG_IRQ, ""); - if (len > 8) { - return -EFAULT; - } -// down(&usbvision->ctrlUrbLock); - if (usbvision->ctrlUrbBusy) { -// up(&usbvision->ctrlUrbLock); - return -EBUSY; - } - usbvision->ctrlUrbBusy = 1; -// up(&usbvision->ctrlUrbLock); - - usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; - usbvision->ctrlUrbSetup.bRequest = USBVISION_OP_CODE; - usbvision->ctrlUrbSetup.wValue = 0; - usbvision->ctrlUrbSetup.wIndex = cpu_to_le16(address); - usbvision->ctrlUrbSetup.wLength = cpu_to_le16(len); - usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev, - usb_sndctrlpipe(usbvision->dev, 1), - (unsigned char *)&usbvision->ctrlUrbSetup, - (void *)usbvision->ctrlUrbBuffer, len, - usbvision_ctrlUrb_complete, - (void *)usbvision); - - memcpy(usbvision->ctrlUrbBuffer, data, len); - - errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC); - if (errCode < 0) { - // error in usb_submit_urb() - usbvision->ctrlUrbBusy = 0; - } - PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode); - return errCode; -} - - -static int usbvision_init_compression(struct usb_usbvision *usbvision) -{ - int errCode = 0; - - usbvision->lastIsocFrameNum = -1; - usbvision->isocDataCount = 0; - usbvision->isocPacketCount = 0; - usbvision->isocSkipCount = 0; - usbvision->comprLevel = 50; - usbvision->lastComprLevel = -1; - usbvision->isocUrbCount = 0; - usbvision->requestIntra = 1; - usbvision->isocMeasureBandwidthCount = 0; - - return errCode; -} - -/* this function measures the used bandwidth since last call - * return: 0 : no error - * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize - */ -static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) -{ - int errCode = 0; - - if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames - usbvision->isocMeasureBandwidthCount++; - return errCode; - } - if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) { - usbvision->usedBandwidth = usbvision->isocDataCount / - (usbvision->isocPacketCount + usbvision->isocSkipCount) * - 100 / usbvision->isocPacketSize; - } - usbvision->isocMeasureBandwidthCount = 0; - usbvision->isocDataCount = 0; - usbvision->isocPacketCount = 0; - usbvision->isocSkipCount = 0; - return errCode; -} - -static int usbvision_adjust_compression (struct usb_usbvision *usbvision) -{ - int errCode = 0; - unsigned char buffer[6]; - - PDEBUG(DBG_IRQ, ""); - if ((adjustCompression) && (usbvision->usedBandwidth > 0)) { - usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2; - RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100); - if (usbvision->comprLevel != usbvision->lastComprLevel) { - int distorsion; - if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) { - buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM Threshold 1 - buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM Threshold 2 - distorsion = 7 + 248 * usbvision->comprLevel / 100; - buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter) - buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra) - distorsion = 1 + 42 * usbvision->comprLevel / 100; - buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter) - buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra) - } - else { //BRIDGE_NT1003 - buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM threshold 1 - buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM threshold 2 - distorsion = 2 + 253 * usbvision->comprLevel / 100; - buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7 - buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11 - distorsion = 0 + 43 * usbvision->comprLevel / 100; - buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7 - buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8 - } - errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); - if (errCode == 0){ - PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], - buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - usbvision->lastComprLevel = usbvision->comprLevel; - } - } - } - return errCode; -} - -static int usbvision_request_intra (struct usb_usbvision *usbvision) -{ - int errCode = 0; - unsigned char buffer[1]; - - PDEBUG(DBG_IRQ, ""); - usbvision->requestIntra = 1; - buffer[0] = 1; - usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); - return errCode; -} - -static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) -{ - int errCode = 0; - unsigned char buffer[1]; - - PDEBUG(DBG_IRQ, ""); - usbvision->requestIntra = 0; - buffer[0] = 0; - usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); - return errCode; -} - -/******************************* - * usbvision utility functions - *******************************/ - -int usbvision_power_off(struct usb_usbvision *usbvision) -{ - int errCode = 0; - - PDEBUG(DBG_FUNC, ""); - - errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); - if (errCode == 1) { - usbvision->power = 0; - } - PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode); - return errCode; -} - -/* - * usbvision_set_video_format() - * - */ -static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format) -{ - static const char proc[] = "usbvision_set_video_format"; - int rc; - unsigned char value[2]; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - PDEBUG(DBG_FUNC, "isocMode %#02x", format); - - if ((format != ISOC_MODE_YUV422) - && (format != ISOC_MODE_YUV420) - && (format != ISOC_MODE_COMPRESS)) { - printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420", - format); - format = ISOC_MODE_YUV420; - } - value[0] = 0x0A; //TODO: See the effect of the filter - value[1] = format; - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_FILT_CONT, value, 2, HZ); - - if (rc < 0) { - printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - } - usbvision->isocMode = format; - return rc; -} - -/* - * usbvision_set_output() - * - */ - -int usbvision_set_output(struct usb_usbvision *usbvision, int width, - int height) -{ - int errCode = 0; - int UsbWidth, UsbHeight; - unsigned int frameRate=0, frameDrop=0; - unsigned char value[4]; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) { - return 0; - } - - if (width > MAX_USB_WIDTH) { - UsbWidth = width / 2; - usbvision->stretch_width = 2; - } - else { - UsbWidth = width; - usbvision->stretch_width = 1; - } - - if (height > MAX_USB_HEIGHT) { - UsbHeight = height / 2; - usbvision->stretch_height = 2; - } - else { - UsbHeight = height; - usbvision->stretch_height = 1; - } - - RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH); - UsbWidth &= ~(MIN_FRAME_WIDTH-1); - RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); - UsbHeight &= ~(1); - - PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d", - UsbWidth, UsbHeight, width, height, - usbvision->stretch_width, usbvision->stretch_height); - - /* I'll not rewrite the same values */ - if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) { - value[0] = UsbWidth & 0xff; //LSB - value[1] = (UsbWidth >> 8) & 0x03; //MSB - value[2] = UsbHeight & 0xff; //LSB - value[3] = (UsbHeight >> 8) & 0x03; //MSB - - errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); - - if (errCode < 0) { - err("%s failed: error %d", __FUNCTION__, errCode); - return errCode; - } - usbvision->curwidth = usbvision->stretch_width * UsbWidth; - usbvision->curheight = usbvision->stretch_height * UsbHeight; - } - - if (usbvision->isocMode == ISOC_MODE_YUV422) { - frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2); - } - else if (usbvision->isocMode == ISOC_MODE_YUV420) { - frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8); - } - else { - frameRate = FRAMERATE_MAX; - } - - if (usbvision->tvnorm->id & V4L2_STD_625_50) { - frameDrop = frameRate * 32 / 25 - 1; - } - else if (usbvision->tvnorm->id & V4L2_STD_525_60) { - frameDrop = frameRate * 32 / 30 - 1; - } - - RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX); - - PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop); - - frameDrop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled - - /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... - => frameSkip = 4; - => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; - - frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... - => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... - => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; - */ - errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop); - return errCode; -} - - -/* - * usbvision_frames_alloc - * allocate the maximum frames this driver can manage - */ -int usbvision_frames_alloc(struct usb_usbvision *usbvision) -{ - int i; - - /* Allocate memory for the frame buffers */ - usbvision->max_frame_size = MAX_FRAME_SIZE; - usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size; - usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); - - if(usbvision->fbuf == NULL) { - err("%s: unable to allocate %d bytes for fbuf ", - __FUNCTION__, usbvision->fbuf_size); - return -ENOMEM; - } - spin_lock_init(&usbvision->queue_lock); - init_waitqueue_head(&usbvision->wait_frame); - init_waitqueue_head(&usbvision->wait_stream); - - /* Allocate all buffers */ - for (i = 0; i < USBVISION_NUMFRAMES; i++) { - usbvision->frame[i].index = i; - usbvision->frame[i].grabstate = FrameState_Unused; - usbvision->frame[i].data = usbvision->fbuf + - i * usbvision->max_frame_size; - /* - * Set default sizes for read operation. - */ - usbvision->stretch_width = 1; - usbvision->stretch_height = 1; - usbvision->frame[i].width = usbvision->curwidth; - usbvision->frame[i].height = usbvision->curheight; - usbvision->frame[i].bytes_read = 0; - } - return 0; -} - -/* - * usbvision_frames_free - * frees memory allocated for the frames - */ -void usbvision_frames_free(struct usb_usbvision *usbvision) -{ - /* Have to free all that memory */ - if (usbvision->fbuf != NULL) { - usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); - usbvision->fbuf = NULL; - } -} -/* - * usbvision_empty_framequeues() - * prepare queues for incoming and outgoing frames - */ -void usbvision_empty_framequeues(struct usb_usbvision *usbvision) -{ - u32 i; - - INIT_LIST_HEAD(&(usbvision->inqueue)); - INIT_LIST_HEAD(&(usbvision->outqueue)); - - for (i = 0; i < USBVISION_NUMFRAMES; i++) { - usbvision->frame[i].grabstate = FrameState_Unused; - usbvision->frame[i].bytes_read = 0; - } -} - -/* - * usbvision_stream_interrupt() - * stops streaming - */ -int usbvision_stream_interrupt(struct usb_usbvision *usbvision) -{ - int ret = 0; - - /* stop reading from the device */ - - usbvision->streaming = Stream_Interrupt; - ret = wait_event_timeout(usbvision->wait_stream, - (usbvision->streaming == Stream_Idle), - msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); - return ret; -} - -/* - * usbvision_set_compress_params() - * - */ - -static int usbvision_set_compress_params(struct usb_usbvision *usbvision) -{ - static const char proc[] = "usbvision_set_compresion_params: "; - int rc; - unsigned char value[6]; - - value[0] = 0x0F; // Intra-Compression cycle - value[1] = 0x01; // Reg.45 one line per strip - value[2] = 0x00; // Reg.46 Force intra mode on all new frames - value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force) - value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. - value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression - - //catched values for NT1004 - // value[0] = 0xFF; // Never apply intra mode automatically - // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip - // value[2] = 0x01; // Force intra mode on all new frames - // value[3] = 0x00; // Strip size 400 Bytes; do not force up - // value[4] = 0xA2; // - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_INTRA_CYC, value, 5, HZ); - - if (rc < 0) { - printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - return rc; - } - - if (usbvision->bridgeType == BRIDGE_NT1004) { - value[0] = 20; // PCM Threshold 1 - value[1] = 12; // PCM Threshold 2 - value[2] = 255; // Distorsion Threshold inter - value[3] = 255; // Distorsion Threshold intra - value[4] = 43; // Max Distorsion inter - value[5] = 43; // Max Distorsion intra - } - else { - value[0] = 20; // PCM Threshold 1 - value[1] = 12; // PCM Threshold 2 - value[2] = 255; // Distorsion Threshold d7-d0 - value[3] = 0; // Distorsion Threshold d11-d8 - value[4] = 43; // Max Distorsion d7-d0 - value[5] = 0; // Max Distorsion d8 - } - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_PCM_THR1, value, 6, HZ); - - if (rc < 0) { - printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - return rc; - } - - - return rc; -} - - -/* - * usbvision_set_input() - * - * Set the input (saa711x, ...) size x y and other misc input params - * I've no idea if this parameters are right - * - */ -int usbvision_set_input(struct usb_usbvision *usbvision) -{ - static const char proc[] = "usbvision_set_input: "; - int rc; - unsigned char value[8]; - unsigned char dvi_yuv_value; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - /* Set input format expected from decoder*/ - if (usbvision_device_data[usbvision->DevModel].Vin_Reg1 >= 0) { - value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1 & 0xff; - } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { - /* SAA7113 uses 8 bit output */ - value[0] = USBVISION_8_422_SYNC; - } else { - /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses - * as that is how saa7111 is configured */ - value[0] = USBVISION_16_422_SYNC; - /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/ - } - - rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]); - if (rc < 0) { - printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - return rc; - } - - - if (usbvision->tvnorm->id & V4L2_STD_PAL) { - value[0] = 0xC0; - value[1] = 0x02; //0x02C0 -> 704 Input video line length - value[2] = 0x20; - value[3] = 0x01; //0x0120 -> 288 Input video n. of lines - value[4] = 0x60; - value[5] = 0x00; //0x0060 -> 96 Input video h offset - value[6] = 0x16; - value[7] = 0x00; //0x0016 -> 22 Input video v offset - } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) { - value[0] = 0xC0; - value[1] = 0x02; //0x02C0 -> 704 Input video line length - value[2] = 0x20; - value[3] = 0x01; //0x0120 -> 288 Input video n. of lines - value[4] = 0x01; - value[5] = 0x00; //0x0001 -> 01 Input video h offset - value[6] = 0x01; - value[7] = 0x00; //0x0001 -> 01 Input video v offset - } else { /* V4L2_STD_NTSC */ - value[0] = 0xD0; - value[1] = 0x02; //0x02D0 -> 720 Input video line length - value[2] = 0xF0; - value[3] = 0x00; //0x00F0 -> 240 Input video number of lines - value[4] = 0x50; - value[5] = 0x00; //0x0050 -> 80 Input video h offset - value[6] = 0x10; - value[7] = 0x00; //0x0010 -> 16 Input video v offset - } - - if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) { - value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff; - value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8; - } - - if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) { - value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff; - value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8; - } - - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, /* USBVISION specific code */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_LXSIZE_I, value, 8, HZ); - if (rc < 0) { - printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - return rc; - } - - - dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ - - if(usbvision_device_data[usbvision->DevModel].Dvi_yuv >= 0){ - dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv & 0xff; - } - else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { - /* This changes as the fine sync control changes. Further investigation necessary */ - dvi_yuv_value = 0x06; - } - - return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value)); -} - - -/* - * usbvision_set_dram_settings() - * - * Set the buffer address needed by the usbvision dram to operate - * This values has been taken with usbsnoop. - * - */ - -static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) -{ - int rc; - unsigned char value[8]; - - if (usbvision->isocMode == ISOC_MODE_COMPRESS) { - value[0] = 0x42; - value[1] = 0x71; - value[2] = 0xff; - value[3] = 0x00; - value[4] = 0x98; - value[5] = 0xe0; - value[6] = 0x71; - value[7] = 0xff; - // UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) - // FDL: 0x00000-0x0E099 = 57498 Words - // VDW: 0x0E3FF-0x3FFFF - } - else { - value[0] = 0x42; - value[1] = 0x00; - value[2] = 0xff; - value[3] = 0x00; - value[4] = 0x00; - value[5] = 0x00; - value[6] = 0x00; - value[7] = 0xff; - } - /* These are the values of the address of the video buffer, - * they have to be loaded into the USBVISION_DRM_PRM1-8 - * - * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 - * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff - * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 - * Only used in compressed mode - * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff - * Only used in compressed mode - * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 - * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff - */ - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, /* USBVISION specific code */ - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_DRM_PRM1, value, 8, HZ); - - if (rc < 0) { - err("%sERROR=%d", __FUNCTION__, rc); - return rc; - } - - /* Restart the video buffer logic */ - if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | - USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0) - return rc; - rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00); - - return rc; -} - -/* - * () - * - * Power on the device, enables suspend-resume logic - * & reset the isoc End-Point - * - */ - -int usbvision_power_on(struct usb_usbvision *usbvision) -{ - int errCode = 0; - - PDEBUG(DBG_FUNC, ""); - - usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); - usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_RES2); - usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID); - errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); - if (errCode == 1) { - usbvision->power = 1; - } - PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode); - return errCode; -} - - -/* - * usbvision timer stuff - */ - -// to call usbvision_power_off from task queue -static void call_usbvision_power_off(struct work_struct *work) -{ - struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork); - - PDEBUG(DBG_FUNC, ""); - down_interruptible(&usbvision->lock); - if(usbvision->user == 0) { - usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); - - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } - up(&usbvision->lock); -} - -static void usbvision_powerOffTimer(unsigned long data) -{ - struct usb_usbvision *usbvision = (void *) data; - - PDEBUG(DBG_FUNC, ""); - del_timer(&usbvision->powerOffTimer); - INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off); - (void) schedule_work(&usbvision->powerOffWork); - -} - -void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision) -{ - init_timer(&usbvision->powerOffTimer); - usbvision->powerOffTimer.data = (long) usbvision; - usbvision->powerOffTimer.function = usbvision_powerOffTimer; -} - -void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision) -{ - mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME); -} - -void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision) -{ - if (timer_pending(&usbvision->powerOffTimer)) { - del_timer(&usbvision->powerOffTimer); - } -} - -/* - * usbvision_begin_streaming() - * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no - * idea about the rest - */ -int usbvision_begin_streaming(struct usb_usbvision *usbvision) -{ - int errCode = 0; - - if (usbvision->isocMode == ISOC_MODE_COMPRESS) { - usbvision_init_compression(usbvision); - } - errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | - usbvision->Vin_Reg2_Preset); - return errCode; -} - -/* - * usbvision_restart_isoc() - * Not sure yet if touching here PWR_REG make loose the config - */ - -int usbvision_restart_isoc(struct usb_usbvision *usbvision) -{ - int ret; - - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0) - return ret; - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID | - USBVISION_RES2)) < 0) - return ret; - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_VIN_REG2, - USBVISION_KEEP_BLANK | USBVISION_NOHVALID | - usbvision->Vin_Reg2_Preset)) < 0) return ret; - - /* TODO: schedule timeout */ - while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) && 0x01) != 1); - - return 0; -} - -int usbvision_audio_off(struct usb_usbvision *usbvision) -{ - if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) { - printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n"); - return -1; - } - usbvision->AudioMute = 0; - usbvision->AudioChannel = USBVISION_AUDIO_MUTE; - return 0; -} - -int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel) -{ - if (!usbvision->AudioMute) { - if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) { - printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n"); - return -1; - } - } - usbvision->AudioChannel = AudioChannel; - return 0; -} - -int usbvision_setup(struct usb_usbvision *usbvision,int format) -{ - usbvision_set_video_format(usbvision, format); - usbvision_set_dram_settings(usbvision); - usbvision_set_compress_params(usbvision); - usbvision_set_input(usbvision); - usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT); - usbvision_restart_isoc(usbvision); - - /* cosas del PCM */ - return USBVISION_IS_OPERATIONAL(usbvision); -} - - -int usbvision_sbuf_alloc(struct usb_usbvision *usbvision) -{ - int i, errCode = 0; - const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; - - /* Clean pointers so we know if we allocated something */ - for (i = 0; i < USBVISION_NUMSBUF; i++) - usbvision->sbuf[i].data = NULL; - - for (i = 0; i < USBVISION_NUMSBUF; i++) { - usbvision->sbuf[i].data = kzalloc(sb_size, GFP_KERNEL); - if (usbvision->sbuf[i].data == NULL) { - err("%s: unable to allocate %d bytes for sbuf", __FUNCTION__, sb_size); - errCode = -ENOMEM; - break; - } - } - return errCode; -} - - -void usbvision_sbuf_free(struct usb_usbvision *usbvision) -{ - int i; - - for (i = 0; i < USBVISION_NUMSBUF; i++) { - if (usbvision->sbuf[i].data != NULL) { - kfree(usbvision->sbuf[i].data); - usbvision->sbuf[i].data = NULL; - } - } -} - -/* - * usbvision_init_isoc() - * - */ -int usbvision_init_isoc(struct usb_usbvision *usbvision) -{ - struct usb_device *dev = usbvision->dev; - int bufIdx, errCode, regValue; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EFAULT; - - usbvision->curFrame = NULL; - scratch_reset(usbvision); - - /* Alternate interface 1 is is the biggest frame size */ - errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive); - if (errCode < 0) { - usbvision->last_error = errCode; - return -EBUSY; - } - - regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; - usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; - PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); - - usbvision->usb_bandwidth = regValue >> 1; - PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); - - - - /* We double buffer the Iso lists */ - - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { - int j, k; - struct urb *urb; - - urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); - if (urb == NULL) { - err("%s: usb_alloc_urb() failed", __FUNCTION__); - return -ENOMEM; - } - usbvision->sbuf[bufIdx].urb = urb; - urb->dev = dev; - urb->context = usbvision; - urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); - urb->transfer_flags = URB_ISO_ASAP; - urb->interval = 1; - urb->transfer_buffer = usbvision->sbuf[bufIdx].data; - urb->complete = usbvision_isocIrq; - urb->number_of_packets = USBVISION_URB_FRAMES; - urb->transfer_buffer_length = - usbvision->isocPacketSize * USBVISION_URB_FRAMES; - for (j = k = 0; j < USBVISION_URB_FRAMES; j++, - k += usbvision->isocPacketSize) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = usbvision->isocPacketSize; - } - } - - - /* Submit all URBs */ - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { - errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL); - if (errCode) { - err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode); - } - } - - usbvision->streaming = Stream_Idle; - PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); - return 0; -} - -/* - * usbvision_stop_isoc() - * - * This procedure stops streaming and deallocates URBs. Then it - * activates zero-bandwidth alt. setting of the video interface. - * - */ -void usbvision_stop_isoc(struct usb_usbvision *usbvision) -{ - int bufIdx, errCode, regValue; - - if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) - return; - - /* Unschedule all of the iso td's */ - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { - usb_kill_urb(usbvision->sbuf[bufIdx].urb); - usb_free_urb(usbvision->sbuf[bufIdx].urb); - usbvision->sbuf[bufIdx].urb = NULL; - } - - - PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__); - usbvision->streaming = Stream_Off; - - if (!usbvision->remove_pending) { - - /* Set packet size to 0 */ - errCode = usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->ifaceAltInactive); - if (errCode < 0) { - err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); - usbvision->last_error = errCode; - } - regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; - usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; - PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); - - usbvision->usb_bandwidth = regValue >> 1; - PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); - } -} - -int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) -{ - int mode[4]; - int audio[]= {1, 0, 0, 0}; - struct v4l2_routing route; - //channel 0 is TV with audiochannel 1 (tuner mono) - //channel 1 is Composite with audio channel 0 (line in) - //channel 2 is S-Video with audio channel 0 (line in) - //channel 3 is additional video inputs to the device with audio channel 0 (line in) - - RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); - usbvision->ctl_input = channel; - route.input = SAA7115_COMPOSITE1; - call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); - call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); - - // set the new channel - // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video - // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red - - switch (usbvision_device_data[usbvision->DevModel].Codec) { - case CODEC_SAA7113: - if (SwitchSVideoInput) { // To handle problems with S-Video Input for some devices. Use SwitchSVideoInput parameter when loading the module. - mode[2] = 1; - } - else { - mode[2] = 7; - } - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - mode[0] = 0; mode[1] = 2; mode[3] = 3; // Special for four input devices - } - else { - mode[0] = 0; mode[1] = 2; //modes for regular saa7113 devices - } - break; - case CODEC_SAA7111: - mode[0] = 0; mode[1] = 1; mode[2] = 7; //modes for saa7111 - break; - default: - mode[0] = 0; mode[1] = 1; mode[2] = 7; //default modes - } - route.input = mode[channel]; - call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); - usbvision->channel = channel; - usbvision_set_audio(usbvision, audio[channel]); - return 0; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/trunk/drivers/media/video/usbvision/usbvision-i2c.c b/trunk/drivers/media/video/usbvision/usbvision-i2c.c deleted file mode 100644 index 0f3fba7ea6fe..000000000000 --- a/trunk/drivers/media/video/usbvision/usbvision-i2c.c +++ /dev/null @@ -1,571 +0,0 @@ -/* - * I2C_ALGO_USB.C - * i2c algorithm for USB-I2C Bridges - * - * Copyright (c) 1999-2005 Joerg Heckenbach - * Dwaine Garden - * - * This module is part of usbvision driver project. - * Updates to driver completed by Dwaine P. Garden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "usbvision.h" - -#define DBG_I2C 1<<0 -#define DBG_ALGO 1<<1 - -static int i2c_debug = 0; - -module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -#define PDEBUG(level, fmt, args...) \ - if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) - -static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, - short len); -static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, - short len); - -static inline int try_write_address(struct i2c_adapter *i2c_adap, - unsigned char addr, int retries) -{ - struct i2c_algo_usb_data *adap = i2c_adap->algo_data; - void *data; - int i, ret = -1; - char buf[4]; - - data = i2c_get_adapdata(i2c_adap); - buf[0] = 0x00; - for (i = 0; i <= retries; i++) { - ret = (usbvision_i2c_write(data, addr, buf, 1)); - if (ret == 1) - break; /* success! */ - udelay(5 /*adap->udelay */ ); - if (i == retries) /* no success */ - break; - udelay(adap->udelay); - } - if (i) { - PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); - } - return ret; -} - -static inline int try_read_address(struct i2c_adapter *i2c_adap, - unsigned char addr, int retries) -{ - struct i2c_algo_usb_data *adap = i2c_adap->algo_data; - void *data; - int i, ret = -1; - char buf[4]; - - data = i2c_get_adapdata(i2c_adap); - for (i = 0; i <= retries; i++) { - ret = (usbvision_i2c_read(data, addr, buf, 1)); - if (ret == 1) - break; /* success! */ - udelay(5 /*adap->udelay */ ); - if (i == retries) /* no success */ - break; - udelay(adap->udelay); - } - if (i) { - PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); - } - return ret; -} - -static inline int usb_find_address(struct i2c_adapter *i2c_adap, - struct i2c_msg *msg, int retries, - unsigned char *add) -{ - unsigned short flags = msg->flags; - - unsigned char addr; - int ret; - if ((flags & I2C_M_TEN)) { - /* a ten bit address */ - addr = 0xf0 | ((msg->addr >> 7) & 0x03); - /* try extended address code... */ - ret = try_write_address(i2c_adap, addr, retries); - if (ret != 1) { - err("died at extended address code, while writing"); - return -EREMOTEIO; - } - add[0] = addr; - if (flags & I2C_M_RD) { - /* okay, now switch into reading mode */ - addr |= 0x01; - ret = try_read_address(i2c_adap, addr, retries); - if (ret != 1) { - err("died at extended address code, while reading"); - return -EREMOTEIO; - } - } - - } else { /* normal 7bit address */ - addr = (msg->addr << 1); - if (flags & I2C_M_RD) - addr |= 1; - if (flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - - add[0] = addr; - if (flags & I2C_M_RD) - ret = try_read_address(i2c_adap, addr, retries); - else - ret = try_write_address(i2c_adap, addr, retries); - - if (ret != 1) { - return -EREMOTEIO; - } - } - return 0; -} - -static int -usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) -{ - struct i2c_msg *pmsg; - void *data; - int i, ret; - unsigned char addr; - - data = i2c_get_adapdata(i2c_adap); - - for (i = 0; i < num; i++) { - pmsg = &msgs[i]; - ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); - if (ret != 0) { - PDEBUG(DBG_ALGO,"got NAK from device, message #%d", i); - return (ret < 0) ? ret : -EREMOTEIO; - } - - if (pmsg->flags & I2C_M_RD) { - /* read bytes into buffer */ - ret = (usbvision_i2c_read(data, addr, pmsg->buf, pmsg->len)); - if (ret < pmsg->len) { - return (ret < 0) ? ret : -EREMOTEIO; - } - } else { - /* write bytes from buffer */ - ret = (usbvision_i2c_write(data, addr, pmsg->buf, pmsg->len)); - if (ret < pmsg->len) { - return (ret < 0) ? ret : -EREMOTEIO; - } - } - } - return num; -} - -static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg) -{ - return 0; -} - -static u32 usb_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; -} - - -/* -----exported algorithm data: ------------------------------------- */ - -static struct i2c_algorithm i2c_usb_algo = { - .master_xfer = usb_xfer, - .smbus_xfer = NULL, - .algo_control = algo_control, - .functionality = usb_func, -}; - - -/* - * registering functions to load algorithms at runtime - */ -int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) -{ - PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); - PDEBUG(DBG_ALGO, "ALGO debugging is enabled [i2c]"); - - /* register new adapter to i2c module... */ - - adap->algo = &i2c_usb_algo; - - adap->timeout = 100; /* default values, should */ - adap->retries = 3; /* be replaced by defines */ - - i2c_add_adapter(adap); - - PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name); - - return 0; -} - - -int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap) -{ - - i2c_del_adapter(adap); - - PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name); - - return 0; -} - - -/* ----------------------------------------------------------------------- */ -/* usbvision specific I2C functions */ -/* ----------------------------------------------------------------------- */ -static struct i2c_adapter i2c_adap_template; -static struct i2c_algo_usb_data i2c_algo_template; -static struct i2c_client i2c_client_template; - -int usbvision_init_i2c(struct usb_usbvision *usbvision) -{ - memcpy(&usbvision->i2c_adap, &i2c_adap_template, - sizeof(struct i2c_adapter)); - memcpy(&usbvision->i2c_algo, &i2c_algo_template, - sizeof(struct i2c_algo_usb_data)); - memcpy(&usbvision->i2c_client, &i2c_client_template, - sizeof(struct i2c_client)); - - sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), - " #%d", usbvision->vdev->minor & 0x1f); - PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); - - i2c_set_adapdata(&usbvision->i2c_adap, usbvision); - i2c_set_clientdata(&usbvision->i2c_client, usbvision); - i2c_set_algo_usb_data(&usbvision->i2c_algo, usbvision); - - usbvision->i2c_adap.algo_data = &usbvision->i2c_algo; - usbvision->i2c_client.adapter = &usbvision->i2c_adap; - - if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { - printk(KERN_ERR "usbvision_init_i2c: can't write reg\n"); - return -EBUSY; - } - -#ifdef CONFIG_MODULES - /* Request the load of the i2c modules we need */ - switch (usbvision_device_data[usbvision->DevModel].Codec) { - case CODEC_SAA7113: - request_module("saa7115"); - break; - case CODEC_SAA7111: - request_module("saa7115"); - break; - } - if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { - request_module("tuner"); - } -#endif - - return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap); -} - -void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, - void *arg) -{ - BUG_ON(NULL == usbvision->i2c_adap.algo_data); - i2c_clients_command(&usbvision->i2c_adap, cmd, arg); -} - -static int attach_inform(struct i2c_client *client) -{ - struct usb_usbvision *usbvision; - - usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); - - switch (client->addr << 1) { - case 0x43: - case 0x4b: - { - struct tuner_setup tun_setup; - - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = TUNER_TDA9887; - tun_setup.addr = client->addr; - - call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); - - break; - } - case 0x42: - PDEBUG(DBG_I2C,"attach_inform: saa7114 detected."); - break; - case 0x4a: - PDEBUG(DBG_I2C,"attach_inform: saa7113 detected."); - break; - case 0xa0: - PDEBUG(DBG_I2C,"attach_inform: eeprom detected."); - break; - - default: - { - struct tuner_setup tun_setup; - - PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1); - usbvision->tuner_addr = client->addr; - - if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) { - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = usbvision->tuner_type; - tun_setup.addr = usbvision->tuner_addr; - call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); - } - } - break; - } - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct usb_usbvision *usbvision; - - usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); - - PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name); - return 0; -} - -static int -usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, - char *buf, short len) -{ - int rc, retries; - - for (retries = 5;;) { - rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr); - if (rc < 0) - return rc; - - /* Initiate byte read cycle */ - /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */ - /* d3 0=Wr 1=Rd */ - rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, - (len & 0x07) | 0x18); - if (rc < 0) - return rc; - - /* Test for Busy and ACK */ - do { - /* USBVISION_SER_CONT -> d4 == 0 busy */ - rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); - } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ - if (rc < 0) - return rc; - - /* USBVISION_SER_CONT -> d5 == 1 Not ack */ - if ((rc & 0x20) == 0) /* Ack? */ - break; - - /* I2C abort */ - rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); - if (rc < 0) - return rc; - - if (--retries < 0) - return -1; - } - - switch (len) { - case 4: - buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4); - case 3: - buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3); - case 2: - buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2); - case 1: - buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1); - break; - default: - printk(KERN_ERR - "usbvision_i2c_read_max4: buffer length > 4\n"); - } - - if (i2c_debug & DBG_I2C) { - int idx; - for (idx = 0; idx < len; idx++) { - PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr); - } - } - return len; -} - - -static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, - unsigned char addr, const char *buf, - short len) -{ - int rc, retries; - int i; - unsigned char value[6]; - unsigned char ser_cont; - - ser_cont = (len & 0x07) | 0x10; - - value[0] = addr; - value[1] = ser_cont; - for (i = 0; i < len; i++) - value[i + 2] = buf[i]; - - for (retries = 5;;) { - rc = usb_control_msg(usbvision->dev, - usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_SER_ADRS, value, - len + 2, HZ); - - if (rc < 0) - return rc; - - rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, - (len & 0x07) | 0x10); - if (rc < 0) - return rc; - - /* Test for Busy and ACK */ - do { - rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); - } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ - if (rc < 0) - return rc; - - if ((rc & 0x20) == 0) /* Ack? */ - break; - - /* I2C abort */ - usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); - - if (--retries < 0) - return -1; - - } - - if (i2c_debug & DBG_I2C) { - int idx; - for (idx = 0; idx < len; idx++) { - PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr); - } - } - return len; -} - -static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, - short len) -{ - char *bufPtr = buf; - int retval; - int wrcount = 0; - int count; - int maxLen = 4; - struct usb_usbvision *usbvision = (struct usb_usbvision *) data; - - while (len > 0) { - count = (len > maxLen) ? maxLen : len; - retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count); - if (retval > 0) { - len -= count; - bufPtr += count; - wrcount += count; - } else - return (retval < 0) ? retval : -EFAULT; - } - return wrcount; -} - -static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, - short len) -{ - char temp[4]; - int retval, i; - int rdcount = 0; - int count; - struct usb_usbvision *usbvision = (struct usb_usbvision *) data; - - while (len > 0) { - count = (len > 3) ? 4 : len; - retval = usbvision_i2c_read_max4(usbvision, addr, temp, count); - if (retval > 0) { - for (i = 0; i < len; i++) - buf[rdcount + i] = temp[i]; - len -= count; - rdcount += count; - } else - return (retval < 0) ? retval : -EFAULT; - } - return rdcount; -} - -static struct i2c_algo_usb_data i2c_algo_template = { - .data = NULL, - .inb = usbvision_i2c_read, - .outb = usbvision_i2c_write, - .udelay = 10, - .mdelay = 10, - .timeout = 100, -}; - -static struct i2c_adapter i2c_adap_template = { - .owner = THIS_MODULE, - .name = "usbvision", - .id = I2C_HW_B_BT848, /* FIXME */ - .algo = NULL, - .algo_data = NULL, - .client_register = attach_inform, - .client_unregister = detach_inform, -#ifdef I2C_ADAP_CLASS_TV_ANALOG - .class = I2C_ADAP_CLASS_TV_ANALOG, -#else - .class = I2C_CLASS_TV_ANALOG, -#endif -}; - -static struct i2c_client i2c_client_template = { - .name = "usbvision internal", -}; - -EXPORT_SYMBOL(usbvision_i2c_usb_add_bus); -EXPORT_SYMBOL(usbvision_i2c_usb_del_bus); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/trunk/drivers/media/video/usbvision/usbvision-video.c b/trunk/drivers/media/video/usbvision/usbvision-video.c deleted file mode 100644 index 864446c012eb..000000000000 --- a/trunk/drivers/media/video/usbvision/usbvision-video.c +++ /dev/null @@ -1,2051 +0,0 @@ -/* - * USB USBVISION Video device driver 0.9.9 - * - * - * - * Copyright (c) 1999-2005 Joerg Heckenbach - * - * This module is part of usbvision driver project. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Let's call the version 0.... until compression decoding is completely - * implemented. - * - * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach. - * It was based on USB CPiA driver written by Peter Pregler, - * Scott J. Bertin and Johannes Erdfelt - * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler & - * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink - * Updates to driver completed by Dwaine P. Garden - * - * - * TODO: - * - use submit_urb for all setup packets - * - Fix memory settings for nt1004. It is 4 times as big as the - * nt1003 memory. - * - Add audio on endpoint 3 for nt1004 chip. Seems impossible, needs a codec interface. Which one? - * - Clean up the driver. - * - optimization for performance. - * - Add Videotext capability (VBI). Working on it..... - * - Check audio for other devices - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_KMOD -#include -#endif - -#include "usbvision.h" - -#define DRIVER_AUTHOR "Joerg Heckenbach , Dwaine Garden " -#define DRIVER_NAME "usbvision" -#define DRIVER_ALIAS "USBVision" -#define DRIVER_DESC "USBVision USB Video Device Driver for Linux" -#define DRIVER_LICENSE "GPL" -#define USBVISION_DRIVER_VERSION_MAJOR 0 -#define USBVISION_DRIVER_VERSION_MINOR 9 -#define USBVISION_DRIVER_VERSION_PATCHLEVEL 9 -#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,USBVISION_DRIVER_VERSION_MINOR,USBVISION_DRIVER_VERSION_PATCHLEVEL) -#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) "." __stringify(USBVISION_DRIVER_VERSION_MINOR) "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) - -#define ENABLE_HEXDUMP 0 /* Enable if you need it */ - - -#ifdef USBVISION_DEBUG - #define PDEBUG(level, fmt, args...) \ - if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) -#else - #define PDEBUG(level, fmt, args...) do {} while(0) -#endif - -#define DBG_IOCTL 1<<0 -#define DBG_IO 1<<1 -#define DBG_PROBE 1<<2 -#define DBG_MMAP 1<<3 - -//String operations -#define rmspace(str) while(*str==' ') str++; -#define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; - - -static int usbvision_nr = 0; // sequential number of usbvision device - -static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { - { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, - { 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" }, - { 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" }, - { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" }, - { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" }, - { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" }, - { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 ! - { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } -}; - -/* supported tv norms */ -static struct usbvision_tvnorm tvnorms[] = { - { - .name = "PAL", - .id = V4L2_STD_PAL, - }, { - .name = "NTSC", - .id = V4L2_STD_NTSC, - }, { - .name = "SECAM", - .id = V4L2_STD_SECAM, - }, { - .name = "PAL-M", - .id = V4L2_STD_PAL_M, - } -}; - -#define TVNORMS ARRAY_SIZE(tvnorms) - -// Function prototypes -static void usbvision_release(struct usb_usbvision *usbvision); - -// Default initalization of device driver parameters -static int isocMode = ISOC_MODE_COMPRESS; // Set the default format for ISOC endpoint -static int video_debug = 0; // Set the default Debug Mode of the device driver -static int PowerOnAtOpen = 1; // Set the default device to power on at startup -static int video_nr = -1; // Sequential Number of Video Device -static int radio_nr = -1; // Sequential Number of Radio Device -static int vbi_nr = -1; // Sequential Number of VBI Device -static char *CustomDevice=NULL; // Set as nothing.... - -// Grab parameters for the device driver - -#if defined(module_param) // Showing parameters under SYSFS -module_param(isocMode, int, 0444); -module_param(video_debug, int, 0444); -module_param(PowerOnAtOpen, int, 0444); -module_param(video_nr, int, 0444); -module_param(radio_nr, int, 0444); -module_param(vbi_nr, int, 0444); -module_param(CustomDevice, charp, 0444); -#else // Old Style -MODULE_PARAM(isocMode, "i"); -MODULE_PARM(video_debug, "i"); // Grab the Debug Mode of the device driver -MODULE_PARM(adjustCompression, "i"); // Grab the compression to be adaptive -MODULE_PARM(PowerOnAtOpen, "i"); // Grab the device to power on at startup -MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. -MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...) -MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...) -MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...) -MODULE_PARM(CustomDevice, "s"); // .... CustomDevice -#endif - -MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); -MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); -MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); -MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); -MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); -MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX). Default: -1 (autodetect)"); -MODULE_PARM_DESC(CustomDevice, " Define the fine tuning parameters for the device. Default: null"); - - -// Misc stuff -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); -MODULE_VERSION(USBVISION_VERSION_STRING); -MODULE_ALIAS(DRIVER_ALIAS); - - -/****************************************************************************************/ -/* SYSFS Code - Copied from the stv680.c usb module. */ -/* Device information is located at /sys/class/video4linux/video0 */ -/* Device parameters information is located at /sys/module/usbvision */ -/* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */ -/****************************************************************************************/ - - -#define YES_NO(x) ((x) ? "Yes" : "No") - -static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd) -{ - struct video_device *vdev = to_video_device(cd); - return video_get_drvdata(vdev); -} - -static ssize_t show_version(struct class_device *cd, char *buf) -{ - return sprintf(buf, "%s\n", USBVISION_VERSION_STRING); -} -static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL); - -static ssize_t show_model(struct class_device *class_dev, char *buf) -{ - struct video_device *vdev = to_video_device(class_dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString); -} -static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); - -static ssize_t show_hue(struct class_device *class_dev, char *buf) -{ - struct video_device *vdev = to_video_device(class_dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_HUE; - ctrl.value = 0; - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); - return sprintf(buf, "%d\n", ctrl.value >> 8); -} -static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); - -static ssize_t show_contrast(struct class_device *class_dev, char *buf) -{ - struct video_device *vdev = to_video_device(class_dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_CONTRAST; - ctrl.value = 0; - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); - return sprintf(buf, "%d\n", ctrl.value >> 8); -} -static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); - -static ssize_t show_brightness(struct class_device *class_dev, char *buf) -{ - struct video_device *vdev = to_video_device(class_dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_BRIGHTNESS; - ctrl.value = 0; - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); - return sprintf(buf, "%d\n", ctrl.value >> 8); -} -static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); - -static ssize_t show_saturation(struct class_device *class_dev, char *buf) -{ - struct video_device *vdev = to_video_device(class_dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_SATURATION; - ctrl.value = 0; - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); - return sprintf(buf, "%d\n", ctrl.value >> 8); -} -static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); - -static ssize_t show_streaming(struct class_device *class_dev, char *buf) -{ - struct video_device *vdev = to_video_device(class_dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0)); -} -static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); - -static ssize_t show_compression(struct class_device *class_dev, char *buf) -{ - struct video_device *vdev = to_video_device(class_dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); -} -static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); - -static ssize_t show_device_bridge(struct class_device *class_dev, char *buf) -{ - struct video_device *vdev = to_video_device(class_dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%d\n", usbvision->bridgeType); -} -static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); - -static void usbvision_create_sysfs(struct video_device *vdev) -{ - int res; - if (vdev) { - res=video_device_create_file(vdev, &class_device_attr_version); - res=video_device_create_file(vdev, &class_device_attr_model); - res=video_device_create_file(vdev, &class_device_attr_hue); - res=video_device_create_file(vdev, &class_device_attr_contrast); - res=video_device_create_file(vdev, &class_device_attr_brightness); - res=video_device_create_file(vdev, &class_device_attr_saturation); - res=video_device_create_file(vdev, &class_device_attr_streaming); - res=video_device_create_file(vdev, &class_device_attr_compression); - res=video_device_create_file(vdev, &class_device_attr_bridge); - } -} - -static void usbvision_remove_sysfs(struct video_device *vdev) -{ - if (vdev) { - video_device_remove_file(vdev, &class_device_attr_version); - video_device_remove_file(vdev, &class_device_attr_model); - video_device_remove_file(vdev, &class_device_attr_hue); - video_device_remove_file(vdev, &class_device_attr_contrast); - video_device_remove_file(vdev, &class_device_attr_brightness); - video_device_remove_file(vdev, &class_device_attr_saturation); - video_device_remove_file(vdev, &class_device_attr_streaming); - video_device_remove_file(vdev, &class_device_attr_compression); - video_device_remove_file(vdev, &class_device_attr_bridge); - } -} - - -/* - * usbvision_open() - * - * This is part of Video 4 Linux API. The driver can be opened by one - * client only (checks internal counter 'usbvision->user'). The procedure - * then allocates buffers needed for video processing. - * - */ -static int usbvision_v4l2_open(struct inode *inode, struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - int errCode = 0; - - PDEBUG(DBG_IO, "open"); - - - usbvision_reset_powerOffTimer(usbvision); - - if (usbvision->user) - errCode = -EBUSY; - else { - /* Allocate memory for the frame buffers */ - errCode = usbvision_frames_alloc(usbvision); - if(!errCode) { - /* Allocate memory for the scratch ring buffer */ - errCode = usbvision_scratch_alloc(usbvision); - if(!errCode) { - /* Allocate memory for the USB S buffers */ - errCode = usbvision_sbuf_alloc(usbvision); - if ((!errCode) && (usbvision->isocMode==ISOC_MODE_COMPRESS)) { - /* Allocate intermediate decompression buffers only if needed */ - errCode = usbvision_decompress_alloc(usbvision); - } - } - } - if (errCode) { - /* Deallocate all buffers if trouble */ - usbvision_frames_free(usbvision); - usbvision_scratch_free(usbvision); - usbvision_sbuf_free(usbvision); - usbvision_decompress_free(usbvision); - } - } - - /* If so far no errors then we shall start the camera */ - if (!errCode) { - down(&usbvision->lock); - if (usbvision->power == 0) { - usbvision_power_on(usbvision); - usbvision_init_i2c(usbvision); - } - - /* Send init sequence only once, it's large! */ - if (!usbvision->initialized) { - int setup_ok = 0; - setup_ok = usbvision_setup(usbvision,isocMode); - if (setup_ok) - usbvision->initialized = 1; - else - errCode = -EBUSY; - } - - if (!errCode) { - usbvision_begin_streaming(usbvision); - errCode = usbvision_init_isoc(usbvision); - /* device needs to be initialized before isoc transfer */ - usbvision_muxsel(usbvision,0); - usbvision->user++; - } - else { - if (PowerOnAtOpen) { - usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } - } - up(&usbvision->lock); - } - - if (errCode) { - } - - /* prepare queues */ - usbvision_empty_framequeues(usbvision); - - PDEBUG(DBG_IO, "success"); - return errCode; -} - -/* - * usbvision_v4l2_close() - * - * This is part of Video 4 Linux API. The procedure - * stops streaming and deallocates all buffers that were earlier - * allocated in usbvision_v4l2_open(). - * - */ -static int usbvision_v4l2_close(struct inode *inode, struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - - PDEBUG(DBG_IO, "close"); - down(&usbvision->lock); - - usbvision_audio_off(usbvision); - usbvision_restart_isoc(usbvision); - usbvision_stop_isoc(usbvision); - - usbvision_decompress_free(usbvision); - usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); - usbvision_scratch_free(usbvision); - usbvision_sbuf_free(usbvision); - - usbvision->user--; - - if (PowerOnAtOpen) { - /* power off in a little while to avoid off/on every close/open short sequences */ - usbvision_set_powerOffTimer(usbvision); - usbvision->initialized = 0; - } - - up(&usbvision->lock); - - if (usbvision->remove_pending) { - info("%s: Final disconnect", __FUNCTION__); - usbvision_release(usbvision); - } - - PDEBUG(DBG_IO, "success"); - - - return 0; -} - - -/* - * usbvision_ioctl() - * - * This is part of Video 4 Linux API. The procedure handles ioctl() calls. - * - */ -static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EFAULT; - - switch (cmd) { - -#ifdef CONFIG_VIDEO_ADV_DEBUG - /* ioctls to allow direct acces to the NT100x registers */ - case VIDIOC_INT_G_REGISTER: - { - struct v4l2_register *reg = arg; - int errCode; - - if (reg->i2c_id != 0) - return -EINVAL; - /* NT100x has a 8-bit register space */ - errCode = usbvision_read_reg(usbvision, reg->reg&0xff); - if (errCode < 0) { - err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode); - } - else { - reg->val=(unsigned char)errCode; - PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X", - (unsigned int)reg->reg, reg->val); - errCode = 0; // No error - } - return errCode; - } - case VIDIOC_INT_S_REGISTER: - { - struct v4l2_register *reg = arg; - int errCode; - - if (reg->i2c_id != 0) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); - if (errCode < 0) { - err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode); - } - else { - PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X", - (unsigned int)reg->reg, reg->val); - errCode = 0; - } - return 0; - } -#endif - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *vc=arg; - - memset(vc, 0, sizeof(*vc)); - strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); - strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, - sizeof(vc->card)); - strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, - sizeof(vc->bus_info)); - vc->version = USBVISION_DRIVER_VERSION; - vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING | - (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); - PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP"); - return 0; - } - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *vi = arg; - int chan; - - if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) - return -EINVAL; - if (usbvision->have_tuner) { - chan = vi->index; - } - else { - chan = vi->index + 1; //skip Television string - } - switch(chan) { - case 0: - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - strcpy(vi->name, "White Video Input"); - } - else { - strcpy(vi->name, "Television"); - vi->type = V4L2_INPUT_TYPE_TUNER; - vi->audioset = 1; - vi->tuner = chan; - vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM; - } - break; - case 1: - vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - strcpy(vi->name, "Green Video Input"); - } - else { - strcpy(vi->name, "Composite Video Input"); - } - vi->std = V4L2_STD_PAL; - break; - case 2: - vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - strcpy(vi->name, "Yellow Video Input"); - } - else { - strcpy(vi->name, "S-Video Input"); - } - vi->std = V4L2_STD_PAL; - break; - case 3: - vi->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(vi->name, "Red Video Input"); - vi->std = V4L2_STD_PAL; - break; - } - PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x", - vi->name, vi->index, vi->tuner,vi->type,(int)vi->std); - return 0; - } - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *e = arg; - unsigned int i; - int ret; - - i = e->index; - if (i >= TVNORMS) - return -EINVAL; - ret = v4l2_video_std_construct(e, tvnorms[e->index].id, - tvnorms[e->index].name); - e->index = i; - if (ret < 0) - return ret; - return 0; - } - case VIDIOC_G_INPUT: - { - int *input = arg; - *input = usbvision->ctl_input; - return 0; - } - case VIDIOC_S_INPUT: - { - int *input = arg; - if ((*input >= usbvision->video_inputs) || (*input < 0) ) - return -EINVAL; - usbvision->ctl_input = *input; - - down(&usbvision->lock); - usbvision_muxsel(usbvision, usbvision->ctl_input); - usbvision_set_input(usbvision); - usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); - up(&usbvision->lock); - return 0; - } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; - - *id = usbvision->tvnorm->id; - - PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name); - return 0; - } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - unsigned int i; - - for (i = 0; i < TVNORMS; i++) - if (*id == tvnorms[i].id) - break; - if (i == TVNORMS) - for (i = 0; i < TVNORMS; i++) - if (*id & tvnorms[i].id) - break; - if (i == TVNORMS) - return -EINVAL; - - down(&usbvision->lock); - usbvision->tvnorm = &tvnorms[i]; - - call_i2c_clients(usbvision, VIDIOC_S_STD, - &usbvision->tvnorm->id); - - up(&usbvision->lock); - - PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name); - return 0; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *vt = arg; - - if (!usbvision->have_tuner || vt->index) // Only tuner 0 - return -EINVAL; - strcpy(vt->name, "Television"); - /* Let clients fill in the remainder of this struct */ - call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); - - PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc); - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || vt->index) - return -EINVAL; - /* let clients handle this */ - call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); - - PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER"); - return 0; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *freq = arg; - - freq->tuner = 0; // Only one tuner - freq->type = V4L2_TUNER_ANALOG_TV; - freq->frequency = usbvision->freq; - PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency); - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *freq = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || freq->tuner) - return -EINVAL; - - usbvision->freq = freq->frequency; - call_i2c_clients(usbvision, cmd, freq); - PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency); - return 0; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *v = arg; - memset(v,0, sizeof(v)); - strcpy(v->name, "TV"); - PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO"); - return 0; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *v = arg; - if(v->index) { - return -EINVAL; - } - PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO"); - return 0; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - int id=ctrl->id; - - memset(ctrl,0,sizeof(*ctrl)); - ctrl->id=id; - - call_i2c_clients(usbvision, cmd, arg); - - if (ctrl->type) - return 0; - else - return -EINVAL; - - PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); - call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); - return 0; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - - PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); - call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); - return 0; - } - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *vr = arg; - int ret; - - RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); - - // Check input validity : the user must do a VIDEO CAPTURE and MMAP method. - if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (vr->memory != V4L2_MEMORY_MMAP)) - return -EINVAL; - - if(usbvision->streaming == Stream_On) { - if ((ret = usbvision_stream_interrupt(usbvision))) - return ret; - } - - usbvision_empty_framequeues(usbvision); - - usbvision->curFrame = NULL; - - PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count); - return 0; - } - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *vb = arg; - struct usbvision_frame *frame; - - // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) - - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } - if(vb->index>=USBVISION_NUMFRAMES) { - return -EINVAL; - } - // Updating the corresponding frame state - vb->flags = 0; - frame = &usbvision->frame[vb->index]; - if(frame->grabstate >= FrameState_Ready) - vb->flags |= V4L2_BUF_FLAG_QUEUED; - if(frame->grabstate >= FrameState_Done) - vb->flags |= V4L2_BUF_FLAG_DONE; - if(frame->grabstate == FrameState_Unused) - vb->flags |= V4L2_BUF_FLAG_MAPPED; - vb->memory = V4L2_MEMORY_MMAP; - - vb->m.offset = vb->index*usbvision->max_frame_size; - - vb->memory = V4L2_MEMORY_MMAP; - vb->field = V4L2_FIELD_NONE; - vb->length = usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel; - vb->timestamp = usbvision->frame[vb->index].timestamp; - vb->sequence = usbvision->frame[vb->index].sequence; - return 0; - } - case VIDIOC_QBUF: - { - struct v4l2_buffer *vb = arg; - struct usbvision_frame *frame; - unsigned long lock_flags; - - // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } - if(vb->index>=USBVISION_NUMFRAMES) { - return -EINVAL; - } - - frame = &usbvision->frame[vb->index]; - - if (frame->grabstate != FrameState_Unused) { - return -EAGAIN; - } - - /* Mark it as ready and enqueue frame */ - frame->grabstate = FrameState_Ready; - frame->scanstate = ScanState_Scanning; - frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ - - vb->flags &= ~V4L2_BUF_FLAG_DONE; - - /* set v4l2_format index */ - frame->v4l2_format = usbvision->palette; - - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - - PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index); - return 0; - } - case VIDIOC_DQBUF: - { - struct v4l2_buffer *vb = arg; - int ret; - struct usbvision_frame *f; - unsigned long lock_flags; - - if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (list_empty(&(usbvision->outqueue))) { - if (usbvision->streaming == Stream_Idle) - return -EINVAL; - ret = wait_event_interruptible - (usbvision->wait_frame, - !list_empty(&(usbvision->outqueue))); - if (ret) - return ret; - } - - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - f = list_entry(usbvision->outqueue.next, - struct usbvision_frame, frame); - list_del(usbvision->outqueue.next); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - - f->grabstate = FrameState_Unused; - - vb->memory = V4L2_MEMORY_MMAP; - vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; - vb->index = f->index; - vb->sequence = f->sequence; - vb->timestamp = f->timestamp; - vb->field = V4L2_FIELD_NONE; - vb->bytesused = f->scanlength; - - return 0; - } - case VIDIOC_STREAMON: - { - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; - - usbvision->streaming = Stream_On; - - call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); - - PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON"); - - return 0; - } - case VIDIOC_STREAMOFF: - { - int *type = arg; - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if(usbvision->streaming == Stream_On) { - usbvision_stream_interrupt(usbvision); - // Stop all video streamings - call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); - } - usbvision_empty_framequeues(usbvision); - - PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF"); - return 0; - } - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *vfd = arg; - - if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { - return -EINVAL; - } - vfd->flags = 0; - vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); - vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; - memset(vfd->reserved, 0, sizeof(vfd->reserved)); - return 0; - } - case VIDIOC_G_FMT: - { - struct v4l2_format *vf = arg; - - switch (vf->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - vf->fmt.pix.width = usbvision->curwidth; - vf->fmt.pix.height = usbvision->curheight; - vf->fmt.pix.pixelformat = usbvision->palette.format; - vf->fmt.pix.bytesperline = usbvision->curwidth*usbvision->palette.bytes_per_pixel; - vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight; - vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ - PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - default: - PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type); - return -EINVAL; - } - return 0; - } - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - { - struct v4l2_format *vf = arg; - int formatIdx,ret; - - switch(vf->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - /* Find requested format in available ones */ - for(formatIdx=0;formatIdxfmt.pix.pixelformat == usbvision_v4l2_format[formatIdx].format) { - usbvision->palette = usbvision_v4l2_format[formatIdx]; - break; - } - } - /* robustness */ - if(formatIdx == USBVISION_SUPPORTED_PALETTES) { - return -EINVAL; - } - RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); - RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); - - vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel; - vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; - - if(cmd == VIDIOC_TRY_FMT) { - PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - - /* stop io in case it is already in progress */ - if(usbvision->streaming == Stream_On) { - if ((ret = usbvision_stream_interrupt(usbvision))) - return ret; - } - usbvision_empty_framequeues(usbvision); - - usbvision->curFrame = NULL; - - // by now we are committed to the new data... - down(&usbvision->lock); - usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); - up(&usbvision->lock); - - PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - default: - return -EINVAL; - } - } - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl); -} - - -static ssize_t usbvision_v4l2_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - int noblock = file->f_flags & O_NONBLOCK; - unsigned long lock_flags; - - int frmx = -1; - int ret,i; - struct usbvision_frame *frame; - - PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock); - - if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) - return -EFAULT; - - /* no stream is running, make it running ! */ - usbvision->streaming = Stream_On; - call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); - - /* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ - for(i=0;iframe[i]; - if(frame->grabstate == FrameState_Unused) { - /* Mark it as ready and enqueue frame */ - frame->grabstate = FrameState_Ready; - frame->scanstate = ScanState_Scanning; - frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ - - /* set v4l2_format index */ - frame->v4l2_format = usbvision->palette; - - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - list_add_tail(&frame->frame, &usbvision->inqueue); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - } - } - - /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */ - if (list_empty(&(usbvision->outqueue))) { - if(noblock) - return -EAGAIN; - - ret = wait_event_interruptible - (usbvision->wait_frame, - !list_empty(&(usbvision->outqueue))); - if (ret) - return ret; - } - - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - frame = list_entry(usbvision->outqueue.next, - struct usbvision_frame, frame); - list_del(usbvision->outqueue.next); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - - /* An error returns an empty frame */ - if (frame->grabstate == FrameState_Error) { - frame->bytes_read = 0; - return 0; - } - - PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__, - frame->index, frame->bytes_read, frame->scanlength); - - /* copy bytes to user space; we allow for partials reads */ - if ((count + frame->bytes_read) > (unsigned long)frame->scanlength) - count = frame->scanlength - frame->bytes_read; - - if (copy_to_user(buf, frame->data + frame->bytes_read, count)) { - return -EFAULT; - } - - frame->bytes_read += count; - PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__, - (unsigned long)count, frame->bytes_read); - - // For now, forget the frame if it has not been read in one shot. -/* if (frame->bytes_read >= frame->scanlength) {// All data has been read */ - frame->bytes_read = 0; - - /* Mark it as available to be used again. */ - usbvision->frame[frmx].grabstate = FrameState_Unused; -/* } */ - - return count; -} - -static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) -{ - unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; - void *pos; - u32 i; - - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - - down(&usbvision->lock); - - if (!USBVISION_IS_OPERATIONAL(usbvision)) { - up(&usbvision->lock); - return -EFAULT; - } - - if (!(vma->vm_flags & VM_WRITE) || - size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) { - up(&usbvision->lock); - return -EINVAL; - } - - for (i = 0; i < USBVISION_NUMFRAMES; i++) { - if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff) - break; - } - if (i == USBVISION_NUMFRAMES) { - PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); - up(&usbvision->lock); - return -EINVAL; - } - - /* VM_IO is eventually going to replace PageReserved altogether */ - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ - - pos = usbvision->frame[i].data; - while (size > 0) { - - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed"); - up(&usbvision->lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - up(&usbvision->lock); - return 0; -} - - -/* - * Here comes the stuff for radio on usbvision based devices - * - */ -static int usbvision_radio_open(struct inode *inode, struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - struct v4l2_frequency freq; - int errCode = 0; - - PDEBUG(DBG_IO, "%s:", __FUNCTION__); - - down(&usbvision->lock); - - if (usbvision->user) { - err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__); - errCode = -EBUSY; - } - else { - if(PowerOnAtOpen) { - usbvision_reset_powerOffTimer(usbvision); - if (usbvision->power == 0) { - usbvision_power_on(usbvision); - usbvision_init_i2c(usbvision); - } - } - - // If so far no errors then we shall start the radio - usbvision->radio = 1; - call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); - freq.frequency = 1517; //SWR3 @ 94.8MHz - call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq); - usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); - usbvision->user++; - } - - if (errCode) { - if (PowerOnAtOpen) { - usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } - } - up(&usbvision->lock); - return errCode; -} - - -static int usbvision_radio_close(struct inode *inode, struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - int errCode = 0; - - PDEBUG(DBG_IO, ""); - - down(&usbvision->lock); - - usbvision_audio_off(usbvision); - usbvision->radio=0; - usbvision->user--; - - if (PowerOnAtOpen) { - usbvision_set_powerOffTimer(usbvision); - usbvision->initialized = 0; - } - - up(&usbvision->lock); - - if (usbvision->remove_pending) { - info("%s: Final disconnect", __FUNCTION__); - usbvision_release(usbvision); - } - - - PDEBUG(DBG_IO, "success"); - - return errCode; -} - -static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EIO; - - switch (cmd) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *vc=arg; - - memset(vc, 0, sizeof(*vc)); - strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); - strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, - sizeof(vc->card)); - strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, - sizeof(vc->bus_info)); - vc->version = USBVISION_DRIVER_VERSION; - vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); - PDEBUG(DBG_IO, "VIDIOC_QUERYCAP"); - return 0; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - int id=ctrl->id; - - memset(ctrl,0,sizeof(*ctrl)); - ctrl->id=id; - - call_i2c_clients(usbvision, cmd, arg); - PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); - - if (ctrl->type) - return 0; - else - return -EINVAL; - - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); - PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); - return 0; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - - call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); - PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); - return 0; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - - if (t->index > 0) - return -EINVAL; - - memset(t,0,sizeof(*t)); - strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; - - /* Let clients fill in the remainder of this struct */ - call_i2c_clients(usbvision,VIDIOC_G_TUNER,t); - PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc); - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || vt->index) - return -EINVAL; - /* let clients handle this */ - call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); - - PDEBUG(DBG_IO, "VIDIOC_S_TUNER"); - return 0; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *a = arg; - - memset(a,0,sizeof(*a)); - strcpy(a->name,"Radio"); - PDEBUG(DBG_IO, "VIDIOC_G_AUDIO"); - return 0; - } - case VIDIOC_S_AUDIO: - case VIDIOC_S_INPUT: - case VIDIOC_S_STD: - return 0; - - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - memset(f,0,sizeof(*f)); - - f->type = V4L2_TUNER_RADIO; - f->frequency = usbvision->freq; - call_i2c_clients(usbvision, cmd, f); - PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency); - - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - if (f->tuner != 0) - return -EINVAL; - usbvision->freq = f->frequency; - call_i2c_clients(usbvision, cmd, f); - PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency); - - return 0; - } - default: - { - PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd); - return -ENOIOCTLCMD; - } - } - return 0; -} - - -static int usbvision_radio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl); -} - - -/* - * Here comes the stuff for vbi on usbvision based devices - * - */ -static int usbvision_vbi_open(struct inode *inode, struct file *file) -{ - /* TODO */ - return -EINVAL; - -} - -static int usbvision_vbi_close(struct inode *inode, struct file *file) -{ - /* TODO */ - return -EINVAL; -} - -static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - /* TODO */ - return -EINVAL; -} - -static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, usbvision_do_vbi_ioctl); -} - - -// -// Video registration stuff -// - -// Video template -static struct file_operations usbvision_fops = { - .owner = THIS_MODULE, - .open = usbvision_v4l2_open, - .release = usbvision_v4l2_close, - .read = usbvision_v4l2_read, - .mmap = usbvision_v4l2_mmap, - .ioctl = usbvision_v4l2_ioctl, - .llseek = no_llseek, -}; -static struct video_device usbvision_video_template = { - .owner = THIS_MODULE, - .type = VID_TYPE_TUNER | VID_TYPE_CAPTURE, - .hardware = VID_HARDWARE_USBVISION, - .fops = &usbvision_fops, - .name = "usbvision-video", - .release = video_device_release, - .minor = -1, -}; - - -// Radio template -static struct file_operations usbvision_radio_fops = { - .owner = THIS_MODULE, - .open = usbvision_radio_open, - .release = usbvision_radio_close, - .ioctl = usbvision_radio_ioctl, - .llseek = no_llseek, -}; - -static struct video_device usbvision_radio_template= -{ - .owner = THIS_MODULE, - .type = VID_TYPE_TUNER, - .hardware = VID_HARDWARE_USBVISION, - .fops = &usbvision_radio_fops, - .release = video_device_release, - .name = "usbvision-radio", - .minor = -1, -}; - - -// vbi template -static struct file_operations usbvision_vbi_fops = { - .owner = THIS_MODULE, - .open = usbvision_vbi_open, - .release = usbvision_vbi_close, - .ioctl = usbvision_vbi_ioctl, - .llseek = no_llseek, -}; - -static struct video_device usbvision_vbi_template= -{ - .owner = THIS_MODULE, - .type = VID_TYPE_TUNER, - .hardware = VID_HARDWARE_USBVISION, - .fops = &usbvision_vbi_fops, - .release = video_device_release, - .name = "usbvision-vbi", - .minor = -1, -}; - - -static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, - struct video_device *vdev_template, - char *name) -{ - struct usb_device *usb_dev = usbvision->dev; - struct video_device *vdev; - - if (usb_dev == NULL) { - err("%s: usbvision->dev is not set", __FUNCTION__); - return NULL; - } - - vdev = video_device_alloc(); - if (NULL == vdev) { - return NULL; - } - *vdev = *vdev_template; -// vdev->minor = -1; - vdev->dev = &usb_dev->dev; - snprintf(vdev->name, sizeof(vdev->name), "%s", name); - video_set_drvdata(vdev, usbvision); - return vdev; -} - -// unregister video4linux devices -static void usbvision_unregister_video(struct usb_usbvision *usbvision) -{ - // vbi Device: - if (usbvision->vbi) { - PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f); - if (usbvision->vbi->minor != -1) { - video_unregister_device(usbvision->vbi); - } - else { - video_device_release(usbvision->vbi); - } - usbvision->vbi = NULL; - } - - // Radio Device: - if (usbvision->rdev) { - PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f); - if (usbvision->rdev->minor != -1) { - video_unregister_device(usbvision->rdev); - } - else { - video_device_release(usbvision->rdev); - } - usbvision->rdev = NULL; - } - - // Video Device: - if (usbvision->vdev) { - PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f); - if (usbvision->vdev->minor != -1) { - video_unregister_device(usbvision->vdev); - } - else { - video_device_release(usbvision->vdev); - } - usbvision->vdev = NULL; - } -} - -// register video4linux devices -static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) -{ - // Video Device: - usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); - if (usbvision->vdev == NULL) { - goto err_exit; - } - if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) { - goto err_exit; - } - info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f); - - // Radio Device: - if (usbvision_device_data[usbvision->DevModel].Radio) { - // usbvision has radio - usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); - if (usbvision->rdev == NULL) { - goto err_exit; - } - if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) { - goto err_exit; - } - info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f); - } - // vbi Device: - if (usbvision_device_data[usbvision->DevModel].vbi) { - usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI"); - if (usbvision->vdev == NULL) { - goto err_exit; - } - if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { - goto err_exit; - } - info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f); - } - // all done - return 0; - - err_exit: - err("USBVision[%d]: video_register_device() failed", usbvision->nr); - usbvision_unregister_video(usbvision); - return -1; -} - -/* - * usbvision_alloc() - * - * This code allocates the struct usb_usbvision. It is filled with default values. - * - * Returns NULL on error, a pointer to usb_usbvision else. - * - */ -static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) -{ - struct usb_usbvision *usbvision; - - if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { - goto err_exit; - } - - usbvision->dev = dev; - - init_MUTEX(&usbvision->lock); /* to 1 == available */ - - // prepare control urb for control messages during interrupts - usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); - if (usbvision->ctrlUrb == NULL) { - goto err_exit; - } - init_waitqueue_head(&usbvision->ctrlUrb_wq); - init_MUTEX(&usbvision->ctrlUrbLock); /* to 1 == available */ - - usbvision_init_powerOffTimer(usbvision); - - return usbvision; - -err_exit: - if (usbvision && usbvision->ctrlUrb) { - usb_free_urb(usbvision->ctrlUrb); - } - if (usbvision) { - kfree(usbvision); - } - return NULL; -} - -/* - * usbvision_release() - * - * This code does final release of struct usb_usbvision. This happens - * after the device is disconnected -and- all clients closed their files. - * - */ -static void usbvision_release(struct usb_usbvision *usbvision) -{ - PDEBUG(DBG_PROBE, ""); - - down(&usbvision->lock); - - usbvision_reset_powerOffTimer(usbvision); - - usbvision->initialized = 0; - - up(&usbvision->lock); - - usbvision_remove_sysfs(usbvision->vdev); - usbvision_unregister_video(usbvision); - - if (usbvision->ctrlUrb) { - usb_free_urb(usbvision->ctrlUrb); - } - - kfree(usbvision); - - PDEBUG(DBG_PROBE, "success"); -} - - -/******************************** usb interface *****************************************/ - -static void usbvision_configure_video(struct usb_usbvision *usbvision) -{ - int model,i; - - if (usbvision == NULL) - return; - - model = usbvision->DevModel; - usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; - - if (usbvision_device_data[usbvision->DevModel].Vin_Reg2 >= 0) { - usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2 & 0xff; - } else { - usbvision->Vin_Reg2_Preset = 0; - } - - for (i = 0; i < TVNORMS; i++) - if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode) - break; - if (i == TVNORMS) - i = 0; - usbvision->tvnorm = &tvnorms[i]; /* set default norm */ - - usbvision->video_inputs = usbvision_device_data[model].VideoChannels; - usbvision->ctl_input = 0; - - /* This should be here to make i2c clients to be able to register */ - usbvision_audio_off(usbvision); //first switch off audio - if (!PowerOnAtOpen) { - usbvision_power_on(usbvision); //and then power up the noisy tuner - usbvision_init_i2c(usbvision); - } -} - -/* - * usbvision_probe() - * - * This procedure queries device descriptor and accepts the interface - * if it looks like USBVISION video device - * - */ -static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; - const struct usb_host_interface *interface; - struct usb_usbvision *usbvision = NULL; - const struct usb_endpoint_descriptor *endpoint; - int model; - - PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", - dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); - /* Is it an USBVISION video dev? */ - model = 0; - for(model = 0; usbvision_device_data[model].idVendor; model++) { - if (le16_to_cpu(dev->descriptor.idVendor) != usbvision_device_data[model].idVendor) { - continue; - } - if (le16_to_cpu(dev->descriptor.idProduct) != usbvision_device_data[model].idProduct) { - continue; - } - - info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString); - break; - } - - if (usbvision_device_data[model].idVendor == 0) { - return -ENODEV; //no matching device - } - if (usbvision_device_data[model].Interface >= 0) { - interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; - } - else { - interface = &dev->actconfig->interface[ifnum]->altsetting[0]; - } - endpoint = &interface->endpoint[1].desc; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { - err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); - err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes); - return -ENODEV; - } - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { - err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum); - return -ENODEV; - } - - usb_get_dev(dev); - - if ((usbvision = usbvision_alloc(dev)) == NULL) { - err("%s: couldn't allocate USBVision struct", __FUNCTION__); - return -ENOMEM; - } - if (dev->descriptor.bNumConfigurations > 1) { - usbvision->bridgeType = BRIDGE_NT1004; - } - else if (usbvision_device_data[model].ModelString == "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)") { - usbvision->bridgeType = BRIDGE_NT1005; - } - else { - usbvision->bridgeType = BRIDGE_NT1003; - } - PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); - - down(&usbvision->lock); - - usbvision->nr = usbvision_nr++; - - usbvision->have_tuner = usbvision_device_data[model].Tuner; - if (usbvision->have_tuner) { - usbvision->tuner_type = usbvision_device_data[model].TunerType; - } - - usbvision->tuner_addr = ADDR_UNSET; - - usbvision->DevModel = model; - usbvision->remove_pending = 0; - usbvision->iface = ifnum; - usbvision->ifaceAltInactive = 0; - usbvision->ifaceAltActive = 1; - usbvision->video_endp = endpoint->bEndpointAddress; - usbvision->isocPacketSize = 0; - usbvision->usb_bandwidth = 0; - usbvision->user = 0; - usbvision->streaming = Stream_Off; - usbvision_register_video(usbvision); - usbvision_configure_video(usbvision); - up(&usbvision->lock); - - - usb_set_intfdata (intf, usbvision); - usbvision_create_sysfs(usbvision->vdev); - - PDEBUG(DBG_PROBE, "success"); - return 0; -} - - -/* - * usbvision_disconnect() - * - * This procedure stops all driver activity, deallocates interface-private - * structure (pointed by 'ptr') and after that driver should be removable - * with no ill consequences. - * - */ -static void __devexit usbvision_disconnect(struct usb_interface *intf) -{ - struct usb_usbvision *usbvision = usb_get_intfdata(intf); - - PDEBUG(DBG_PROBE, ""); - - if (usbvision == NULL) { - err("%s: usb_get_intfdata() failed", __FUNCTION__); - return; - } - usb_set_intfdata (intf, NULL); - - down(&usbvision->lock); - - // At this time we ask to cancel outstanding URBs - usbvision_stop_isoc(usbvision); - - if (usbvision->power) { - usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); - usbvision_power_off(usbvision); - } - usbvision->remove_pending = 1; // Now all ISO data will be ignored - - usb_put_dev(usbvision->dev); - usbvision->dev = NULL; // USB device is no more - - up(&usbvision->lock); - - if (usbvision->user) { - info("%s: In use, disconnect pending", __FUNCTION__); - wake_up_interruptible(&usbvision->wait_frame); - wake_up_interruptible(&usbvision->wait_stream); - } - else { - usbvision_release(usbvision); - } - - PDEBUG(DBG_PROBE, "success"); - -} - -static struct usb_driver usbvision_driver = { - .name = "usbvision", - .id_table = usbvision_table, - .probe = usbvision_probe, - .disconnect = usbvision_disconnect -}; - -/* - * customdevice_process() - * - * This procedure preprocesses CustomDevice parameter if any - * - */ -void customdevice_process(void) -{ - usbvision_device_data[0]=usbvision_device_data[1]; - usbvision_table[0]=usbvision_table[1]; - - if(CustomDevice) - { - char *parse=CustomDevice; - - PDEBUG(DBG_PROBE, "CustomDevide=%s", CustomDevice); - - /*format is CustomDevice="0x0573 0x4D31 0 7113 3 PAL 1 1 1 5 -1 -1 -1 -1 -1" - usbvision_device_data[0].idVendor; - usbvision_device_data[0].idProduct; - usbvision_device_data[0].Interface; - usbvision_device_data[0].Codec; - usbvision_device_data[0].VideoChannels; - usbvision_device_data[0].VideoNorm; - usbvision_device_data[0].AudioChannels; - usbvision_device_data[0].Radio; - usbvision_device_data[0].Tuner; - usbvision_device_data[0].TunerType; - usbvision_device_data[0].Vin_Reg1; - usbvision_device_data[0].Vin_Reg2; - usbvision_device_data[0].X_Offset; - usbvision_device_data[0].Y_Offset; - usbvision_device_data[0].Dvi_yuv; - usbvision_device_data[0].ModelString; - */ - - rmspace(parse); - usbvision_device_data[0].ModelString="USBVISION Custom Device"; - - parse+=2; - sscanf(parse,"%x",&usbvision_device_data[0].idVendor); - goto2next(parse); - PDEBUG(DBG_PROBE, "idVendor=0x%.4X", usbvision_device_data[0].idVendor); - parse+=2; - sscanf(parse,"%x",&usbvision_device_data[0].idProduct); - goto2next(parse); - PDEBUG(DBG_PROBE, "idProduct=0x%.4X", usbvision_device_data[0].idProduct); - sscanf(parse,"%d",&usbvision_device_data[0].Interface); - goto2next(parse); - PDEBUG(DBG_PROBE, "Interface=%d", usbvision_device_data[0].Interface); - sscanf(parse,"%d",&usbvision_device_data[0].Codec); - goto2next(parse); - PDEBUG(DBG_PROBE, "Codec=%d", usbvision_device_data[0].Codec); - sscanf(parse,"%d",&usbvision_device_data[0].VideoChannels); - goto2next(parse); - PDEBUG(DBG_PROBE, "VideoChannels=%d", usbvision_device_data[0].VideoChannels); - - switch(*parse) - { - case 'P': - PDEBUG(DBG_PROBE, "VideoNorm=PAL"); - usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL; - break; - - case 'S': - PDEBUG(DBG_PROBE, "VideoNorm=SECAM"); - usbvision_device_data[0].VideoNorm=VIDEO_MODE_SECAM; - break; - - case 'N': - PDEBUG(DBG_PROBE, "VideoNorm=NTSC"); - usbvision_device_data[0].VideoNorm=VIDEO_MODE_NTSC; - break; - - default: - PDEBUG(DBG_PROBE, "VideoNorm=PAL (by default)"); - usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL; - break; - } - goto2next(parse); - - sscanf(parse,"%d",&usbvision_device_data[0].AudioChannels); - goto2next(parse); - PDEBUG(DBG_PROBE, "AudioChannels=%d", usbvision_device_data[0].AudioChannels); - sscanf(parse,"%d",&usbvision_device_data[0].Radio); - goto2next(parse); - PDEBUG(DBG_PROBE, "Radio=%d", usbvision_device_data[0].Radio); - sscanf(parse,"%d",&usbvision_device_data[0].Tuner); - goto2next(parse); - PDEBUG(DBG_PROBE, "Tuner=%d", usbvision_device_data[0].Tuner); - sscanf(parse,"%d",&usbvision_device_data[0].TunerType); - goto2next(parse); - PDEBUG(DBG_PROBE, "TunerType=%d", usbvision_device_data[0].TunerType); - sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg1); - goto2next(parse); - PDEBUG(DBG_PROBE, "Vin_Reg1=%d", usbvision_device_data[0].Vin_Reg1); - sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg2); - goto2next(parse); - PDEBUG(DBG_PROBE, "Vin_Reg2=%d", usbvision_device_data[0].Vin_Reg2); - sscanf(parse,"%d",&usbvision_device_data[0].X_Offset); - goto2next(parse); - PDEBUG(DBG_PROBE, "X_Offset=%d", usbvision_device_data[0].X_Offset); - sscanf(parse,"%d",&usbvision_device_data[0].Y_Offset); - goto2next(parse); - PDEBUG(DBG_PROBE, "Y_Offset=%d", usbvision_device_data[0].Y_Offset); - sscanf(parse,"%d",&usbvision_device_data[0].Dvi_yuv); - PDEBUG(DBG_PROBE, "Dvi_yuv=%d", usbvision_device_data[0].Dvi_yuv); - - //add to usbvision_table also - usbvision_table[0].match_flags=USB_DEVICE_ID_MATCH_DEVICE; - usbvision_table[0].idVendor=usbvision_device_data[0].idVendor; - usbvision_table[0].idProduct=usbvision_device_data[0].idProduct; - - } -} - - - -/* - * usbvision_init() - * - * This code is run to initialize the driver. - * - */ -static int __init usbvision_init(void) -{ - int errCode; - - PDEBUG(DBG_PROBE, ""); - - PDEBUG(DBG_IOCTL, "IOCTL debugging is enabled [video]"); - PDEBUG(DBG_IO, "IO debugging is enabled [video]"); - PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]"); - PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); - - /* disable planar mode support unless compression enabled */ - if (isocMode != ISOC_MODE_COMPRESS ) { - // FIXME : not the right way to set supported flag - usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420 - usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P - } - - customdevice_process(); - - errCode = usb_register(&usbvision_driver); - - if (errCode == 0) { - info(DRIVER_DESC " : " USBVISION_VERSION_STRING); - PDEBUG(DBG_PROBE, "success"); - } - return errCode; -} - -static void __exit usbvision_exit(void) -{ - PDEBUG(DBG_PROBE, ""); - - usb_deregister(&usbvision_driver); - PDEBUG(DBG_PROBE, "success"); -} - -module_init(usbvision_init); -module_exit(usbvision_exit); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/trunk/drivers/media/video/usbvision/usbvision.h b/trunk/drivers/media/video/usbvision/usbvision.h deleted file mode 100644 index 0e7e3d653cac..000000000000 --- a/trunk/drivers/media/video/usbvision/usbvision.h +++ /dev/null @@ -1,558 +0,0 @@ -/* - * USBVISION.H - * usbvision header file - * - * Copyright (c) 1999-2005 Joerg Heckenbach - * Dwaine Garden - * - * - * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list - * - * This module is part of usbvision driver project. - * Updates to driver completed by Dwaine P. Garden - * v4l2 conversion by Thierry Merle - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#ifndef __LINUX_USBVISION_H -#define __LINUX_USBVISION_H - -#include -#include -#include -#include -#include - -#define USBVISION_DEBUG /* Turn on debug messages */ - -#ifndef VID_HARDWARE_USBVISION - #define VID_HARDWARE_USBVISION 34 /* USBVision Video Grabber */ -#endif - -#define USBVISION_PWR_REG 0x00 - #define USBVISION_SSPND_EN (1 << 1) - #define USBVISION_RES2 (1 << 2) - #define USBVISION_PWR_VID (1 << 5) - #define USBVISION_E2_EN (1 << 7) -#define USBVISION_CONFIG_REG 0x01 -#define USBVISION_ADRS_REG 0x02 -#define USBVISION_ALTER_REG 0x03 -#define USBVISION_FORCE_ALTER_REG 0x04 -#define USBVISION_STATUS_REG 0x05 -#define USBVISION_IOPIN_REG 0x06 - #define USBVISION_IO_1 (1 << 0) - #define USBVISION_IO_2 (1 << 1) - #define USBVISION_AUDIO_IN 0 - #define USBVISION_AUDIO_TV 1 - #define USBVISION_AUDIO_RADIO 2 - #define USBVISION_AUDIO_MUTE 3 -#define USBVISION_SER_MODE 0x07 -#define USBVISION_SER_ADRS 0x08 -#define USBVISION_SER_CONT 0x09 -#define USBVISION_SER_DAT1 0x0A -#define USBVISION_SER_DAT2 0x0B -#define USBVISION_SER_DAT3 0x0C -#define USBVISION_SER_DAT4 0x0D -#define USBVISION_EE_DATA 0x0E -#define USBVISION_EE_LSBAD 0x0F -#define USBVISION_EE_CONT 0x10 -#define USBVISION_DRM_CONT 0x12 - #define USBVISION_REF (1 << 0) - #define USBVISION_RES_UR (1 << 2) - #define USBVISION_RES_FDL (1 << 3) - #define USBVISION_RES_VDW (1 << 4) -#define USBVISION_DRM_PRM1 0x13 -#define USBVISION_DRM_PRM2 0x14 -#define USBVISION_DRM_PRM3 0x15 -#define USBVISION_DRM_PRM4 0x16 -#define USBVISION_DRM_PRM5 0x17 -#define USBVISION_DRM_PRM6 0x18 -#define USBVISION_DRM_PRM7 0x19 -#define USBVISION_DRM_PRM8 0x1A -#define USBVISION_VIN_REG1 0x1B - #define USBVISION_8_422_SYNC 0x01 - #define USBVISION_16_422_SYNC 0x02 - #define USBVISION_VSNC_POL (1 << 3) - #define USBVISION_HSNC_POL (1 << 4) - #define USBVISION_FID_POL (1 << 5) - #define USBVISION_HVALID_PO (1 << 6) - #define USBVISION_VCLK_POL (1 << 7) -#define USBVISION_VIN_REG2 0x1C - #define USBVISION_AUTO_FID (1 << 0) - #define USBVISION_NONE_INTER (1 << 1) - #define USBVISION_NOHVALID (1 << 2) - #define USBVISION_UV_ID (1 << 3) - #define USBVISION_FIX_2C (1 << 4) - #define USBVISION_SEND_FID (1 << 5) - #define USBVISION_KEEP_BLANK (1 << 7) -#define USBVISION_LXSIZE_I 0x1D -#define USBVISION_MXSIZE_I 0x1E -#define USBVISION_LYSIZE_I 0x1F -#define USBVISION_MYSIZE_I 0x20 -#define USBVISION_LX_OFFST 0x21 -#define USBVISION_MX_OFFST 0x22 -#define USBVISION_LY_OFFST 0x23 -#define USBVISION_MY_OFFST 0x24 -#define USBVISION_FRM_RATE 0x25 -#define USBVISION_LXSIZE_O 0x26 -#define USBVISION_MXSIZE_O 0x27 -#define USBVISION_LYSIZE_O 0x28 -#define USBVISION_MYSIZE_O 0x29 -#define USBVISION_FILT_CONT 0x2A -#define USBVISION_VO_MODE 0x2B -#define USBVISION_INTRA_CYC 0x2C -#define USBVISION_STRIP_SZ 0x2D -#define USBVISION_FORCE_INTRA 0x2E -#define USBVISION_FORCE_UP 0x2F -#define USBVISION_BUF_THR 0x30 -#define USBVISION_DVI_YUV 0x31 -#define USBVISION_AUDIO_CONT 0x32 -#define USBVISION_AUD_PK_LEN 0x33 -#define USBVISION_BLK_PK_LEN 0x34 -#define USBVISION_PCM_THR1 0x38 -#define USBVISION_PCM_THR2 0x39 -#define USBVISION_DIST_THR_L 0x3A -#define USBVISION_DIST_THR_H 0x3B -#define USBVISION_MAX_DIST_L 0x3C -#define USBVISION_MAX_DIST_H 0x3D -#define USBVISION_OP_CODE 0x33 - -#define MAX_BYTES_PER_PIXEL 4 - -#define MIN_FRAME_WIDTH 64 -#define MAX_USB_WIDTH 320 //384 -#define MAX_FRAME_WIDTH 320 //384 /*streching sometimes causes crashes*/ - -#define MIN_FRAME_HEIGHT 48 -#define MAX_USB_HEIGHT 240 //288 -#define MAX_FRAME_HEIGHT 240 //288 /*Streching sometimes causes crashes*/ - -#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) -#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask - -#define USBVISION_URB_FRAMES 32 -#define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023 - -#define USBVISION_NUM_HEADERMARKER 20 -#define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ -#define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */ - -#define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds - - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 31 - -enum { - ISOC_MODE_YUV422 = 0x03, - ISOC_MODE_YUV420 = 0x14, - ISOC_MODE_COMPRESS = 0x60, -}; - -/* This macro restricts an int variable to an inclusive range */ -#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } - -/* - * We use macros to do YUV -> RGB conversion because this is - * very important for speed and totally unimportant for size. - * - * YUV -> RGB Conversion - * --------------------- - * - * B = 1.164*(Y-16) + 2.018*(V-128) - * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) - * R = 1.164*(Y-16) + 1.596*(U-128) - * - * If you fancy integer arithmetics (as you should), hear this: - * - * 65536*B = 76284*(Y-16) + 132252*(V-128) - * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) - * 65536*R = 76284*(Y-16) + 104595*(U-128) - * - * Make sure the output values are within [0..255] range. - */ -#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) -#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ - int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ - mm_y = (my) - 16; \ - mm_u = (mu) - 128; \ - mm_v = (mv) - 128; \ - mm_yc= mm_y * 76284; \ - mm_b = (mm_yc + 132252*mm_v ) >> 16; \ - mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ - mm_r = (mm_yc + 104595*mm_u ) >> 16; \ - mb = LIMIT_RGB(mm_b); \ - mg = LIMIT_RGB(mm_g); \ - mr = LIMIT_RGB(mm_r); \ -} - -/* Debugging aid */ -#define USBVISION_SAY_AND_WAIT(what) { \ - wait_queue_head_t wq; \ - init_waitqueue_head(&wq); \ - printk(KERN_INFO "Say: %s\n", what); \ - interruptible_sleep_on_timeout (&wq, HZ*3); \ -} - -/* - * This macro checks if usbvision is still operational. The 'usbvision' - * pointer must be valid, usbvision->dev must be valid, we are not - * removing the device and the device has not erred on us. - */ -#define USBVISION_IS_OPERATIONAL(udevice) (\ - (udevice != NULL) && \ - ((udevice)->dev != NULL) && \ - ((udevice)->last_error == 0) && \ - (!(udevice)->remove_pending)) - -/* I2C structures */ -struct i2c_algo_usb_data { - void *data; /* private data for lowlevel routines */ - int (*inb) (void *data, unsigned char addr, char *buf, short len); - int (*outb) (void *data, unsigned char addr, char *buf, short len); - - /* local settings */ - int udelay; - int mdelay; - int timeout; -}; - -#define I2C_USB_ADAP_MAX 16 - -/* ----------------------------------------------------------------- */ -/* usbvision video structures */ -/* ----------------------------------------------------------------- */ -enum ScanState { - ScanState_Scanning, /* Scanning for header */ - ScanState_Lines /* Parsing lines */ -}; - -/* Completion states of the data parser */ -enum ParseState { - ParseState_Continue, /* Just parse next item */ - ParseState_NextFrame, /* Frame done, send it to V4L */ - ParseState_Out, /* Not enough data for frame */ - ParseState_EndParse /* End parsing */ -}; - -enum FrameState { - FrameState_Unused, /* Unused (no MCAPTURE) */ - FrameState_Ready, /* Ready to start grabbing */ - FrameState_Grabbing, /* In the process of being grabbed into */ - FrameState_Done, /* Finished grabbing, but not been synced yet */ - FrameState_DoneHold, /* Are syncing or reading */ - FrameState_Error, /* Something bad happened while processing */ -}; - -/* stream states */ -enum StreamState { - Stream_Off, /* Driver streaming is completely OFF */ - Stream_Idle, /* Driver streaming is ready to be put ON by the application */ - Stream_Interrupt, /* Driver streaming must be interrupted */ - Stream_On, /* Driver streaming is put ON by the application */ -}; - -enum IsocState { - IsocState_InFrame, /* Isoc packet is member of frame */ - IsocState_NoFrame, /* Isoc packet is not member of any frame */ -}; - -struct usb_device; - -struct usbvision_sbuf { - char *data; - struct urb *urb; -}; - -#define USBVISION_MAGIC_1 0x55 -#define USBVISION_MAGIC_2 0xAA -#define USBVISION_HEADER_LENGTH 0x0c -#define USBVISION_SAA7111_ADDR 0x48 -#define USBVISION_SAA7113_ADDR 0x4a -#define USBVISION_IIC_LRACK 0x20 -#define USBVISION_IIC_LRNACK 0x30 -#define USBVISION_FRAME_FORMAT_PARAM_INTRA (1<<7) - -struct usbvision_v4l2_format_st { - int supported; - int bytes_per_pixel; - int depth; - int format; - char *desc; -}; -#define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format) - -struct usbvision_frame_header { - unsigned char magic_1; /* 0 magic */ - unsigned char magic_2; /* 1 magic */ - unsigned char headerLength; /* 2 */ - unsigned char frameNum; /* 3 */ - unsigned char framePhase; /* 4 */ - unsigned char frameLatency; /* 5 */ - unsigned char dataFormat; /* 6 */ - unsigned char formatParam; /* 7 */ - unsigned char frameWidthLo; /* 8 */ - unsigned char frameWidthHi; /* 9 */ - unsigned char frameHeightLo; /* 10 */ - unsigned char frameHeightHi; /* 11 */ - __u16 frameWidth; /* 8 - 9 after endian correction*/ - __u16 frameHeight; /* 10 - 11 after endian correction*/ -}; - -/* tvnorms */ -struct usbvision_tvnorm { - char *name; - v4l2_std_id id; - /* mode for saa7113h */ - int mode; -}; - -struct usbvision_frame { - char *data; /* Frame buffer */ - struct usbvision_frame_header isocHeader; /* Header from stream */ - - int width; /* Width application is expecting */ - int height; /* Height */ - int index; /* Frame index */ - int frmwidth; /* Width the frame actually is */ - int frmheight; /* Height */ - - volatile int grabstate; /* State of grabbing */ - int scanstate; /* State of scanning */ - - struct list_head frame; - - int curline; /* Line of frame we're working on */ - - long scanlength; /* uncompressed, raw data length of frame */ - long bytes_read; /* amount of scanlength that has been read from data */ - struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ - int v4l2_linesize; /* bytes for one videoline*/ - struct timeval timestamp; - int sequence; // How many video frames we send to user -}; - -#define CODEC_SAA7113 7113 -#define CODEC_SAA7111 7111 -#define BRIDGE_NT1003 1003 -#define BRIDGE_NT1004 1004 -#define BRIDGE_NT1005 1005 - -struct usbvision_device_data_st { - int idVendor; - int idProduct; - int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ - int Codec; - int VideoChannels; - __u64 VideoNorm; - int AudioChannels; - int Radio; - int vbi; - int Tuner; - int TunerType; - int Vin_Reg1; - int Vin_Reg2; - int X_Offset; - int Y_Offset; - int Dvi_yuv; - char *ModelString; -}; - -/* Declared on usbvision-cards.c */ -extern struct usbvision_device_data_st usbvision_device_data[]; -extern struct usb_device_id usbvision_table[]; - -struct usb_usbvision { - struct video_device *vdev; /* Video Device */ - struct video_device *rdev; /* Radio Device */ - struct video_device *vbi; /* VBI Device */ - - /* i2c Declaration Section*/ - struct i2c_adapter i2c_adap; - struct i2c_algo_usb_data i2c_algo; - struct i2c_client i2c_client; - - struct urb *ctrlUrb; - unsigned char ctrlUrbBuffer[8]; - int ctrlUrbBusy; - struct usb_ctrlrequest ctrlUrbSetup; - wait_queue_head_t ctrlUrb_wq; // Processes waiting - struct semaphore ctrlUrbLock; - - /* configuration part */ - int have_tuner; - int tuner_type; - int tuner_addr; - int bridgeType; // NT1003, NT1004, NT1005 - int channel; - int radio; - int video_inputs; // # of inputs - unsigned long freq; - int AudioMute; - int AudioChannel; - int isocMode; // format of video data for the usb isoc-transfer - unsigned int nr; // Number of the device - - /* Device structure */ - struct usb_device *dev; - unsigned char iface; /* Video interface number */ - unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */ - unsigned char Vin_Reg2_Preset; - struct semaphore lock; - struct timer_list powerOffTimer; - struct work_struct powerOffWork; - int power; /* is the device powered on? */ - int user; /* user count for exclusive use */ - int initialized; /* Had we already sent init sequence? */ - int DevModel; /* What type of USBVISION device we got? */ - enum StreamState streaming; /* Are we streaming Isochronous? */ - int last_error; /* What calamity struck us? */ - int curwidth; /* width of the frame the device is currently set to*/ - int curheight; /* height of the frame the device is currently set to*/ - int stretch_width; /* stretch-factor for frame width (from usb to screen)*/ - int stretch_height; /* stretch-factor for frame height (from usb to screen)*/ - char *fbuf; /* Videodev buffer area for mmap*/ - int max_frame_size; /* Bytes in one video frame */ - int fbuf_size; /* Videodev buffer size */ - spinlock_t queue_lock; /* spinlock for protecting mods on inqueue and outqueue */ - struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ - wait_queue_head_t wait_frame; /* Processes waiting */ - wait_queue_head_t wait_stream; /* Processes waiting */ - struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header - struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer - struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering - volatile int remove_pending; /* If set then about to exit */ - - /* Scratch space from the Isochronous Pipe.*/ - unsigned char *scratch; - int scratch_read_ptr; - int scratch_write_ptr; - int scratch_headermarker[USBVISION_NUM_HEADERMARKER]; - int scratch_headermarker_read_ptr; - int scratch_headermarker_write_ptr; - enum IsocState isocstate; - struct usbvision_v4l2_format_st palette; - - struct v4l2_capability vcap; /* Video capabilities */ - unsigned int ctl_input; /* selected input */ - struct usbvision_tvnorm *tvnorm; /* selected tv norm */ - unsigned char video_endp; /* 0x82 for USBVISION devices based */ - - // Decompression stuff: - unsigned char *IntraFrameBuffer; /* Buffer for reference frame */ - int BlockPos; //for test only - int requestIntra; // 0 = normal; 1 = intra frame is requested; - int lastIsocFrameNum; // check for lost isoc frames - int isocPacketSize; // need to calculate usedBandwidth - int usedBandwidth; // used bandwidth 0-100%, need to set comprLevel - int comprLevel; // How strong (100) or weak (0) is compression - int lastComprLevel; // How strong (100) or weak (0) was compression - int usb_bandwidth; /* Mbit/s */ - - /* Statistics that can be overlayed on the screen */ - unsigned long isocUrbCount; // How many URBs we received so far - unsigned long urb_length; /* Length of last URB */ - unsigned long isocDataCount; /* How many bytes we received */ - unsigned long header_count; /* How many frame headers we found */ - unsigned long scratch_ovf_count; /* How many times we overflowed scratch */ - unsigned long isocSkipCount; /* How many empty ISO packets received */ - unsigned long isocErrCount; /* How many bad ISO packets received */ - unsigned long isocPacketCount; // How many packets we totally got - unsigned long timeInIrq; // How long do we need for interrupt - int isocMeasureBandwidthCount; - int frame_num; // How many video frames we send to user - int maxStripLen; // How big is the biggest strip - int comprBlockPos; - int stripLenErrors; // How many times was BlockPos greater than StripLen - int stripMagicErrors; - int stripLineNumberErrors; - int ComprBlockTypes[4]; -}; - - -/* --------------------------------------------------------------- */ -/* defined in usbvision-i2c.c */ -/* i2c-algo-usb declaration */ -/* --------------------------------------------------------------- */ - -int usbvision_i2c_usb_add_bus(struct i2c_adapter *); -int usbvision_i2c_usb_del_bus(struct i2c_adapter *); - -static inline void *i2c_get_algo_usb_data (struct i2c_algo_usb_data *dev) -{ - return dev->data; -} - -static inline void i2c_set_algo_usb_data (struct i2c_algo_usb_data *dev, void *data) -{ - dev->data = data; -} - - -/* ----------------------------------------------------------------------- */ -/* usbvision specific I2C functions */ -/* ----------------------------------------------------------------------- */ -int usbvision_init_i2c(struct usb_usbvision *usbvision); -void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); - -/* defined in usbvision-core.c */ -void *usbvision_rvmalloc(unsigned long size); -void usbvision_rvfree(void *mem, unsigned long size); -int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); -int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, - unsigned char value); - -int usbvision_frames_alloc(struct usb_usbvision *usbvision); -void usbvision_frames_free(struct usb_usbvision *usbvision); -int usbvision_scratch_alloc(struct usb_usbvision *usbvision); -void usbvision_scratch_free(struct usb_usbvision *usbvision); -int usbvision_sbuf_alloc(struct usb_usbvision *usbvision); -void usbvision_sbuf_free(struct usb_usbvision *usbvision); -int usbvision_decompress_alloc(struct usb_usbvision *usbvision); -void usbvision_decompress_free(struct usb_usbvision *usbvision); - -int usbvision_setup(struct usb_usbvision *usbvision,int format); -int usbvision_init_isoc(struct usb_usbvision *usbvision); -int usbvision_restart_isoc(struct usb_usbvision *usbvision); -void usbvision_stop_isoc(struct usb_usbvision *usbvision); - -int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel); -int usbvision_audio_off(struct usb_usbvision *usbvision); - -int usbvision_begin_streaming(struct usb_usbvision *usbvision); -void usbvision_empty_framequeues(struct usb_usbvision *dev); -int usbvision_stream_interrupt(struct usb_usbvision *dev); - -int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); -int usbvision_set_input(struct usb_usbvision *usbvision); -int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); - -void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision); -void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision); -void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision); -int usbvision_power_off(struct usb_usbvision *usbvision); -int usbvision_power_on(struct usb_usbvision *usbvision); - -#endif /* __LINUX_USBVISION_H */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/trunk/drivers/media/video/v4l1-compat.c b/trunk/drivers/media/video/v4l1-compat.c index 8a13e595304e..1d899e2db394 100644 --- a/trunk/drivers/media/video/v4l1-compat.c +++ b/trunk/drivers/media/video/v4l1-compat.c @@ -350,7 +350,6 @@ v4l_compat_translate_ioctl(struct inode *inode, struct video_buffer *buffer = arg; memset(buffer, 0, sizeof(*buffer)); - memset(&fbuf2, 0, sizeof(fbuf2)); err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); if (err < 0) { @@ -617,7 +616,6 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCSPICT: /* set tone controls & partial capture format */ { struct video_picture *pict = arg; - memset(&fbuf2, 0, sizeof(fbuf2)); set_v4l_control(inode, file, V4L2_CID_BRIGHTNESS, pict->brightness, drv); @@ -710,22 +708,12 @@ v4l_compat_translate_ioctl(struct inode *inode, } case VIDIOCSTUNER: /* select a tuner input */ { - struct video_tuner *tun = arg; - struct v4l2_tuner t; - memset(&t,0,sizeof(t)); - - t.index=tun->tuner; - - err = drv(inode, file, VIDIOC_S_INPUT, &t); - if (err < 0) - dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err); - + err = 0; break; } case VIDIOCGFREQ: /* get frequency */ { unsigned long *freq = arg; - memset(&freq2,0,sizeof(freq2)); freq2.tuner = 0; err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); @@ -738,8 +726,8 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCSFREQ: /* set frequency */ { unsigned long *freq = arg; - memset(&freq2,0,sizeof(freq2)); + freq2.tuner = 0; drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); freq2.frequency = *freq; err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); @@ -750,7 +738,6 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCGAUDIO: /* get audio properties/controls */ { struct video_audio *aud = arg; - memset(&aud2,0,sizeof(aud2)); err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); if (err < 0) { @@ -911,7 +898,6 @@ v4l_compat_translate_ioctl(struct inode *inode, { int *i = arg; - memset(&buf2,0,sizeof(buf2)); buf2.index = *i; buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); diff --git a/trunk/drivers/media/video/v4l2-common.c b/trunk/drivers/media/video/v4l2-common.c index 752c82c37f55..78d28b03ec93 100644 --- a/trunk/drivers/media/video/v4l2-common.c +++ b/trunk/drivers/media/video/v4l2-common.c @@ -87,78 +87,6 @@ MODULE_LICENSE("GPL"); */ -char *v4l2_norm_to_name(v4l2_std_id id) -{ - char *name; - - switch (id) { - case V4L2_STD_PAL: - name="PAL"; break; - case V4L2_STD_PAL_BG: - name="PAL-BG"; break; - case V4L2_STD_PAL_DK: - name="PAL-DK"; break; - case V4L2_STD_PAL_B: - name="PAL-B"; break; - case V4L2_STD_PAL_B1: - name="PAL-B1"; break; - case V4L2_STD_PAL_G: - name="PAL-G"; break; - case V4L2_STD_PAL_H: - name="PAL-H"; break; - case V4L2_STD_PAL_I: - name="PAL-I"; break; - case V4L2_STD_PAL_D: - name="PAL-D"; break; - case V4L2_STD_PAL_D1: - name="PAL-D1"; break; - case V4L2_STD_PAL_K: - name="PAL-K"; break; - case V4L2_STD_PAL_M: - name="PAL-M"; break; - case V4L2_STD_PAL_N: - name="PAL-N"; break; - case V4L2_STD_PAL_Nc: - name="PAL-Nc"; break; - case V4L2_STD_PAL_60: - name="PAL-60"; break; - case V4L2_STD_NTSC: - name="NTSC"; break; - case V4L2_STD_NTSC_M: - name="NTSC-M"; break; - case V4L2_STD_NTSC_M_JP: - name="NTSC-M-JP"; break; - case V4L2_STD_NTSC_443: - name="NTSC-443"; break; - case V4L2_STD_NTSC_M_KR: - name="NTSC-M-KR"; break; - case V4L2_STD_SECAM: - name="SECAM"; break; - case V4L2_STD_SECAM_DK: - name="SECAM-DK"; break; - case V4L2_STD_SECAM_B: - name="SECAM-B"; break; - case V4L2_STD_SECAM_D: - name="SECAM-D"; break; - case V4L2_STD_SECAM_G: - name="SECAM-G"; break; - case V4L2_STD_SECAM_H: - name="SECAM-H"; break; - case V4L2_STD_SECAM_K: - name="SECAM-K"; break; - case V4L2_STD_SECAM_K1: - name="SECAM-K1"; break; - case V4L2_STD_SECAM_L: - name="SECAM-L"; break; - case V4L2_STD_SECAM_LC: - name="SECAM-LC"; break; - default: - name="Unknown"; break; - } - - return name; -} - /* Fill in the fields of a v4l2_standard structure according to the 'id' and 'transmission' parameters. Returns negative on error. */ int v4l2_video_std_construct(struct v4l2_standard *vs, @@ -256,13 +184,11 @@ char *v4l2_field_names[] = { }; char *v4l2_type_names[] = { - [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", - [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", - [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", - [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", - [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", - [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", - [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out", + [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", + [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", + [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", + [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", + [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", }; static char *v4l2_memory_names[] = { @@ -1525,7 +1451,6 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) /* ----------------------------------------------------------------- */ -EXPORT_SYMBOL(v4l2_norm_to_name); EXPORT_SYMBOL(v4l2_video_std_construct); EXPORT_SYMBOL(v4l2_prio_init); diff --git a/trunk/drivers/media/video/videocodec.c b/trunk/drivers/media/video/videocodec.c index 290e64135650..2ae3fb250630 100644 --- a/trunk/drivers/media/video/videocodec.c +++ b/trunk/drivers/media/video/videocodec.c @@ -346,7 +346,7 @@ videocodec_build_table (void) size); kfree(videocodec_buf); - videocodec_buf = kmalloc(size, GFP_KERNEL); + videocodec_buf = (char *) kmalloc(size, GFP_KERNEL); i = 0; i += scnprintf(videocodec_buf + i, size - 1, diff --git a/trunk/drivers/media/video/videodev.c b/trunk/drivers/media/video/videodev.c index 6a0e8ca72948..41ec0c4b35a2 100644 --- a/trunk/drivers/media/video/videodev.c +++ b/trunk/drivers/media/video/videodev.c @@ -342,7 +342,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " "bytesused=%d, flags=0x%08d, " - "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n", + "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", (p->timestamp.tv_sec/3600), (int)(p->timestamp.tv_sec/60)%60, (int)(p->timestamp.tv_sec%60), @@ -352,7 +352,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, p->bytesused,p->flags, p->field,p->sequence, prt_names(p->memory,v4l2_memory_names), - p->m.userptr, p->length); + p->m.userptr); dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " "flags=0x%08d, frames=%d, userbits=0x%08x\n", tc->hours,tc->minutes,tc->seconds, @@ -369,13 +369,9 @@ static inline void dbgrect(struct video_device *vfd, char *s, static inline void v4l_print_pix_fmt (struct video_device *vfd, struct v4l2_pix_format *fmt) { - dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, " + dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, " "bytesperline=%d sizeimage=%d, colorspace=%d\n", - fmt->width,fmt->height, - (fmt->pixelformat & 0xff), - (fmt->pixelformat >> 8) & 0xff, - (fmt->pixelformat >> 16) & 0xff, - (fmt->pixelformat >> 24) & 0xff, + fmt->width,fmt->height,fmt->pixelformat, prt_names(fmt->field,v4l2_field_names_FIXME), fmt->bytesperline,fmt->sizeimage,fmt->colorspace); }; @@ -432,10 +428,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, v4l_print_ioctl(vfd->name, cmd); } - if (_IOC_TYPE(cmd)=='v') - return v4l_compat_translate_ioctl(inode,file,cmd,arg, - __video_do_ioctl); - switch(cmd) { /* --- capabilities ------------------------------------------ */ case VIDIOC_QUERYCAP: @@ -534,13 +526,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, } if (!ret) dbgarg (cmd, "index=%d, type=%d, flags=%d, " - "pixelformat=%c%c%c%c, description='%s'\n", + "description=%s," + " pixelformat=0x%8x\n", f->index, f->type, f->flags, - (f->pixelformat & 0xff), - (f->pixelformat >> 8) & 0xff, - (f->pixelformat >> 16) & 0xff, - (f->pixelformat >> 24) & 0xff, - f->description); + f->description, + f->pixelformat); + break; } case VIDIOC_G_FMT: @@ -838,85 +829,20 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_ENUMSTD: { struct v4l2_standard *p = arg; - v4l2_std_id id = vfd->tvnorms,curr_id=0; - unsigned int index = p->index,i; + unsigned int index = p->index; - if (index<0) { - ret=-EINVAL; + if (!vfd->tvnormsize) { + printk (KERN_WARNING "%s: no TV norms defined!\n", + vfd->name); break; } - /* Return norm array on a canonical way */ - for (i=0;i<= index && id; i++) { - if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { - curr_id = V4L2_STD_PAL; - } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { - curr_id = V4L2_STD_PAL_BG; - } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { - curr_id = V4L2_STD_PAL_DK; - } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { - curr_id = V4L2_STD_PAL_B; - } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { - curr_id = V4L2_STD_PAL_B1; - } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { - curr_id = V4L2_STD_PAL_G; - } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { - curr_id = V4L2_STD_PAL_H; - } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { - curr_id = V4L2_STD_PAL_I; - } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { - curr_id = V4L2_STD_PAL_D; - } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { - curr_id = V4L2_STD_PAL_D1; - } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { - curr_id = V4L2_STD_PAL_K; - } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { - curr_id = V4L2_STD_PAL_M; - } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { - curr_id = V4L2_STD_PAL_N; - } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { - curr_id = V4L2_STD_PAL_Nc; - } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { - curr_id = V4L2_STD_PAL_60; - } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { - curr_id = V4L2_STD_NTSC; - } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { - curr_id = V4L2_STD_NTSC_M; - } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { - curr_id = V4L2_STD_NTSC_M_JP; - } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { - curr_id = V4L2_STD_NTSC_443; - } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { - curr_id = V4L2_STD_NTSC_M_KR; - } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { - curr_id = V4L2_STD_SECAM; - } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { - curr_id = V4L2_STD_SECAM_DK; - } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { - curr_id = V4L2_STD_SECAM_B; - } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { - curr_id = V4L2_STD_SECAM_D; - } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { - curr_id = V4L2_STD_SECAM_G; - } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { - curr_id = V4L2_STD_SECAM_H; - } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { - curr_id = V4L2_STD_SECAM_K; - } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { - curr_id = V4L2_STD_SECAM_K1; - } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { - curr_id = V4L2_STD_SECAM_L; - } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { - curr_id = V4L2_STD_SECAM_LC; - } else { - break; - } - id &= ~curr_id; + if (index<0 || index >= vfd->tvnormsize) { + ret=-EINVAL; + break; } - if (i<=index) - return -EINVAL; - - v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id)); + v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, + vfd->tvnorms[p->index].name); p->index = index; dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " @@ -942,23 +868,39 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, } case VIDIOC_S_STD: { - v4l2_std_id *id = arg,norm; + v4l2_std_id *id = arg; + unsigned int i; + + if (!vfd->tvnormsize) { + printk (KERN_WARNING "%s: no TV norms defined!\n", + vfd->name); + break; + } dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); - norm = (*id) & vfd->tvnorms; - if ( vfd->tvnorms && !norm) /* Check if std is supported */ + /* First search for exact match */ + for (i = 0; i < vfd->tvnormsize; i++) + if (*id == vfd->tvnorms[i].id) + break; + /* Then for a generic video std that contains desired std */ + if (i == vfd->tvnormsize) + for (i = 0; i < vfd->tvnormsize; i++) + if (*id & vfd->tvnorms[i].id) + break; + if (i == vfd->tvnormsize) { break; + } /* Calls the specific handler */ if (vfd->vidioc_s_std) - ret=vfd->vidioc_s_std(file, fh, &norm); + ret=vfd->vidioc_s_std(file, fh, i); else ret=-EINVAL; /* Updates standard information */ - if (ret>=0) - vfd->current_norm=norm; + if (!ret) + vfd->current_norm=*id; break; } @@ -1146,13 +1088,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_AUDIO: { struct v4l2_audio *p=arg; - __u32 index=p->index; if (!vfd->vidioc_g_audio) break; - - memset(p,0,sizeof(*p)); - p->index=index; dbgarg(cmd, "Get for index=%d\n", p->index); ret=vfd->vidioc_g_audio(file, fh, p); if (!ret) @@ -1350,12 +1288,25 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_g_parm(file, fh, p); } else { struct v4l2_standard s; + int i; + + if (!vfd->tvnormsize) { + printk (KERN_WARNING "%s: no TV norms defined!\n", + vfd->name); + break; + } if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + for (i = 0; i < vfd->tvnormsize; i++) + if (vfd->tvnorms[i].id == vfd->current_norm) + break; + if (i >= vfd->tvnormsize) + return -EINVAL; + v4l2_video_std_construct(&s, vfd->current_norm, - v4l2_norm_to_name(vfd->current_norm)); + vfd->tvnorms[i].name); memset(p,0,sizeof(*p)); @@ -1378,14 +1329,8 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_TUNER: { struct v4l2_tuner *p=arg; - __u32 index=p->index; - if (!vfd->vidioc_g_tuner) break; - - memset(p,0,sizeof(*p)); - p->index=index; - ret=vfd->vidioc_g_tuner(file, fh, p); if (!ret) dbgarg (cmd, "index=%d, name=%s, type=%d, " @@ -1418,9 +1363,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_frequency *p=arg; if (!vfd->vidioc_g_frequency) break; - - memset(p,0,sizeof(*p)); - ret=vfd->vidioc_g_frequency(file, fh, p); if (!ret) dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", @@ -1454,7 +1396,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_log_status(file, fh); break; } - } /* switch */ + + /* --- Others --------------------------------------------- */ + + default: + ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl); + } if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { if (ret<0) { diff --git a/trunk/drivers/media/video/vino.c b/trunk/drivers/media/video/vino.c index a373c142e742..6b6dff4d236a 100644 --- a/trunk/drivers/media/video/vino.c +++ b/trunk/drivers/media/video/vino.c @@ -782,7 +782,7 @@ static int vino_i2c_add_bus(void) static int vino_i2c_del_bus(void) { - return i2c_del_adapter(&vino_i2c_adapter); + return i2c_sgi_del_bus(&vino_i2c_adapter); } static int i2c_camera_command(unsigned int cmd, void *arg) diff --git a/trunk/drivers/media/video/vivi.c b/trunk/drivers/media/video/vivi.c index 474ddb779643..9986de5cb3d6 100644 --- a/trunk/drivers/media/video/vivi.c +++ b/trunk/drivers/media/video/vivi.c @@ -1044,8 +1044,16 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) return (0); } -static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i) +static struct v4l2_tvnorm tvnorms[] = { + { + .name = "NTSC-M", + .id = V4L2_STD_NTSC_M, + } +}; + +static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a) { + return 0; } @@ -1325,8 +1333,8 @@ static struct video_device vivi = { #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif - .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, + .tvnorms = tvnorms, + .tvnormsize = ARRAY_SIZE(tvnorms), }; /* ----------------------------------------------------------------- Initialization and module stuff @@ -1353,6 +1361,8 @@ static int __init vivi_init(void) dev->vidq.timeout.data = (unsigned long)dev; init_timer(&dev->vidq.timeout); + vivi.current_norm = tvnorms[0].id; + ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); return ret; diff --git a/trunk/drivers/media/video/zoran_card.c b/trunk/drivers/media/video/zoran_card.c index 4d1eb2fba34a..653822ce391c 100644 --- a/trunk/drivers/media/video/zoran_card.c +++ b/trunk/drivers/media/video/zoran_card.c @@ -849,7 +849,7 @@ zoran_register_i2c (struct zoran *zr) static void zoran_unregister_i2c (struct zoran *zr) { - i2c_del_adapter(&zr->i2c_adapter); + i2c_bit_del_bus((&zr->i2c_adapter)); } /* Check a zoran_params struct for correctness, insert default params */ diff --git a/trunk/drivers/media/video/zr36120.c b/trunk/drivers/media/video/zr36120.c new file mode 100644 index 000000000000..0cbf564388a6 --- /dev/null +++ b/trunk/drivers/media/video/zr36120.c @@ -0,0 +1,2079 @@ +/* + zr36120.c - Zoran 36120/36125 based framegrabbers + + Copyright (C) 1998-1999 Pauline Middelink + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tuner.h" +#include "zr36120.h" +#include "zr36120_mem.h" + +/* mark an required function argument unused - lintism */ +#define UNUSED(x) (void)(x) + +/* sensible default */ +#ifndef CARDTYPE +#define CARDTYPE 0 +#endif + +/* Anybody who uses more than four? */ +#define ZORAN_MAX 4 + +static unsigned int triton1=0; /* triton1 chipset? */ +static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE }; +static int video_nr = -1; +static int vbi_nr = -1; + +static struct pci_device_id zr36120_pci_tbl[] = { + { PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, zr36120_pci_tbl); + +MODULE_AUTHOR("Pauline Middelink "); +MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber"); +MODULE_LICENSE("GPL"); + +module_param(triton1, uint, 0); +module_param_array(cardtype, uint, NULL, 0); +module_param(video_nr, int, 0); +module_param(vbi_nr, int, 0); + +static int zoran_cards; +static struct zoran zorans[ZORAN_MAX]; + +/* + * the meaning of each element can be found in zr36120.h + * Determining the value of gpdir/gpval can be tricky. The + * best way is to run the card under the original software + * and read the values from the general purpose registers + * 0x28 and 0x2C. How you do that is left as an exercise + * to the impatient reader :) + */ +#define T 1 /* to separate the bools from the ints */ +#define F 0 +static struct tvcard tvcards[] = { + /* reported working by */ +/*0*/ { "Trust Victor II", + 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, + /* reported working by */ +/*1*/ { "Aitech WaveWatcher TV-PCI", + 3, 0, T, F, T, T, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } }, + /* reported working by ? */ +/*2*/ { "Genius Video Wonder PCI Video Capture Card", + 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, + /* reported working by */ +/*3*/ { "Guillemot Maxi-TV PCI", + 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, + /* reported working by "Craig Whitmore */ +/*4*/ { "Quadrant Buster", + 3, 3, T, F, T, T, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } }, + /* a debug entry which has all inputs mapped */ +/*5*/ { "ZR36120 based framegrabber (all inputs enabled)", + 6, 0, T, T, T, T, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } } +}; +#undef T +#undef F +#define NRTVCARDS (sizeof(tvcards)/sizeof(tvcards[0])) + +#ifdef __sparc__ +#define ENDIANESS 0 +#else +#define ENDIANESS ZORAN_VFEC_LE +#endif + +static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = { +/* n/a */ { "n/a", 0, 0 }, +/* GREY */ { "GRAY", 0, 0 }, +/* HI240 */ { "HI240", 0, 0 }, +/* RGB565 */ { "RGB565", ZORAN_VFEC_RGB_RGB565|ENDIANESS, 2 }, +/* RGB24 */ { "RGB24", ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 }, +/* RGB32 */ { "RGB32", ZORAN_VFEC_RGB_RGB888|ENDIANESS, 4 }, +/* RGB555 */ { "RGB555", ZORAN_VFEC_RGB_RGB555|ENDIANESS, 2 }, +/* YUV422 */ { "YUV422", ZORAN_VFEC_RGB_YUV422|ENDIANESS, 2 }, +/* YUYV */ { "YUYV", 0, 0 }, +/* UYVY */ { "UYVY", 0, 0 }, +/* YUV420 */ { "YUV420", 0, 0 }, +/* YUV411 */ { "YUV411", 0, 0 }, +/* RAW */ { "RAW", 0, 0 }, +/* YUV422P */ { "YUV422P", 0, 0 }, +/* YUV411P */ { "YUV411P", 0, 0 }}; +#define NRPALETTES (sizeof(palette2fmt)/sizeof(palette2fmt[0])) +#undef ENDIANESS + +/* ----------------------------------------------------------------------- */ +/* ZORAN chipset detector */ +/* shamelessly stolen from bttv.c */ +/* Reason for beeing here: we need to detect if we are running on a */ +/* Triton based chipset, and if so, enable a certain bit */ +/* ----------------------------------------------------------------------- */ +static +void __init handle_chipset(void) +{ + /* Just in case some nut set this to something dangerous */ + if (triton1) + triton1 = ZORAN_VDC_TRICOM; + + if (pci_pci_problems & PCIPCI_TRITON) { + printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n"); + triton1 = ZORAN_VDC_TRICOM; + } +} + +/* ----------------------------------------------------------------------- */ +/* ZORAN functions */ +/* ----------------------------------------------------------------------- */ + +static void zoran_set_geo(struct zoran* ztv, struct vidinfo* i); + +#if 0 /* unused */ +static +void zoran_dump(struct zoran *ztv) +{ + char str[256]; + char *p=str; /* shut up, gcc! */ + int i; + + for (i=0; i<0x60; i+=4) { + if ((i % 16) == 0) { + if (i) printk("%s\n",str); + p = str; + p+= sprintf(str, KERN_DEBUG " %04x: ",i); + } + p += sprintf(p, "%08x ",zrread(i)); + } +} +#endif /* unused */ + +static +void reap_states(struct zoran* ztv) +{ + /* count frames */ + ztv->fieldnr++; + + /* + * Are we busy at all? + * This depends on if there is a workqueue AND the + * videotransfer is enabled on the chip... + */ + if (ztv->workqueue && (zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) + { + struct vidinfo* newitem; + + /* did we get a complete frame? */ + if (zrread(ZORAN_VSTR) & ZORAN_VSTR_GRAB) + return; + +DEBUG(printk(CARD_DEBUG "completed %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); + + /* we are done with this buffer, tell everyone */ + ztv->workqueue->status = FBUFFER_DONE; + ztv->workqueue->fieldnr = ztv->fieldnr; + /* not good, here for BTTV_FIELDNR reasons */ + ztv->lastfieldnr = ztv->fieldnr; + + switch (ztv->workqueue->kindof) { + case FBUFFER_GRAB: + wake_up_interruptible(&ztv->grabq); + break; + case FBUFFER_VBI: + wake_up_interruptible(&ztv->vbiq); + break; + default: + printk(CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",CARD,ztv->workqueue->kindof); + } + + /* item completed, skip to next item in queue */ + write_lock(&ztv->lock); + newitem = ztv->workqueue->next; + ztv->workqueue->next = 0; /* mark completed */ + ztv->workqueue = newitem; + write_unlock(&ztv->lock); + } + + /* + * ok, so it seems we have nothing in progress right now. + * Lets see if we can find some work. + */ + if (ztv->workqueue) + { + struct vidinfo* newitem; +again: + +DEBUG(printk(CARD_DEBUG "starting %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); + + /* loadup the frame settings */ + read_lock(&ztv->lock); + zoran_set_geo(ztv,ztv->workqueue); + read_unlock(&ztv->lock); + + switch (ztv->workqueue->kindof) { + case FBUFFER_GRAB: + case FBUFFER_VBI: + zrand(~ZORAN_OCR_OVLEN, ZORAN_OCR); + zror(ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); + zror(ZORAN_VDC_VIDEN,ZORAN_VDC); + + /* start single-shot grab */ + zror(ZORAN_VSTR_GRAB, ZORAN_VSTR); + break; + default: + printk(CARD_INFO "what is this doing on the queue? (kindof=%d)\n",CARD,ztv->workqueue->kindof); + write_lock(&ztv->lock); + newitem = ztv->workqueue->next; + ztv->workqueue->next = 0; + ztv->workqueue = newitem; + write_unlock(&ztv->lock); + if (newitem) + goto again; /* yeah, sure.. */ + } + /* bye for now */ + return; + } +DEBUG(printk(CARD_DEBUG "nothing in queue\n",CARD)); + + /* + * What? Even the workqueue is empty? Am i really here + * for nothing? Did i come all that way to... do nothing? + */ + + /* do we need to overlay? */ + if (test_bit(STATE_OVERLAY, &ztv->state)) + { + /* are we already overlaying? */ + if (!(zrread(ZORAN_OCR) & ZORAN_OCR_OVLEN) || + !(zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) + { +DEBUG(printk(CARD_DEBUG "starting overlay\n",CARD)); + + read_lock(&ztv->lock); + zoran_set_geo(ztv,&ztv->overinfo); + read_unlock(&ztv->lock); + + zror(ZORAN_OCR_OVLEN, ZORAN_OCR); + zrand(~ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); + zror(ZORAN_VDC_VIDEN,ZORAN_VDC); + } + + /* + * leave overlaying on, but turn interrupts off. + */ + zrand(~ZORAN_ICR_EN,ZORAN_ICR); + return; + } + + /* do we have any VBI idle time processing? */ + if (test_bit(STATE_VBI, &ztv->state)) + { + struct vidinfo* item; + struct vidinfo* lastitem; + + /* protect the workqueue */ + write_lock(&ztv->lock); + lastitem = ztv->workqueue; + if (lastitem) + while (lastitem->next) lastitem = lastitem->next; + for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) + if (item->next == 0 && item->status == FBUFFER_FREE) + { +DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item)); + item->status = FBUFFER_BUSY; + if (!lastitem) + ztv->workqueue = item; + else + lastitem->next = item; + lastitem = item; + } + write_unlock(&ztv->lock); + if (ztv->workqueue) + goto again; /* hey, _i_ graduated :) */ + } + + /* + * Then we must be realy IDLE + */ +DEBUG(printk(CARD_DEBUG "turning off\n",CARD)); + /* nothing further to do, disable DMA and further IRQs */ + zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); + zrand(~ZORAN_ICR_EN,ZORAN_ICR); +} + +static +void zoran_irq(int irq, void *dev_id) +{ + u32 stat,estat; + int count = 0; + struct zoran *ztv = dev_id; + + UNUSED(irq); + for (;;) { + /* get/clear interrupt status bits */ + stat=zrread(ZORAN_ISR); + estat=stat & zrread(ZORAN_ICR); + if (!estat) + return; + zrwrite(estat,ZORAN_ISR); + IDEBUG(printk(CARD_DEBUG "estat %08x\n",CARD,estat)); + IDEBUG(printk(CARD_DEBUG " stat %08x\n",CARD,stat)); + + if (estat & ZORAN_ISR_CODE) + { + IDEBUG(printk(CARD_DEBUG "CodReplIRQ\n",CARD)); + } + if (estat & ZORAN_ISR_GIRQ0) + { + IDEBUG(printk(CARD_DEBUG "GIRQ0\n",CARD)); + if (!ztv->card->usegirq1) + reap_states(ztv); + } + if (estat & ZORAN_ISR_GIRQ1) + { + IDEBUG(printk(CARD_DEBUG "GIRQ1\n",CARD)); + if (ztv->card->usegirq1) + reap_states(ztv); + } + + count++; + if (count > 10) + printk(CARD_ERR "irq loop %d (%x)\n",CARD,count,estat); + if (count > 20) + { + zrwrite(0, ZORAN_ICR); + printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD); + } + } +} + +static +int zoran_muxsel(struct zoran* ztv, int channel, int norm) +{ + int rv; + + /* set the new video norm */ + rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm); + if (rv) + return rv; + ztv->norm = norm; + + /* map the given channel to the cards decoder's channel */ + channel = ztv->card->video_mux[channel] & CHANNEL_MASK; + + /* set the new channel */ + rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &channel); + return rv; +} + +/* Tell the interrupt handler what to to. */ +static +void zoran_cap(struct zoran* ztv, int on) +{ +DEBUG(printk(CARD_DEBUG "zoran_cap(%d) state=%x\n",CARD,on,ztv->state)); + + if (on) { + ztv->running = 1; + + /* + * turn interrupts (back) on. The DMA will be enabled + * inside the irq handler when it detects a restart. + */ + zror(ZORAN_ICR_EN,ZORAN_ICR); + } + else { + /* + * turn both interrupts and DMA off + */ + zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); + zrand(~ZORAN_ICR_EN,ZORAN_ICR); + + ztv->running = 0; + } +} + +static ulong dmask[] = { + 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, + 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, + 0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, + 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, + 0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000, + 0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000, + 0xFF000000, 0xFE000000, 0xFC000000, 0xF8000000, + 0xF0000000, 0xE0000000, 0xC0000000, 0x80000000 +}; + +static +void zoran_built_overlay(struct zoran* ztv, int count, struct video_clip *vcp) +{ + ulong* mtop; + int ystep = (ztv->vidXshift + ztv->vidWidth+31)/32; /* next DWORD */ + int i; + +DEBUG(printk(KERN_DEBUG " overlay at %p, ystep=%d, clips=%d\n",ztv->overinfo.overlay,ystep,count)); + + for (i=0; ix,vp->y,vp->width,vp->height)); + } + + /* + * activate the visible portion of the screen + * Note we take some shortcuts here, because we + * know the width can never be < 32. (I.e. a DWORD) + * We also assume the overlay starts somewhere in + * the FIRST dword. + */ + { + int start = ztv->vidXshift; + ulong firstd = dmask[start]; + ulong lastd = ~dmask[(start + ztv->overinfo.w) & 31]; + mtop = ztv->overinfo.overlay; + for (i=0; ioverinfo.h; i++) { + int w = ztv->vidWidth; + ulong* line = mtop; + if (start & 31) { + *line++ = firstd; + w -= 32-(start&31); + } + memset(line, ~0, w/8); + if (w & 31) + line[w/32] = lastd; + mtop += ystep; + } + } + + /* process clipping regions */ + for (i=0; ix < 0 || (uint)vcp->x > ztv->overinfo.w || + vcp->y < 0 || vcp->y > ztv->overinfo.h || + vcp->width < 0 || (uint)(vcp->x+vcp->width) > ztv->overinfo.w || + vcp->height < 0 || (vcp->y+vcp->height) > ztv->overinfo.h) + { + DEBUG(printk(CARD_DEBUG "invalid clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",CARD,vcp->x,vcp->y,vcp->width,vcp->height,ztv->overinfo.w,ztv->overinfo.h)); + if (vcp->x < 0) vcp->x = 0; + if ((uint)vcp->x > ztv->overinfo.w) vcp->x = ztv->overinfo.w; + if (vcp->y < 0) vcp->y = 0; + if (vcp->y > ztv->overinfo.h) vcp->y = ztv->overinfo.h; + if (vcp->width < 0) vcp->width = 0; + if ((uint)(vcp->x+vcp->width) > ztv->overinfo.w) vcp->width = ztv->overinfo.w - vcp->x; + if (vcp->height < 0) vcp->height = 0; + if (vcp->y+vcp->height > ztv->overinfo.h) vcp->height = ztv->overinfo.h - vcp->y; +// continue; + } + + mtop = &ztv->overinfo.overlay[vcp->y*ystep]; + for (h=0; h<=vcp->height; h++) { + int w; + int x = ztv->vidXshift + vcp->x; + for (w=0; w<=vcp->width; w++) { + clear_bit(x&31, &mtop[x/32]); + x++; + } + mtop += ystep; + } + ++vcp; + } + + mtop = ztv->overinfo.overlay; + zrwrite(virt_to_bus(mtop), ZORAN_MTOP); + zrwrite(virt_to_bus(mtop+ystep), ZORAN_MBOT); + zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR); +} + +struct tvnorm +{ + u16 Wt, Wa, Ht, Ha, HStart, VStart; +}; + +static struct tvnorm tvnorms[] = { + /* PAL-BDGHI */ +/* { 864, 720, 625, 576, 131, 21 },*/ +/*00*/ { 864, 768, 625, 576, 81, 17 }, + /* NTSC */ +/*01*/ { 858, 720, 525, 480, 121, 10 }, + /* SECAM */ +/*02*/ { 864, 720, 625, 576, 131, 21 }, + /* BW50 */ +/*03*/ { 864, 720, 625, 576, 131, 21 }, + /* BW60 */ +/*04*/ { 858, 720, 525, 480, 121, 10 } +}; +#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) + +/* + * Program the chip for a setup as described in the vidinfo struct. + * + * Side-effects: calculates vidXshift, vidInterlace, + * vidHeight, vidWidth which are used in a later stage + * to calculate the overlay mask + * + * This is an internal function, as such it does not check the + * validity of the struct members... Spectaculair crashes will + * follow /very/ quick when you're wrong and the chip right :) + */ +static +void zoran_set_geo(struct zoran* ztv, struct vidinfo* i) +{ + ulong top, bot; + int stride; + int winWidth, winHeight; + int maxWidth, maxHeight, maxXOffset, maxYOffset; + long vfec; + +DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i->x,i->y,i->w,i->h,ztv->norm,i->format,i->bpp,i->bpl,i->busadr,i->overlay)); + + /* + * make sure the DMA transfers are inhibited during our + * reprogramming of the chip + */ + zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); + + maxWidth = tvnorms[ztv->norm].Wa; + maxHeight = tvnorms[ztv->norm].Ha/2; + maxXOffset = tvnorms[ztv->norm].HStart; + maxYOffset = tvnorms[ztv->norm].VStart; + + /* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */ + vfec = (zrread(ZORAN_VFEC) & (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) | + (palette2fmt[i->format].mode & (ZORAN_VFEC_RGB|ZORAN_VFEC_ERRDIF|ZORAN_VFEC_LE|ZORAN_VFEC_PACK24)); + + /* + * Set top, bottom ptrs. Since these must be DWORD aligned, + * possible adjust the x and the width of the window. + * so the endposition stay the same. The vidXshift will make + * sure we are not writing pixels before the requested x. + */ + ztv->vidXshift = 0; + winWidth = i->w; + if (winWidth < 0) + winWidth = -winWidth; + top = i->busadr + i->x*i->bpp + i->y*i->bpl; + if (top & 3) { + ztv->vidXshift = (top & 3) / i->bpp; + winWidth += ztv->vidXshift; + DEBUG(printk(KERN_DEBUG " window-x shifted %d pixels left\n",ztv->vidXshift)); + top &= ~3; + } + + /* + * bottom points to next frame but in interleaved mode we want + * to 'mix' the 2 frames to one capture, so 'bot' points to one + * (physical) line below the top line. + */ + bot = top + i->bpl; + zrwrite(top,ZORAN_VTOP); + zrwrite(bot,ZORAN_VBOT); + + /* + * Make sure the winWidth is DWORD aligned too, + * thereby automaticly making sure the stride to the + * next line is DWORD aligned too (as required by spec). + */ + if ((winWidth*i->bpp) & 3) { +DEBUG(printk(KERN_DEBUG " window-width enlarged by %d pixels\n",(winWidth*i->bpp) & 3)); + winWidth += (winWidth*i->bpp) & 3; + } + + /* determine the DispMode and stride */ + if (i->h >= 0 && i->h <= maxHeight) { + /* single frame grab suffices for this height. */ + vfec |= ZORAN_VFEC_DISPMOD; + ztv->vidInterlace = 0; + stride = i->bpl - (winWidth*i->bpp); + winHeight = i->h; + } + else { + /* interleaving needed for this height */ + ztv->vidInterlace = 1; + stride = i->bpl*2 - (winWidth*i->bpp); + winHeight = i->h/2; + } + if (winHeight < 0) /* can happen for VBI! */ + winHeight = -winHeight; + + /* safety net, sometimes bpl is too short??? */ + if (stride<0) { +DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride)); + stride = 0; + } + + zraor((winHeight<<12)|(winWidth<<0),~(ZORAN_VDC_VIDWINHT|ZORAN_VDC_VIDWINWID), ZORAN_VDC); + zraor(stride<<16,~ZORAN_VSTR_DISPSTRIDE,ZORAN_VSTR); + + /* remember vidWidth, vidHeight for overlay calculations */ + ztv->vidWidth = winWidth; + ztv->vidHeight = winHeight; +DEBUG(printk(KERN_DEBUG " top=%08lx, bottom=%08lx\n",top,bot)); +DEBUG(printk(KERN_DEBUG " winWidth=%d, winHeight=%d\n",winWidth,winHeight)); +DEBUG(printk(KERN_DEBUG " maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight)); +DEBUG(printk(KERN_DEBUG " stride=%d\n",stride)); + + /* + * determine horizontal scales and crops + */ + if (i->w < 0) { + int Hstart = 1; + int Hend = Hstart + winWidth; +DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Hstart, Hend)); + zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); + } + else { + int Wa = maxWidth; + int X = (winWidth*64+Wa-1)/Wa; + int We = winWidth*64/X; + int HorDcm = 64-X; + int hcrop1 = 2*(Wa-We)/4; + /* + * BUGFIX: Juha Nurmela + * found the solution to the color phase shift. + * See ChangeLog for the full explanation) + */ + int Hstart = (maxXOffset + hcrop1) | 1; + int Hend = Hstart + We - 1; + +DEBUG(printk(KERN_DEBUG " X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend)); + + zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); + vfec |= HorDcm<<14; + + if (HorDcm<16) + vfec |= ZORAN_VFEC_HFILTER_1; /* no filter */ + else if (HorDcm<32) + vfec |= ZORAN_VFEC_HFILTER_3; /* 3 tap filter */ + else if (HorDcm<48) + vfec |= ZORAN_VFEC_HFILTER_4; /* 4 tap filter */ + else vfec |= ZORAN_VFEC_HFILTER_5; /* 5 tap filter */ + } + + /* + * Determine vertical scales and crops + * + * when height is negative, we want to read starting at line 0 + * One day someone might need access to these lines... + */ + if (i->h < 0) { + int Vstart = 0; + int Vend = Vstart + winHeight; +DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Vstart, Vend)); + zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); + } + else { + int Ha = maxHeight; + int Y = (winHeight*64+Ha-1)/Ha; + int He = winHeight*64/Y; + int VerDcm = 64-Y; + int vcrop1 = 2*(Ha-He)/4; + int Vstart = maxYOffset + vcrop1; + int Vend = Vstart + He - 1; + +DEBUG(printk(KERN_DEBUG " Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend)); + zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); + vfec |= VerDcm<<8; + } + +DEBUG(printk(KERN_DEBUG " F: format=%d(=%s)\n",i->format,palette2fmt[i->format].name)); + + /* setup the requested format */ + zrwrite(vfec, ZORAN_VFEC); +} + +static +void zoran_common_open(struct zoran* ztv, int flags) +{ + UNUSED(flags); + + /* already opened? */ + if (ztv->users++ != 0) + return; + + /* unmute audio */ + /* /what/ audio? */ + + ztv->state = 0; + + /* setup the encoder to the initial values */ + ztv->picture.colour=254<<7; + ztv->picture.brightness=128<<8; + ztv->picture.hue=128<<8; + ztv->picture.contrast=216<<7; + i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture); + + /* default to the composite input since my camera is there */ + zoran_muxsel(ztv, 0, VIDEO_MODE_PAL); +} + +static +void zoran_common_close(struct zoran* ztv) +{ + if (--ztv->users != 0) + return; + + /* mute audio */ + /* /what/ audio? */ + + /* stop the chip */ + zoran_cap(ztv, 0); +} + +/* + * Open a zoran card. Right now the flags are just a hack + */ +static int zoran_open(struct video_device *dev, int flags) +{ + struct zoran *ztv = (struct zoran*)dev; + struct vidinfo* item; + char* pos; + + DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags)); + + /********************************************* + * We really should be doing lazy allocing... + *********************************************/ + /* allocate a frame buffer */ + if (!ztv->fbuffer) + ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE); + if (!ztv->fbuffer) { + /* could not get a buffer, bail out */ + return -ENOBUFS; + } + /* at this time we _always_ have a framebuffer */ + memset(ztv->fbuffer,0,ZORAN_MAX_FBUFSIZE); + + if (!ztv->overinfo.overlay) + ztv->overinfo.overlay = kmalloc(1024*1024/8, GFP_KERNEL); + if (!ztv->overinfo.overlay) { + /* could not get an overlay buffer, bail out */ + bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); + return -ENOBUFS; + } + /* at this time we _always_ have a overlay */ + + /* clear buffer status, and give them a DMAable address */ + pos = ztv->fbuffer; + for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) + { + item->status = FBUFFER_FREE; + item->memadr = pos; + item->busadr = virt_to_bus(pos); + pos += ZORAN_MAX_FBUFFER; + } + + /* do the common part of all open's */ + zoran_common_open(ztv, flags); + + return 0; +} + +static +void zoran_close(struct video_device* dev) +{ + struct zoran *ztv = (struct zoran*)dev; + + DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD)); + + /* driver specific closure */ + clear_bit(STATE_OVERLAY, &ztv->state); + + zoran_common_close(ztv); + + /* + * This is sucky but right now I can't find a good way to + * be sure its safe to free the buffer. We wait 5-6 fields + * which is more than sufficient to be sure. + */ + msleep(100); /* Wait 1/10th of a second */ + + /* free the allocated framebuffer */ + bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); + ztv->fbuffer = 0; + kfree(ztv->overinfo.overlay); + ztv->overinfo.overlay = 0; + +} + +/* + * This read function could be used reentrant in a SMP situation. + * + * This is made possible by the spinlock which is kept till we + * found and marked a buffer for our own use. The lock must + * be released as soon as possible to prevent lock contention. + */ +static +long zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) +{ + struct zoran *ztv = (struct zoran*)dev; + unsigned long max; + struct vidinfo* unused = 0; + struct vidinfo* done = 0; + + DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock)); + + /* find ourself a free or completed buffer */ + for (;;) { + struct vidinfo* item; + + write_lock_irq(&ztv->lock); + for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) + { + if (!unused && item->status == FBUFFER_FREE) + unused = item; + if (!done && item->status == FBUFFER_DONE) + done = item; + } + if (done || unused) + break; + + /* no more free buffers, wait for them. */ + write_unlock_irq(&ztv->lock); + if (nonblock) + return -EWOULDBLOCK; + interruptible_sleep_on(&ztv->grabq); + if (signal_pending(current)) + return -EINTR; + } + + /* Do we have 'ready' data? */ + if (!done) { + /* no? than this will take a while... */ + if (nonblock) { + write_unlock_irq(&ztv->lock); + return -EWOULDBLOCK; + } + + /* mark the unused buffer as wanted */ + unused->status = FBUFFER_BUSY; + unused->w = 320; + unused->h = 240; + unused->format = VIDEO_PALETTE_RGB24; + unused->bpp = palette2fmt[unused->format].bpp; + unused->bpl = unused->w * unused->bpp; + unused->next = 0; + { /* add to tail of queue */ + struct vidinfo* oldframe = ztv->workqueue; + if (!oldframe) ztv->workqueue = unused; + else { + while (oldframe->next) oldframe = oldframe->next; + oldframe->next = unused; + } + } + write_unlock_irq(&ztv->lock); + + /* tell the state machine we want it filled /NOW/ */ + zoran_cap(ztv, 1); + + /* wait till this buffer gets grabbed */ + wait_event_interruptible(ztv->grabq, + (unused->status != FBUFFER_BUSY)); + /* see if a signal did it */ + if (signal_pending(current)) + return -EINTR; + done = unused; + } + else + write_unlock_irq(&ztv->lock); + + /* Yes! we got data! */ + max = done->bpl * done->h; + if (count > max) + count = max; + if (copy_to_user((void*)buf, done->memadr, count)) + count = -EFAULT; + + /* keep the engine running */ + done->status = FBUFFER_FREE; +// zoran_cap(ztv,1); + + /* tell listeners this buffer became free */ + wake_up_interruptible(&ztv->grabq); + + /* goodbye */ + DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count)); + return count; +} + +static +long zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock) +{ + struct zoran *ztv = (struct zoran *)dev; + UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock); + DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD)); + return -EINVAL; +} + +static +unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait) +{ + struct zoran *ztv = (struct zoran *)dev; + struct vidinfo* item; + unsigned int mask = 0; + + poll_wait(file, &ztv->grabq, wait); + + for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) + if (item->status == FBUFFER_DONE) + { + mask |= (POLLIN | POLLRDNORM); + break; + } + + DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask)); + + return mask; +} + +/* append a new clipregion to the vector of video_clips */ +static +void new_clip(struct video_window* vw, struct video_clip* vcp, int x, int y, int w, int h) +{ + vcp[vw->clipcount].x = x; + vcp[vw->clipcount].y = y; + vcp[vw->clipcount].width = w; + vcp[vw->clipcount].height = h; + vw->clipcount++; +} + +static +int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) +{ + struct zoran* ztv = (struct zoran*)dev; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability c; + DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD)); + + strcpy(c.name,ztv->video_dev.name); + c.type = VID_TYPE_CAPTURE| + VID_TYPE_OVERLAY| + VID_TYPE_CLIPPING| + VID_TYPE_FRAMERAM| + VID_TYPE_SCALES; + if (ztv->have_tuner) + c.type |= VID_TYPE_TUNER; + if (pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) + c.type &= ~VID_TYPE_OVERLAY; + if (ztv->have_decoder) { + c.channels = ztv->card->video_inputs; + c.audios = ztv->card->audio_inputs; + } else + /* no decoder -> no channels */ + c.channels = c.audios = 0; + c.maxwidth = 768; + c.maxheight = 576; + c.minwidth = 32; + c.minheight = 32; + if (copy_to_user(arg,&c,sizeof(c))) + return -EFAULT; + break; + } + + case VIDIOCGCHAN: + { + struct video_channel v; + int mux; + if (copy_from_user(&v, arg,sizeof(v))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel)); + v.flags=VIDEO_VC_AUDIO +#ifdef VIDEO_VC_NORM + |VIDEO_VC_NORM +#endif + ; + v.tuners=0; + v.type=VIDEO_TYPE_CAMERA; +#ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API + v.norm=VIDEO_MODE_PAL| + VIDEO_MODE_NTSC| + VIDEO_MODE_SECAM; +#else + v.norm=VIDEO_MODE_PAL; +#endif + /* too many inputs? no decoder -> no channels */ + if (!ztv->have_decoder || v.channel < 0 || v.channel >= ztv->card->video_inputs) + return -EINVAL; + + /* now determine the name of the channel */ + mux = ztv->card->video_mux[v.channel]; + if (mux & IS_TUNER) { + /* lets assume only one tuner, yes? */ + strcpy(v.name,"Television"); + v.type = VIDEO_TYPE_TV; + if (ztv->have_tuner) { + v.flags |= VIDEO_VC_TUNER; + v.tuners = 1; + } + } + else if (mux & IS_SVHS) + sprintf(v.name,"S-Video-%d",v.channel); + else + sprintf(v.name,"CVBS-%d",v.channel); + + if (copy_to_user(arg,&v,sizeof(v))) + return -EFAULT; + break; + } + case VIDIOCSCHAN: + { /* set video channel */ + struct video_channel v; + if (copy_from_user(&v, arg,sizeof(v))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm)); + + /* too many inputs? no decoder -> no channels */ + if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs || v.channel < 0) + return -EINVAL; + + if (v.norm != VIDEO_MODE_PAL && + v.norm != VIDEO_MODE_NTSC && + v.norm != VIDEO_MODE_SECAM && + v.norm != VIDEO_MODE_AUTO) + return -EOPNOTSUPP; + + /* make it happen, nr1! */ + return zoran_muxsel(ztv,v.channel,v.norm); + } + + case VIDIOCGTUNER: + { + struct video_tuner v; + if (copy_from_user(&v, arg,sizeof(v))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner)); + + /* Only no or one tuner for now */ + if (!ztv->have_tuner || v.tuner) + return -EINVAL; + + strcpy(v.name,"Television"); + v.rangelow = 0; + v.rangehigh = ~0; + v.flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; + v.mode = ztv->norm; + v.signal = 0xFFFF; /* unknown */ + + if (copy_to_user(arg,&v,sizeof(v))) + return -EFAULT; + break; + } + case VIDIOCSTUNER: + { + struct video_tuner v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode)); + + /* Only no or one tuner for now */ + if (!ztv->have_tuner || v.tuner) + return -EINVAL; + + /* and it only has certain valid modes */ + if( v.mode != VIDEO_MODE_PAL && + v.mode != VIDEO_MODE_NTSC && + v.mode != VIDEO_MODE_SECAM) + return -EOPNOTSUPP; + + /* engage! */ + return zoran_muxsel(ztv,v.tuner,v.mode); + } + + case VIDIOCGPICT: + { + struct video_picture p = ztv->picture; + DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD)); + p.depth = ztv->depth; + switch (p.depth) { + case 8: p.palette=VIDEO_PALETTE_YUV422; + break; + case 15: p.palette=VIDEO_PALETTE_RGB555; + break; + case 16: p.palette=VIDEO_PALETTE_RGB565; + break; + case 24: p.palette=VIDEO_PALETTE_RGB24; + break; + case 32: p.palette=VIDEO_PALETTE_RGB32; + break; + } + if (copy_to_user(arg, &p, sizeof(p))) + return -EFAULT; + break; + } + case VIDIOCSPICT: + { + struct video_picture p; + if (copy_from_user(&p, arg,sizeof(p))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette)); + + /* depth must match with framebuffer */ + if (p.depth != ztv->depth) + return -EINVAL; + + /* check if palette matches this bpp */ + if (p.palette>NRPALETTES || + palette2fmt[p.palette].bpp != ztv->overinfo.bpp) + return -EINVAL; + + write_lock_irq(&ztv->lock); + ztv->overinfo.format = p.palette; + ztv->picture = p; + write_unlock_irq(&ztv->lock); + + /* tell the decoder */ + i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p); + break; + } + + case VIDIOCGWIN: + { + struct video_window vw; + DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD)); + read_lock(&ztv->lock); + vw.x = ztv->overinfo.x; + vw.y = ztv->overinfo.y; + vw.width = ztv->overinfo.w; + vw.height = ztv->overinfo.h; + vw.chromakey= 0; + vw.flags = 0; + if (ztv->vidInterlace) + vw.flags|=VIDEO_WINDOW_INTERLACE; + read_unlock(&ztv->lock); + if (copy_to_user(arg,&vw,sizeof(vw))) + return -EFAULT; + break; + } + case VIDIOCSWIN: + { + struct video_window vw; + struct video_clip *vcp; + int on; + if (copy_from_user(&vw,arg,sizeof(vw))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount)); + + if (vw.flags) + return -EINVAL; + + if (vw.clipcount <0 || vw.clipcount>256) + return -EDOM; /* Too many! */ + + /* + * Do any clips. + */ + vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4)); + if (vcp==NULL) + return -ENOMEM; + if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) { + vfree(vcp); + return -EFAULT; + } + + on = ztv->running; + if (on) + zoran_cap(ztv, 0); + + /* + * strange, it seems xawtv sometimes calls us with 0 + * width and/or height. Ignore these values + */ + if (vw.x == 0) + vw.x = ztv->overinfo.x; + if (vw.y == 0) + vw.y = ztv->overinfo.y; + + /* by now we are committed to the new data... */ + write_lock_irq(&ztv->lock); + ztv->overinfo.x = vw.x; + ztv->overinfo.y = vw.y; + ztv->overinfo.w = vw.width; + ztv->overinfo.h = vw.height; + write_unlock_irq(&ztv->lock); + + /* + * Impose display clips + */ + if (vw.x+vw.width > ztv->swidth) + new_clip(&vw, vcp, ztv->swidth-vw.x, 0, vw.width-1, vw.height-1); + if (vw.y+vw.height > ztv->sheight) + new_clip(&vw, vcp, 0, ztv->sheight-vw.y, vw.width-1, vw.height-1); + + /* built the requested clipping zones */ + zoran_set_geo(ztv, &ztv->overinfo); + zoran_built_overlay(ztv, vw.clipcount, vcp); + vfree(vcp); + + /* if we were on, restart the video engine */ + if (on) + zoran_cap(ztv, 1); + break; + } + + case VIDIOCCAPTURE: + { + int v; + if (get_user(v, (int *)arg)) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v)); + + if (v==0) { + clear_bit(STATE_OVERLAY, &ztv->state); + zoran_cap(ztv, 1); + } + else { + /* is VIDIOCSFBUF, VIDIOCSWIN done? */ + if (ztv->overinfo.busadr==0 || ztv->overinfo.w==0 || ztv->overinfo.h==0) + return -EINVAL; + + set_bit(STATE_OVERLAY, &ztv->state); + zoran_cap(ztv, 1); + } + break; + } + + case VIDIOCGFBUF: + { + struct video_buffer v; + DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD)); + read_lock(&ztv->lock); + v.base = (void *)ztv->overinfo.busadr; + v.height = ztv->sheight; + v.width = ztv->swidth; + v.depth = ztv->depth; + v.bytesperline = ztv->overinfo.bpl; + read_unlock(&ztv->lock); + if(copy_to_user(arg, &v,sizeof(v))) + return -EFAULT; + break; + } + case VIDIOCSFBUF: + { + struct video_buffer v; + if(!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (pcipci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) + return -ENXIO; + if (copy_from_user(&v, arg,sizeof(v))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline)); + + if (v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32) + return -EINVAL; + if (v.bytesperline<1) + return -EINVAL; + if (ztv->running) + return -EBUSY; + write_lock_irq(&ztv->lock); + ztv->overinfo.busadr = (ulong)v.base; + ztv->sheight = v.height; + ztv->swidth = v.width; + ztv->depth = v.depth; /* bits per pixel */ + ztv->overinfo.bpp = ((v.depth+1)&0x38)/8;/* bytes per pixel */ + ztv->overinfo.bpl = v.bytesperline; /* bytes per line */ + write_unlock_irq(&ztv->lock); + break; + } + + case VIDIOCKEY: + { + /* Will be handled higher up .. */ + break; + } + + case VIDIOCSYNC: + { + int i; + if (get_user(i, (int *) arg)) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i)); + if (i<0 || i>ZORAN_MAX_FBUFFERS) + return -EINVAL; + switch (ztv->grabinfo[i].status) { + case FBUFFER_FREE: + return -EINVAL; + case FBUFFER_BUSY: + /* wait till this buffer gets grabbed */ + wait_event_interruptible(ztv->grabq, + (ztv->grabinfo[i].status != FBUFFER_BUSY)); + /* see if a signal did it */ + if (signal_pending(current)) + return -EINTR; + /* don't fall through; a DONE buffer is not UNUSED */ + break; + case FBUFFER_DONE: + ztv->grabinfo[i].status = FBUFFER_FREE; + /* tell ppl we have a spare buffer */ + wake_up_interruptible(&ztv->grabq); + break; + } + DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i)); + break; + } + + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + struct vidinfo* frame; + if (copy_from_user(&vm,arg,sizeof(vm))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format)); + if (vm.frame<0 || vm.frame>ZORAN_MAX_FBUFFERS || + vm.width<32 || vm.width>768 || + vm.height<32 || vm.height>576 || + vm.format>NRPALETTES || + palette2fmt[vm.format].mode == 0) + return -EINVAL; + + /* we are allowed to take over UNUSED and DONE buffers */ + frame = &ztv->grabinfo[vm.frame]; + if (frame->status == FBUFFER_BUSY) + return -EBUSY; + + /* setup the other parameters if they are given */ + write_lock_irq(&ztv->lock); + frame->w = vm.width; + frame->h = vm.height; + frame->format = vm.format; + frame->bpp = palette2fmt[frame->format].bpp; + frame->bpl = frame->w*frame->bpp; + frame->status = FBUFFER_BUSY; + frame->next = 0; + { /* add to tail of queue */ + struct vidinfo* oldframe = ztv->workqueue; + if (!oldframe) ztv->workqueue = frame; + else { + while (oldframe->next) oldframe = oldframe->next; + oldframe->next = frame; + } + } + write_unlock_irq(&ztv->lock); + zoran_cap(ztv, 1); + break; + } + + case VIDIOCGMBUF: + { + struct video_mbuf mb; + int i; + DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD)); + mb.size = ZORAN_MAX_FBUFSIZE; + mb.frames = ZORAN_MAX_FBUFFERS; + for (i=0; ivideo_dev.minor; + vu.vbi = ztv->vbi_dev.minor; + vu.radio = VIDEO_NO_UNIT; + vu.audio = VIDEO_NO_UNIT; + vu.teletext = VIDEO_NO_UNIT; + if(copy_to_user(arg, &vu,sizeof(vu))) + return -EFAULT; + break; + } + + case VIDIOCGFREQ: + { + unsigned long v = ztv->tuner_freq; + if (copy_to_user(arg,&v,sizeof(v))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD)); + break; + } + case VIDIOCSFREQ: + { + unsigned long v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD)); + + if (ztv->have_tuner) { + int fixme = v; + if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0) + return -EAGAIN; + } + ztv->tuner_freq = v; + break; + } + + /* Why isn't this in the API? + * And why doesn't it take a buffer number? + case BTTV_FIELDNR: + { + unsigned long v = ztv->lastfieldnr; + if (copy_to_user(arg,&v,sizeof(v))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD)); + break; + } + */ + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static +int zoran_mmap(struct vm_area_struct *vma, struct video_device* dev, const char* adr, unsigned long size) +{ + struct zoran* ztv = (struct zoran*)dev; + unsigned long start = (unsigned long)adr; + unsigned long pos; + + DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size)); + + /* sanity checks */ + if (size > ZORAN_MAX_FBUFSIZE || !ztv->fbuffer) + return -EINVAL; + + /* start mapping the whole shabang to user memory */ + pos = (unsigned long)ztv->fbuffer; + while (size>0) { + unsigned long pfn = virt_to_phys((void*)pos) >> PAGE_SHIFT; + if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + return 0; +} + +static struct video_device zr36120_template= +{ + .owner = THIS_MODULE, + .name = "UNSET", + .type = VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY, + .hardware = VID_HARDWARE_ZR36120, + .open = zoran_open, + .close = zoran_close, + .read = zoran_read, + .write = zoran_write, + .poll = zoran_poll, + .ioctl = zoran_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .mmap = zoran_mmap, + .minor = -1, +}; + +static +int vbi_open(struct video_device *dev, int flags) +{ + struct zoran *ztv = dev->priv; + struct vidinfo* item; + + DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags)); + + /* + * During VBI device open, we continiously grab VBI-like + * data in the vbi buffer when we have nothing to do. + * Only when there is an explicit request for VBI data + * (read call) we /force/ a read. + */ + + /* allocate buffers */ + for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) + { + item->status = FBUFFER_FREE; + + /* alloc */ + if (!item->memadr) { + item->memadr = bmalloc(ZORAN_VBI_BUFSIZE); + if (!item->memadr) { + /* could not get a buffer, bail out */ + while (item != ztv->readinfo) { + item--; + bfree(item->memadr, ZORAN_VBI_BUFSIZE); + item->memadr = 0; + item->busadr = 0; + } + return -ENOBUFS; + } + } + + /* determine the DMAable address */ + item->busadr = virt_to_bus(item->memadr); + } + + /* do the common part of all open's */ + zoran_common_open(ztv, flags); + + set_bit(STATE_VBI, &ztv->state); + /* start read-ahead */ + zoran_cap(ztv, 1); + + return 0; +} + +static +void vbi_close(struct video_device *dev) +{ + struct zoran *ztv = dev->priv; + struct vidinfo* item; + + DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD)); + + /* driver specific closure */ + clear_bit(STATE_VBI, &ztv->state); + + zoran_common_close(ztv); + + /* + * This is sucky but right now I can't find a good way to + * be sure its safe to free the buffer. We wait 5-6 fields + * which is more than sufficient to be sure. + */ + msleep(100); /* Wait 1/10th of a second */ + + for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) + { + if (item->memadr) + bfree(item->memadr, ZORAN_VBI_BUFSIZE); + item->memadr = 0; + } + +} + +/* + * This read function could be used reentrant in a SMP situation. + * + * This is made possible by the spinlock which is kept till we + * found and marked a buffer for our own use. The lock must + * be released as soon as possible to prevent lock contention. + */ +static +long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) +{ + struct zoran *ztv = dev->priv; + unsigned long max; + struct vidinfo* unused = 0; + struct vidinfo* done = 0; + + DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock)); + + /* find ourself a free or completed buffer */ + for (;;) { + struct vidinfo* item; + + write_lock_irq(&ztv->lock); + for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) { + if (!unused && item->status == FBUFFER_FREE) + unused = item; + if (!done && item->status == FBUFFER_DONE) + done = item; + } + if (done || unused) + break; + + /* no more free buffers, wait for them. */ + write_unlock_irq(&ztv->lock); + if (nonblock) + return -EWOULDBLOCK; + interruptible_sleep_on(&ztv->vbiq); + if (signal_pending(current)) + return -EINTR; + } + + /* Do we have 'ready' data? */ + if (!done) { + /* no? than this will take a while... */ + if (nonblock) { + write_unlock_irq(&ztv->lock); + return -EWOULDBLOCK; + } + + /* mark the unused buffer as wanted */ + unused->status = FBUFFER_BUSY; + unused->next = 0; + { /* add to tail of queue */ + struct vidinfo* oldframe = ztv->workqueue; + if (!oldframe) ztv->workqueue = unused; + else { + while (oldframe->next) oldframe = oldframe->next; + oldframe->next = unused; + } + } + write_unlock_irq(&ztv->lock); + + /* tell the state machine we want it filled /NOW/ */ + zoran_cap(ztv, 1); + + /* wait till this buffer gets grabbed */ + wait_event_interruptible(ztv->vbiq, + (unused->status != FBUFFER_BUSY)); + /* see if a signal did it */ + if (signal_pending(current)) + return -EINTR; + done = unused; + } + else + write_unlock_irq(&ztv->lock); + + /* Yes! we got data! */ + max = done->bpl * -done->h; + if (count > max) + count = max; + + /* check if the user gave us enough room to write the data */ + if (!access_ok(VERIFY_WRITE, buf, count)) { + count = -EFAULT; + goto out; + } + + /* + * Now transform/strip the data from YUV to Y-only + * NB. Assume the Y is in the LSB of the YUV data. + */ + { + unsigned char* optr = buf; + unsigned char* eptr = buf+count; + + /* are we beeing accessed from an old driver? */ + if (count == 2*19*2048) { + /* + * Extreme HACK, old VBI programs expect 2048 points + * of data, and we only got 864 orso. Double each + * datapoint and clear the rest of the line. + * This way we have appear to have a + * sample_frequency of 29.5 Mc. + */ + int x,y; + unsigned char* iptr = done->memadr+1; + for (y=done->h; optrw; x++) + { + unsigned char a = iptr[x*2]; + __put_user(a, optr++); + __put_user(a, optr++); + } + /* and clear the rest of the line */ + for (x*=2; optrbpl; x++) + __put_user(0, optr++); + /* next line */ + iptr += done->bpl; + } + } + else { + /* + * Other (probably newer) programs asked + * us what geometry we are using, and are + * reading the correct size. + */ + int x,y; + unsigned char* iptr = done->memadr+1; + for (y=done->h; optrw; x++) + __put_user(iptr[x*2], optr++); + /* and clear the rest of the line */ + for (;optrbpl; x++) + __put_user(0, optr++); + /* next line */ + iptr += done->bpl; + } + } + + /* API compliance: + * place the framenumber (half fieldnr) in the last long + */ + __put_user(done->fieldnr/2, ((ulong*)eptr)[-1]); + } + + /* keep the engine running */ + done->status = FBUFFER_FREE; + zoran_cap(ztv, 1); + + /* tell listeners this buffer just became free */ + wake_up_interruptible(&ztv->vbiq); + + /* goodbye */ +out: + DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count)); + return count; +} + +static +unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) +{ + struct zoran *ztv = dev->priv; + struct vidinfo* item; + unsigned int mask = 0; + + poll_wait(file, &ztv->vbiq, wait); + + for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) + if (item->status == FBUFFER_DONE) + { + mask |= (POLLIN | POLLRDNORM); + break; + } + + DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask)); + + return mask; +} + +static +int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct zoran* ztv = dev->priv; + + switch (cmd) { + case VIDIOCGVBIFMT: + { + struct vbi_format f; + DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD)); + f.sampling_rate = 14750000UL; + f.samples_per_line = -ztv->readinfo[0].w; + f.sample_format = VIDEO_PALETTE_RAW; + f.start[0] = f.start[1] = ztv->readinfo[0].y; + f.start[1] += 312; + f.count[0] = f.count[1] = -ztv->readinfo[0].h; + f.flags = VBI_INTERLACED; + if (copy_to_user(arg,&f,sizeof(f))) + return -EFAULT; + break; + } + case VIDIOCSVBIFMT: + { + struct vbi_format f; + int i; + if (copy_from_user(&f, arg,sizeof(f))) + return -EFAULT; + DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags)); + + /* lots of parameters are fixed... (PAL) */ + if (f.sampling_rate != 14750000UL || + f.samples_per_line > 864 || + f.sample_format != VIDEO_PALETTE_RAW || + f.start[0] < 0 || + f.start[0] != f.start[1]-312 || + f.count[0] != f.count[1] || + f.start[0]+f.count[0] >= 288 || + f.flags != VBI_INTERLACED) + return -EINVAL; + + write_lock_irq(&ztv->lock); + ztv->readinfo[0].y = f.start[0]; + ztv->readinfo[0].w = -f.samples_per_line; + ztv->readinfo[0].h = -f.count[0]; + ztv->readinfo[0].bpl = f.samples_per_line*ztv->readinfo[0].bpp; + for (i=1; ireadinfo[i] = ztv->readinfo[i]; + write_unlock_irq(&ztv->lock); + break; + } + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static struct video_device vbi_template= +{ + .owner = THIS_MODULE, + .name = "UNSET", + .type = VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, + .hardware = VID_HARDWARE_ZR36120, + .open = vbi_open, + .close = vbi_close, + .read = vbi_read, + .write = zoran_write, + .poll = vbi_poll, + .ioctl = vbi_ioctl, + .minor = -1, +}; + +/* + * Scan for a Zoran chip, request the irq and map the io memory + */ +static +int __init find_zoran(void) +{ + int result; + struct zoran *ztv; + struct pci_dev *dev = NULL; + unsigned char revision; + int zoran_num = 0; + + while ((dev = pci_get_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev))) + { + /* Ok, a ZR36120/ZR36125 found! */ + ztv = &zorans[zoran_num]; + ztv->dev = dev; + + if (pci_enable_device(dev)) + continue; + + pci_read_config_byte(dev, PCI_CLASS_REVISION, &revision); + printk(KERN_INFO "zoran: Zoran %x (rev %d) ", + dev->device, revision); + printk("bus: %d, devfn: %d, irq: %d, ", + dev->bus->number, dev->devfn, dev->irq); + printk("memory: 0x%08lx.\n", ztv->zoran_adr); + + ztv->zoran_mem = ioremap(ztv->zoran_adr, 0x1000); + DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv->zoran_mem)); + + result = request_irq(dev->irq, zoran_irq, + IRQF_SHARED|IRQF_DISABLED,"zoran", ztv); + if (result==-EINVAL) + { + iounmap(ztv->zoran_mem); + printk(KERN_ERR "zoran: Bad irq number or handler\n"); + continue; + } + if (result==-EBUSY) + printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq); + if (result < 0) { + iounmap(ztv->zoran_mem); + continue; + } + /* Enable bus-mastering */ + pci_set_master(dev); + /* Keep a reference */ + pci_dev_get(dev); + zoran_num++; + } + if(zoran_num) + printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num); + return zoran_num; +} + +static +int __init init_zoran(int card) +{ + struct zoran *ztv = &zorans[card]; + int i; + + /* if the given cardtype valid? */ + if (cardtype[card]>=NRTVCARDS) { + printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]); + return -1; + } + + /* reset the zoran */ + zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI); + udelay(10); + zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI); + udelay(10); + + /* zoran chip specific details */ + ztv->card = tvcards+cardtype[card]; /* point to the selected card */ + ztv->norm = 0; /* PAL */ + ztv->tuner_freq = 0; + + /* videocard details */ + ztv->swidth = 800; + ztv->sheight = 600; + ztv->depth = 16; + + /* State details */ + ztv->fbuffer = 0; + ztv->overinfo.kindof = FBUFFER_OVERLAY; + ztv->overinfo.status = FBUFFER_FREE; + ztv->overinfo.x = 0; + ztv->overinfo.y = 0; + ztv->overinfo.w = 768; /* 640 */ + ztv->overinfo.h = 576; /* 480 */ + ztv->overinfo.format = VIDEO_PALETTE_RGB565; + ztv->overinfo.bpp = palette2fmt[ztv->overinfo.format].bpp; + ztv->overinfo.bpl = ztv->overinfo.bpp*ztv->swidth; + ztv->overinfo.busadr = 0; + ztv->overinfo.memadr = 0; + ztv->overinfo.overlay = 0; + for (i=0; igrabinfo[i] = ztv->overinfo; + ztv->grabinfo[i].kindof = FBUFFER_GRAB; + } + init_waitqueue_head(&ztv->grabq); + + /* VBI details */ + ztv->readinfo[0] = ztv->overinfo; + ztv->readinfo[0].kindof = FBUFFER_VBI; + ztv->readinfo[0].w = -864; + ztv->readinfo[0].h = -38; + ztv->readinfo[0].format = VIDEO_PALETTE_YUV422; + ztv->readinfo[0].bpp = palette2fmt[ztv->readinfo[0].format].bpp; + ztv->readinfo[0].bpl = 1024*ztv->readinfo[0].bpp; + for (i=1; ireadinfo[i] = ztv->readinfo[0]; + init_waitqueue_head(&ztv->vbiq); + + /* maintenance data */ + ztv->have_decoder = 0; + ztv->have_tuner = 0; + ztv->tuner_type = 0; + ztv->running = 0; + ztv->users = 0; + rwlock_init(&ztv->lock); + ztv->workqueue = 0; + ztv->fieldnr = 0; + ztv->lastfieldnr = 0; + + if (triton1) + zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC); + + /* external FL determines TOP frame */ + zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); + + /* set HSpol */ + if (ztv->card->hsync_pos) + zrwrite(ZORAN_VFEH_HSPOL, ZORAN_VFEH); + /* set VSpol */ + if (ztv->card->vsync_pos) + zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV); + + /* Set the proper General Purpuse register bits */ + /* implicit: no softreset, 0 waitstates */ + zrwrite(ZORAN_PCI_SOFTRESET|(ztv->card->gpdir<<0),ZORAN_PCI); + /* implicit: 3 duration and recovery PCI clocks on guest 0-3 */ + zrwrite(ztv->card->gpval<<24,ZORAN_GUEST); + + /* clear interrupt status */ + zrwrite(~0, ZORAN_ISR); + + /* + * i2c template + */ + ztv->i2c = zoran_i2c_bus_template; + sprintf(ztv->i2c.name,"zoran-%d",card); + ztv->i2c.data = ztv; + + /* + * Now add the template and register the device unit + */ + ztv->video_dev = zr36120_template; + strcpy(ztv->video_dev.name, ztv->i2c.name); + ztv->video_dev.priv = ztv; + if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) + return -1; + + ztv->vbi_dev = vbi_template; + strcpy(ztv->vbi_dev.name, ztv->i2c.name); + ztv->vbi_dev.priv = ztv; + if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) { + video_unregister_device(&ztv->video_dev); + return -1; + } + i2c_register_bus(&ztv->i2c); + + /* set interrupt mask - the PIN enable will be set later */ + zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR); + + printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name); + return 0; +} + +static +void release_zoran(int max) +{ + struct zoran *ztv; + int i; + + for (i=0;idev->irq,ztv); + + /* unregister i2c_bus */ + i2c_unregister_bus((&ztv->i2c)); + + /* unmap and free memory */ + if (ztv->zoran_mem) + iounmap(ztv->zoran_mem); + + /* Drop PCI device */ + pci_dev_put(ztv->dev); + + video_unregister_device(&ztv->video_dev); + video_unregister_device(&ztv->vbi_dev); + } +} + +void __exit zr36120_exit(void) +{ + release_zoran(zoran_cards); +} + +int __init zr36120_init(void) +{ + int card; + + handle_chipset(); + zoran_cards = find_zoran(); + if (zoran_cards <= 0) + return -EIO; + + /* initialize Zorans */ + for (card=0; card +#include + +#include +#include + +#include + +/* + * Debug macro's, place an x behind the ) for actual debug-compilation + * E.g. #define DEBUG(x...) x + */ +#define DEBUG(x...) /* Debug driver */ +#define IDEBUG(x...) /* Debug interrupt handler */ +#define PDEBUG 0 /* Debug PCI writes */ + +/* defined in zr36120_i2c */ +extern struct i2c_bus zoran_i2c_bus_template; + +#define ZORAN_MAX_FBUFFERS 2 +#define ZORAN_MAX_FBUFFER (768*576*2) +#define ZORAN_MAX_FBUFSIZE (ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER) + +#define ZORAN_VBI_BUFFERS 2 +#define ZORAN_VBI_BUFSIZE (22*1024*2) + +struct tvcard { + char* name; /* name of the cardtype */ + int video_inputs; /* number of channels defined in video_mux */ + int audio_inputs; /* number of channels defined in audio_mux */ + __u32 swapi2c:1, /* need to swap i2c wires SDA/SCL? */ + usegirq1:1, /* VSYNC at GIRQ1 instead of GIRQ0? */ + vsync_pos:1, /* positive VSYNC signal? */ + hsync_pos:1, /* positive HSYNC signal? */ + gpdir:8, /* General Purpose Direction register */ + gpval:8; /* General Purpose Value register */ + int video_mux[6]; /* mapping channel number to physical input */ +#define IS_TUNER 0x80 +#define IS_SVHS 0x40 +#define CHANNEL_MASK 0x3F + int audio_mux[6]; /* mapping channel number to physical input */ +}; +#define TUNER(x) ((x)|IS_TUNER) +#define SVHS(x) ((x)|IS_SVHS) + +struct vidinfo { + struct vidinfo* next; /* next active buffer */ + uint kindof; +#define FBUFFER_OVERLAY 0 +#define FBUFFER_GRAB 1 +#define FBUFFER_VBI 2 + uint status; +#define FBUFFER_FREE 0 +#define FBUFFER_BUSY 1 +#define FBUFFER_DONE 2 + ulong fieldnr; /* # of field, not framer! */ + uint x,y; + int w,h; /* w,h can be negative! */ + uint format; /* index in palette2fmt[] */ + uint bpp; /* lookup from palette2fmt[] */ + uint bpl; /* calc: width * bpp */ + ulong busadr; /* bus addr for DMA engine */ + char* memadr; /* kernel addr for making copies */ + ulong* overlay; /* kernel addr of overlay mask */ +}; + +struct zoran +{ + struct video_device video_dev; +#define CARD_DEBUG KERN_DEBUG "%s(%lu): " +#define CARD_INFO KERN_INFO "%s(%lu): " +#define CARD_ERR KERN_ERR "%s(%lu): " +#define CARD ztv->video_dev.name,ztv->fieldnr + + /* zoran chip specific details */ + struct i2c_bus i2c; /* i2c registration data */ + struct pci_dev* dev; /* ptr to PCI device */ + ulong zoran_adr; /* bus address of IO memory */ + char* zoran_mem; /* kernel address of IO memory */ + struct tvcard* card; /* the cardtype */ + uint norm; /* 0=PAL, 1=NTSC, 2=SECAM */ + uint tuner_freq; /* Current freq in kHz */ + struct video_picture picture; /* Current picture params */ + + /* videocard details */ + uint swidth; /* screen width */ + uint sheight; /* screen height */ + uint depth; /* depth in bits */ + + /* State details */ + char* fbuffer; /* framebuffers for mmap */ + struct vidinfo overinfo; /* overlay data */ + struct vidinfo grabinfo[ZORAN_MAX_FBUFFERS]; /* grabbing data*/ + wait_queue_head_t grabq; /* grabbers queue */ + + /* VBI details */ + struct video_device vbi_dev; + struct vidinfo readinfo[2]; /* VBI data - flip buffers */ + wait_queue_head_t vbiq; /* vbi queue */ + + /* maintenance data */ + int have_decoder; /* did we detect a mux? */ + int have_tuner; /* did we detect a tuner? */ + int users; /* howmany video/vbi open? */ + int tuner_type; /* tuner type, when found */ + int running; /* are we rolling? */ + rwlock_t lock; + long state; /* what is requested of us? */ +#define STATE_OVERLAY 0 +#define STATE_VBI 1 + struct vidinfo* workqueue; /* buffers to grab, head is active */ + ulong fieldnr; /* #field, ticked every VSYNC */ + ulong lastfieldnr; /* #field, ticked every GRAB */ + + int vidInterlace; /* calculated */ + int vidXshift; /* calculated */ + uint vidWidth; /* calculated */ + uint vidHeight; /* calculated */ +}; + +#define zrwrite(dat,adr) writel((dat),(char *) (ztv->zoran_mem+(adr))) +#define zrread(adr) readl(ztv->zoran_mem+(adr)) + +#if PDEBUG == 0 +#define zrand(dat,adr) zrwrite((dat) & zrread(adr), adr) +#define zror(dat,adr) zrwrite((dat) | zrread(adr), adr) +#define zraor(dat,mask,adr) zrwrite( ((dat)&~(mask)) | ((mask)&zrread(adr)), adr) +#else +#define zrand(dat, adr) \ +do { \ + ulong data = (dat) & zrread((adr)); \ + zrwrite(data, (adr)); \ + if (0 != (~(dat) & zrread((adr)))) \ + printk(KERN_DEBUG "zoran: zrand at %d(%d) detected set bits(%x)\n", __LINE__, (adr), (dat)); \ +} while(0) + +#define zror(dat, adr) \ +do { \ + ulong data = (dat) | zrread((adr)); \ + zrwrite(data, (adr)); \ + if ((dat) != ((dat) & zrread(adr))) \ + printk(KERN_DEBUG "zoran: zror at %d(%d) detected unset bits(%x)\n", __LINE__, (adr), (dat)); \ +} while(0) + +#define zraor(dat, mask, adr) \ +do { \ + ulong data; \ + if ((dat) & (mask)) \ + printk(KERN_DEBUG "zoran: zraor at %d(%d) detected bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ + data = ((dat)&~(mask)) | ((mask) & zrread((adr))); \ + zrwrite(data,(adr)); \ + if ( (dat) != (~(mask) & zrread((adr))) ) \ + printk(KERN_DEBUG "zoran: zraor at %d(%d) could not set all bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ +} while(0) +#endif + +#endif + +/* zoran PCI address space */ +#define ZORAN_VFEH 0x000 /* Video Front End Horizontal Conf. */ +#define ZORAN_VFEH_HSPOL (1<<30) +#define ZORAN_VFEH_HSTART (0x3FF<<10) +#define ZORAN_VFEH_HEND (0x3FF<<0) + +#define ZORAN_VFEV 0x004 /* Video Front End Vertical Conf. */ +#define ZORAN_VFEV_VSPOL (1<<30) +#define ZORAN_VFEV_VSTART (0x3FF<<10) +#define ZORAN_VFEV_VEND (0x3FF<<0) + +#define ZORAN_VFEC 0x008 /* Video Front End Scaler and Pixel */ +#define ZORAN_VFEC_EXTFL (1<<26) +#define ZORAN_VFEC_TOPFIELD (1<<25) +#define ZORAN_VFEC_VCLKPOL (1<<24) +#define ZORAN_VFEC_HFILTER (7<<21) +#define ZORAN_VFEC_HFILTER_1 (0<<21) /* no lumi, 3-tap chromo */ +#define ZORAN_VFEC_HFILTER_2 (1<<21) /* 3-tap lumi, 3-tap chromo */ +#define ZORAN_VFEC_HFILTER_3 (2<<21) /* 4-tap lumi, 4-tap chromo */ +#define ZORAN_VFEC_HFILTER_4 (3<<21) /* 5-tap lumi, 4-tap chromo */ +#define ZORAN_VFEC_HFILTER_5 (4<<21) /* 4-tap lumi, 4-tap chromo */ +#define ZORAN_VFEC_DUPFLD (1<<20) +#define ZORAN_VFEC_HORDCM (63<<14) +#define ZORAN_VFEC_VERDCM (63<<8) +#define ZORAN_VFEC_DISPMOD (1<<6) +#define ZORAN_VFEC_RGB (3<<3) +#define ZORAN_VFEC_RGB_YUV422 (0<<3) +#define ZORAN_VFEC_RGB_RGB888 (1<<3) +#define ZORAN_VFEC_RGB_RGB565 (2<<3) +#define ZORAN_VFEC_RGB_RGB555 (3<<3) +#define ZORAN_VFEC_ERRDIF (1<<2) +#define ZORAN_VFEC_PACK24 (1<<1) +#define ZORAN_VFEC_LE (1<<0) + +#define ZORAN_VTOP 0x00C /* Video Display "Top" */ + +#define ZORAN_VBOT 0x010 /* Video Display "Bottom" */ + +#define ZORAN_VSTR 0x014 /* Video Display Stride */ +#define ZORAN_VSTR_DISPSTRIDE (0xFFFF<<16) +#define ZORAN_VSTR_VIDOVF (1<<8) +#define ZORAN_VSTR_SNAPSHOT (1<<1) +#define ZORAN_VSTR_GRAB (1<<0) + +#define ZORAN_VDC 0x018 /* Video Display Conf. */ +#define ZORAN_VDC_VIDEN (1<<31) +#define ZORAN_VDC_MINPIX (0x1F<<25) +#define ZORAN_VDC_TRICOM (1<<24) +#define ZORAN_VDC_VIDWINHT (0x3FF<<12) +#define ZORAN_VDC_VIDWINWID (0x3FF<<0) + +#define ZORAN_MTOP 0x01C /* Masking Map "Top" */ + +#define ZORAN_MBOT 0x020 /* Masking Map "Bottom" */ + +#define ZORAN_OCR 0x024 /* Overlay Control */ +#define ZORAN_OCR_OVLEN (1<<15) +#define ZORAN_OCR_MASKSTRIDE (0xFF<<0) + +#define ZORAN_PCI 0x028 /* System, PCI and GPP Control */ +#define ZORAN_PCI_SOFTRESET (1<<24) +#define ZORAN_PCI_WAITSTATE (3<<16) +#define ZORAN_PCI_GENPURDIR (0xFF<<0) + +#define ZORAN_GUEST 0x02C /* GuestBus Control */ + +#define ZORAN_CSOURCE 0x030 /* Code Source Address */ + +#define ZORAN_CTRANS 0x034 /* Code Transfer Control */ + +#define ZORAN_CMEM 0x038 /* Code Memory Pointer */ + +#define ZORAN_ISR 0x03C /* Interrupt Status Register */ +#define ZORAN_ISR_CODE (1<<28) +#define ZORAN_ISR_GIRQ0 (1<<29) +#define ZORAN_ISR_GIRQ1 (1<<30) + +#define ZORAN_ICR 0x040 /* Interrupt Control Register */ +#define ZORAN_ICR_EN (1<<24) +#define ZORAN_ICR_CODE (1<<28) +#define ZORAN_ICR_GIRQ0 (1<<29) +#define ZORAN_ICR_GIRQ1 (1<<30) + +#define ZORAN_I2C 0x044 /* I2C-Bus */ +#define ZORAN_I2C_SCL (1<<1) +#define ZORAN_I2C_SDA (1<<0) + +#define ZORAN_POST 0x48 /* PostOffice */ +#define ZORAN_POST_PEN (1<<25) +#define ZORAN_POST_TIME (1<<24) +#define ZORAN_POST_DIR (1<<23) +#define ZORAN_POST_GUESTID (3<<20) +#define ZORAN_POST_GUEST (7<<16) +#define ZORAN_POST_DATA (0xFF<<0) + +#endif diff --git a/trunk/drivers/media/video/zr36120_i2c.c b/trunk/drivers/media/video/zr36120_i2c.c new file mode 100644 index 000000000000..21fde43a6aed --- /dev/null +++ b/trunk/drivers/media/video/zr36120_i2c.c @@ -0,0 +1,132 @@ +/* + zr36120_i2c.c - Zoran 36120/36125 based framegrabbers + + Copyright (C) 1998-1999 Pauline Middelink + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include +#include + +#include "tuner.h" +#include "zr36120.h" + +/* ----------------------------------------------------------------------- */ +/* I2C functions */ +/* ----------------------------------------------------------------------- */ + +/* software I2C functions */ + +#define I2C_DELAY 10 + +static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data) +{ + struct zoran *ztv = (struct zoran*)bus->data; + unsigned int b = 0; + if (data) b |= ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA; + if (ctrl) b |= ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL; + zrwrite(b, ZORAN_I2C); + udelay(I2C_DELAY); +} + +static int i2c_getdataline(struct i2c_bus *bus) +{ + struct zoran *ztv = (struct zoran*)bus->data; + if (ztv->card->swapi2c) + return zrread(ZORAN_I2C) & ZORAN_I2C_SCL; + return zrread(ZORAN_I2C) & ZORAN_I2C_SDA; +} + +static +void attach_inform(struct i2c_bus *bus, int id) +{ + struct zoran *ztv = (struct zoran*)bus->data; + struct video_decoder_capability dc; + int rv; + + switch (id) { + case I2C_DRIVERID_VIDEODECODER: + DEBUG(printk(CARD_INFO "decoder attached\n",CARD)); + + /* fetch the capabilities of the decoder */ + rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc); + if (rv) { + DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD)); + break; + } + DEBUG(printk(CARD_DEBUG "capabilities %d %d %d\n",CARD,dc.flags,dc.inputs,dc.outputs)); + + /* Test if the decoder can de VBI transfers */ + if (dc.flags & 16 /*VIDEO_DECODER_VBI*/) + ztv->have_decoder = 2; + else + ztv->have_decoder = 1; + break; + case I2C_DRIVERID_TUNER: + ztv->have_tuner = 1; + DEBUG(printk(CARD_INFO "tuner attached\n",CARD)); + if (ztv->tuner_type >= 0) + { + if (i2c_control_device(&ztv->i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&ztv->tuner_type)<0) + DEBUG(printk(CARD_INFO "attach_inform; tuner won't be set to type %d\n",CARD,ztv->tuner_type)); + } + break; + default: + DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id)); + break; + } +} + +static +void detach_inform(struct i2c_bus *bus, int id) +{ + struct zoran *ztv = (struct zoran*)bus->data; + + switch (id) { + case I2C_DRIVERID_VIDEODECODER: + ztv->have_decoder = 0; + DEBUG(printk(CARD_INFO "decoder detached\n",CARD)); + break; + case I2C_DRIVERID_TUNER: + ztv->have_tuner = 0; + DEBUG(printk(CARD_INFO "tuner detached\n",CARD)); + break; + default: + DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id)); + break; + } +} + +struct i2c_bus zoran_i2c_bus_template = +{ + "ZR36120", + I2C_BUSID_ZORAN, + NULL, + + SPIN_LOCK_UNLOCKED, + + attach_inform, + detach_inform, + + i2c_setlines, + i2c_getdataline, + NULL, + NULL +}; diff --git a/trunk/drivers/media/video/zr36120_mem.c b/trunk/drivers/media/video/zr36120_mem.c new file mode 100644 index 000000000000..416eaa93b8a4 --- /dev/null +++ b/trunk/drivers/media/video/zr36120_mem.c @@ -0,0 +1,78 @@ +/* + zr36120_mem.c - Zoran 36120/36125 based framegrabbers + + Copyright (C) 1998-1999 Pauline Middelink + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#ifdef CONFIG_BIGPHYS_AREA +#include +#endif + +#include "zr36120.h" +#include "zr36120_mem.h" + +/*******************************/ +/* Memory management functions */ +/*******************************/ + +void* bmalloc(unsigned long size) +{ + void* mem; +#ifdef CONFIG_BIGPHYS_AREA + mem = bigphysarea_alloc_pages(size/PAGE_SIZE, 1, GFP_KERNEL); +#else + /* + * The following function got a lot of memory at boottime, + * so we know its always there... + */ + mem = (void*)__get_free_pages(GFP_USER|GFP_DMA,get_order(size)); +#endif + if (mem) { + unsigned long adr = (unsigned long)mem; + while (size > 0) { + SetPageReserved(virt_to_page(phys_to_virt(adr))); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + } + return mem; +} + +void bfree(void* mem, unsigned long size) +{ + if (mem) { + unsigned long adr = (unsigned long)mem; + unsigned long siz = size; + while (siz > 0) { + ClearPageReserved(virt_to_page(phys_to_virt(adr))); + adr += PAGE_SIZE; + siz -= PAGE_SIZE; + } +#ifdef CONFIG_BIGPHYS_AREA + bigphysarea_free_pages(mem); +#else + free_pages((unsigned long)mem,get_order(size)); +#endif + } +} + +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/media/video/zr36120_mem.h b/trunk/drivers/media/video/zr36120_mem.h new file mode 100644 index 000000000000..aad117acc91d --- /dev/null +++ b/trunk/drivers/media/video/zr36120_mem.h @@ -0,0 +1,3 @@ +/* either kmalloc() or bigphysarea() alloced memory - continuous */ +void* bmalloc(unsigned long size); +void bfree(void* mem, unsigned long size); diff --git a/trunk/drivers/message/i2o/core.h b/trunk/drivers/message/i2o/core.h index cbe384fb848c..dc388a3ff5e0 100644 --- a/trunk/drivers/message/i2o/core.h +++ b/trunk/drivers/message/i2o/core.h @@ -18,7 +18,7 @@ extern struct i2o_driver i2o_exec_driver; extern int i2o_exec_lct_get(struct i2o_controller *); extern int __init i2o_exec_init(void); -extern void i2o_exec_exit(void); +extern void __exit i2o_exec_exit(void); /* driver */ extern struct bus_type i2o_bus_type; @@ -26,7 +26,7 @@ extern struct bus_type i2o_bus_type; extern int i2o_driver_dispatch(struct i2o_controller *, u32); extern int __init i2o_driver_init(void); -extern void i2o_driver_exit(void); +extern void __exit i2o_driver_exit(void); /* PCI */ extern int __init i2o_pci_init(void); diff --git a/trunk/drivers/message/i2o/driver.c b/trunk/drivers/message/i2o/driver.c index d3235f213c89..9104b65ff70f 100644 --- a/trunk/drivers/message/i2o/driver.c +++ b/trunk/drivers/message/i2o/driver.c @@ -362,7 +362,7 @@ int __init i2o_driver_init(void) * * Unregisters the I2O bus and frees driver array. */ -void i2o_driver_exit(void) +void __exit i2o_driver_exit(void) { bus_unregister(&i2o_bus_type); kfree(i2o_drivers); diff --git a/trunk/drivers/message/i2o/exec-osm.c b/trunk/drivers/message/i2o/exec-osm.c index a539d3b61e76..902753b2c661 100644 --- a/trunk/drivers/message/i2o/exec-osm.c +++ b/trunk/drivers/message/i2o/exec-osm.c @@ -595,7 +595,7 @@ int __init i2o_exec_init(void) * * Unregisters the Exec OSM from the I2O core. */ -void i2o_exec_exit(void) +void __exit i2o_exec_exit(void) { i2o_driver_unregister(&i2o_exec_driver); }; diff --git a/trunk/drivers/message/i2o/i2o_config.c b/trunk/drivers/message/i2o/i2o_config.c index e33d446e7493..1de30d711671 100644 --- a/trunk/drivers/message/i2o/i2o_config.c +++ b/trunk/drivers/message/i2o/i2o_config.c @@ -186,7 +186,7 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type) if (!dev) return -ENXIO; - ops = kmalloc(kcmd.oplen, GFP_KERNEL); + ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL); if (!ops) return -ENOMEM; @@ -199,7 +199,7 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type) * It's possible to have a _very_ large table * and that the user asks for all of it at once... */ - res = kmalloc(65536, GFP_KERNEL); + res = (u8 *) kmalloc(65536, GFP_KERNEL); if (!res) { kfree(ops); return -ENOMEM; diff --git a/trunk/drivers/mmc/at91_mci.c b/trunk/drivers/mmc/at91_mci.c index 08a33c33f6ed..4633dbc9a90f 100644 --- a/trunk/drivers/mmc/at91_mci.c +++ b/trunk/drivers/mmc/at91_mci.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver + * linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver * * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved * @@ -11,7 +11,7 @@ */ /* - This is the AT91 MCI driver that has been tested with both MMC cards + This is the AT91RM9200 MCI driver that has been tested with both MMC cards and SD-cards. Boards that support write protect are now supported. The CCAT91SBC001 board does not support SD cards. @@ -38,8 +38,8 @@ controller to manage the transfers. A read is done from the controller directly to the scatterlist passed in from the request. - Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte - swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug. + Due to a bug in the controller, when a read is completed, all the words are byte + swapped in the scatterlist buffers. The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY @@ -72,7 +72,6 @@ #include #include #include -#include #include #include #include @@ -81,17 +80,33 @@ #undef SUPPORT_4WIRE -#define FL_SENT_COMMAND (1 << 0) -#define FL_SENT_STOP (1 << 1) +static struct clk *mci_clk; -#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \ - | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \ - | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE) +#define FL_SENT_COMMAND (1 << 0) +#define FL_SENT_STOP (1 << 1) -#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg)) -#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg)) +/* + * Read from a MCI register. + */ +static inline unsigned long at91_mci_read(unsigned int reg) +{ + void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI; + + return __raw_readl(mci_base + reg); +} + +/* + * Write to a MCI register. + */ +static inline void at91_mci_write(unsigned int reg, unsigned long value) +{ + void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI; + + __raw_writel(value, mci_base + reg); +} + /* * Low level type for this driver */ @@ -101,14 +116,9 @@ struct at91mci_host struct mmc_command *cmd; struct mmc_request *request; - void __iomem *baseaddr; - int irq; - struct at91_mmc_data *board; int present; - struct clk *mci_clk; - /* * Flag indicating when the command has been sent. This is used to * work out whether or not to send the stop @@ -148,6 +158,7 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data for (i = 0; i < len; i++) { struct scatterlist *sg; int amount; + int index; unsigned int *sgbuffer; sg = &data->sg[i]; @@ -155,15 +166,10 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; amount = min(size, sg->length); size -= amount; + amount /= 4; - if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ - int index; - - for (index = 0; index < (amount / 4); index++) - *dmabuf++ = swab32(sgbuffer[index]); - } - else - memcpy(dmabuf, sgbuffer, amount); + for (index = 0; index < amount; index++) + *dmabuf++ = swab32(sgbuffer[index]); kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); @@ -211,13 +217,13 @@ static void at91mci_pre_dma_read(struct at91mci_host *host) /* Check to see if this needs filling */ if (i == 0) { - if (at91_mci_read(host, AT91_PDC_RCR) != 0) { + if (at91_mci_read(AT91_PDC_RCR) != 0) { pr_debug("Transfer active in current\n"); continue; } } else { - if (at91_mci_read(host, AT91_PDC_RNCR) != 0) { + if (at91_mci_read(AT91_PDC_RNCR) != 0) { pr_debug("Transfer active in next\n"); continue; } @@ -234,12 +240,12 @@ static void at91mci_pre_dma_read(struct at91mci_host *host) pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length); if (i == 0) { - at91_mci_write(host, AT91_PDC_RPR, sg->dma_address); - at91_mci_write(host, AT91_PDC_RCR, sg->length / 4); + at91_mci_write(AT91_PDC_RPR, sg->dma_address); + at91_mci_write(AT91_PDC_RCR, sg->length / 4); } else { - at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address); - at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4); + at91_mci_write(AT91_PDC_RNPR, sg->dma_address); + at91_mci_write(AT91_PDC_RNCR, sg->length / 4); } } @@ -270,6 +276,8 @@ static void at91mci_post_dma_read(struct at91mci_host *host) while (host->in_use_index < host->transfer_index) { unsigned int *buffer; + int index; + int len; struct scatterlist *sg; @@ -287,13 +295,11 @@ static void at91mci_post_dma_read(struct at91mci_host *host) data->bytes_xfered += sg->length; - if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ - int index; + len = sg->length / 4; - for (index = 0; index < (sg->length / 4); index++) - buffer[index] = swab32(buffer[index]); + for (index = 0; index < len; index++) { + buffer[index] = swab32(buffer[index]); } - kunmap_atomic(buffer, KM_BIO_SRC_IRQ); flush_dcache_page(sg->page); } @@ -302,8 +308,8 @@ static void at91mci_post_dma_read(struct at91mci_host *host) if (host->transfer_index < data->sg_len) at91mci_pre_dma_read(host); else { - at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF); - at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); + at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF); + at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); } pr_debug("post dma read done\n"); @@ -320,11 +326,11 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host) pr_debug("Handling the transmit\n"); /* Disable the transfer */ - at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); + at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); /* Now wait for cmd ready */ - at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE); - at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY); + at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE); + at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY); cmd = host->cmd; if (!cmd) return; @@ -338,23 +344,21 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host) /* * Enable the controller */ -static void at91_mci_enable(struct at91mci_host *host) +static void at91_mci_enable(void) { - at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN); - at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); - at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); - at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a); - - /* use Slot A or B (only one at same time) */ - at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b); + at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN); + at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF); + at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); + at91_mci_write(AT91_MCI_MR, 0x834A); + at91_mci_write(AT91_MCI_SDCR, 0x0); } /* * Disable the controller */ -static void at91_mci_disable(struct at91mci_host *host) +static void at91_mci_disable(void) { - at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST); + at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST); } /* @@ -374,13 +378,13 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ /* Not sure if this is needed */ #if 0 - if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { + if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { pr_debug("Clearing timeout\n"); - at91_mci_write(host, AT91_MCI_ARGR, 0); - at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD); - while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) { + at91_mci_write(AT91_MCI_ARGR, 0); + at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD); + while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) { /* spin */ - pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR)); + pr_debug("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR)); } } #endif @@ -427,32 +431,32 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ /* * Set the arguments and send the command */ - pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n", - cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR)); + pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n", + cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR)); if (!data) { - at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS); - at91_mci_write(host, AT91_PDC_RPR, 0); - at91_mci_write(host, AT91_PDC_RCR, 0); - at91_mci_write(host, AT91_PDC_RNPR, 0); - at91_mci_write(host, AT91_PDC_RNCR, 0); - at91_mci_write(host, AT91_PDC_TPR, 0); - at91_mci_write(host, AT91_PDC_TCR, 0); - at91_mci_write(host, AT91_PDC_TNPR, 0); - at91_mci_write(host, AT91_PDC_TNCR, 0); - - at91_mci_write(host, AT91_MCI_ARGR, cmd->arg); - at91_mci_write(host, AT91_MCI_CMDR, cmdr); + at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS); + at91_mci_write(AT91_PDC_RPR, 0); + at91_mci_write(AT91_PDC_RCR, 0); + at91_mci_write(AT91_PDC_RNPR, 0); + at91_mci_write(AT91_PDC_RNCR, 0); + at91_mci_write(AT91_PDC_TPR, 0); + at91_mci_write(AT91_PDC_TCR, 0); + at91_mci_write(AT91_PDC_TNPR, 0); + at91_mci_write(AT91_PDC_TNCR, 0); + + at91_mci_write(AT91_MCI_ARGR, cmd->arg); + at91_mci_write(AT91_MCI_CMDR, cmdr); return AT91_MCI_CMDRDY; } - mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */ - at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE); + mr = at91_mci_read(AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */ + at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE); /* * Disable the PDC controller */ - at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); + at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); if (cmdr & AT91_MCI_TRCMD_START) { data->bytes_xfered = 0; @@ -481,8 +485,8 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ pr_debug("Transmitting %d bytes\n", host->total_length); - at91_mci_write(host, AT91_PDC_TPR, host->physical_address); - at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4); + at91_mci_write(AT91_PDC_TPR, host->physical_address); + at91_mci_write(AT91_PDC_TCR, host->total_length / 4); ier = AT91_MCI_TXBUFE; } } @@ -492,14 +496,14 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ * the data sheet says */ - at91_mci_write(host, AT91_MCI_ARGR, cmd->arg); - at91_mci_write(host, AT91_MCI_CMDR, cmdr); + at91_mci_write(AT91_MCI_ARGR, cmd->arg); + at91_mci_write(AT91_MCI_CMDR, cmdr); if (cmdr & AT91_MCI_TRCMD_START) { if (cmdr & AT91_MCI_TRDIR) - at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN); + at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN); else - at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN); + at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN); } return ier; } @@ -516,7 +520,7 @@ static void at91mci_process_command(struct at91mci_host *host, struct mmc_comman pr_debug("setting ier to %08X\n", ier); /* Stop on errors or the required value */ - at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier); + at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier); } /* @@ -544,19 +548,19 @@ static void at91mci_completed_command(struct at91mci_host *host) struct mmc_command *cmd = host->cmd; unsigned int status; - at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); + at91_mci_write(AT91_MCI_IDR, 0xffffffff); - cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0)); - cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1)); - cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2)); - cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3)); + cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0)); + cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1)); + cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2)); + cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3)); if (host->buffer) { dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address); host->buffer = NULL; } - status = at91_mci_read(host, AT91_MCI_SR); + status = at91_mci_read(AT91_MCI_SR); pr_debug("Status = %08X [%08X %08X %08X %08X]\n", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); @@ -607,18 +611,18 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { int clkdiv; struct at91mci_host *host = mmc_priv(mmc); - unsigned long at91_master_clock = clk_get_rate(host->mci_clk); + unsigned long at91_master_clock = clk_get_rate(mci_clk); host->bus_mode = ios->bus_mode; if (ios->clock == 0) { /* Disable the MCI controller */ - at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS); + at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS); clkdiv = 0; } else { /* Enable the MCI controller */ - at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN); + at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN); if ((at91_master_clock % (ios->clock * 2)) == 0) clkdiv = ((at91_master_clock / ios->clock) / 2) - 1; @@ -630,25 +634,25 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) { pr_debug("MMC: Setting controller bus width to 4\n"); - at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS); + at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS); } else { pr_debug("MMC: Setting controller bus width to 1\n"); - at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); + at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); } /* Set the clock divider */ - at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv); + at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv); /* maybe switch power to the card */ if (host->board->vcc_pin) { switch (ios->power_mode) { case MMC_POWER_OFF: - at91_set_gpio_value(host->board->vcc_pin, 0); + at91_set_gpio_output(host->board->vcc_pin, 0); break; case MMC_POWER_UP: case MMC_POWER_ON: - at91_set_gpio_value(host->board->vcc_pin, 1); + at91_set_gpio_output(host->board->vcc_pin, 1); break; } } @@ -661,40 +665,39 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) { struct at91mci_host *host = devid; int completed = 0; - unsigned int int_status, int_mask; - int_status = at91_mci_read(host, AT91_MCI_SR); - int_mask = at91_mci_read(host, AT91_MCI_IMR); - - pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask, - int_status & int_mask); - - int_status = int_status & int_mask; + unsigned int int_status; - if (int_status & AT91_MCI_ERRORS) { + int_status = at91_mci_read(AT91_MCI_SR); + pr_debug("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR), + int_status & at91_mci_read(AT91_MCI_IMR)); + + if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000) completed = 1; - - if (int_status & AT91_MCI_UNRE) - pr_debug("MMC: Underrun error\n"); - if (int_status & AT91_MCI_OVRE) - pr_debug("MMC: Overrun error\n"); - if (int_status & AT91_MCI_DTOE) - pr_debug("MMC: Data timeout\n"); - if (int_status & AT91_MCI_DCRCE) - pr_debug("MMC: CRC error in data\n"); - if (int_status & AT91_MCI_RTOE) - pr_debug("MMC: Response timeout\n"); - if (int_status & AT91_MCI_RENDE) - pr_debug("MMC: Response end bit error\n"); - if (int_status & AT91_MCI_RCRCE) - pr_debug("MMC: Response CRC error\n"); - if (int_status & AT91_MCI_RDIRE) - pr_debug("MMC: Response direction error\n"); - if (int_status & AT91_MCI_RINDE) - pr_debug("MMC: Response index error\n"); - } else { - /* Only continue processing if no errors */ + int_status &= at91_mci_read(AT91_MCI_IMR); + + if (int_status & AT91_MCI_UNRE) + pr_debug("MMC: Underrun error\n"); + if (int_status & AT91_MCI_OVRE) + pr_debug("MMC: Overrun error\n"); + if (int_status & AT91_MCI_DTOE) + pr_debug("MMC: Data timeout\n"); + if (int_status & AT91_MCI_DCRCE) + pr_debug("MMC: CRC error in data\n"); + if (int_status & AT91_MCI_RTOE) + pr_debug("MMC: Response timeout\n"); + if (int_status & AT91_MCI_RENDE) + pr_debug("MMC: Response end bit error\n"); + if (int_status & AT91_MCI_RCRCE) + pr_debug("MMC: Response CRC error\n"); + if (int_status & AT91_MCI_RDIRE) + pr_debug("MMC: Response direction error\n"); + if (int_status & AT91_MCI_RINDE) + pr_debug("MMC: Response index error\n"); + + /* Only continue processing if no errors */ + if (!completed) { if (int_status & AT91_MCI_TXBUFE) { pr_debug("TX buffer empty\n"); at91_mci_handle_transmitted(host); @@ -702,11 +705,12 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) if (int_status & AT91_MCI_RXBUFF) { pr_debug("RX buffer full\n"); - at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY); + at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); } - if (int_status & AT91_MCI_ENDTX) + if (int_status & AT91_MCI_ENDTX) { pr_debug("Transmit has ended\n"); + } if (int_status & AT91_MCI_ENDRX) { pr_debug("Receive has ended\n"); @@ -715,33 +719,37 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) if (int_status & AT91_MCI_NOTBUSY) { pr_debug("Card is ready\n"); - at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY); + at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); } - if (int_status & AT91_MCI_DTIP) + if (int_status & AT91_MCI_DTIP) { pr_debug("Data transfer in progress\n"); + } - if (int_status & AT91_MCI_BLKE) + if (int_status & AT91_MCI_BLKE) { pr_debug("Block transfer has ended\n"); + } - if (int_status & AT91_MCI_TXRDY) + if (int_status & AT91_MCI_TXRDY) { pr_debug("Ready to transmit\n"); + } - if (int_status & AT91_MCI_RXRDY) + if (int_status & AT91_MCI_RXRDY) { pr_debug("Ready to receive\n"); + } if (int_status & AT91_MCI_CMDRDY) { pr_debug("Command ready\n"); completed = 1; } } + at91_mci_write(AT91_MCI_IDR, int_status); if (completed) { pr_debug("Completed command\n"); - at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); + at91_mci_write(AT91_MCI_IDR, 0xffffffff); at91mci_completed_command(host); - } else - at91_mci_write(host, AT91_MCI_IDR, int_status); + } return IRQ_HANDLED; } @@ -761,7 +769,7 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host) present ? "insert" : "remove"); if (!present) { pr_debug("****** Resetting SD-card bus width ******\n"); - at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); + at91_mci_write(AT91_MCI_SDCR, 0); } mmc_detect_change(host->mmc, msecs_to_jiffies(100)); } @@ -798,22 +806,15 @@ static int at91_mci_probe(struct platform_device *pdev) { struct mmc_host *mmc; struct at91mci_host *host; - struct resource *res; int ret; pr_debug("Probe MCI devices\n"); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME)) - return -EBUSY; + at91_mci_disable(); + at91_mci_enable(); mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); if (!mmc) { pr_debug("Failed to allocate mmc host\n"); - release_mem_region(res->start, res->end - res->start + 1); return -ENOMEM; } @@ -832,51 +833,30 @@ static int at91_mci_probe(struct platform_device *pdev) #ifdef SUPPORT_4WIRE mmc->caps |= MMC_CAP_4_BIT_DATA; #else - printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n"); + printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n"); #endif } /* * Get Clock */ - host->mci_clk = clk_get(&pdev->dev, "mci_clk"); - if (IS_ERR(host->mci_clk)) { + mci_clk = clk_get(&pdev->dev, "mci_clk"); + if (IS_ERR(mci_clk)) { printk(KERN_ERR "AT91 MMC: no clock defined.\n"); mmc_free_host(mmc); - release_mem_region(res->start, res->end - res->start + 1); return -ENODEV; } - - /* - * Map I/O region - */ - host->baseaddr = ioremap(res->start, res->end - res->start + 1); - if (!host->baseaddr) { - clk_put(host->mci_clk); - mmc_free_host(mmc); - release_mem_region(res->start, res->end - res->start + 1); - return -ENOMEM; - } - - /* - * Reset hardware - */ - clk_enable(host->mci_clk); /* Enable the peripheral clock */ - at91_mci_disable(host); - at91_mci_enable(host); + clk_enable(mci_clk); /* Enable the peripheral clock */ /* * Allocate the MCI interrupt */ - host->irq = platform_get_irq(pdev, 0); - ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host); + ret = request_irq(AT91RM9200_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host); if (ret) { - printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n"); - clk_disable(host->mci_clk); - clk_put(host->mci_clk); + printk(KERN_ERR "Failed to request MCI interrupt\n"); + clk_disable(mci_clk); + clk_put(mci_clk); mmc_free_host(mmc); - iounmap(host->baseaddr); - release_mem_region(res->start, res->end - res->start + 1); return ret; } @@ -899,10 +879,10 @@ static int at91_mci_probe(struct platform_device *pdev) ret = request_irq(host->board->det_pin, at91_mmc_det_irq, 0, DRIVER_NAME, host); if (ret) - printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n"); + printk(KERN_ERR "couldn't allocate MMC detect irq\n"); } - pr_debug("Added MCI driver\n"); + pr_debug(KERN_INFO "Added MCI driver\n"); return 0; } @@ -914,7 +894,6 @@ static int at91_mci_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct at91mci_host *host; - struct resource *res; if (!mmc) return -1; @@ -926,19 +905,16 @@ static int at91_mci_remove(struct platform_device *pdev) cancel_delayed_work(&host->mmc->detect); } - at91_mci_disable(host); mmc_remove_host(mmc); - free_irq(host->irq, host); - - clk_disable(host->mci_clk); /* Disable the peripheral clock */ - clk_put(host->mci_clk); + at91_mci_disable(); + free_irq(AT91RM9200_ID_MCI, host); + mmc_free_host(mmc); - iounmap(host->baseaddr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start + 1); + clk_disable(mci_clk); /* Disable the peripheral clock */ + clk_put(mci_clk); - mmc_free_host(mmc); platform_set_drvdata(pdev, NULL); + pr_debug("MCI Removed\n"); return 0; diff --git a/trunk/drivers/mmc/mmc_queue.c b/trunk/drivers/mmc/mmc_queue.c index 3e35a43819fb..a17423a4ed8f 100644 --- a/trunk/drivers/mmc/mmc_queue.c +++ b/trunk/drivers/mmc/mmc_queue.c @@ -78,10 +78,8 @@ static int mmc_queue_thread(void *d) spin_unlock_irq(q->queue_lock); if (!req) { - if (kthread_should_stop()) { - set_current_state(TASK_RUNNING); + if (kthread_should_stop()) break; - } up(&mq->thread_sem); schedule(); down(&mq->thread_sem); diff --git a/trunk/drivers/mmc/sdhci.c b/trunk/drivers/mmc/sdhci.c index c2d13d7e9911..cd98117632d3 100644 --- a/trunk/drivers/mmc/sdhci.c +++ b/trunk/drivers/mmc/sdhci.c @@ -1170,8 +1170,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) } if (pci_resource_len(pdev, first_bar + slot) != 0x100) { - printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. " - "You may experience problems.\n"); + printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n"); + return -ENODEV; } if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { diff --git a/trunk/drivers/mtd/devices/mtd_dataflash.c b/trunk/drivers/mtd/devices/mtd_dataflash.c index 0a7e86859bf1..5db716045927 100644 --- a/trunk/drivers/mtd/devices/mtd_dataflash.c +++ b/trunk/drivers/mtd/devices/mtd_dataflash.c @@ -459,7 +459,7 @@ add_dataflash(struct spi_device *spi, char *name, struct mtd_info *device; struct flash_platform_data *pdata = spi->dev.platform_data; - priv = kzalloc(sizeof *priv, GFP_KERNEL); + priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/trunk/drivers/mtd/rfd_ftl.c b/trunk/drivers/mtd/rfd_ftl.c index 0f3baa5d9c2a..fa4362fb4dd8 100644 --- a/trunk/drivers/mtd/rfd_ftl.c +++ b/trunk/drivers/mtd/rfd_ftl.c @@ -768,7 +768,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) if (mtd->type != MTD_NORFLASH) return; - part = kzalloc(sizeof(struct partition), GFP_KERNEL); + part = kcalloc(1, sizeof(struct partition), GFP_KERNEL); if (!part) return; diff --git a/trunk/drivers/net/8139too.c b/trunk/drivers/net/8139too.c index 35ad5cff18e6..931028f672de 100644 --- a/trunk/drivers/net/8139too.c +++ b/trunk/drivers/net/8139too.c @@ -2131,15 +2131,14 @@ static int rtl8139_poll(struct net_device *dev, int *budget) } if (done) { - unsigned long flags; /* * Order is important since data can get interrupted * again when we think we are done. */ - local_irq_save(flags); + local_irq_disable(); RTL_W16_F(IntrMask, rtl8139_intr_mask); __netif_rx_complete(dev); - local_irq_restore(flags); + local_irq_enable(); } spin_unlock(&tp->rx_lock); diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 8aa8dd02b910..9de0eed6755b 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -2384,14 +2384,6 @@ config CHELSIO_T1_1G Enables support for Chelsio's gigabit Ethernet PCI cards. If you are using only 10G cards say 'N' here. -config CHELSIO_T1_NAPI - bool "Use Rx Polling (NAPI)" - depends on CHELSIO_T1 - default y - help - NAPI is a driver API designed to reduce CPU and interrupt load - when the driver is receiving lots of packets from the card. - config EHEA tristate "eHEA Ethernet support" depends on IBMEBUS diff --git a/trunk/drivers/net/appletalk/ipddp.c b/trunk/drivers/net/appletalk/ipddp.c index f22e46dfd770..b98592a8bac8 100644 --- a/trunk/drivers/net/appletalk/ipddp.c +++ b/trunk/drivers/net/appletalk/ipddp.c @@ -186,7 +186,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) */ static int ipddp_create(struct ipddp_route *new_rt) { - struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL); + struct ipddp_route *rt =(struct ipddp_route*) kmalloc(sizeof(*rt), GFP_KERNEL); if (rt == NULL) return -ENOMEM; diff --git a/trunk/drivers/net/bsd_comp.c b/trunk/drivers/net/bsd_comp.c index 7845eaf6f29f..bae1de1e7802 100644 --- a/trunk/drivers/net/bsd_comp.c +++ b/trunk/drivers/net/bsd_comp.c @@ -395,7 +395,7 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp) * Allocate the main control structure for this instance. */ maxmaxcode = MAXCODE(bits); - db = kmalloc(sizeof (struct bsd_db), + db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db), GFP_KERNEL); if (!db) { diff --git a/trunk/drivers/net/chelsio/cxgb2.c b/trunk/drivers/net/chelsio/cxgb2.c index fd5d821f3f2a..de48eadddbc4 100644 --- a/trunk/drivers/net/chelsio/cxgb2.c +++ b/trunk/drivers/net/chelsio/cxgb2.c @@ -220,8 +220,9 @@ static int cxgb_up(struct adapter *adapter) t1_interrupts_clear(adapter); - adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev); - err = request_irq(adapter->pdev->irq, t1_interrupt, + adapter->params.has_msi = !disable_msi && pci_enable_msi(adapter->pdev) == 0; + err = request_irq(adapter->pdev->irq, + t1_select_intr_handler(adapter), adapter->params.has_msi ? 0 : IRQF_SHARED, adapter->name, adapter); if (err) { @@ -763,7 +764,18 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) { struct adapter *adapter = dev->priv; - adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs; + /* + * If RX coalescing is requested we use NAPI, otherwise interrupts. + * This choice can be made only when all ports and the TOE are off. + */ + if (adapter->open_device_map == 0) + adapter->params.sge.polling = c->use_adaptive_rx_coalesce; + + if (adapter->params.sge.polling) { + adapter->params.sge.rx_coalesce_usecs = 0; + } else { + adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs; + } adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce; adapter->params.sge.sample_interval_usecs = c->rate_sample_interval; t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge); @@ -932,7 +944,7 @@ static void t1_netpoll(struct net_device *dev) struct adapter *adapter = dev->priv; local_irq_save(flags); - t1_interrupt(adapter->pdev->irq, adapter); + t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter); local_irq_restore(flags); } #endif @@ -1153,10 +1165,7 @@ static int __devinit init_one(struct pci_dev *pdev, #ifdef CONFIG_NET_POLL_CONTROLLER netdev->poll_controller = t1_netpoll; #endif -#ifdef CONFIG_CHELSIO_T1_NAPI netdev->weight = 64; - netdev->poll = t1_poll; -#endif SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops); } diff --git a/trunk/drivers/net/chelsio/sge.c b/trunk/drivers/net/chelsio/sge.c index 659cb2252e44..0ca8d876e16f 100644 --- a/trunk/drivers/net/chelsio/sge.c +++ b/trunk/drivers/net/chelsio/sge.c @@ -1413,20 +1413,16 @@ static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) if (unlikely(adapter->vlan_grp && p->vlan_valid)) { st->vlan_xtract++; -#ifdef CONFIG_CHELSIO_T1_NAPI + if (adapter->params.sge.polling) vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, ntohs(p->vlan)); -#else + else vlan_hwaccel_rx(skb, adapter->vlan_grp, ntohs(p->vlan)); -#endif - } else { -#ifdef CONFIG_CHELSIO_T1_NAPI + } else if (adapter->params.sge.polling) netif_receive_skb(skb); -#else + else netif_rx(skb); -#endif - } return 0; } @@ -1576,7 +1572,6 @@ static int process_responses(struct adapter *adapter, int budget) return budget; } -#ifdef CONFIG_CHELSIO_T1_NAPI /* * A simpler version of process_responses() that handles only pure (i.e., * non data-carrying) responses. Such respones are too light-weight to justify @@ -1624,76 +1619,92 @@ static int process_pure_responses(struct adapter *adapter, struct respQ_e *e) * or protection from interrupts as data interrupts are off at this point and * other adapter interrupts do not interfere. */ -int t1_poll(struct net_device *dev, int *budget) +static int t1_poll(struct net_device *dev, int *budget) { struct adapter *adapter = dev->priv; int effective_budget = min(*budget, dev->quota); - int work_done = process_responses(adapter, effective_budget); + int work_done = process_responses(adapter, effective_budget); *budget -= work_done; dev->quota -= work_done; if (work_done >= effective_budget) return 1; - spin_lock_irq(&adapter->async_lock); __netif_rx_complete(dev); - writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); - writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA, - adapter->regs + A_PL_ENABLE); - spin_unlock_irq(&adapter->async_lock); + /* + * Because we don't atomically flush the following write it is + * possible that in very rare cases it can reach the device in a way + * that races with a new response being written plus an error interrupt + * causing the NAPI interrupt handler below to return unhandled status + * to the OS. To protect against this would require flushing the write + * and doing both the write and the flush with interrupts off. Way too + * expensive and unjustifiable given the rarity of the race. + */ + writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); return 0; } +/* + * Returns true if the device is already scheduled for polling. + */ +static inline int napi_is_scheduled(struct net_device *dev) +{ + return test_bit(__LINK_STATE_RX_SCHED, &dev->state); +} + /* * NAPI version of the main interrupt handler. */ -irqreturn_t t1_interrupt(int irq, void *data) +static irqreturn_t t1_interrupt_napi(int irq, void *data) { + int handled; struct adapter *adapter = data; - struct net_device *dev = adapter->sge->netdev; struct sge *sge = adapter->sge; - u32 cause; - int handled = 0; + struct respQ *q = &adapter->sge->respQ; - cause = readl(adapter->regs + A_PL_CAUSE); - if (cause == 0 || cause == ~0) - return IRQ_NONE; + /* + * Clear the SGE_DATA interrupt first thing. Normally the NAPI + * handler has control of the response queue and the interrupt handler + * can look at the queue reliably only once it knows NAPI is off. + * We can't wait that long to clear the SGE_DATA interrupt because we + * could race with t1_poll rearming the SGE interrupt, so we need to + * clear the interrupt speculatively and really early on. + */ + writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE); spin_lock(&adapter->async_lock); - if (cause & F_PL_INTR_SGE_DATA) { - struct respQ *q = &adapter->sge->respQ; + if (!napi_is_scheduled(sge->netdev)) { struct respQ_e *e = &q->entries[q->cidx]; - handled = 1; - writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE); - - if (e->GenerationBit == q->genbit && - __netif_rx_schedule_prep(dev)) { - if (e->DataValid || process_pure_responses(adapter, e)) { - /* mask off data IRQ */ - writel(adapter->slow_intr_mask, - adapter->regs + A_PL_ENABLE); - __netif_rx_schedule(sge->netdev); - goto unlock; - } - /* no data, no NAPI needed */ - netif_poll_enable(dev); - - } - writel(q->cidx, adapter->regs + A_SG_SLEEPING); - } else - handled = t1_slow_intr_handler(adapter); - + if (e->GenerationBit == q->genbit) { + if (e->DataValid || + process_pure_responses(adapter, e)) { + if (likely(__netif_rx_schedule_prep(sge->netdev))) + __netif_rx_schedule(sge->netdev); + else if (net_ratelimit()) + printk(KERN_INFO + "NAPI schedule failure!\n"); + } else + writel(q->cidx, adapter->regs + A_SG_SLEEPING); + + handled = 1; + goto unlock; + } else + writel(q->cidx, adapter->regs + A_SG_SLEEPING); + } else if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA) { + printk(KERN_ERR "data interrupt while NAPI running\n"); + } + + handled = t1_slow_intr_handler(adapter); if (!handled) sge->stats.unhandled_irqs++; -unlock: + unlock: spin_unlock(&adapter->async_lock); return IRQ_RETVAL(handled != 0); } -#else /* * Main interrupt handler, optimized assuming that we took a 'DATA' * interrupt. @@ -1709,7 +1720,7 @@ irqreturn_t t1_interrupt(int irq, void *data) * 5. If we took an interrupt, but no valid respQ descriptors was found we * let the slow_intr_handler run and do error handling. */ -irqreturn_t t1_interrupt(int irq, void *cookie) +static irqreturn_t t1_interrupt(int irq, void *cookie) { int work_done; struct respQ_e *e; @@ -1741,7 +1752,11 @@ irqreturn_t t1_interrupt(int irq, void *cookie) spin_unlock(&adapter->async_lock); return IRQ_RETVAL(work_done != 0); } -#endif + +irq_handler_t t1_select_intr_handler(adapter_t *adapter) +{ + return adapter->params.sge.polling ? t1_interrupt_napi : t1_interrupt; +} /* * Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it. @@ -2018,6 +2033,7 @@ static void sge_tx_reclaim_cb(unsigned long data) */ int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p) { + sge->netdev->poll = t1_poll; sge->fixed_intrtimer = p->rx_coalesce_usecs * core_ticks_per_usec(sge->adapter); writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER); @@ -2218,6 +2234,7 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, p->coalesce_enable = 0; p->sample_interval_usecs = 0; + p->polling = 0; return sge; nomem_port: diff --git a/trunk/drivers/net/chelsio/sge.h b/trunk/drivers/net/chelsio/sge.h index d132a0ef2a22..7ceb0117d039 100644 --- a/trunk/drivers/net/chelsio/sge.h +++ b/trunk/drivers/net/chelsio/sge.h @@ -76,9 +76,7 @@ struct sge *t1_sge_create(struct adapter *, struct sge_params *); int t1_sge_configure(struct sge *, struct sge_params *); int t1_sge_set_coalesce_params(struct sge *, struct sge_params *); void t1_sge_destroy(struct sge *); -irqreturn_t t1_interrupt(int irq, void *cookie); -int t1_poll(struct net_device *, int *); - +irq_handler_t t1_select_intr_handler(adapter_t *adapter); int t1_start_xmit(struct sk_buff *skb, struct net_device *dev); void t1_set_vlan_accel(struct adapter *adapter, int on_off); void t1_sge_start(struct sge *); diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c index c2ae2a24629b..03bf164f9e8d 100644 --- a/trunk/drivers/net/e100.c +++ b/trunk/drivers/net/e100.c @@ -1930,8 +1930,9 @@ static int e100_rx_alloc_list(struct nic *nic) nic->rx_to_use = nic->rx_to_clean = NULL; nic->ru_running = RU_UNINITIALIZED; - if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) + if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC))) return -ENOMEM; + memset(nic->rxs, 0, sizeof(struct rx) * count); for(rx = nic->rxs, i = 0; i < count; rx++, i++) { rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; diff --git a/trunk/drivers/net/hamradio/baycom_epp.c b/trunk/drivers/net/hamradio/baycom_epp.c index 153b6dc80af4..8a83db0fb3b7 100644 --- a/trunk/drivers/net/hamradio/baycom_epp.c +++ b/trunk/drivers/net/hamradio/baycom_epp.c @@ -1177,7 +1177,7 @@ static void baycom_probe(struct net_device *dev) dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */ dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); - memcpy(dev->dev_addr, &null_ax25_address, AX25_ADDR_LEN); + memcpy(dev->dev_addr, &ax25_nocall, AX25_ADDR_LEN); dev->tx_queue_len = 16; /* New style flags */ diff --git a/trunk/drivers/net/irda/donauboe.c b/trunk/drivers/net/irda/donauboe.c index 11af0ae7510e..16620bd97fbf 100644 --- a/trunk/drivers/net/irda/donauboe.c +++ b/trunk/drivers/net/irda/donauboe.c @@ -1603,7 +1603,7 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid) irda_qos_bits_to_value (&self->qos); /* Allocate twice the size to guarantee alignment */ - self->ringbuf = kmalloc(OBOE_RING_LEN << 1, GFP_KERNEL); + self->ringbuf = (void *) kmalloc (OBOE_RING_LEN << 1, GFP_KERNEL); if (!self->ringbuf) { printk (KERN_ERR DRIVER_NAME ": can't allocate DMA buffers\n"); diff --git a/trunk/drivers/net/irda/irda-usb.c b/trunk/drivers/net/irda/irda-usb.c index 3ca1082ec776..6e95645e7245 100644 --- a/trunk/drivers/net/irda/irda-usb.c +++ b/trunk/drivers/net/irda/irda-usb.c @@ -1747,7 +1747,7 @@ static int irda_usb_probe(struct usb_interface *intf, /* Don't change this buffer size and allocation without doing * some heavy and complete testing. Don't ask why :-( * Jean II */ - self->speed_buff = kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); + self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); if (self->speed_buff == NULL) goto err_out_3; diff --git a/trunk/drivers/net/irda/irport.c b/trunk/drivers/net/irda/irport.c index 3098960dc2a1..654a68b490ae 100644 --- a/trunk/drivers/net/irda/irport.c +++ b/trunk/drivers/net/irda/irport.c @@ -164,7 +164,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq) /* Allocate memory if needed */ if (self->tx_buff.truesize > 0) { - self->tx_buff.head = kmalloc(self->tx_buff.truesize, + self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, GFP_KERNEL); if (self->tx_buff.head == NULL) { IRDA_ERROR("%s(), can't allocate memory for " diff --git a/trunk/drivers/net/lp486e.c b/trunk/drivers/net/lp486e.c index 177c502f7385..b833016f1825 100644 --- a/trunk/drivers/net/lp486e.c +++ b/trunk/drivers/net/lp486e.c @@ -884,7 +884,7 @@ static int i596_start_xmit (struct sk_buff *skb, struct net_device *dev) { dev->trans_start = jiffies; - tx_cmd = kmalloc((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC); + tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC); if (tx_cmd == NULL) { printk(KERN_WARNING "%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name); lp->stats.tx_dropped++; @@ -1266,7 +1266,7 @@ static void set_multicast_list(struct net_device *dev) { if (dev->mc_count > 0) { struct dev_mc_list *dmi; char *cp; - cmd = kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC); + cmd = (struct i596_cmd *)kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC); if (cmd == NULL) { printk (KERN_ERR "%s: set_multicast Memory squeeze.\n", dev->name); return; diff --git a/trunk/drivers/net/macb.c b/trunk/drivers/net/macb.c index 25b559b5d5ed..bd0ce98c939c 100644 --- a/trunk/drivers/net/macb.c +++ b/trunk/drivers/net/macb.c @@ -264,12 +264,12 @@ static void macb_update_stats(struct macb *bp) WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); for(; p < end; p++, reg++) - *p += __raw_readl(reg); + *p += readl(reg); } -static void macb_periodic_task(struct work_struct *work) +static void macb_periodic_task(void *arg) { - struct macb *bp = container_of(work, struct macb, periodic_task.work); + struct macb *bp = arg; macb_update_stats(bp); macb_check_media(bp, 1, 0); @@ -1088,7 +1088,7 @@ static int __devinit macb_probe(struct platform_device *pdev) dev->base_addr = regs->start; - INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task); + INIT_WORK(&bp->periodic_task, macb_periodic_task, bp); mutex_init(&bp->mdio_mutex); init_completion(&bp->mdio_complete); diff --git a/trunk/drivers/net/macb.h b/trunk/drivers/net/macb.h index 27bf0ae0f0bb..8c253db69881 100644 --- a/trunk/drivers/net/macb.h +++ b/trunk/drivers/net/macb.h @@ -250,9 +250,9 @@ /* Register access macros */ #define macb_readl(port,reg) \ - __raw_readl((port)->regs + MACB_##reg) + readl((port)->regs + MACB_##reg) #define macb_writel(port,reg,value) \ - __raw_writel((value), (port)->regs + MACB_##reg) + writel((value), (port)->regs + MACB_##reg) struct dma_desc { u32 addr; @@ -377,7 +377,7 @@ struct macb { unsigned int rx_pending, tx_pending; - struct delayed_work periodic_task; + struct work_struct periodic_task; struct mutex mdio_mutex; struct completion mdio_complete; diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 94ac168be593..81f127a78afa 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -71,7 +71,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.1.0" +#define MYRI10GE_VERSION_STR "1.0.0" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -92,13 +92,8 @@ MODULE_LICENSE("Dual BSD/GPL"); #define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff) #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff -#define MYRI10GE_ALLOC_ORDER 0 -#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE) -#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1) - struct myri10ge_rx_buffer_state { - struct page *page; - int page_offset; + struct sk_buff *skb; DECLARE_PCI_UNMAP_ADDR(bus) DECLARE_PCI_UNMAP_LEN(len) }; @@ -121,14 +116,9 @@ struct myri10ge_rx_buf { u8 __iomem *wc_fifo; /* w/c rx dma addr fifo address */ struct mcp_kreq_ether_recv *shadow; /* host shadow of recv ring */ struct myri10ge_rx_buffer_state *info; - struct page *page; - dma_addr_t bus; - int page_offset; int cnt; - int fill_cnt; int alloc_fail; int mask; /* number of rx slots -1 */ - int watchdog_needed; }; struct myri10ge_tx_buf { @@ -160,7 +150,6 @@ struct myri10ge_priv { struct myri10ge_rx_buf rx_big; struct myri10ge_rx_done rx_done; int small_bytes; - int big_bytes; struct net_device *dev; struct net_device_stats stats; u8 __iomem *sram; @@ -249,6 +238,11 @@ module_param(myri10ge_force_firmware, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_force_firmware, "Force firmware to assume aligned completions\n"); +static int myri10ge_skb_cross_4k = 0; +module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_skb_cross_4k, + "Can a small skb cross a 4KB boundary?\n"); + static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; module_param(myri10ge_initial_mtu, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n"); @@ -272,10 +266,6 @@ static int myri10ge_debug = -1; /* defaults above */ module_param(myri10ge_debug, int, 0); MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); -static int myri10ge_fill_thresh = 256; -module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n"); - #define MYRI10GE_FW_OFFSET 1024*1024 #define MYRI10GE_HIGHPART_TO_U32(X) \ (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0) @@ -283,9 +273,9 @@ MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n"); #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) -static inline void put_be32(__be32 val, __be32 __iomem * p) +static inline void put_be32(__be32 val, __be32 __iomem *p) { - __raw_writel((__force __u32) val, (__force void __iomem *)p); + __raw_writel((__force __u32)val, (__force void __iomem *)p); } static int @@ -814,179 +804,194 @@ myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst, mb(); } -static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum) +/* + * Set of routines to get a new receive buffer. Any buffer which + * crosses a 4KB boundary must start on a 4KB boundary due to PCIe + * wdma restrictions. We also try to align any smaller allocation to + * at least a 16 byte boundary for efficiency. We assume the linux + * memory allocator works by powers of 2, and will not return memory + * smaller than 2KB which crosses a 4KB boundary. If it does, we fall + * back to allocating 2x as much space as required. + * + * We intend to replace large (>4KB) skb allocations by using + * pages directly and building a fraglist in the near future. + */ + +static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev, + int bytes) { - struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); + struct sk_buff *skb; + unsigned long data, roundup; - if ((skb->protocol == htons(ETH_P_8021Q)) && - (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || - vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { - skb->csum = hw_csum; - skb->ip_summed = CHECKSUM_COMPLETE; - } + skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD); + if (skb == NULL) + return NULL; + + /* Correct skb->truesize so that socket buffer + * accounting is not confused the rounding we must + * do to satisfy alignment constraints. + */ + skb->truesize -= 4096; + + data = (unsigned long)(skb->data); + roundup = (-data) & (4095); + skb_reserve(skb, roundup); + return skb; } -static inline void -myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va, - struct skb_frag_struct *rx_frags, int len, int hlen) +/* Allocate 2x as much space as required and use whichever portion + * does not cross a 4KB boundary */ +static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev, + unsigned int bytes) { - struct skb_frag_struct *skb_frags; - - skb->len = skb->data_len = len; - skb->truesize = len + sizeof(struct sk_buff); - /* attach the page(s) */ - - skb_frags = skb_shinfo(skb)->frags; - while (len > 0) { - memcpy(skb_frags, rx_frags, sizeof(*skb_frags)); - len -= rx_frags->size; - skb_frags++; - rx_frags++; - skb_shinfo(skb)->nr_frags++; - } - - /* pskb_may_pull is not available in irq context, but - * skb_pull() (for ether_pad and eth_type_trans()) requires - * the beginning of the packet in skb_headlen(), move it - * manually */ - memcpy(skb->data, va, hlen); - skb_shinfo(skb)->frags[0].page_offset += hlen; - skb_shinfo(skb)->frags[0].size -= hlen; - skb->data_len -= hlen; - skb->tail += hlen; - skb_pull(skb, MXGEFW_PAD); + struct sk_buff *skb; + unsigned long data, boundary; + + skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1); + if (unlikely(skb == NULL)) + return NULL; + + /* Correct skb->truesize so that socket buffer + * accounting is not confused the rounding we must + * do to satisfy alignment constraints. + */ + skb->truesize -= bytes + MXGEFW_PAD; + + data = (unsigned long)(skb->data); + boundary = (data + 4095UL) & ~4095UL; + if ((boundary - data) >= (bytes + MXGEFW_PAD)) + return skb; + + skb_reserve(skb, boundary - data); + return skb; } -static void -myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, - int bytes, int watchdog) +/* Allocate just enough space, and verify that the allocated + * space does not cross a 4KB boundary */ +static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev, + int bytes) { - struct page *page; - int idx; + struct sk_buff *skb; + unsigned long roundup, data, end; + + skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD); + if (unlikely(skb == NULL)) + return NULL; + + /* Round allocated buffer to 16 byte boundary */ + data = (unsigned long)(skb->data); + roundup = (-data) & 15UL; + skb_reserve(skb, roundup); + /* Verify that the data buffer does not cross a page boundary */ + data = (unsigned long)(skb->data); + end = data + bytes + MXGEFW_PAD - 1; + if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) { + printk(KERN_NOTICE + "myri10ge_alloc_small: small skb crossed 4KB boundary\n"); + myri10ge_skb_cross_4k = 1; + dev_kfree_skb_any(skb); + skb = myri10ge_alloc_small_safe(dev, bytes); + } + return skb; +} - if (unlikely(rx->watchdog_needed && !watchdog)) - return; +static inline int +myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp, + int bytes, int idx) +{ + struct net_device *dev = mgp->dev; + struct pci_dev *pdev = mgp->pdev; + struct sk_buff *skb; + dma_addr_t bus; + int len, retval = 0; - /* try to refill entire ring */ - while (rx->fill_cnt != (rx->cnt + rx->mask + 1)) { - idx = rx->fill_cnt & rx->mask; + bytes += VLAN_HLEN; /* account for 802.1q vlan tag */ - if ((bytes < MYRI10GE_ALLOC_SIZE / 2) && - (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) { - /* we can use part of previous page */ - get_page(rx->page); - } else { - /* we need a new page */ - page = - alloc_pages(GFP_ATOMIC | __GFP_COMP, - MYRI10GE_ALLOC_ORDER); - if (unlikely(page == NULL)) { - if (rx->fill_cnt - rx->cnt < 16) - rx->watchdog_needed = 1; - return; - } - rx->page = page; - rx->page_offset = 0; - rx->bus = pci_map_page(mgp->pdev, page, 0, - MYRI10GE_ALLOC_SIZE, - PCI_DMA_FROMDEVICE); - } - rx->info[idx].page = rx->page; - rx->info[idx].page_offset = rx->page_offset; - /* note that this is the address of the start of the - * page */ - pci_unmap_addr_set(&rx->info[idx], bus, rx->bus); - rx->shadow[idx].addr_low = - htonl(MYRI10GE_LOWPART_TO_U32(rx->bus) + rx->page_offset); - rx->shadow[idx].addr_high = - htonl(MYRI10GE_HIGHPART_TO_U32(rx->bus)); - - /* start next packet on a cacheline boundary */ - rx->page_offset += SKB_DATA_ALIGN(bytes); - rx->fill_cnt++; - - /* copy 8 descriptors to the firmware at a time */ - if ((idx & 7) == 7) { - if (rx->wc_fifo == NULL) - myri10ge_submit_8rx(&rx->lanai[idx - 7], - &rx->shadow[idx - 7]); - else { - mb(); - myri10ge_pio_copy(rx->wc_fifo, - &rx->shadow[idx - 7], 64); - } + if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ ) + skb = myri10ge_alloc_big(dev, bytes); + else if (myri10ge_skb_cross_4k) + skb = myri10ge_alloc_small_safe(dev, bytes); + else + skb = myri10ge_alloc_small(dev, bytes); + + if (unlikely(skb == NULL)) { + rx->alloc_fail++; + retval = -ENOBUFS; + goto done; + } + + /* set len so that it only covers the area we + * need mapped for DMA */ + len = bytes + MXGEFW_PAD; + + bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); + rx->info[idx].skb = skb; + pci_unmap_addr_set(&rx->info[idx], bus, bus); + pci_unmap_len_set(&rx->info[idx], len, len); + rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus)); + rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus)); + +done: + /* copy 8 descriptors (64-bytes) to the mcp at a time */ + if ((idx & 7) == 7) { + if (rx->wc_fifo == NULL) + myri10ge_submit_8rx(&rx->lanai[idx - 7], + &rx->shadow[idx - 7]); + else { + mb(); + myri10ge_pio_copy(rx->wc_fifo, + &rx->shadow[idx - 7], 64); } } + return retval; } -static inline void -myri10ge_unmap_rx_page(struct pci_dev *pdev, - struct myri10ge_rx_buffer_state *info, int bytes) +static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum) { - /* unmap the recvd page if we're the only or last user of it */ - if (bytes >= MYRI10GE_ALLOC_SIZE / 2 || - (info->page_offset + 2 * bytes) > MYRI10GE_ALLOC_SIZE) { - pci_unmap_page(pdev, (pci_unmap_addr(info, bus) - & ~(MYRI10GE_ALLOC_SIZE - 1)), - MYRI10GE_ALLOC_SIZE, PCI_DMA_FROMDEVICE); + struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); + + if ((skb->protocol == htons(ETH_P_8021Q)) && + (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || + vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { + skb->csum = hw_csum; + skb->ip_summed = CHECKSUM_COMPLETE; } } -#define MYRI10GE_HLEN 64 /* The number of bytes to copy from a - * page into an skb */ - -static inline int +static inline unsigned long myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, int bytes, int len, __wsum csum) { + dma_addr_t bus; struct sk_buff *skb; - struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; - int i, idx, hlen, remainder; - struct pci_dev *pdev = mgp->pdev; - struct net_device *dev = mgp->dev; - u8 *va; + int idx, unmap_len; - len += MXGEFW_PAD; idx = rx->cnt & rx->mask; - va = page_address(rx->info[idx].page) + rx->info[idx].page_offset; - prefetch(va); - /* Fill skb_frag_struct(s) with data from our receive */ - for (i = 0, remainder = len; remainder > 0; i++) { - myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes); - rx_frags[i].page = rx->info[idx].page; - rx_frags[i].page_offset = rx->info[idx].page_offset; - if (remainder < MYRI10GE_ALLOC_SIZE) - rx_frags[i].size = remainder; - else - rx_frags[i].size = MYRI10GE_ALLOC_SIZE; - rx->cnt++; - idx = rx->cnt & rx->mask; - remainder -= MYRI10GE_ALLOC_SIZE; - } - - hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; + rx->cnt++; - /* allocate an skb to attach the page(s) to. */ + /* save a pointer to the received skb */ + skb = rx->info[idx].skb; + bus = pci_unmap_addr(&rx->info[idx], bus); + unmap_len = pci_unmap_len(&rx->info[idx], len); - skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); - if (unlikely(skb == NULL)) { - mgp->stats.rx_dropped++; - do { - i--; - put_page(rx_frags[i].page); - } while (i != 0); + /* try to replace the received skb */ + if (myri10ge_getbuf(rx, mgp, bytes, idx)) { + /* drop the frame -- the old skbuf is re-cycled */ + mgp->stats.rx_dropped += 1; return 0; } - /* Attach the pages to the skb, and trim off any padding */ - myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen); - if (skb_shinfo(skb)->frags[0].size <= 0) { - put_page(skb_shinfo(skb)->frags[0].page); - skb_shinfo(skb)->nr_frags = 0; - } - skb->protocol = eth_type_trans(skb, dev); - skb->dev = dev; + /* unmap the recvd skb */ + pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE); + + /* mcp implicitly skips 1st bytes so that packet is properly + * aligned */ + skb_reserve(skb, MXGEFW_PAD); + /* set the length of the frame */ + skb_put(skb, len); + + skb->protocol = eth_type_trans(skb, mgp->dev); if (mgp->csum_flag) { if ((skb->protocol == htons(ETH_P_IP)) || (skb->protocol == htons(ETH_P_IPV6))) { @@ -995,8 +1000,9 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, } else myri10ge_vlan_ip_csum(skb, csum); } + netif_receive_skb(skb); - dev->last_rx = jiffies; + mgp->dev->last_rx = jiffies; return 1; } @@ -1073,7 +1079,7 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) length, checksum); else rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big, - mgp->big_bytes, + mgp->dev->mtu + ETH_HLEN, length, checksum); rx_packets += rx_ok; rx_bytes += rx_ok * (unsigned long)length; @@ -1088,14 +1094,6 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) rx_done->cnt = cnt; mgp->stats.rx_packets += rx_packets; mgp->stats.rx_bytes += rx_bytes; - - /* restock receive rings if needed */ - if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh) - myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, - mgp->small_bytes + MXGEFW_PAD, 0); - if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh) - myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); - } static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) @@ -1486,48 +1484,56 @@ static int myri10ge_allocate_rings(struct net_device *dev) goto abort_with_rx_small_info; /* Fill the receive rings */ - mgp->rx_big.cnt = 0; - mgp->rx_small.cnt = 0; - mgp->rx_big.fill_cnt = 0; - mgp->rx_small.fill_cnt = 0; - mgp->rx_small.page_offset = MYRI10GE_ALLOC_SIZE; - mgp->rx_big.page_offset = MYRI10GE_ALLOC_SIZE; - mgp->rx_small.watchdog_needed = 0; - mgp->rx_big.watchdog_needed = 0; - myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, - mgp->small_bytes + MXGEFW_PAD, 0); - if (mgp->rx_small.fill_cnt < mgp->rx_small.mask + 1) { - printk(KERN_ERR "myri10ge: %s: alloced only %d small bufs\n", - dev->name, mgp->rx_small.fill_cnt); - goto abort_with_rx_small_ring; + for (i = 0; i <= mgp->rx_small.mask; i++) { + status = myri10ge_getbuf(&mgp->rx_small, mgp, + mgp->small_bytes, i); + if (status) { + printk(KERN_ERR + "myri10ge: %s: alloced only %d small bufs\n", + dev->name, i); + goto abort_with_rx_small_ring; + } } - myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); - if (mgp->rx_big.fill_cnt < mgp->rx_big.mask + 1) { - printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n", - dev->name, mgp->rx_big.fill_cnt); - goto abort_with_rx_big_ring; + for (i = 0; i <= mgp->rx_big.mask; i++) { + status = + myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i); + if (status) { + printk(KERN_ERR + "myri10ge: %s: alloced only %d big bufs\n", + dev->name, i); + goto abort_with_rx_big_ring; + } } return 0; abort_with_rx_big_ring: - for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { - int idx = i & mgp->rx_big.mask; - myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx], - mgp->big_bytes); - put_page(mgp->rx_big.info[idx].page); + for (i = 0; i <= mgp->rx_big.mask; i++) { + if (mgp->rx_big.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_big.info[i].skb); + if (pci_unmap_len(&mgp->rx_big.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_big.info[i], + bus), + pci_unmap_len(&mgp->rx_big.info[i], + len), + PCI_DMA_FROMDEVICE); } abort_with_rx_small_ring: - for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { - int idx = i & mgp->rx_small.mask; - myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx], - mgp->small_bytes + MXGEFW_PAD); - put_page(mgp->rx_small.info[idx].page); + for (i = 0; i <= mgp->rx_small.mask; i++) { + if (mgp->rx_small.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_small.info[i].skb); + if (pci_unmap_len(&mgp->rx_small.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_small.info[i], + bus), + pci_unmap_len(&mgp->rx_small.info[i], + len), + PCI_DMA_FROMDEVICE); } - kfree(mgp->rx_big.info); abort_with_rx_small_info: @@ -1560,24 +1566,30 @@ static void myri10ge_free_rings(struct net_device *dev) mgp = netdev_priv(dev); - for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { - idx = i & mgp->rx_big.mask; - if (i == mgp->rx_big.fill_cnt - 1) - mgp->rx_big.info[idx].page_offset = MYRI10GE_ALLOC_SIZE; - myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx], - mgp->big_bytes); - put_page(mgp->rx_big.info[idx].page); + for (i = 0; i <= mgp->rx_big.mask; i++) { + if (mgp->rx_big.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_big.info[i].skb); + if (pci_unmap_len(&mgp->rx_big.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_big.info[i], + bus), + pci_unmap_len(&mgp->rx_big.info[i], + len), + PCI_DMA_FROMDEVICE); + } + + for (i = 0; i <= mgp->rx_small.mask; i++) { + if (mgp->rx_small.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_small.info[i].skb); + if (pci_unmap_len(&mgp->rx_small.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_small.info[i], + bus), + pci_unmap_len(&mgp->rx_small.info[i], + len), + PCI_DMA_FROMDEVICE); } - for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { - idx = i & mgp->rx_small.mask; - if (i == mgp->rx_small.fill_cnt - 1) - mgp->rx_small.info[idx].page_offset = - MYRI10GE_ALLOC_SIZE; - myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx], - mgp->small_bytes + MXGEFW_PAD); - put_page(mgp->rx_small.info[idx].page); - } tx = &mgp->tx; while (tx->done != tx->req) { idx = tx->done & tx->mask; @@ -1645,18 +1657,19 @@ static int myri10ge_open(struct net_device *dev) */ if (dev->mtu <= ETH_DATA_LEN) - /* enough for a TCP header */ - mgp->small_bytes = (128 > SMP_CACHE_BYTES) - ? (128 - MXGEFW_PAD) - : (SMP_CACHE_BYTES - MXGEFW_PAD); + mgp->small_bytes = 128; /* enough for a TCP header */ else - /* enough for a vlan encapsulated ETH_DATA_LEN frame */ - mgp->small_bytes = VLAN_ETH_FRAME_LEN; + mgp->small_bytes = ETH_FRAME_LEN; /* enough for an ETH_DATA_LEN frame */ /* Override the small buffer size? */ if (myri10ge_small_bytes > 0) mgp->small_bytes = myri10ge_small_bytes; + /* If the user sets an obscenely small MTU, adjust the small + * bytes down to nearly nothing */ + if (mgp->small_bytes >= (dev->mtu + ETH_HLEN)) + mgp->small_bytes = 64; + /* get the lanai pointers to the send and receive rings */ status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); @@ -1692,23 +1705,17 @@ static int myri10ge_open(struct net_device *dev) mgp->rx_big.wc_fifo = NULL; } + status = myri10ge_allocate_rings(dev); + if (status != 0) + goto abort_with_nothing; + /* Firmware needs the big buff size as a power of 2. Lie and * tell him the buffer is larger, because we only use 1 * buffer/pkt, and the mtu will prevent overruns. */ - big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD; - if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) { - while ((big_pow2 & (big_pow2 - 1)) != 0) - big_pow2++; - mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD; - } else { - big_pow2 = MYRI10GE_ALLOC_SIZE; - mgp->big_bytes = big_pow2; - } - - status = myri10ge_allocate_rings(dev); - if (status != 0) - goto abort_with_nothing; + big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD; + while ((big_pow2 & (big_pow2 - 1)) != 0) + big_pow2++; /* now give firmware buffers sizes, and MTU */ cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; @@ -2199,7 +2206,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev) struct myri10ge_cmd cmd; struct myri10ge_priv *mgp; struct dev_mc_list *mc_list; - __be32 data[2] = { 0, 0 }; + __be32 data[2] = {0, 0}; int err; mgp = netdev_priv(dev); @@ -2618,7 +2625,7 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) static void myri10ge_watchdog(struct work_struct *work) { struct myri10ge_priv *mgp = - container_of(work, struct myri10ge_priv, watchdog_work); + container_of(work, struct myri10ge_priv, watchdog_work); u32 reboot; int status; u16 cmd, vendor; @@ -2691,21 +2698,6 @@ static void myri10ge_watchdog_timer(unsigned long arg) struct myri10ge_priv *mgp; mgp = (struct myri10ge_priv *)arg; - - if (mgp->rx_small.watchdog_needed) { - myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, - mgp->small_bytes + MXGEFW_PAD, 1); - if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt >= - myri10ge_fill_thresh) - mgp->rx_small.watchdog_needed = 0; - } - if (mgp->rx_big.watchdog_needed) { - myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 1); - if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt >= - myri10ge_fill_thresh) - mgp->rx_big.watchdog_needed = 0; - } - if (mgp->tx.req != mgp->tx.done && mgp->tx.done == mgp->watchdog_tx_done && mgp->watchdog_tx_req != mgp->watchdog_tx_done) diff --git a/trunk/drivers/net/phy/phy_device.c b/trunk/drivers/net/phy/phy_device.c index a4d7529ef415..b01fc70a57db 100644 --- a/trunk/drivers/net/phy/phy_device.c +++ b/trunk/drivers/net/phy/phy_device.c @@ -50,7 +50,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) struct phy_device *dev; /* We allocate the device, and initialize the * default values */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); if (NULL == dev) return (struct phy_device*) PTR_ERR((void*)-ENOMEM); diff --git a/trunk/drivers/net/ppp_deflate.c b/trunk/drivers/net/ppp_deflate.c index 72c8d6628f58..f54c55242f4a 100644 --- a/trunk/drivers/net/ppp_deflate.c +++ b/trunk/drivers/net/ppp_deflate.c @@ -121,7 +121,7 @@ static void *z_comp_alloc(unsigned char *options, int opt_len) if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) return NULL; - state = kmalloc(sizeof(*state), + state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) return NULL; @@ -341,7 +341,7 @@ static void *z_decomp_alloc(unsigned char *options, int opt_len) if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) return NULL; - state = kmalloc(sizeof(*state), GFP_KERNEL); + state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) return NULL; diff --git a/trunk/drivers/net/ppp_mppe.c b/trunk/drivers/net/ppp_mppe.c index d5bdd2574659..f3655fd772f5 100644 --- a/trunk/drivers/net/ppp_mppe.c +++ b/trunk/drivers/net/ppp_mppe.c @@ -200,7 +200,7 @@ static void *mppe_alloc(unsigned char *options, int optlen) || options[0] != CI_MPPE || options[1] != CILEN_MPPE) goto out; - state = kmalloc(sizeof(*state), GFP_KERNEL); + state = (struct ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) goto out; diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index 8a39376f87dc..b60f0451f6cd 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -749,7 +749,7 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base) struct skge_element *e; int i; - ring->start = kcalloc(ring->count, sizeof(*e), GFP_KERNEL); + ring->start = kcalloc(sizeof(*e), ring->count, GFP_KERNEL); if (!ring->start) return -ENOMEM; diff --git a/trunk/drivers/net/slip.c b/trunk/drivers/net/slip.c index a0806d262fc6..39c2152a07f4 100644 --- a/trunk/drivers/net/slip.c +++ b/trunk/drivers/net/slip.c @@ -229,10 +229,10 @@ static int sl_realloc_bufs(struct slip *sl, int mtu) if (len < 576 * 2) len = 576 * 2; - xbuff = kmalloc(len + 4, GFP_ATOMIC); - rbuff = kmalloc(len + 4, GFP_ATOMIC); + xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC); + rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC); #ifdef SL_INCLUDE_CSLIP - cbuff = kmalloc(len + 4, GFP_ATOMIC); + cbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC); #endif diff --git a/trunk/drivers/net/smc91x.h b/trunk/drivers/net/smc91x.h index d2767e6584a9..9367c574477a 100644 --- a/trunk/drivers/net/smc91x.h +++ b/trunk/drivers/net/smc91x.h @@ -362,6 +362,96 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, #define SMC_IRQ_FLAGS (0) +#elif defined(CONFIG_ARCH_VERSATILE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define SMC_IRQ_FLAGS (0) + +#elif defined(CONFIG_ARCH_VERSATILE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define SMC_IRQ_FLAGS (0) + +#elif defined(CONFIG_ARCH_VERSATILE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define SMC_IRQ_FLAGS (0) + +#elif defined(CONFIG_ARCH_VERSATILE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define SMC_IRQ_FLAGS (0) + +#elif defined(CONFIG_ARCH_VERSATILE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define SMC_IRQ_FLAGS (0) + #else #define SMC_CAN_USE_8BIT 1 diff --git a/trunk/drivers/net/ucc_geth.c b/trunk/drivers/net/ucc_geth.c index 8243150f5b05..1f05511fa390 100644 --- a/trunk/drivers/net/ucc_geth.c +++ b/trunk/drivers/net/ucc_geth.c @@ -194,9 +194,9 @@ static void enqueue(struct list_head *node, struct list_head *lh) { unsigned long flags; - spin_lock_irqsave(&ugeth_lock, flags); + spin_lock_irqsave(ugeth_lock, flags); list_add_tail(node, lh); - spin_unlock_irqrestore(&ugeth_lock, flags); + spin_unlock_irqrestore(ugeth_lock, flags); } #endif /* CONFIG_UGETH_FILTERING */ @@ -204,14 +204,14 @@ static struct list_head *dequeue(struct list_head *lh) { unsigned long flags; - spin_lock_irqsave(&ugeth_lock, flags); + spin_lock_irqsave(ugeth_lock, flags); if (!list_empty(lh)) { struct list_head *node = lh->next; list_del(node); - spin_unlock_irqrestore(&ugeth_lock, flags); + spin_unlock_irqrestore(ugeth_lock, flags); return node; } else { - spin_unlock_irqrestore(&ugeth_lock, flags); + spin_unlock_irqrestore(ugeth_lock, flags); return NULL; } } @@ -1852,8 +1852,6 @@ static int init_phy(struct net_device *dev) mii_info->mdio_read = &read_phy_reg; mii_info->mdio_write = &write_phy_reg; - spin_lock_init(&mii_info->mdio_lock); - ugeth->mii_info = mii_info; spin_lock_irq(&ugeth->lock); diff --git a/trunk/drivers/net/wan/Kconfig b/trunk/drivers/net/wan/Kconfig index 21f76f51c95e..d5ab9cf13257 100644 --- a/trunk/drivers/net/wan/Kconfig +++ b/trunk/drivers/net/wan/Kconfig @@ -382,7 +382,7 @@ config SDLA # Wan router core. config WAN_ROUTER_DRIVERS - tristate "WAN router drivers" + bool "WAN router drivers" depends on WAN && WAN_ROUTER ---help--- Connect LAN to WAN via Linux box. @@ -393,8 +393,7 @@ config WAN_ROUTER_DRIVERS . Note that the answer to this question won't directly affect the - kernel except for how subordinate drivers may be built: - saying N will just cause the configurator to skip all + kernel: saying N will just cause the configurator to skip all the questions about WAN router drivers. If unsure, say N. diff --git a/trunk/drivers/net/wan/hostess_sv11.c b/trunk/drivers/net/wan/hostess_sv11.c index a02c5fb40567..a4f735723c41 100644 --- a/trunk/drivers/net/wan/hostess_sv11.c +++ b/trunk/drivers/net/wan/hostess_sv11.c @@ -231,7 +231,7 @@ static struct sv11_device *sv11_init(int iobase, int irq) return NULL; } - sv = kmalloc(sizeof(struct sv11_device), GFP_KERNEL); + sv=(struct sv11_device *)kmalloc(sizeof(struct sv11_device), GFP_KERNEL); if(!sv) goto fail3; diff --git a/trunk/drivers/net/wan/pc300_drv.c b/trunk/drivers/net/wan/pc300_drv.c index 62184dee377c..36d1c3ff7078 100644 --- a/trunk/drivers/net/wan/pc300_drv.c +++ b/trunk/drivers/net/wan/pc300_drv.c @@ -3455,7 +3455,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if ((err = pci_enable_device(pdev)) < 0) return err; - card = kmalloc(sizeof(pc300_t), GFP_KERNEL); + card = (pc300_t *) kmalloc(sizeof(pc300_t), GFP_KERNEL); if (card == NULL) { printk("PC300 found at RAM 0x%016llx, " "but could not allocate card structure.\n", diff --git a/trunk/drivers/net/wan/pc300_tty.c b/trunk/drivers/net/wan/pc300_tty.c index 5873c346e7e9..b2a23aed4428 100644 --- a/trunk/drivers/net/wan/pc300_tty.c +++ b/trunk/drivers/net/wan/pc300_tty.c @@ -784,7 +784,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev) continue; } - new = kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC); + new = (st_cpc_rx_buf *)kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC); if (new == 0) { cpc_tty_rx_disc_frame(pc300chan); continue; diff --git a/trunk/drivers/net/wan/x25_asy.c b/trunk/drivers/net/wan/x25_asy.c index 1c9edd97accd..9c3ccc669143 100644 --- a/trunk/drivers/net/wan/x25_asy.c +++ b/trunk/drivers/net/wan/x25_asy.c @@ -123,8 +123,8 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu) unsigned char *xbuff, *rbuff; int len = 2* newmtu; - xbuff = kmalloc(len + 4, GFP_ATOMIC); - rbuff = kmalloc(len + 4, GFP_ATOMIC); + xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC); + rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC); if (xbuff == NULL || rbuff == NULL) { @@ -465,11 +465,11 @@ static int x25_asy_open(struct net_device *dev) len = dev->mtu * 2; - sl->rbuff = kmalloc(len + 4, GFP_KERNEL); + sl->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL); if (sl->rbuff == NULL) { goto norbuff; } - sl->xbuff = kmalloc(len + 4, GFP_KERNEL); + sl->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL); if (sl->xbuff == NULL) { goto noxbuff; } diff --git a/trunk/drivers/net/wireless/hostap/hostap_ap.c b/trunk/drivers/net/wireless/hostap/hostap_ap.c index efb8cf3bd8ad..974a8e5bec8b 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_ap.c +++ b/trunk/drivers/net/wireless/hostap/hostap_ap.c @@ -1253,7 +1253,7 @@ static char * ap_auth_make_challenge(struct ap_data *ap) return NULL; } - tmpbuf = kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC); + tmpbuf = (char *) kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC); if (tmpbuf == NULL) { PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n"); return NULL; diff --git a/trunk/drivers/net/wireless/hostap/hostap_download.c b/trunk/drivers/net/wireless/hostap/hostap_download.c index c7678e67697d..24fc387bba67 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_download.c +++ b/trunk/drivers/net/wireless/hostap/hostap_download.c @@ -201,7 +201,7 @@ static u8 * prism2_read_pda(struct net_device *dev) 0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */, }; - buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL); + buf = (u8 *) kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL); if (buf == NULL) return NULL; diff --git a/trunk/drivers/net/wireless/hostap/hostap_hw.c b/trunk/drivers/net/wireless/hostap/hostap_hw.c index 3079378fb8cd..a394a23b9a20 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_hw.c +++ b/trunk/drivers/net/wireless/hostap/hostap_hw.c @@ -2252,7 +2252,7 @@ static int hostap_tx_compl_read(local_info_t *local, int error, if (txdesc->sw_support) { len = le16_to_cpu(txdesc->data_len); if (len < PRISM2_DATA_MAXLEN) { - *payload = kmalloc(len, GFP_ATOMIC); + *payload = (char *) kmalloc(len, GFP_ATOMIC); if (*payload == NULL || hfa384x_from_bap(dev, BAP0, *payload, len)) { PDEBUG(DEBUG_EXTRA, "%s: could not read TX " diff --git a/trunk/drivers/net/wireless/hostap/hostap_ioctl.c b/trunk/drivers/net/wireless/hostap/hostap_ioctl.c index cb08bc5db2bd..3b7b8063ff1c 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/trunk/drivers/net/wireless/hostap/hostap_ioctl.c @@ -3829,7 +3829,7 @@ static int prism2_ioctl_priv_hostapd(local_info_t *local, struct iw_point *p) p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) return -EINVAL; - param = kmalloc(p->length, GFP_KERNEL); + param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL); if (param == NULL) return -ENOMEM; diff --git a/trunk/drivers/net/wireless/hostap/hostap_main.c b/trunk/drivers/net/wireless/hostap/hostap_main.c index 04c19cefa1da..0796be9d9e77 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_main.c +++ b/trunk/drivers/net/wireless/hostap/hostap_main.c @@ -250,7 +250,7 @@ u16 hostap_tx_callback_register(local_info_t *local, unsigned long flags; struct hostap_tx_callback_info *entry; - entry = kmalloc(sizeof(*entry), + entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) return 0; diff --git a/trunk/drivers/net/wireless/ipw2100.c b/trunk/drivers/net/wireless/ipw2100.c index 0e94fbbf7a94..dd9ba4aad7bb 100644 --- a/trunk/drivers/net/wireless/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2100.c @@ -2246,7 +2246,7 @@ static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) if (priv->snapshot[0]) return 1; for (i = 0; i < 0x30; i++) { - priv->snapshot[i] = kmalloc(0x1000, GFP_ATOMIC); + priv->snapshot[i] = (u8 *) kmalloc(0x1000, GFP_ATOMIC); if (!priv->snapshot[i]) { IPW_DEBUG_INFO("%s: Error allocating snapshot " "buffer %d\n", priv->net_dev->name, i); diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.c b/trunk/drivers/net/wireless/prism54/isl_ioctl.c index 838d510213c6..96606ed10076 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.c +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.c @@ -2775,7 +2775,7 @@ prism54_hostapd(struct net_device *ndev, struct iw_point *p) p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) return -EINVAL; - param = kmalloc(p->length, GFP_KERNEL); + param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL); if (param == NULL) return -ENOMEM; diff --git a/trunk/drivers/net/wireless/wavelan_cs.c b/trunk/drivers/net/wireless/wavelan_cs.c index 5eb81638e846..233d906c08f0 100644 --- a/trunk/drivers/net/wireless/wavelan_cs.c +++ b/trunk/drivers/net/wireless/wavelan_cs.c @@ -603,7 +603,7 @@ static wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char se if(lp->wavepoint_table.num_wavepoints==MAX_WAVEPOINTS) return NULL; - new_wavepoint = kmalloc(sizeof(wavepoint_history),GFP_ATOMIC); + new_wavepoint=(wavepoint_history *) kmalloc(sizeof(wavepoint_history),GFP_ATOMIC); if(new_wavepoint==NULL) return NULL; diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c index 78ea72fb8f0c..77e11ddad836 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c @@ -101,7 +101,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr /* Allocate a single memory block for values and addresses. */ count16 = 2*count; - a16 = kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), + a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), GFP_NOFS); if (!a16) { dev_dbg_f(zd_chip_dev(chip), diff --git a/trunk/drivers/parisc/iosapic.c b/trunk/drivers/parisc/iosapic.c index 6fb3f7979f21..12bab64a62a1 100644 --- a/trunk/drivers/parisc/iosapic.c +++ b/trunk/drivers/parisc/iosapic.c @@ -874,7 +874,7 @@ void *iosapic_register(unsigned long hpa) return NULL; } - isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL); + isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL); if (!isi) { BUG(); return NULL; diff --git a/trunk/drivers/parport/Kconfig b/trunk/drivers/parport/Kconfig index 36c6a1bfe558..c7fa28a28b9f 100644 --- a/trunk/drivers/parport/Kconfig +++ b/trunk/drivers/parport/Kconfig @@ -82,6 +82,9 @@ config PARPORT_PC_PCMCIA Say Y here if you need PCMCIA support for your PC-style parallel ports. If unsure, say N. +config PARPORT_NOT_PC + bool + config PARPORT_IP32 tristate "SGI IP32 builtin port (EXPERIMENTAL)" depends on SGI_IP32 && PARPORT && EXPERIMENTAL @@ -155,8 +158,5 @@ config PARPORT_1284 transfer modes. Also say Y if you want device ID information to appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N. -config PARPORT_NOT_PC - bool - endmenu diff --git a/trunk/drivers/pci/hotplug/Kconfig b/trunk/drivers/pci/hotplug/Kconfig index adce4204d87d..6e780db9454d 100644 --- a/trunk/drivers/pci/hotplug/Kconfig +++ b/trunk/drivers/pci/hotplug/Kconfig @@ -76,8 +76,7 @@ config HOTPLUG_PCI_IBM config HOTPLUG_PCI_ACPI tristate "ACPI PCI Hotplug driver" - depends on HOTPLUG_PCI - depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) + depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI) help Say Y here if you have a system that supports PCI Hotplug using ACPI. diff --git a/trunk/drivers/pci/hotplug/cpqphp_nvram.c b/trunk/drivers/pci/hotplug/cpqphp_nvram.c index ae5e974c45a7..298a6cfd8406 100644 --- a/trunk/drivers/pci/hotplug/cpqphp_nvram.c +++ b/trunk/drivers/pci/hotplug/cpqphp_nvram.c @@ -520,7 +520,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) return 2; while (nummem--) { - mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!mem_node) break; @@ -548,7 +548,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) } while (numpmem--) { - p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!p_mem_node) break; @@ -576,7 +576,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) } while (numio--) { - io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!io_node) break; @@ -604,7 +604,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) } while (numbus--) { - bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!bus_node) break; diff --git a/trunk/drivers/pci/hotplug/pciehp_hpc.c b/trunk/drivers/pci/hotplug/pciehp_hpc.c index 25d3aadfddbf..6d3f580f2666 100644 --- a/trunk/drivers/pci/hotplug/pciehp_hpc.c +++ b/trunk/drivers/pci/hotplug/pciehp_hpc.c @@ -1320,7 +1320,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) DBG_ENTER_ROUTINE spin_lock_init(&list_lock); - php_ctlr = kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); + php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); if (!php_ctlr) { /* allocate controller state data */ err("%s: HPC controller memory allocation error!\n", __FUNCTION__); diff --git a/trunk/drivers/pci/pcie/aer/aerdrv.c b/trunk/drivers/pci/pcie/aer/aerdrv.c index 6f5fabbd14e5..55866b6b26fa 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv.c @@ -148,7 +148,7 @@ static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev) { struct aer_rpc *rpc; - if (!(rpc = kmalloc(sizeof(struct aer_rpc), + if (!(rpc = (struct aer_rpc *)kmalloc(sizeof(struct aer_rpc), GFP_KERNEL))) return NULL; diff --git a/trunk/drivers/pcmcia/at91_cf.c b/trunk/drivers/pcmcia/at91_cf.c index 3334f22a86c0..52d4a38b3667 100644 --- a/trunk/drivers/pcmcia/at91_cf.c +++ b/trunk/drivers/pcmcia/at91_cf.c @@ -230,7 +230,7 @@ static int __init at91_cf_probe(struct platform_device *pdev) if (!io) return -ENODEV; - cf = kzalloc(sizeof *cf, GFP_KERNEL); + cf = kcalloc(1, sizeof *cf, GFP_KERNEL); if (!cf) return -ENOMEM; diff --git a/trunk/drivers/pcmcia/omap_cf.c b/trunk/drivers/pcmcia/omap_cf.c index e65a6b8188f6..06bf7f48836e 100644 --- a/trunk/drivers/pcmcia/omap_cf.c +++ b/trunk/drivers/pcmcia/omap_cf.c @@ -220,7 +220,7 @@ static int __devinit omap_cf_probe(struct device *dev) if (irq < 0) return -EINVAL; - cf = kzalloc(sizeof *cf, GFP_KERNEL); + cf = kcalloc(1, sizeof *cf, GFP_KERNEL); if (!cf) return -ENOMEM; init_timer(&cf->timer); diff --git a/trunk/drivers/pnp/isapnp/core.c b/trunk/drivers/pnp/isapnp/core.c index a0b158704ca1..3ac5b123215a 100644 --- a/trunk/drivers/pnp/isapnp/core.c +++ b/trunk/drivers/pnp/isapnp/core.c @@ -395,7 +395,7 @@ static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigne struct pnp_id * id; if (!dev) return; - id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); if (!id) return; sprintf(id->id, "%c%c%c%x%x%x%x", @@ -419,7 +419,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si struct pnp_dev *dev; isapnp_peek(tmp, size); - dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); + dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL); if (!dev) return NULL; dev->number = number; @@ -450,7 +450,7 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option, unsigned long bits; isapnp_peek(tmp, size); - irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); + irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); if (!irq) return; bits = (tmp[1] << 8) | tmp[0]; @@ -474,7 +474,7 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option, struct pnp_dma *dma; isapnp_peek(tmp, size); - dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); + dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL); if (!dma) return; dma->map = tmp[0]; @@ -494,7 +494,7 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option, struct pnp_port *port; isapnp_peek(tmp, size); - port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); + port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; port->min = (tmp[2] << 8) | tmp[1]; @@ -517,7 +517,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, struct pnp_port *port; isapnp_peek(tmp, size); - port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); + port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; port->min = port->max = (tmp[1] << 8) | tmp[0]; @@ -539,7 +539,7 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option, struct pnp_mem *mem; isapnp_peek(tmp, size); - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = ((tmp[2] << 8) | tmp[1]) << 8; @@ -562,7 +562,7 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option, struct pnp_mem *mem; isapnp_peek(tmp, size); - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; @@ -584,7 +584,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, struct pnp_mem *mem; isapnp_peek(tmp, size); - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; @@ -829,7 +829,7 @@ static unsigned char __init isapnp_checksum(unsigned char *data) static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device) { - struct pnp_id * id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); if (!id) return; sprintf(id->id, "%c%c%c%x%x%x%x", @@ -865,7 +865,7 @@ static int __init isapnp_build_device_list(void) header[4], header[5], header[6], header[7], header[8]); printk(KERN_DEBUG "checksum = 0x%x\n", checksum); #endif - if ((card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL) + if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL) continue; card->number = csn; diff --git a/trunk/drivers/pnp/pnpacpi/core.c b/trunk/drivers/pnp/pnpacpi/core.c index 62eda5d59024..6cf34a63c790 100644 --- a/trunk/drivers/pnp/pnpacpi/core.c +++ b/trunk/drivers/pnp/pnpacpi/core.c @@ -139,7 +139,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) return 0; pnp_dbg("ACPI device : hid %s", acpi_device_hid(device)); - dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); + dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL); if (!dev) { pnp_err("Out of memory"); return -ENOMEM; @@ -169,7 +169,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) dev->number = num; /* set the initial values for the PnP device */ - dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) goto err; pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id); @@ -201,7 +201,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) for (i = 0; i < cid_list->count; i++) { if (!ispnpidacpi(cid_list->id[i].value)) continue; - dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) continue; diff --git a/trunk/drivers/pnp/pnpacpi/rsparser.c b/trunk/drivers/pnp/pnpacpi/rsparser.c index 7a535542fe92..379048fdf05d 100644 --- a/trunk/drivers/pnp/pnpacpi/rsparser.c +++ b/trunk/drivers/pnp/pnpacpi/rsparser.c @@ -298,7 +298,7 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso if (p->channel_count == 0) return; - dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); + dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL); if (!dma) return; @@ -354,7 +354,7 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option, if (p->interrupt_count == 0) return; - irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); + irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); if (!irq) return; @@ -375,7 +375,7 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, if (p->interrupt_count == 0) return; - irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); + irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); if (!irq) return; @@ -396,7 +396,7 @@ pnpacpi_parse_port_option(struct pnp_option *option, if (io->address_length == 0) return; - port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); + port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; port->min = io->minimum; @@ -417,7 +417,7 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option, if (io->address_length == 0) return; - port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); + port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; port->min = port->max = io->address; @@ -436,7 +436,7 @@ pnpacpi_parse_mem24_option(struct pnp_option *option, if (p->address_length == 0) return; - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = p->minimum; @@ -459,7 +459,7 @@ pnpacpi_parse_mem32_option(struct pnp_option *option, if (p->address_length == 0) return; - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = p->minimum; @@ -482,7 +482,7 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, if (p->address_length == 0) return; - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = mem->max = p->address; @@ -514,7 +514,7 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) return; if (p->resource_type == ACPI_MEMORY_RANGE) { - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = mem->max = p->minimum; @@ -524,7 +524,7 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0; pnp_register_mem_resource(option, mem); } else if (p->resource_type == ACPI_IO_RANGE) { - port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); + port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; port->min = port->max = p->minimum; @@ -721,7 +721,7 @@ int pnpacpi_build_resource_template(acpi_handle handle, if (!res_cnt) return -EINVAL; buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1; - buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL); + buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL); if (!buffer->pointer) return -ENOMEM; pnp_dbg("Res cnt %d", res_cnt); diff --git a/trunk/drivers/pnp/pnpbios/core.c b/trunk/drivers/pnp/pnpbios/core.c index 95738dbd5d45..33adeba1a31f 100644 --- a/trunk/drivers/pnp/pnpbios/core.c +++ b/trunk/drivers/pnp/pnpbios/core.c @@ -109,10 +109,10 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) if (!current->fs->root) { return -EAGAIN; } - if (!(envp = kcalloc(20, sizeof (char *), GFP_KERNEL))) { + if (!(envp = (char **) kcalloc (20, sizeof (char *), GFP_KERNEL))) { return -ENOMEM; } - if (!(buf = kzalloc(256, GFP_KERNEL))) { + if (!(buf = kcalloc (1, 256, GFP_KERNEL))) { kfree (envp); return -ENOMEM; } @@ -220,7 +220,7 @@ static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table if(!pnpbios_is_dynamic(dev)) return -EPERM; - node = kzalloc(node_info.max_node_size, GFP_KERNEL); + node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); if (!node) return -1; if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { @@ -243,7 +243,7 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table if (!pnpbios_is_dynamic(dev)) return -EPERM; - node = kzalloc(node_info.max_node_size, GFP_KERNEL); + node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); if (!node) return -1; if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { @@ -294,7 +294,7 @@ static int pnpbios_disable_resources(struct pnp_dev *dev) if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev)) return -EPERM; - node = kzalloc(node_info.max_node_size, GFP_KERNEL); + node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); if (!node) return -ENOMEM; @@ -336,7 +336,7 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node) } /* set the initial values for the PnP device */ - dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) return -1; pnpid32_to_pnpid(node->eisa_id,id); @@ -374,7 +374,7 @@ static void __init build_devlist(void) struct pnp_bios_node *node; struct pnp_dev *dev; - node = kzalloc(node_info.max_node_size, GFP_KERNEL); + node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); if (!node) return; @@ -391,7 +391,7 @@ static void __init build_devlist(void) break; } nodes_got++; - dev = kzalloc(sizeof (struct pnp_dev), GFP_KERNEL); + dev = kcalloc(1, sizeof (struct pnp_dev), GFP_KERNEL); if (!dev) break; if(insert_device(dev,node)<0) diff --git a/trunk/drivers/pnp/pnpbios/proc.c b/trunk/drivers/pnp/pnpbios/proc.c index 8027073f7919..5a3dfc97f5e9 100644 --- a/trunk/drivers/pnp/pnpbios/proc.c +++ b/trunk/drivers/pnp/pnpbios/proc.c @@ -87,7 +87,7 @@ static int proc_read_escd(char *buf, char **start, off_t pos, return -EFBIG; } - tmpbuf = kzalloc(escd.escd_size, GFP_KERNEL); + tmpbuf = kcalloc(1, escd.escd_size, GFP_KERNEL); if (!tmpbuf) return -ENOMEM; if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) { @@ -133,7 +133,7 @@ static int proc_read_devices(char *buf, char **start, off_t pos, if (pos >= 0xff) return 0; - node = kzalloc(node_info.max_node_size, GFP_KERNEL); + node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); if (!node) return -ENOMEM; for (nodenum=pos; nodenum<0xff; ) { @@ -168,7 +168,7 @@ static int proc_read_node(char *buf, char **start, off_t pos, u8 nodenum = (long)data; int len; - node = kzalloc(node_info.max_node_size, GFP_KERNEL); + node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); if (!node) return -ENOMEM; if (pnp_bios_get_dev_node(&nodenum, boot, node)) { kfree(node); @@ -188,7 +188,7 @@ static int proc_write_node(struct file *file, const char __user *buf, u8 nodenum = (long)data; int ret = count; - node = kzalloc(node_info.max_node_size, GFP_KERNEL); + node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); if (!node) return -ENOMEM; if (pnp_bios_get_dev_node(&nodenum, boot, node)) { diff --git a/trunk/drivers/pnp/pnpbios/rsparser.c b/trunk/drivers/pnp/pnpbios/rsparser.c index 95b79685a9d1..ef508a4de557 100644 --- a/trunk/drivers/pnp/pnpbios/rsparser.c +++ b/trunk/drivers/pnp/pnpbios/rsparser.c @@ -248,7 +248,7 @@ static void pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem * mem; - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = ((p[5] << 8) | p[4]) << 8; @@ -264,7 +264,7 @@ static void pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem * mem; - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; @@ -280,7 +280,7 @@ static void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem * mem; - mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; @@ -297,7 +297,7 @@ pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option) struct pnp_irq * irq; unsigned long bits; - irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); + irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); if (!irq) return; bits = (p[2] << 8) | p[1]; @@ -314,7 +314,7 @@ static void pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option) { struct pnp_dma * dma; - dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); + dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL); if (!dma) return; dma->map = p[1]; @@ -327,7 +327,7 @@ static void pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option) { struct pnp_port * port; - port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); + port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; port->min = (p[3] << 8) | p[2]; @@ -343,7 +343,7 @@ static void pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option) { struct pnp_port * port; - port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); + port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; port->min = port->max = (p[2] << 8) | p[1]; @@ -527,7 +527,7 @@ pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_de case SMALL_TAG_COMPATDEVID: /* compatible ID */ if (len != 4) goto len_err; - dev_id = kzalloc(sizeof (struct pnp_id), GFP_KERNEL); + dev_id = kcalloc(1, sizeof (struct pnp_id), GFP_KERNEL); if (!dev_id) return NULL; memset(dev_id, 0, sizeof(struct pnp_id)); diff --git a/trunk/drivers/ps3/Makefile b/trunk/drivers/ps3/Makefile index 8433eb7562cb..b52d547b7a78 100644 --- a/trunk/drivers/ps3/Makefile +++ b/trunk/drivers/ps3/Makefile @@ -1,2 +1 @@ obj-y += system-bus.o -obj-$(CONFIG_PS3_VUART) += vuart.o diff --git a/trunk/drivers/ps3/vuart.c b/trunk/drivers/ps3/vuart.c deleted file mode 100644 index 6974f65bcda5..000000000000 --- a/trunk/drivers/ps3/vuart.c +++ /dev/null @@ -1,965 +0,0 @@ -/* - * PS3 virtual uart - * - * Copyright (C) 2006 Sony Computer Entertainment Inc. - * Copyright 2006 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 - */ - -#include -#include -#include -#include - -#include -#include - -#include "vuart.h" - -MODULE_AUTHOR("Sony Corporation"); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("ps3 vuart"); - -/** - * vuart - An inter-partition data link service. - * port 0: PS3 AV Settings. - * port 2: PS3 System Manager. - * - * The vuart provides a bi-directional byte stream data link between logical - * partitions. Its primary role is as a communications link between the guest - * OS and the system policy module. The current HV does not support any - * connections other than those listed. - */ - -enum {PORT_COUNT = 3,}; - -enum vuart_param { - PARAM_TX_TRIGGER = 0, - PARAM_RX_TRIGGER = 1, - PARAM_INTERRUPT_MASK = 2, - PARAM_RX_BUF_SIZE = 3, /* read only */ - PARAM_RX_BYTES = 4, /* read only */ - PARAM_TX_BUF_SIZE = 5, /* read only */ - PARAM_TX_BYTES = 6, /* read only */ - PARAM_INTERRUPT_STATUS = 7, /* read only */ -}; - -enum vuart_interrupt_bit { - INTERRUPT_BIT_TX = 0, - INTERRUPT_BIT_RX = 1, - INTERRUPT_BIT_DISCONNECT = 2, -}; - -enum vuart_interrupt_mask { - INTERRUPT_MASK_TX = 1, - INTERRUPT_MASK_RX = 2, - INTERRUPT_MASK_DISCONNECT = 4, -}; - -/** - * struct ports_bmp - bitmap indicating ports needing service. - * - * A 256 bit read only bitmap indicating ports needing service. Do not write - * to these bits. Must not cross a page boundary. - */ - -struct ports_bmp { - u64 status; - u64 unused[3]; -} __attribute__ ((aligned (32))); - -/* redefine dev_dbg to do a syntax check */ - -#if !defined(DEBUG) -#undef dev_dbg -static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg( - const struct device *_dev, const char *fmt, ...) {return 0;} -#endif - -#define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__) -static void __attribute__ ((unused)) _dump_ports_bmp( - const struct ports_bmp* bmp, const char* func, int line) -{ - pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status); -} - -static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id, - unsigned int *port_number) -{ - switch(match_id) { - case PS3_MATCH_ID_AV_SETTINGS: - *port_number = 0; - return 0; - case PS3_MATCH_ID_SYSTEM_MANAGER: - *port_number = 2; - return 0; - default: - WARN_ON(1); - *port_number = UINT_MAX; - return -EINVAL; - }; -} - -#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__) -static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number, - const char* func, int line) -{ -#if defined(DEBUG) - static const char *strings[] = { - "tx_trigger ", - "rx_trigger ", - "interrupt_mask ", - "rx_buf_size ", - "rx_bytes ", - "tx_buf_size ", - "tx_bytes ", - "interrupt_status", - }; - int result; - unsigned int i; - u64 value; - - for (i = 0; i < ARRAY_SIZE(strings); i++) { - result = lv1_get_virtual_uart_param(port_number, i, &value); - - if (result) { - pr_debug("%s:%d: port_%u: %s failed: %s\n", func, line, - port_number, strings[i], ps3_result(result)); - continue; - } - pr_debug("%s:%d: port_%u: %s = %lxh\n", - func, line, port_number, strings[i], value); - } -#endif -} - -struct vuart_triggers { - unsigned long rx; - unsigned long tx; -}; - -int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, - struct vuart_triggers *trig) -{ - int result; - unsigned long size; - unsigned long val; - - result = lv1_get_virtual_uart_param(dev->port_number, - PARAM_TX_TRIGGER, &trig->tx); - - if (result) { - dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n", - __func__, __LINE__, ps3_result(result)); - return result; - } - - result = lv1_get_virtual_uart_param(dev->port_number, - PARAM_RX_BUF_SIZE, &size); - - if (result) { - dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n", - __func__, __LINE__, ps3_result(result)); - return result; - } - - result = lv1_get_virtual_uart_param(dev->port_number, - PARAM_RX_TRIGGER, &val); - - if (result) { - dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n", - __func__, __LINE__, ps3_result(result)); - return result; - } - - trig->rx = size - val; - - dev_dbg(&dev->core, "%s:%d: tx %lxh, rx %lxh\n", __func__, __LINE__, - trig->tx, trig->rx); - - return result; -} - -int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, - unsigned int rx) -{ - int result; - unsigned long size; - - result = lv1_set_virtual_uart_param(dev->port_number, - PARAM_TX_TRIGGER, tx); - - if (result) { - dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n", - __func__, __LINE__, ps3_result(result)); - return result; - } - - result = lv1_get_virtual_uart_param(dev->port_number, - PARAM_RX_BUF_SIZE, &size); - - if (result) { - dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n", - __func__, __LINE__, ps3_result(result)); - return result; - } - - result = lv1_set_virtual_uart_param(dev->port_number, - PARAM_RX_TRIGGER, size - rx); - - if (result) { - dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n", - __func__, __LINE__, ps3_result(result)); - return result; - } - - dev_dbg(&dev->core, "%s:%d: tx %xh, rx %xh\n", __func__, __LINE__, - tx, rx); - - return result; -} - -static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, - unsigned long *bytes_waiting) -{ - int result = lv1_get_virtual_uart_param(dev->port_number, - PARAM_RX_BYTES, bytes_waiting); - - if (result) - dev_dbg(&dev->core, "%s:%d: rx_bytes failed: %s\n", - __func__, __LINE__, ps3_result(result)); - - dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, - *bytes_waiting); - return result; -} - -static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, - unsigned long mask) -{ - int result; - - dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); - - dev->interrupt_mask = mask; - - result = lv1_set_virtual_uart_param(dev->port_number, - PARAM_INTERRUPT_MASK, dev->interrupt_mask); - - if (result) - dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", - __func__, __LINE__, ps3_result(result)); - - return result; -} - -static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev, - unsigned long *status) -{ - int result = lv1_get_virtual_uart_param(dev->port_number, - PARAM_INTERRUPT_STATUS, status); - - if (result) - dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", - __func__, __LINE__, ps3_result(result)); - - dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", - __func__, __LINE__, dev->interrupt_mask, *status, - dev->interrupt_mask & *status); - - return result; -} - -int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) -{ - return (dev->interrupt_mask & INTERRUPT_MASK_TX) ? 0 - : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask - | INTERRUPT_MASK_TX); -} - -int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) -{ - return (dev->interrupt_mask & INTERRUPT_MASK_RX) ? 0 - : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask - | INTERRUPT_MASK_RX); -} - -int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) -{ - return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 - : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask - | INTERRUPT_MASK_DISCONNECT); -} - -int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) -{ - return (dev->interrupt_mask & INTERRUPT_MASK_TX) - ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask - & ~INTERRUPT_MASK_TX) : 0; -} - -int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) -{ - return (dev->interrupt_mask & INTERRUPT_MASK_RX) - ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask - & ~INTERRUPT_MASK_RX) : 0; -} - -int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) -{ - return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) - ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask - & ~INTERRUPT_MASK_DISCONNECT) : 0; -} - -/** - * ps3_vuart_raw_write - Low level write helper. - * - * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write. - */ - -static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, - const void* buf, unsigned int bytes, unsigned long *bytes_written) -{ - int result; - - dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); - - result = lv1_write_virtual_uart(dev->port_number, - ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); - - if (result) { - dev_dbg(&dev->core, "%s:%d: lv1_write_virtual_uart failed: " - "%s\n", __func__, __LINE__, ps3_result(result)); - return result; - } - - dev->stats.bytes_written += *bytes_written; - - dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, - __LINE__, *bytes_written, bytes, dev->stats.bytes_written); - - return result; -} - -/** - * ps3_vuart_raw_read - Low level read helper. - * - * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read. - */ - -static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, - unsigned int bytes, unsigned long *bytes_read) -{ - int result; - - dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); - - result = lv1_read_virtual_uart(dev->port_number, - ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); - - if (result) { - dev_dbg(&dev->core, "%s:%d: lv1_read_virtual_uart failed: %s\n", - __func__, __LINE__, ps3_result(result)); - return result; - } - - dev->stats.bytes_read += *bytes_read; - - dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, - *bytes_read, bytes, dev->stats.bytes_read); - - return result; -} - -/** - * struct list_buffer - An element for a port device fifo buffer list. - */ - -struct list_buffer { - struct list_head link; - const unsigned char *head; - const unsigned char *tail; - unsigned long dbg_number; - unsigned char data[]; -}; - -/** - * ps3_vuart_write - the entry point for writing data to a port - * - * If the port is idle on entry as much of the incoming data is written to - * the port as the port will accept. Otherwise a list buffer is created - * and any remaning incoming data is copied to that buffer. The buffer is - * then enqueued for transmision via the transmit interrupt. - */ - -int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, - unsigned int bytes) -{ - static unsigned long dbg_number; - int result; - unsigned long flags; - struct list_buffer *lb; - - dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, - bytes, bytes); - - spin_lock_irqsave(&dev->tx_list.lock, flags); - - if (list_empty(&dev->tx_list.head)) { - unsigned long bytes_written; - - result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); - - spin_unlock_irqrestore(&dev->tx_list.lock, flags); - - if (result) { - dev_dbg(&dev->core, - "%s:%d: ps3_vuart_raw_write failed\n", - __func__, __LINE__); - return result; - } - - if (bytes_written == bytes) { - dev_dbg(&dev->core, "%s:%d: wrote %xh bytes\n", - __func__, __LINE__, bytes); - return 0; - } - - bytes -= bytes_written; - buf += bytes_written; - } else - spin_unlock_irqrestore(&dev->tx_list.lock, flags); - - lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); - - if (!lb) { - return -ENOMEM; - } - - memcpy(lb->data, buf, bytes); - lb->head = lb->data; - lb->tail = lb->data + bytes; - lb->dbg_number = ++dbg_number; - - spin_lock_irqsave(&dev->tx_list.lock, flags); - list_add_tail(&lb->link, &dev->tx_list.head); - ps3_vuart_enable_interrupt_tx(dev); - spin_unlock_irqrestore(&dev->tx_list.lock, flags); - - dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", - __func__, __LINE__, lb->dbg_number, bytes); - - return 0; -} - -/** - * ps3_vuart_read - the entry point for reading data from a port - * - * If enough bytes to satisfy the request are held in the buffer list those - * bytes are dequeued and copied to the caller's buffer. Emptied list buffers - * are retiered. If the request cannot be statified by bytes held in the list - * buffers -EAGAIN is returned. - */ - -int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, - unsigned int bytes) -{ - unsigned long flags; - struct list_buffer *lb, *n; - unsigned long bytes_read; - - dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, - bytes, bytes); - - spin_lock_irqsave(&dev->rx_list.lock, flags); - - if (dev->rx_list.bytes_held < bytes) { - spin_unlock_irqrestore(&dev->rx_list.lock, flags); - dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", - __func__, __LINE__, bytes - dev->rx_list.bytes_held); - return -EAGAIN; - } - - list_for_each_entry_safe(lb, n, &dev->rx_list.head, link) { - bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); - - memcpy(buf, lb->head, bytes_read); - buf += bytes_read; - bytes -= bytes_read; - dev->rx_list.bytes_held -= bytes_read; - - if (bytes_read < lb->tail - lb->head) { - lb->head += bytes_read; - spin_unlock_irqrestore(&dev->rx_list.lock, flags); - - dev_dbg(&dev->core, - "%s:%d: dequeued buf_%lu, %lxh bytes\n", - __func__, __LINE__, lb->dbg_number, bytes_read); - return 0; - } - - dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__, - lb->dbg_number); - - list_del(&lb->link); - kfree(lb); - } - spin_unlock_irqrestore(&dev->rx_list.lock, flags); - - dev_dbg(&dev->core, "%s:%d: dequeued buf_%lu, %xh bytes\n", - __func__, __LINE__, lb->dbg_number, bytes); - - return 0; -} - -/** - * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler - * - * Services the transmit interrupt for the port. Writes as much data from the - * buffer list as the port will accept. Retires any emptied list buffers and - * adjusts the final list buffer state for a partial write. - */ - -static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) -{ - int result = 0; - unsigned long flags; - struct list_buffer *lb, *n; - unsigned long bytes_total = 0; - - dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - - spin_lock_irqsave(&dev->tx_list.lock, flags); - - list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) { - - unsigned long bytes_written; - - result = ps3_vuart_raw_write(dev, lb->head, lb->tail - lb->head, - &bytes_written); - - if (result) { - dev_dbg(&dev->core, - "%s:%d: ps3_vuart_raw_write failed\n", - __func__, __LINE__); - break; - } - - bytes_total += bytes_written; - - if (bytes_written < lb->tail - lb->head) { - lb->head += bytes_written; - dev_dbg(&dev->core, - "%s:%d cleared buf_%lu, %lxh bytes\n", - __func__, __LINE__, lb->dbg_number, - bytes_written); - goto port_full; - } - - dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__, - lb->dbg_number); - - list_del(&lb->link); - kfree(lb); - } - - ps3_vuart_disable_interrupt_tx(dev); -port_full: - spin_unlock_irqrestore(&dev->tx_list.lock, flags); - dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", - __func__, __LINE__, bytes_total); - return result; -} - -/** - * ps3_vuart_handle_interrupt_rx - third stage receive interrupt handler - * - * Services the receive interrupt for the port. Creates a list buffer and - * copies all waiting port data to that buffer and enqueues the buffer in the - * buffer list. Buffer list data is dequeued via ps3_vuart_read. - */ - -static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) -{ - static unsigned long dbg_number; - int result = 0; - unsigned long flags; - struct list_buffer *lb; - unsigned long bytes; - - dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - - result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes); - - if (result) - return -EIO; - - BUG_ON(!bytes); - - /* add some extra space for recently arrived data */ - - bytes += 128; - - lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC); - - if (!lb) - return -ENOMEM; - - ps3_vuart_raw_read(dev, lb->data, bytes, &bytes); - - lb->head = lb->data; - lb->tail = lb->data + bytes; - lb->dbg_number = ++dbg_number; - - spin_lock_irqsave(&dev->rx_list.lock, flags); - list_add_tail(&lb->link, &dev->rx_list.head); - dev->rx_list.bytes_held += bytes; - spin_unlock_irqrestore(&dev->rx_list.lock, flags); - - dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n", - __func__, __LINE__, lb->dbg_number, bytes); - - return 0; -} - -static int ps3_vuart_handle_interrupt_disconnect( - struct ps3_vuart_port_device *dev) -{ - dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - BUG_ON("no support"); - return -1; -} - -/** - * ps3_vuart_handle_port_interrupt - second stage interrupt handler - * - * Services any pending interrupt types for the port. Passes control to the - * third stage type specific interrupt handler. Returns control to the first - * stage handler after one iteration. - */ - -static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) -{ - int result; - unsigned long status; - - result = ps3_vuart_get_interrupt_mask(dev, &status); - - if (result) - return result; - - dev_dbg(&dev->core, "%s:%d: status: %lxh\n", __func__, __LINE__, - status); - - if (status & INTERRUPT_MASK_DISCONNECT) { - dev->stats.disconnect_interrupts++; - result = ps3_vuart_handle_interrupt_disconnect(dev); - if (result) - ps3_vuart_disable_interrupt_disconnect(dev); - } - - if (status & INTERRUPT_MASK_TX) { - dev->stats.tx_interrupts++; - result = ps3_vuart_handle_interrupt_tx(dev); - if (result) - ps3_vuart_disable_interrupt_tx(dev); - } - - if (status & INTERRUPT_MASK_RX) { - dev->stats.rx_interrupts++; - result = ps3_vuart_handle_interrupt_rx(dev); - if (result) - ps3_vuart_disable_interrupt_rx(dev); - } - - return 0; -} - -struct vuart_private { - unsigned int in_use; - unsigned int virq; - struct ps3_vuart_port_device *devices[PORT_COUNT]; - const struct ports_bmp bmp; -}; - -/** - * ps3_vuart_irq_handler - first stage interrupt handler - * - * Loops finding any interrupting port and its associated instance data. - * Passes control to the second stage port specific interrupt handler. Loops - * until all outstanding interrupts are serviced. - */ - -static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) -{ - struct vuart_private *private; - - BUG_ON(!_private); - private = (struct vuart_private *)_private; - - while (1) { - unsigned int port; - - dump_ports_bmp(&private->bmp); - - port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status); - - if (port == BITS_PER_LONG) - break; - - BUG_ON(port >= PORT_COUNT); - BUG_ON(!private->devices[port]); - - ps3_vuart_handle_port_interrupt(private->devices[port]); - } - - return IRQ_HANDLED; -} - -static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv) -{ - int result; - struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv); - struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); - - result = dev->match_id == drv->match_id; - - dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, - __LINE__, dev->match_id, dev->core.bus_id, drv->match_id, - drv->core.name, (result ? "match" : "miss")); - - return result; -} - -static struct vuart_private vuart_private; - -static int ps3_vuart_probe(struct device *_dev) -{ - int result; - unsigned long tmp; - struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); - struct ps3_vuart_port_driver *drv = - to_ps3_vuart_port_driver(_dev->driver); - - dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - - BUG_ON(!drv); - - result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number); - - if (result) { - dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n", - __func__, __LINE__, dev->match_id); - result = -EINVAL; - goto fail_match; - } - - if (vuart_private.devices[dev->port_number]) { - dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, - __LINE__, dev->port_number); - result = -EBUSY; - goto fail_match; - } - - vuart_private.devices[dev->port_number] = dev; - - INIT_LIST_HEAD(&dev->tx_list.head); - spin_lock_init(&dev->tx_list.lock); - INIT_LIST_HEAD(&dev->rx_list.head); - spin_lock_init(&dev->rx_list.lock); - - vuart_private.in_use++; - if (vuart_private.in_use == 1) { - result = ps3_alloc_vuart_irq((void*)&vuart_private.bmp.status, - &vuart_private.virq); - - if (result) { - dev_dbg(&dev->core, - "%s:%d: ps3_alloc_vuart_irq failed (%d)\n", - __func__, __LINE__, result); - result = -EPERM; - goto fail_alloc_irq; - } - - result = request_irq(vuart_private.virq, ps3_vuart_irq_handler, - IRQF_DISABLED, "vuart", &vuart_private); - - if (result) { - dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n", - __func__, __LINE__, result); - goto fail_request_irq; - } - } - - ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX); - - /* clear stale pending interrupts */ - ps3_vuart_get_interrupt_mask(dev, &tmp); - - ps3_vuart_set_triggers(dev, 1, 1); - - if (drv->probe) - result = drv->probe(dev); - else { - result = 0; - dev_info(&dev->core, "%s:%d: no probe method\n", __func__, - __LINE__); - } - - if (result) { - dev_dbg(&dev->core, "%s:%d: drv->probe failed\n", - __func__, __LINE__); - goto fail_probe; - } - - return result; - -fail_probe: -fail_request_irq: - vuart_private.in_use--; - if (!vuart_private.in_use) { - ps3_free_vuart_irq(vuart_private.virq); - vuart_private.virq = NO_IRQ; - } -fail_alloc_irq: -fail_match: - dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); - return result; -} - -static int ps3_vuart_remove(struct device *_dev) -{ - struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); - struct ps3_vuart_port_driver *drv = - to_ps3_vuart_port_driver(_dev->driver); - - dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, - dev->core.bus_id); - - BUG_ON(vuart_private.in_use < 1); - - if (drv->remove) - drv->remove(dev); - else - dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__, - __LINE__, dev->core.bus_id); - - vuart_private.in_use--; - - if (!vuart_private.in_use) { - free_irq(vuart_private.virq, &vuart_private); - ps3_free_vuart_irq(vuart_private.virq); - vuart_private.virq = NO_IRQ; - } - return 0; -} - -/** - * ps3_vuart - The vuart instance. - * - * The vuart is managed as a bus that port devices connect to. - */ - -struct bus_type ps3_vuart = { - .name = "ps3_vuart", - .match = ps3_vuart_match, - .probe = ps3_vuart_probe, - .remove = ps3_vuart_remove, -}; - -int __init ps3_vuart_init(void) -{ - int result; - - pr_debug("%s:%d:\n", __func__, __LINE__); - result = bus_register(&ps3_vuart); - BUG_ON(result); - return result; -} - -void __exit ps3_vuart_exit(void) -{ - pr_debug("%s:%d:\n", __func__, __LINE__); - bus_unregister(&ps3_vuart); -} - -core_initcall(ps3_vuart_init); -module_exit(ps3_vuart_exit); - -/** - * ps3_vuart_port_release_device - Remove a vuart port device. - */ - -static void ps3_vuart_port_release_device(struct device *_dev) -{ - struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); -#if defined(DEBUG) - memset(dev, 0xad, sizeof(struct ps3_vuart_port_device)); -#endif - kfree(dev); -} - -/** - * ps3_vuart_port_device_register - Add a vuart port device. - */ - -int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev) -{ - int result; - static unsigned int dev_count = 1; - - dev->core.parent = NULL; - dev->core.bus = &ps3_vuart; - dev->core.release = ps3_vuart_port_release_device; - - snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x", - dev_count++); - - dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__); - - result = device_register(&dev->core); - - return result; -} - -EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); - -/** - * ps3_vuart_port_driver_register - Add a vuart port device driver. - */ - -int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv) -{ - int result; - - pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); - drv->core.bus = &ps3_vuart; - result = driver_register(&drv->core); - return result; -} - -EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); - -/** - * ps3_vuart_port_driver_unregister - Remove a vuart port device driver. - */ - -void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) -{ - driver_unregister(&drv->core); -} - -EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); diff --git a/trunk/drivers/ps3/vuart.h b/trunk/drivers/ps3/vuart.h deleted file mode 100644 index 28fd89f0c8aa..000000000000 --- a/trunk/drivers/ps3/vuart.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * PS3 virtual uart - * - * Copyright (C) 2006 Sony Computer Entertainment Inc. - * Copyright 2006 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 - */ - -#if !defined(_PS3_VUART_H) -#define _PS3_VUART_H - -struct ps3_vuart_stats { - unsigned long bytes_written; - unsigned long bytes_read; - unsigned long tx_interrupts; - unsigned long rx_interrupts; - unsigned long disconnect_interrupts; -}; - -/** - * struct ps3_vuart_port_device - a device on a vuart port - */ - -struct ps3_vuart_port_device { - enum ps3_match_id match_id; - struct device core; - - /* private driver variables */ - unsigned int port_number; - unsigned long interrupt_mask; - struct { - spinlock_t lock; - struct list_head head; - } tx_list; - struct { - unsigned long bytes_held; - spinlock_t lock; - struct list_head head; - } rx_list; - struct ps3_vuart_stats stats; -}; - -/** - * struct ps3_vuart_port_driver - a driver for a device on a vuart port - */ - -struct ps3_vuart_port_driver { - enum ps3_match_id match_id; - struct device_driver core; - int (*probe)(struct ps3_vuart_port_device *); - int (*remove)(struct ps3_vuart_port_device *); - int (*tx_event)(struct ps3_vuart_port_device *dev); - int (*rx_event)(struct ps3_vuart_port_device *dev); - int (*disconnect_event)(struct ps3_vuart_port_device *dev); - /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */ - /* int (*resume)(struct ps3_vuart_port_device *); */ -}; - -int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev); -int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv); -void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv); -int ps3_vuart_write(struct ps3_vuart_port_device *dev, - const void* buf, unsigned int bytes); -int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, - unsigned int bytes); -static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver( - struct device_driver *_drv) -{ - return container_of(_drv, struct ps3_vuart_port_driver, core); -} -static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device( - struct device *_dev) -{ - return container_of(_dev, struct ps3_vuart_port_device, core); -} - -int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, - unsigned int bytes); -int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, - unsigned int bytes); - -#endif diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index 09660e2ab051..2a63ab2b47f4 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -288,7 +288,7 @@ config RTC_DRV_PL031 To compile this driver as a module, choose M here: the module will be called rtc-pl031. -config RTC_DRV_AT91RM9200 +config RTC_DRV_AT91 tristate "AT91RM9200" depends on RTC_CLASS && ARCH_AT91RM9200 help diff --git a/trunk/drivers/rtc/Makefile b/trunk/drivers/rtc/Makefile index e6beedacc966..bd4c45d333f0 100644 --- a/trunk/drivers/rtc/Makefile +++ b/trunk/drivers/rtc/Makefile @@ -35,5 +35,5 @@ obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o -obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o +obj-$(CONFIG_RTC_DRV_AT91) += rtc-at91.o obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o diff --git a/trunk/drivers/rtc/rtc-at91rm9200.c b/trunk/drivers/rtc/rtc-at91.c similarity index 99% rename from trunk/drivers/rtc/rtc-at91rm9200.c rename to trunk/drivers/rtc/rtc-at91.c index 4f654c901c64..5c8addcaf1fb 100644 --- a/trunk/drivers/rtc/rtc-at91rm9200.c +++ b/trunk/drivers/rtc/rtc-at91.c @@ -137,9 +137,6 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); tm->tm_year = at91_alarm_year - 1900; - alrm->enabled = (at91_sys_read(AT91_RTC_IMR) & AT91_RTC_ALARM) - ? 1 : 0; - pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -226,6 +223,8 @@ static int at91_rtc_proc(struct device *dev, struct seq_file *seq) { unsigned long imr = at91_sys_read(AT91_RTC_IMR); + seq_printf(seq, "alarm_IRQ\t: %s\n", + (imr & AT91_RTC_ALARM) ? "yes" : "no"); seq_printf(seq, "update_IRQ\t: %s\n", (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); seq_printf(seq, "periodic_IRQ\t: %s\n", diff --git a/trunk/drivers/rtc/rtc-dev.c b/trunk/drivers/rtc/rtc-dev.c index 94d3df62a5fa..828b329e08e0 100644 --- a/trunk/drivers/rtc/rtc-dev.c +++ b/trunk/drivers/rtc/rtc-dev.c @@ -435,7 +435,7 @@ static int rtc_dev_add_device(struct class_device *class_dev, goto err_cdev_del; } - dev_dbg(class_dev->dev, "rtc intf: dev (%d:%d)\n", + dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n", MAJOR(rtc->rtc_dev->devt), MINOR(rtc->rtc_dev->devt)); diff --git a/trunk/drivers/rtc/rtc-ds1672.c b/trunk/drivers/rtc/rtc-ds1672.c index 205fa28593b7..dfef1637bfb8 100644 --- a/trunk/drivers/rtc/rtc-ds1672.c +++ b/trunk/drivers/rtc/rtc-ds1672.c @@ -199,7 +199,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) struct i2c_client *client; struct rtc_device *rtc; - dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__); + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { err = -ENODEV; diff --git a/trunk/drivers/rtc/rtc-lib.c b/trunk/drivers/rtc/rtc-lib.c index 7bbc26a34bd2..ba795a4db1e9 100644 --- a/trunk/drivers/rtc/rtc-lib.c +++ b/trunk/drivers/rtc/rtc-lib.c @@ -117,85 +117,4 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) } EXPORT_SYMBOL(rtc_tm_to_time); - -/* Merge the valid (i.e. non-negative) fields of alarm into the current - * time. If the valid alarm fields are earlier than the equivalent - * fields in the time, carry one into the least significant invalid - * field, so that the alarm expiry is in the future. It assumes that the - * least significant invalid field is more significant than the most - * significant valid field, and that the seconds field is valid. - * - * This is used by alarms that take relative (rather than absolute) - * times, and/or have a simple binary second counter instead of - * day/hour/minute/sec registers. - */ -void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm) -{ - int *alarmp = &alarm->tm_sec; - int *timep = &now->tm_sec; - int carry_into, i; - - /* Ignore everything past the 6th element (tm_year). */ - for (i = 5; i > 0; i--) { - if (alarmp[i] < 0) - alarmp[i] = timep[i]; - else - break; - } - - /* No carry needed if all fields are valid. */ - if (i == 5) - return; - - for (carry_into = i + 1; i >= 0; i--) { - if (alarmp[i] < timep[i]) - break; - - if (alarmp[i] > timep[i]) - return; - } - - switch (carry_into) { - case 1: - alarm->tm_min++; - - if (alarm->tm_min < 60) - return; - - alarm->tm_min = 0; - /* fall-through */ - - case 2: - alarm->tm_hour++; - - if (alarm->tm_hour < 60) - return; - - alarm->tm_hour = 0; - /* fall-through */ - - case 3: - alarm->tm_mday++; - - if (alarm->tm_mday <= rtc_days_in_month[alarm->tm_mon]) - return; - - alarm->tm_mday = 1; - /* fall-through */ - - case 4: - alarm->tm_mon++; - - if (alarm->tm_mon <= 12) - return; - - alarm->tm_mon = 1; - /* fall-through */ - - case 5: - alarm->tm_year++; - } -} -EXPORT_SYMBOL(rtc_merge_alarm); - MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-omap.c b/trunk/drivers/rtc/rtc-omap.c index d59880d44fba..eac5fb1fc02f 100644 --- a/trunk/drivers/rtc/rtc-omap.c +++ b/trunk/drivers/rtc/rtc-omap.c @@ -279,8 +279,9 @@ static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) local_irq_enable(); bcd2tm(&alm->time); - alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG) + alm->pending = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG) & OMAP_RTC_INTERRUPTS_IT_ALARM); + alm->enabled = alm->pending && device_may_wakeup(dev); return 0; } diff --git a/trunk/drivers/rtc/rtc-pcf8563.c b/trunk/drivers/rtc/rtc-pcf8563.c index 4b72b8ef5d66..a760cf69af90 100644 --- a/trunk/drivers/rtc/rtc-pcf8563.c +++ b/trunk/drivers/rtc/rtc-pcf8563.c @@ -192,7 +192,7 @@ static int pcf8563_validate_client(struct i2c_client *client) xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (xfer != ARRAY_SIZE(msgs)) { - dev_err(&client->dev, + dev_err(&client->adapter->dev, "%s: could not read register 0x%02X\n", __FUNCTION__, pattern[i].reg); @@ -203,7 +203,7 @@ static int pcf8563_validate_client(struct i2c_client *client) if (value > pattern[i].max || value < pattern[i].min) { - dev_dbg(&client->dev, + dev_dbg(&client->adapter->dev, "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " "max=%d, value=%d, raw=0x%02X\n", __FUNCTION__, i, pattern[i].reg, pattern[i].mask, @@ -253,7 +253,7 @@ static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) int err = 0; - dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__); + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { err = -ENODEV; diff --git a/trunk/drivers/rtc/rtc-proc.c b/trunk/drivers/rtc/rtc-proc.c index c272afd62173..d51d8f20e634 100644 --- a/trunk/drivers/rtc/rtc-proc.c +++ b/trunk/drivers/rtc/rtc-proc.c @@ -65,7 +65,7 @@ static int rtc_proc_show(struct seq_file *seq, void *offset) seq_printf(seq, "%02d\n", alrm.time.tm_mday); else seq_printf(seq, "**\n"); - seq_printf(seq, "alarm_IRQ\t: %s\n", + seq_printf(seq, "alrm_wakeup\t: %s\n", alrm.enabled ? "yes" : "no"); seq_printf(seq, "alrm_pending\t: %s\n", alrm.pending ? "yes" : "no"); @@ -120,7 +120,7 @@ static int rtc_proc_add_device(struct class_device *class_dev, ent->owner = rtc->owner; ent->data = class_dev; - dev_dbg(class_dev->dev, "rtc intf: proc\n"); + dev_info(class_dev->dev, "rtc intf: proc\n"); } else rtc_dev = NULL; diff --git a/trunk/drivers/rtc/rtc-rs5c372.c b/trunk/drivers/rtc/rtc-rs5c372.c index 1460f6b769f2..e2c7698fdba3 100644 --- a/trunk/drivers/rtc/rtc-rs5c372.c +++ b/trunk/drivers/rtc/rtc-rs5c372.c @@ -200,7 +200,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) struct i2c_client *client; struct rs5c372 *rs5c372; - dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__); + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { err = -ENODEV; diff --git a/trunk/drivers/rtc/rtc-s3c.c b/trunk/drivers/rtc/rtc-s3c.c index f406a2b55aea..e301dea57bb3 100644 --- a/trunk/drivers/rtc/rtc-s3c.c +++ b/trunk/drivers/rtc/rtc-s3c.c @@ -191,8 +191,6 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) alm_en = readb(base + S3C2410_RTCALM); - alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; - pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", alm_en, alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, @@ -333,8 +331,12 @@ static int s3c_rtc_ioctl(struct device *dev, static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) { + unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM); unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); + seq_printf(seq, "alarm_IRQ\t: %s\n", + (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" ); + seq_printf(seq, "periodic_IRQ\t: %s\n", (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); diff --git a/trunk/drivers/rtc/rtc-sa1100.c b/trunk/drivers/rtc/rtc-sa1100.c index 9c8ead43a59c..bd4d7d174ef4 100644 --- a/trunk/drivers/rtc/rtc-sa1100.c +++ b/trunk/drivers/rtc/rtc-sa1100.c @@ -289,7 +289,9 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) { - seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR); + seq_printf(seq, "trim/divider\t: 0x%08lx\n", RTTR); + seq_printf(seq, "alarm_IRQ\t: %s\n", + (RTSR & RTSR_ALE) ? "yes" : "no" ); seq_printf(seq, "update_IRQ\t: %s\n", (RTSR & RTSR_HZE) ? "yes" : "no"); seq_printf(seq, "periodic_IRQ\t: %s\n", diff --git a/trunk/drivers/rtc/rtc-sh.c b/trunk/drivers/rtc/rtc-sh.c index 72ba1a70f35f..143302a8e79c 100644 --- a/trunk/drivers/rtc/rtc-sh.c +++ b/trunk/drivers/rtc/rtc-sh.c @@ -2,7 +2,6 @@ * SuperH On-Chip RTC Support * * Copyright (C) 2006 Paul Mundt - * Copyright (C) 2006 Jamie Lenehan * * Based on the old arch/sh/kernel/cpu/rtc.c by: * @@ -22,10 +21,7 @@ #include #include #include -#include - -#define DRV_NAME "sh-rtc" -#define DRV_VERSION "0.1.2" +#include #ifdef CONFIG_CPU_SH3 #define rtc_reg_size sizeof(u16) @@ -37,26 +33,22 @@ #define RTC_REG(r) ((r) * rtc_reg_size) -#define R64CNT RTC_REG(0) - -#define RSECCNT RTC_REG(1) /* RTC sec */ -#define RMINCNT RTC_REG(2) /* RTC min */ -#define RHRCNT RTC_REG(3) /* RTC hour */ -#define RWKCNT RTC_REG(4) /* RTC week */ -#define RDAYCNT RTC_REG(5) /* RTC day */ -#define RMONCNT RTC_REG(6) /* RTC month */ -#define RYRCNT RTC_REG(7) /* RTC year */ -#define RSECAR RTC_REG(8) /* ALARM sec */ -#define RMINAR RTC_REG(9) /* ALARM min */ -#define RHRAR RTC_REG(10) /* ALARM hour */ -#define RWKAR RTC_REG(11) /* ALARM week */ -#define RDAYAR RTC_REG(12) /* ALARM day */ -#define RMONAR RTC_REG(13) /* ALARM month */ -#define RCR1 RTC_REG(14) /* Control */ -#define RCR2 RTC_REG(15) /* Control */ - -/* ALARM Bits - or with BCD encoded value */ -#define AR_ENB 0x80 /* Enable for alarm cmp */ +#define R64CNT RTC_REG(0) +#define RSECCNT RTC_REG(1) +#define RMINCNT RTC_REG(2) +#define RHRCNT RTC_REG(3) +#define RWKCNT RTC_REG(4) +#define RDAYCNT RTC_REG(5) +#define RMONCNT RTC_REG(6) +#define RYRCNT RTC_REG(7) +#define RSECAR RTC_REG(8) +#define RMINAR RTC_REG(9) +#define RHRAR RTC_REG(10) +#define RWKAR RTC_REG(11) +#define RDAYAR RTC_REG(12) +#define RMONAR RTC_REG(13) +#define RCR1 RTC_REG(14) +#define RCR2 RTC_REG(15) /* RCR1 Bits */ #define RCR1_CF 0x80 /* Carry Flag */ @@ -79,28 +71,22 @@ struct sh_rtc { unsigned int alarm_irq, periodic_irq, carry_irq; struct rtc_device *rtc_dev; spinlock_t lock; - int rearm_aie; }; -static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) +static irqreturn_t sh_rtc_interrupt(int irq, void *id) { - struct platform_device *pdev = to_platform_device(dev_id); + struct platform_device *pdev = id; struct sh_rtc *rtc = platform_get_drvdata(pdev); unsigned int tmp, events = 0; spin_lock(&rtc->lock); tmp = readb(rtc->regbase + RCR1); - tmp &= ~RCR1_CF; - if (rtc->rearm_aie) { - if (tmp & RCR1_AF) - tmp &= ~RCR1_AF; /* try to clear AF again */ - else { - tmp |= RCR1_AIE; /* AF has cleared, rearm IRQ */ - rtc->rearm_aie = 0; - } - } + if (tmp & RCR1_AF) + events |= RTC_AF | RTC_IRQF; + + tmp &= ~(RCR1_CF | RCR1_AF); writeb(tmp, rtc->regbase + RCR1); @@ -111,45 +97,9 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) -{ - struct platform_device *pdev = to_platform_device(dev_id); - struct sh_rtc *rtc = platform_get_drvdata(pdev); - unsigned int tmp, events = 0; - - spin_lock(&rtc->lock); - - tmp = readb(rtc->regbase + RCR1); - - /* - * If AF is set then the alarm has triggered. If we clear AF while - * the alarm time still matches the RTC time then AF will - * immediately be set again, and if AIE is enabled then the alarm - * interrupt will immediately be retrigger. So we clear AIE here - * and use rtc->rearm_aie so that the carry interrupt will keep - * trying to clear AF and once it stays cleared it'll re-enable - * AIE. - */ - if (tmp & RCR1_AF) { - events |= RTC_AF | RTC_IRQF; - - tmp &= ~(RCR1_AF|RCR1_AIE); - - writeb(tmp, rtc->regbase + RCR1); - - rtc->rearm_aie = 1; - - rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events); - } - - spin_unlock(&rtc->lock); - return IRQ_HANDLED; -} - -static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) +static irqreturn_t sh_rtc_periodic(int irq, void *id) { - struct platform_device *pdev = to_platform_device(dev_id); - struct sh_rtc *rtc = platform_get_drvdata(pdev); + struct sh_rtc *rtc = dev_get_drvdata(id); spin_lock(&rtc->lock); @@ -189,11 +139,10 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable) tmp = readb(rtc->regbase + RCR1); - if (!enable) { - tmp &= ~RCR1_AIE; - rtc->rearm_aie = 0; - } else if (rtc->rearm_aie == 0) + if (enable) tmp |= RCR1_AIE; + else + tmp &= ~RCR1_AIE; writeb(tmp, rtc->regbase + RCR1); @@ -228,7 +177,7 @@ static int sh_rtc_open(struct device *dev) goto err_bad_carry; } - ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED, + ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, IRQF_DISABLED, "sh-rtc alarm", dev); if (unlikely(ret)) { dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n", @@ -251,7 +200,6 @@ static void sh_rtc_release(struct device *dev) struct sh_rtc *rtc = dev_get_drvdata(dev); sh_rtc_setpie(dev, 0); - sh_rtc_setaie(dev, 0); free_irq(rtc->periodic_irq, dev); free_irq(rtc->carry_irq, dev); @@ -319,7 +267,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_hour = BCD2BIN(readb(rtc->regbase + RHRCNT)); tm->tm_wday = BCD2BIN(readb(rtc->regbase + RWKCNT)); tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT)); - tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1; + tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)); #if defined(CONFIG_CPU_SH4) yr = readw(rtc->regbase + RYRCNT); @@ -347,7 +295,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); if (rtc_valid_tm(tm) < 0) dev_err(dev, "invalid date\n"); @@ -374,7 +322,7 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT); writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT); writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT); - writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT); + writeb(BIN2BCD(tm->tm_mon), rtc->regbase + RMONCNT); #ifdef CONFIG_CPU_SH3 year = tm->tm_year % 100; @@ -396,136 +344,12 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) return 0; } -static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off) -{ - unsigned int byte; - int value = 0xff; /* return 0xff for ignored values */ - - byte = readb(rtc->regbase + reg_off); - if (byte & AR_ENB) { - byte &= ~AR_ENB; /* strip the enable bit */ - value = BCD2BIN(byte); - } - - return value; -} - -static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct sh_rtc *rtc = platform_get_drvdata(pdev); - struct rtc_time* tm = &wkalrm->time; - - spin_lock_irq(&rtc->lock); - - tm->tm_sec = sh_rtc_read_alarm_value(rtc, RSECAR); - tm->tm_min = sh_rtc_read_alarm_value(rtc, RMINAR); - tm->tm_hour = sh_rtc_read_alarm_value(rtc, RHRAR); - tm->tm_wday = sh_rtc_read_alarm_value(rtc, RWKAR); - tm->tm_mday = sh_rtc_read_alarm_value(rtc, RDAYAR); - tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR); - if (tm->tm_mon > 0) - tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ - tm->tm_year = 0xffff; - - spin_unlock_irq(&rtc->lock); - - return 0; -} - -static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc, - int value, int reg_off) -{ - /* < 0 for a value that is ignored */ - if (value < 0) - writeb(0, rtc->regbase + reg_off); - else - writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off); -} - -static int sh_rtc_check_alarm(struct rtc_time* tm) -{ - /* - * The original rtc says anything > 0xc0 is "don't care" or "match - * all" - most users use 0xff but rtc-dev uses -1 for the same thing. - * The original rtc doesn't support years - some things use -1 and - * some 0xffff. We use -1 to make out tests easier. - */ - if (tm->tm_year == 0xffff) - tm->tm_year = -1; - if (tm->tm_mon >= 0xff) - tm->tm_mon = -1; - if (tm->tm_mday >= 0xff) - tm->tm_mday = -1; - if (tm->tm_wday >= 0xff) - tm->tm_wday = -1; - if (tm->tm_hour >= 0xff) - tm->tm_hour = -1; - if (tm->tm_min >= 0xff) - tm->tm_min = -1; - if (tm->tm_sec >= 0xff) - tm->tm_sec = -1; - - if (tm->tm_year > 9999 || - tm->tm_mon >= 12 || - tm->tm_mday == 0 || tm->tm_mday >= 32 || - tm->tm_wday >= 7 || - tm->tm_hour >= 24 || - tm->tm_min >= 60 || - tm->tm_sec >= 60) - return -EINVAL; - - return 0; -} - -static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct sh_rtc *rtc = platform_get_drvdata(pdev); - unsigned int rcr1; - struct rtc_time *tm = &wkalrm->time; - int mon, err; - - err = sh_rtc_check_alarm(tm); - if (unlikely(err < 0)) - return err; - - spin_lock_irq(&rtc->lock); - - /* disable alarm interrupt and clear flag */ - rcr1 = readb(rtc->regbase + RCR1); - rcr1 &= ~RCR1_AF; - writeb(rcr1 & ~RCR1_AIE, rtc->regbase + RCR1); - - rtc->rearm_aie = 0; - - /* set alarm time */ - sh_rtc_write_alarm_value(rtc, tm->tm_sec, RSECAR); - sh_rtc_write_alarm_value(rtc, tm->tm_min, RMINAR); - sh_rtc_write_alarm_value(rtc, tm->tm_hour, RHRAR); - sh_rtc_write_alarm_value(rtc, tm->tm_wday, RWKAR); - sh_rtc_write_alarm_value(rtc, tm->tm_mday, RDAYAR); - mon = tm->tm_mon; - if (mon >= 0) - mon += 1; - sh_rtc_write_alarm_value(rtc, mon, RMONAR); - - /* Restore interrupt activation status */ - writeb(rcr1, rtc->regbase + RCR1); - - spin_unlock_irq(&rtc->lock); - - return 0; -} - static struct rtc_class_ops sh_rtc_ops = { .open = sh_rtc_open, .release = sh_rtc_release, .ioctl = sh_rtc_ioctl, .read_time = sh_rtc_read_time, .set_time = sh_rtc_set_time, - .read_alarm = sh_rtc_read_alarm, - .set_alarm = sh_rtc_set_alarm, .proc = sh_rtc_proc, }; @@ -618,7 +442,7 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) } static struct platform_driver sh_rtc_platform_driver = { .driver = { - .name = DRV_NAME, + .name = "sh-rtc", .owner = THIS_MODULE, }, .probe = sh_rtc_probe, @@ -639,6 +463,5 @@ module_init(sh_rtc_init); module_exit(sh_rtc_exit); MODULE_DESCRIPTION("SuperH on-chip RTC driver"); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR("Paul Mundt , Jamie Lenehan "); +MODULE_AUTHOR("Paul Mundt "); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-sysfs.c b/trunk/drivers/rtc/rtc-sysfs.c index 9418a59fb368..625637b84d33 100644 --- a/trunk/drivers/rtc/rtc-sysfs.c +++ b/trunk/drivers/rtc/rtc-sysfs.c @@ -83,7 +83,7 @@ static int __devinit rtc_sysfs_add_device(struct class_device *class_dev, { int err; - dev_dbg(class_dev->dev, "rtc intf: sysfs\n"); + dev_info(class_dev->dev, "rtc intf: sysfs\n"); err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group); if (err) diff --git a/trunk/drivers/rtc/rtc-x1205.c b/trunk/drivers/rtc/rtc-x1205.c index 019ae255b0c8..9a67487d086b 100644 --- a/trunk/drivers/rtc/rtc-x1205.c +++ b/trunk/drivers/rtc/rtc-x1205.c @@ -372,7 +372,7 @@ static int x1205_validate_client(struct i2c_client *client) }; if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { - dev_err(&client->dev, + dev_err(&client->adapter->dev, "%s: could not read register %x\n", __FUNCTION__, probe_zero_pattern[i]); @@ -380,7 +380,7 @@ static int x1205_validate_client(struct i2c_client *client) } if ((buf & probe_zero_pattern[i+1]) != 0) { - dev_err(&client->dev, + dev_err(&client->adapter->dev, "%s: register=%02x, zero pattern=%d, value=%x\n", __FUNCTION__, probe_zero_pattern[i], i, buf); @@ -400,7 +400,7 @@ static int x1205_validate_client(struct i2c_client *client) }; if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { - dev_err(&client->dev, + dev_err(&client->adapter->dev, "%s: could not read register %x\n", __FUNCTION__, probe_limits_pattern[i].reg); @@ -411,7 +411,7 @@ static int x1205_validate_client(struct i2c_client *client) if (value > probe_limits_pattern[i].max || value < probe_limits_pattern[i].min) { - dev_dbg(&client->dev, + dev_dbg(&client->adapter->dev, "%s: register=%x, lim pattern=%d, value=%d\n", __FUNCTION__, probe_limits_pattern[i].reg, i, value); @@ -506,7 +506,7 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) struct i2c_client *client; struct rtc_device *rtc; - dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__); + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { err = -ENODEV; diff --git a/trunk/drivers/s390/char/con3215.c b/trunk/drivers/s390/char/con3215.c index 25b5d7a66417..c9321b920e90 100644 --- a/trunk/drivers/s390/char/con3215.c +++ b/trunk/drivers/s390/char/con3215.c @@ -688,7 +688,7 @@ raw3215_probe (struct ccw_device *cdev) raw->cdev = cdev; raw->inbuf = (char *) raw + sizeof(struct raw3215_info); memset(raw, 0, sizeof(struct raw3215_info)); - raw->buffer = kmalloc(RAW3215_BUFFER_SIZE, + raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL|GFP_DMA); if (raw->buffer == NULL) { spin_lock(&raw3215_device_lock); diff --git a/trunk/drivers/s390/char/keyboard.c b/trunk/drivers/s390/char/keyboard.c index 3e86fd1756e5..e3491a5f5219 100644 --- a/trunk/drivers/s390/char/keyboard.c +++ b/trunk/drivers/s390/char/keyboard.c @@ -377,7 +377,7 @@ do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry __user *user_kbe, if (!(key_map = kbd->key_maps[tmp.kb_table])) { int j; - key_map = kmalloc(sizeof(plain_map), + key_map = (ushort *) kmalloc(sizeof(plain_map), GFP_KERNEL); if (!key_map) return -ENOMEM; diff --git a/trunk/drivers/s390/char/sclp_cpi.c b/trunk/drivers/s390/char/sclp_cpi.c index f7c10d954ec6..732dfbdb85c4 100644 --- a/trunk/drivers/s390/char/sclp_cpi.c +++ b/trunk/drivers/s390/char/sclp_cpi.c @@ -127,7 +127,7 @@ cpi_prepare_req(void) struct cpi_sccb *sccb; struct cpi_evbuf *evb; - req = kmalloc(sizeof(struct sclp_req), GFP_KERNEL); + req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL); if (req == NULL) return ERR_PTR(-ENOMEM); sccb = (struct cpi_sccb *) __get_free_page(GFP_KERNEL | GFP_DMA); diff --git a/trunk/drivers/s390/crypto/zcrypt_cex2a.c b/trunk/drivers/s390/crypto/zcrypt_cex2a.c index 5bb13a9d0898..a62b00083d0c 100644 --- a/trunk/drivers/s390/crypto/zcrypt_cex2a.c +++ b/trunk/drivers/s390/crypto/zcrypt_cex2a.c @@ -295,7 +295,7 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, struct completion work; int rc; - ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); + ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); if (!ap_msg.message) return -ENOMEM; ap_msg.psmid = (((unsigned long long) current->pid) << 32) + @@ -337,7 +337,7 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, struct completion work; int rc; - ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); + ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); if (!ap_msg.message) return -ENOMEM; ap_msg.psmid = (((unsigned long long) current->pid) << 32) + diff --git a/trunk/drivers/s390/crypto/zcrypt_pcica.c b/trunk/drivers/s390/crypto/zcrypt_pcica.c index 32e37014345c..b6a4ecdc8025 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcica.c +++ b/trunk/drivers/s390/crypto/zcrypt_pcica.c @@ -279,7 +279,7 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev, struct completion work; int rc; - ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); + ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); if (!ap_msg.message) return -ENOMEM; ap_msg.psmid = (((unsigned long long) current->pid) << 32) + @@ -321,7 +321,7 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev, struct completion work; int rc; - ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); + ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); if (!ap_msg.message) return -ENOMEM; ap_msg.psmid = (((unsigned long long) current->pid) << 32) + diff --git a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c index b7153c1e15cd..2da8b9381407 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c @@ -717,7 +717,7 @@ long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB) }; int rc; - ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); + ap_msg.message = (void *) kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); if (!ap_msg.message) return -ENOMEM; ap_msg.psmid = (((unsigned long long) current->pid) << 32) + diff --git a/trunk/drivers/s390/net/ctcmain.c b/trunk/drivers/s390/net/ctcmain.c index 03cc263fe0da..3257c22dd79c 100644 --- a/trunk/drivers/s390/net/ctcmain.c +++ b/trunk/drivers/s390/net/ctcmain.c @@ -1646,7 +1646,7 @@ add_channel(struct ccw_device *cdev, enum channel_types type) return -1; } memset(ch, 0, sizeof (struct channel)); - if ((ch->ccw = kmalloc(8*sizeof(struct ccw1), + if ((ch->ccw = (struct ccw1 *) kmalloc(8*sizeof(struct ccw1), GFP_KERNEL | GFP_DMA)) == NULL) { kfree(ch); ctc_pr_warn("ctc: Out of memory in add_channel\n"); @@ -1693,7 +1693,7 @@ add_channel(struct ccw_device *cdev, enum channel_types type) return -1; } fsm_newstate(ch->fsm, CH_STATE_IDLE); - if ((ch->irb = kmalloc(sizeof (struct irb), + if ((ch->irb = (struct irb *) kmalloc(sizeof (struct irb), GFP_KERNEL)) == NULL) { ctc_pr_warn("ctc: Out of memory in add_channel\n"); kfree_fsm(ch->fsm); @@ -2535,7 +2535,7 @@ ctc_print_statistics(struct ctc_priv *priv) DBF_TEXT(trace, 4, __FUNCTION__); if (!priv) return; - sbuf = kmalloc(2048, GFP_KERNEL); + sbuf = (char *)kmalloc(2048, GFP_KERNEL); if (sbuf == NULL) return; p = sbuf; diff --git a/trunk/drivers/s390/net/iucv.c b/trunk/drivers/s390/net/iucv.c index 229aeb5fc399..1476ce2b437c 100644 --- a/trunk/drivers/s390/net/iucv.c +++ b/trunk/drivers/s390/net/iucv.c @@ -772,7 +772,7 @@ iucv_register_program (__u8 pgmname[16], } /* Allocate handler entry */ - new_handler = kmalloc(sizeof(handler), GFP_ATOMIC); + new_handler = (handler *)kmalloc(sizeof(handler), GFP_ATOMIC); if (new_handler == NULL) { printk(KERN_WARNING "%s: storage allocation for new handler " "failed.\n", __FUNCTION__); diff --git a/trunk/drivers/s390/scsi/zfcp_aux.c b/trunk/drivers/s390/scsi/zfcp_aux.c index 85093b71f9fa..5d39b2df0cc4 100644 --- a/trunk/drivers/s390/scsi/zfcp_aux.c +++ b/trunk/drivers/s390/scsi/zfcp_aux.c @@ -237,7 +237,7 @@ zfcp_device_setup(char *devstr) return 0; len = strlen(devstr) + 1; - str = kmalloc(len, GFP_KERNEL); + str = (char *) kmalloc(len, GFP_KERNEL); if (!str) goto err_out; memcpy(str, devstr, len); diff --git a/trunk/drivers/sbus/char/vfc_dev.c b/trunk/drivers/sbus/char/vfc_dev.c index 386e7de0b7e3..2722af5d3404 100644 --- a/trunk/drivers/sbus/char/vfc_dev.c +++ b/trunk/drivers/sbus/char/vfc_dev.c @@ -659,7 +659,7 @@ static int vfc_probe(void) if (!cards) return -ENODEV; - vfc_dev_lst = kmalloc(sizeof(struct vfc_dev *) * + vfc_dev_lst = (struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *) * (cards+1), GFP_KERNEL); if (vfc_dev_lst == NULL) diff --git a/trunk/drivers/scsi/aacraid/aachba.c b/trunk/drivers/scsi/aacraid/aachba.c index 426cd6f49f5d..ac108f9e2674 100644 --- a/trunk/drivers/scsi/aacraid/aachba.c +++ b/trunk/drivers/scsi/aacraid/aachba.c @@ -288,7 +288,7 @@ int aac_get_containers(struct aac_dev *dev) if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) maximum_num_containers = MAXIMUM_NUM_CONTAINERS; - fsa_dev_ptr = kmalloc( + fsa_dev_ptr = (struct fsa_dev_info *) kmalloc( sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL); if (!fsa_dev_ptr) { aac_fib_free(fibptr); diff --git a/trunk/drivers/scsi/aacraid/comminit.c b/trunk/drivers/scsi/aacraid/comminit.c index 6d305b2f854e..d5cf8b91a0e7 100644 --- a/trunk/drivers/scsi/aacraid/comminit.c +++ b/trunk/drivers/scsi/aacraid/comminit.c @@ -386,7 +386,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) * Ok now init the communication subsystem */ - dev->queues = kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL); + dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL); if (dev->queues == NULL) { printk(KERN_ERR "Error could not allocate comm region.\n"); return NULL; diff --git a/trunk/drivers/scsi/aha1542.c b/trunk/drivers/scsi/aha1542.c index 1d239f6c0103..d7a61a6bdaae 100644 --- a/trunk/drivers/scsi/aha1542.c +++ b/trunk/drivers/scsi/aha1542.c @@ -699,7 +699,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) #endif int i; ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */ - SCpnt->host_scribble = kmalloc(512, GFP_KERNEL | GFP_DMA); + SCpnt->host_scribble = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA); sgpnt = (struct scatterlist *) SCpnt->request_buffer; cptr = (struct chain *) SCpnt->host_scribble; if (cptr == NULL) { diff --git a/trunk/drivers/scsi/aic7xxx_old.c b/trunk/drivers/scsi/aic7xxx_old.c index 7d1fec620948..46eed10b25d9 100644 --- a/trunk/drivers/scsi/aic7xxx_old.c +++ b/trunk/drivers/scsi/aic7xxx_old.c @@ -2565,7 +2565,7 @@ aic7xxx_allocate_scb(struct aic7xxx_host *p) } } scb_count = min( (i-1), p->scb_data->maxscbs - p->scb_data->numscbs); - scb_ap = kmalloc(sizeof (struct aic7xxx_scb) * scb_count + scb_ap = (struct aic7xxx_scb *)kmalloc(sizeof (struct aic7xxx_scb) * scb_count + sizeof(struct aic7xxx_scb_dma), GFP_ATOMIC); if (scb_ap == NULL) return(0); diff --git a/trunk/drivers/scsi/dc395x.c b/trunk/drivers/scsi/dc395x.c index a965ed3548d5..e95b367d09ed 100644 --- a/trunk/drivers/scsi/dc395x.c +++ b/trunk/drivers/scsi/dc395x.c @@ -4319,7 +4319,7 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); while (pages--) { - ptr = kmalloc(PAGE_SIZE, GFP_KERNEL); + ptr = (struct SGentry *)kmalloc(PAGE_SIZE, GFP_KERNEL); if (!ptr) { adapter_sg_tables_free(acb); return 1; diff --git a/trunk/drivers/scsi/dpt_i2o.c b/trunk/drivers/scsi/dpt_i2o.c index 365db537a28d..60b1b434eba7 100644 --- a/trunk/drivers/scsi/dpt_i2o.c +++ b/trunk/drivers/scsi/dpt_i2o.c @@ -297,7 +297,7 @@ static void adpt_inquiry(adpt_hba* pHba) s32 rcode; memset(msg, 0, sizeof(msg)); - buf = kmalloc(80,GFP_KERNEL|ADDR32); + buf = (u8*)kmalloc(80,GFP_KERNEL|ADDR32); if(!buf){ printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name); return; @@ -1311,7 +1311,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) schedule_timeout_uninterruptible(1); } while (m == EMPTY_QUEUE); - status = kmalloc(4, GFP_KERNEL|ADDR32); + status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32); if(status == NULL) { adpt_send_nop(pHba, m); printk(KERN_ERR"IOP reset failed - no free memory.\n"); @@ -1444,7 +1444,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) } continue; } - d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL); + d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL); if(d==NULL) { printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name); @@ -2425,7 +2425,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) pDev = pDev->next_lun; } if(!pDev ) { // Something new add it - d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL); + d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL); if(d==NULL) { printk(KERN_CRIT "Out of memory for I2O device data.\n"); @@ -2728,7 +2728,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) kfree(pHba->reply_pool); - pHba->reply_pool = kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); + pHba->reply_pool = (u32*)kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); if(!pHba->reply_pool){ printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name); return -1; diff --git a/trunk/drivers/scsi/initio.c b/trunk/drivers/scsi/initio.c index d561663fb4e4..f160357e37a6 100644 --- a/trunk/drivers/scsi/initio.c +++ b/trunk/drivers/scsi/initio.c @@ -2828,7 +2828,7 @@ static int i91u_detect(struct scsi_host_template * tpnt) for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) { i = tul_num_ch * tul_num_scb * sizeof(SCB); - if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL) + if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL) break; } if (tul_scb == NULL) { diff --git a/trunk/drivers/scsi/osst.c b/trunk/drivers/scsi/osst.c index 7d2311067903..824fe080d1dc 100644 --- a/trunk/drivers/scsi/osst.c +++ b/trunk/drivers/scsi/osst.c @@ -5777,7 +5777,7 @@ static int osst_probe(struct device *dev) dev_num = i; /* allocate a struct osst_tape for this device */ - tpnt = kmalloc(sizeof(struct osst_tape), GFP_ATOMIC); + tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC); if (tpnt == NULL) { write_unlock(&os_scsi_tapes_lock); printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n"); diff --git a/trunk/drivers/scsi/pluto.c b/trunk/drivers/scsi/pluto.c index 3b2e1a53e6e2..aa60a5f1fbc3 100644 --- a/trunk/drivers/scsi/pluto.c +++ b/trunk/drivers/scsi/pluto.c @@ -117,7 +117,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt) #endif return 0; } - fcs = kmalloc(sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA); + fcs = (struct ctrl_inquiry *) kmalloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA); if (!fcs) { printk ("PLUTO: Not enough memory to probe\n"); return 0; diff --git a/trunk/drivers/scsi/sr_ioctl.c b/trunk/drivers/scsi/sr_ioctl.c index 0578ba42718b..d1268cb46837 100644 --- a/trunk/drivers/scsi/sr_ioctl.c +++ b/trunk/drivers/scsi/sr_ioctl.c @@ -546,7 +546,7 @@ int sr_is_xa(Scsi_CD *cd) if (!xa_test) return 0; - raw_sector = kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd)); + raw_sector = (unsigned char *) kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd)); if (!raw_sector) return -ENOMEM; if (0 == sr_read_sector(cd, cd->ms_offset + 16, diff --git a/trunk/drivers/scsi/sr_vendor.c b/trunk/drivers/scsi/sr_vendor.c index 4eb3da996b36..a3e9d0f2eb5b 100644 --- a/trunk/drivers/scsi/sr_vendor.c +++ b/trunk/drivers/scsi/sr_vendor.c @@ -117,7 +117,7 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) density = (blocklength > 2048) ? 0x81 : 0x83; #endif - buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); + buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) return -ENOMEM; @@ -164,7 +164,7 @@ int sr_cd_check(struct cdrom_device_info *cdi) if (cd->cdi.mask & CDC_MULTI_SESSION) return 0; - buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); + buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) return -ENOMEM; diff --git a/trunk/drivers/scsi/sym53c8xx_2/sym_hipd.c b/trunk/drivers/scsi/sym53c8xx_2/sym_hipd.c index 21cd4c7f5289..940fa1e6f994 100644 --- a/trunk/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/trunk/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -5545,7 +5545,7 @@ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram /* * Allocate the array of lists of CCBs hashed by DSA. */ - np->ccbh = kcalloc(CCB_HASH_SIZE, sizeof(struct sym_ccb **), GFP_KERNEL); + np->ccbh = kcalloc(sizeof(struct sym_ccb **), CCB_HASH_SIZE, GFP_KERNEL); if (!np->ccbh) goto attach_failed; diff --git a/trunk/drivers/serial/Kconfig b/trunk/drivers/serial/Kconfig index 2978c09860ee..fc12d5df10e2 100644 --- a/trunk/drivers/serial/Kconfig +++ b/trunk/drivers/serial/Kconfig @@ -151,6 +151,32 @@ config SERIAL_8250_MANY_PORTS say N here to save some memory. You can also say Y if you have an "intelligent" multiport card such as Cyclades, Digiboards, etc. +config SERIAL_8250_SHARE_IRQ + bool "Support for sharing serial interrupts" + depends on SERIAL_8250_EXTENDED + help + Some serial boards have hardware support which allows multiple dumb + serial ports on the same board to share a single IRQ. To enable + support for this in the serial driver, say Y here. + +config SERIAL_8250_DETECT_IRQ + bool "Autodetect IRQ on standard ports (unsafe)" + depends on SERIAL_8250_EXTENDED + help + Say Y here if you want the kernel to try to guess which IRQ + to use for your serial port. + + This is considered unsafe; it is far better to configure the IRQ in + a boot script using the setserial command. + + If unsure, say N. + +config SERIAL_8250_RSA + bool "Support RSA serial ports" + depends on SERIAL_8250_EXTENDED + help + ::: To be written ::: + # # Multi-port serial cards # @@ -173,6 +199,7 @@ config SERIAL_8250_ACCENT To compile this driver as a module, choose M here: the module will be called 8250_accent. + config SERIAL_8250_BOCA tristate "Support Boca cards" depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS @@ -203,32 +230,6 @@ config SERIAL_8250_HUB6 To compile this driver as a module, choose M here: the module will be called 8250_hub6. -config SERIAL_8250_SHARE_IRQ - bool "Support for sharing serial interrupts" - depends on SERIAL_8250_EXTENDED - help - Some serial boards have hardware support which allows multiple dumb - serial ports on the same board to share a single IRQ. To enable - support for this in the serial driver, say Y here. - -config SERIAL_8250_DETECT_IRQ - bool "Autodetect IRQ on standard ports (unsafe)" - depends on SERIAL_8250_EXTENDED - help - Say Y here if you want the kernel to try to guess which IRQ - to use for your serial port. - - This is considered unsafe; it is far better to configure the IRQ in - a boot script using the setserial command. - - If unsure, say N. - -config SERIAL_8250_RSA - bool "Support RSA serial ports" - depends on SERIAL_8250_EXTENDED - help - ::: To be written ::: - config SERIAL_8250_MCA tristate "Support 8250-type ports on MCA buses" depends on SERIAL_8250 != n && MCA @@ -663,7 +664,7 @@ config V850E_UART config V850E_UARTB bool - depends on V850E_UART && V850E_ME2 + depends V850E_UART && V850E_ME2 default y config V850E_UART_CONSOLE @@ -909,7 +910,7 @@ config SERIAL_M32R_PLDSIO config SERIAL_TXX9 bool "TMPTX39XX/49XX SIO support" - depends on HAS_TXX9_SERIAL + depends HAS_TXX9_SERIAL select SERIAL_CORE default y diff --git a/trunk/drivers/serial/icom.c b/trunk/drivers/serial/icom.c index 71e6a24d8c28..7d623003e65e 100644 --- a/trunk/drivers/serial/icom.c +++ b/trunk/drivers/serial/icom.c @@ -1510,7 +1510,7 @@ static int __devinit icom_probe(struct pci_dev *dev, } if ( (retval = pci_request_regions(dev, "icom"))) { - dev_err(&dev->dev, "pci_request_regions FAILED\n"); + dev_err(&dev->dev, "pci_request_region FAILED\n"); pci_disable_device(dev); return retval; } diff --git a/trunk/drivers/serial/sh-sci.c b/trunk/drivers/serial/sh-sci.c index c53b69610a51..9031b57f12dd 100644 --- a/trunk/drivers/serial/sh-sci.c +++ b/trunk/drivers/serial/sh-sci.c @@ -319,28 +319,6 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) sci_out(port, SCFCR, fcr_val); } -#elif defined(CONFIG_CPU_SUBTYPE_SH7722) -static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) -{ - unsigned int fcr_val = 0; - - if (cflag & CRTSCTS) { - fcr_val |= SCFCR_MCE; - - ctrl_outw(0x0000, PORT_PSCR); - } else { - unsigned short data; - - data = ctrl_inw(PORT_PSCR); - data &= 0x033f; - data |= 0x0400; - ctrl_outw(data, PORT_PSCR); - - ctrl_outw(ctrl_inw(SCSPTR0) & 0x17, SCSPTR0); - } - - sci_out(port, SCFCR, fcr_val); -} #else /* For SH7750 */ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) diff --git a/trunk/drivers/serial/sh-sci.h b/trunk/drivers/serial/sh-sci.h index 77f7d6351ab1..e4557cc4f74b 100644 --- a/trunk/drivers/serial/sh-sci.h +++ b/trunk/drivers/serial/sh-sci.h @@ -90,13 +90,6 @@ # define SCSPTR3 0xffe30010 /* 16 bit SCIF */ # define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */ # define SCIF_ONLY -#elif defined(CONFIG_CPU_SUBTYPE_SH7722) -# define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ -# define SCSPTR0 SCPDR0 -# define SCIF_ORER 0x0001 /* overrun error bit */ -# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY -# define PORT_PSCR 0xA405011E #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ @@ -502,7 +495,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfe620000) return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ - return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7300) static inline int sci_rxd_in(struct uart_port *port) @@ -529,13 +521,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7722) -static inline int sci_rxd_in(struct uart_port *port) -{ - if (port->mapbase == 0xffe00000) - return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ - return 1; -} #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) static inline int sci_rxd_in(struct uart_port *port) { @@ -565,7 +550,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xff925000) return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ - return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7780) static inline int sci_rxd_in(struct uart_port *port) @@ -574,7 +558,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe10000) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ - return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7206) static inline int sci_rxd_in(struct uart_port *port) @@ -587,7 +570,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffe9800) return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ - return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7619) static inline int sci_rxd_in(struct uart_port *port) @@ -598,7 +580,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xf8420000) return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ - return 1; } #endif diff --git a/trunk/drivers/spi/pxa2xx_spi.c b/trunk/drivers/spi/pxa2xx_spi.c index 6ed3f1da9296..494d9b856488 100644 --- a/trunk/drivers/spi/pxa2xx_spi.c +++ b/trunk/drivers/spi/pxa2xx_spi.c @@ -49,14 +49,6 @@ MODULE_LICENSE("GPL"); #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) #define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) -/* for testing SSCR1 changes that require SSP restart, basically - * everything except the service and interrupt enables */ -#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \ - | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \ - | SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \ - | SSCR1_STRF | SSCR1_EFWR |SSCR1_RFT \ - | SSCR1_TFT | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) - #define DEFINE_SSP_REG(reg, off) \ static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \ static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); } @@ -131,8 +123,8 @@ struct driver_data { u8 n_bytes; u32 dma_width; int cs_change; - int (*write)(struct driver_data *drv_data); - int (*read)(struct driver_data *drv_data); + void (*write)(struct driver_data *drv_data); + void (*read)(struct driver_data *drv_data); irqreturn_t (*transfer_handler)(struct driver_data *drv_data); void (*cs_control)(u32 command); }; @@ -140,6 +132,7 @@ struct driver_data { struct chip_data { u32 cr0; u32 cr1; + u32 to; u32 psp; u32 timeout; u8 n_bytes; @@ -150,8 +143,8 @@ struct chip_data { u8 enable_dma; u8 bits_per_word; u32 speed_hz; - int (*write)(struct driver_data *drv_data); - int (*read)(struct driver_data *drv_data); + void (*write)(struct driver_data *drv_data); + void (*read)(struct driver_data *drv_data); void (*cs_control)(u32 command); }; @@ -173,118 +166,114 @@ static int flush(struct driver_data *drv_data) return limit; } +static void restore_state(struct driver_data *drv_data) +{ + void *reg = drv_data->ioaddr; + + /* Clear status and disable clock */ + write_SSSR(drv_data->clear_sr, reg); + write_SSCR0(drv_data->cur_chip->cr0 & ~SSCR0_SSE, reg); + + /* Load the registers */ + write_SSCR1(drv_data->cur_chip->cr1, reg); + write_SSCR0(drv_data->cur_chip->cr0, reg); + if (drv_data->ssp_type != PXA25x_SSP) { + write_SSTO(0, reg); + write_SSPSP(drv_data->cur_chip->psp, reg); + } +} + static void null_cs_control(u32 command) { } -static int null_writer(struct driver_data *drv_data) +static void null_writer(struct driver_data *drv_data) { void *reg = drv_data->ioaddr; u8 n_bytes = drv_data->n_bytes; - if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) - || (drv_data->tx == drv_data->tx_end)) - return 0; - - write_SSDR(0, reg); - drv_data->tx += n_bytes; - - return 1; + while ((read_SSSR(reg) & SSSR_TNF) + && (drv_data->tx < drv_data->tx_end)) { + write_SSDR(0, reg); + drv_data->tx += n_bytes; + } } -static int null_reader(struct driver_data *drv_data) +static void null_reader(struct driver_data *drv_data) { void *reg = drv_data->ioaddr; u8 n_bytes = drv_data->n_bytes; while ((read_SSSR(reg) & SSSR_RNE) - && (drv_data->rx < drv_data->rx_end)) { + && (drv_data->rx < drv_data->rx_end)) { read_SSDR(reg); drv_data->rx += n_bytes; } - - return drv_data->rx == drv_data->rx_end; } -static int u8_writer(struct driver_data *drv_data) +static void u8_writer(struct driver_data *drv_data) { void *reg = drv_data->ioaddr; - if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) - || (drv_data->tx == drv_data->tx_end)) - return 0; - - write_SSDR(*(u8 *)(drv_data->tx), reg); - ++drv_data->tx; - - return 1; + while ((read_SSSR(reg) & SSSR_TNF) + && (drv_data->tx < drv_data->tx_end)) { + write_SSDR(*(u8 *)(drv_data->tx), reg); + ++drv_data->tx; + } } -static int u8_reader(struct driver_data *drv_data) +static void u8_reader(struct driver_data *drv_data) { void *reg = drv_data->ioaddr; while ((read_SSSR(reg) & SSSR_RNE) - && (drv_data->rx < drv_data->rx_end)) { + && (drv_data->rx < drv_data->rx_end)) { *(u8 *)(drv_data->rx) = read_SSDR(reg); ++drv_data->rx; } - - return drv_data->rx == drv_data->rx_end; } -static int u16_writer(struct driver_data *drv_data) +static void u16_writer(struct driver_data *drv_data) { void *reg = drv_data->ioaddr; - if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) - || (drv_data->tx == drv_data->tx_end)) - return 0; - - write_SSDR(*(u16 *)(drv_data->tx), reg); - drv_data->tx += 2; - - return 1; + while ((read_SSSR(reg) & SSSR_TNF) + && (drv_data->tx < drv_data->tx_end)) { + write_SSDR(*(u16 *)(drv_data->tx), reg); + drv_data->tx += 2; + } } -static int u16_reader(struct driver_data *drv_data) +static void u16_reader(struct driver_data *drv_data) { void *reg = drv_data->ioaddr; while ((read_SSSR(reg) & SSSR_RNE) - && (drv_data->rx < drv_data->rx_end)) { + && (drv_data->rx < drv_data->rx_end)) { *(u16 *)(drv_data->rx) = read_SSDR(reg); drv_data->rx += 2; } - - return drv_data->rx == drv_data->rx_end; } - -static int u32_writer(struct driver_data *drv_data) +static void u32_writer(struct driver_data *drv_data) { void *reg = drv_data->ioaddr; - if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) - || (drv_data->tx == drv_data->tx_end)) - return 0; - - write_SSDR(*(u32 *)(drv_data->tx), reg); - drv_data->tx += 4; - - return 1; + while ((read_SSSR(reg) & SSSR_TNF) + && (drv_data->tx < drv_data->tx_end)) { + write_SSDR(*(u32 *)(drv_data->tx), reg); + drv_data->tx += 4; + } } -static int u32_reader(struct driver_data *drv_data) +static void u32_reader(struct driver_data *drv_data) { void *reg = drv_data->ioaddr; while ((read_SSSR(reg) & SSSR_RNE) - && (drv_data->rx < drv_data->rx_end)) { + && (drv_data->rx < drv_data->rx_end)) { *(u32 *)(drv_data->rx) = read_SSDR(reg); drv_data->rx += 4; } - - return drv_data->rx == drv_data->rx_end; } static void *next_transfer(struct driver_data *drv_data) @@ -420,134 +409,166 @@ static int wait_dma_channel_stop(int channel) return limit; } -void dma_error_stop(struct driver_data *drv_data, const char *msg) -{ - void *reg = drv_data->ioaddr; - - /* Stop and reset */ - DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; - DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; - write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); - if (drv_data->ssp_type != PXA25x_SSP) - write_SSTO(0, reg); - flush(drv_data); - write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); - - unmap_dma_buffers(drv_data); - - dev_err(&drv_data->pdev->dev, "%s\n", msg); - - drv_data->cur_msg->state = ERROR_STATE; - tasklet_schedule(&drv_data->pump_transfers); -} - -static void dma_transfer_complete(struct driver_data *drv_data) -{ - void *reg = drv_data->ioaddr; - struct spi_message *msg = drv_data->cur_msg; - - /* Clear and disable interrupts on SSP and DMA channels*/ - write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); - write_SSSR(drv_data->clear_sr, reg); - DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; - DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; - - if (wait_dma_channel_stop(drv_data->rx_channel) == 0) - dev_err(&drv_data->pdev->dev, - "dma_handler: dma rx channel stop failed\n"); - - if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) - dev_err(&drv_data->pdev->dev, - "dma_transfer: ssp rx stall failed\n"); - - unmap_dma_buffers(drv_data); - - /* update the buffer pointer for the amount completed in dma */ - drv_data->rx += drv_data->len - - (DCMD(drv_data->rx_channel) & DCMD_LENGTH); - - /* read trailing data from fifo, it does not matter how many - * bytes are in the fifo just read until buffer is full - * or fifo is empty, which ever occurs first */ - drv_data->read(drv_data); - - /* return count of what was actually read */ - msg->actual_length += drv_data->len - - (drv_data->rx_end - drv_data->rx); - - /* Release chip select if requested, transfer delays are - * handled in pump_transfers */ - if (drv_data->cs_change) - drv_data->cs_control(PXA2XX_CS_DEASSERT); - - /* Move to next transfer */ - msg->state = next_transfer(drv_data); - - /* Schedule transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); -} - static void dma_handler(int channel, void *data) { struct driver_data *drv_data = data; + struct spi_message *msg = drv_data->cur_msg; + void *reg = drv_data->ioaddr; u32 irq_status = DCSR(channel) & DMA_INT_MASK; + u32 trailing_sssr = 0; if (irq_status & DCSR_BUSERR) { + /* Disable interrupts, clear status and reset DMA */ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); + if (drv_data->ssp_type != PXA25x_SSP) + write_SSTO(0, reg); + write_SSSR(drv_data->clear_sr, reg); + DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; + DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; + + if (flush(drv_data) == 0) + dev_err(&drv_data->pdev->dev, + "dma_handler: flush fail\n"); + + unmap_dma_buffers(drv_data); + if (channel == drv_data->tx_channel) - dma_error_stop(drv_data, - "dma_handler: " - "bad bus address on tx channel"); + dev_err(&drv_data->pdev->dev, + "dma_handler: bad bus address on " + "tx channel %d, source %x target = %x\n", + channel, DSADR(channel), DTADR(channel)); else - dma_error_stop(drv_data, - "dma_handler: " - "bad bus address on rx channel"); - return; + dev_err(&drv_data->pdev->dev, + "dma_handler: bad bus address on " + "rx channel %d, source %x target = %x\n", + channel, DSADR(channel), DTADR(channel)); + + msg->state = ERROR_STATE; + tasklet_schedule(&drv_data->pump_transfers); } /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */ - if ((channel == drv_data->tx_channel) - && (irq_status & DCSR_ENDINTR) - && (drv_data->ssp_type == PXA25x_SSP)) { + if ((drv_data->ssp_type == PXA25x_SSP) + && (channel == drv_data->tx_channel) + && (irq_status & DCSR_ENDINTR)) { /* Wait for rx to stall */ if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) dev_err(&drv_data->pdev->dev, "dma_handler: ssp rx stall failed\n"); - /* finish this transfer, start the next */ - dma_transfer_complete(drv_data); + /* Clear and disable interrupts on SSP and DMA channels*/ + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); + write_SSSR(drv_data->clear_sr, reg); + DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; + DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; + if (wait_dma_channel_stop(drv_data->rx_channel) == 0) + dev_err(&drv_data->pdev->dev, + "dma_handler: dma rx channel stop failed\n"); + + unmap_dma_buffers(drv_data); + + /* Read trailing bytes */ + /* Calculate number of trailing bytes, read them */ + trailing_sssr = read_SSSR(reg); + if ((trailing_sssr & 0xf008) != 0xf000) { + drv_data->rx = drv_data->rx_end - + (((trailing_sssr >> 12) & 0x0f) + 1); + drv_data->read(drv_data); + } + msg->actual_length += drv_data->len; + + /* Release chip select if requested, transfer delays are + * handled in pump_transfers */ + if (drv_data->cs_change) + drv_data->cs_control(PXA2XX_CS_DEASSERT); + + /* Move to next transfer */ + msg->state = next_transfer(drv_data); + + /* Schedule transfer tasklet */ + tasklet_schedule(&drv_data->pump_transfers); } } static irqreturn_t dma_transfer(struct driver_data *drv_data) { u32 irq_status; + u32 trailing_sssr = 0; + struct spi_message *msg = drv_data->cur_msg; void *reg = drv_data->ioaddr; irq_status = read_SSSR(reg) & drv_data->mask_sr; if (irq_status & SSSR_ROR) { - dma_error_stop(drv_data, "dma_transfer: fifo overrun"); + /* Clear and disable interrupts on SSP and DMA channels*/ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); + if (drv_data->ssp_type != PXA25x_SSP) + write_SSTO(0, reg); + write_SSSR(drv_data->clear_sr, reg); + DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; + DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; + unmap_dma_buffers(drv_data); + + if (flush(drv_data) == 0) + dev_err(&drv_data->pdev->dev, + "dma_transfer: flush fail\n"); + + dev_warn(&drv_data->pdev->dev, "dma_transfer: fifo overun\n"); + + drv_data->cur_msg->state = ERROR_STATE; + tasklet_schedule(&drv_data->pump_transfers); + return IRQ_HANDLED; } /* Check for false positive timeout */ - if ((irq_status & SSSR_TINT) - && (DCSR(drv_data->tx_channel) & DCSR_RUN)) { + if ((irq_status & SSSR_TINT) && DCSR(drv_data->tx_channel) & DCSR_RUN) { write_SSSR(SSSR_TINT, reg); return IRQ_HANDLED; } if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) { - /* Clear and disable timeout interrupt, do the rest in - * dma_transfer_complete */ + /* Clear and disable interrupts on SSP and DMA channels*/ + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); + write_SSSR(drv_data->clear_sr, reg); + DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; + DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; - /* finish this transfer, start the next */ - dma_transfer_complete(drv_data); + if (wait_dma_channel_stop(drv_data->rx_channel) == 0) + dev_err(&drv_data->pdev->dev, + "dma_transfer: dma rx channel stop failed\n"); + + if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) + dev_err(&drv_data->pdev->dev, + "dma_transfer: ssp rx stall failed\n"); + + unmap_dma_buffers(drv_data); + + /* Calculate number of trailing bytes, read them */ + trailing_sssr = read_SSSR(reg); + if ((trailing_sssr & 0xf008) != 0xf000) { + drv_data->rx = drv_data->rx_end - + (((trailing_sssr >> 12) & 0x0f) + 1); + drv_data->read(drv_data); + } + msg->actual_length += drv_data->len; + + /* Release chip select if requested, transfer delays are + * handled in pump_transfers */ + if (drv_data->cs_change) + drv_data->cs_control(PXA2XX_CS_DEASSERT); + + /* Move to next transfer */ + msg->state = next_transfer(drv_data); + + /* Schedule transfer tasklet */ + tasklet_schedule(&drv_data->pump_transfers); return IRQ_HANDLED; } @@ -556,103 +577,89 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) return IRQ_NONE; } -static void int_error_stop(struct driver_data *drv_data, const char* msg) +static irqreturn_t interrupt_transfer(struct driver_data *drv_data) { + struct spi_message *msg = drv_data->cur_msg; void *reg = drv_data->ioaddr; + unsigned long limit = loops_per_jiffy << 1; + u32 irq_status; + u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ? + drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS; - /* Stop and reset SSP */ - write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); - if (drv_data->ssp_type != PXA25x_SSP) - write_SSTO(0, reg); - flush(drv_data); - write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + while ((irq_status = read_SSSR(reg) & irq_mask)) { - dev_err(&drv_data->pdev->dev, "%s\n", msg); + if (irq_status & SSSR_ROR) { - drv_data->cur_msg->state = ERROR_STATE; - tasklet_schedule(&drv_data->pump_transfers); -} + /* Clear and disable interrupts */ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); + if (drv_data->ssp_type != PXA25x_SSP) + write_SSTO(0, reg); + write_SSSR(drv_data->clear_sr, reg); -static void int_transfer_complete(struct driver_data *drv_data) -{ - void *reg = drv_data->ioaddr; + if (flush(drv_data) == 0) + dev_err(&drv_data->pdev->dev, + "interrupt_transfer: flush fail\n"); - /* Stop SSP */ - write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); - if (drv_data->ssp_type != PXA25x_SSP) - write_SSTO(0, reg); + /* Stop the SSP */ - /* Update total byte transfered return count actual bytes read */ - drv_data->cur_msg->actual_length += drv_data->len - - (drv_data->rx_end - drv_data->rx); + dev_warn(&drv_data->pdev->dev, + "interrupt_transfer: fifo overun\n"); - /* Release chip select if requested, transfer delays are - * handled in pump_transfers */ - if (drv_data->cs_change) - drv_data->cs_control(PXA2XX_CS_DEASSERT); + msg->state = ERROR_STATE; + tasklet_schedule(&drv_data->pump_transfers); - /* Move to next transfer */ - drv_data->cur_msg->state = next_transfer(drv_data); + return IRQ_HANDLED; + } - /* Schedule transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); -} + /* Look for false positive timeout */ + if ((irq_status & SSSR_TINT) + && (drv_data->rx < drv_data->rx_end)) + write_SSSR(SSSR_TINT, reg); -static irqreturn_t interrupt_transfer(struct driver_data *drv_data) -{ - void *reg = drv_data->ioaddr; - - u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ? - drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS; + /* Pump data */ + drv_data->read(drv_data); + drv_data->write(drv_data); - u32 irq_status = read_SSSR(reg) & irq_mask; + if (drv_data->tx == drv_data->tx_end) { + /* Disable tx interrupt */ + write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); + irq_mask = drv_data->mask_sr & ~SSSR_TFS; - if (irq_status & SSSR_ROR) { - int_error_stop(drv_data, "interrupt_transfer: fifo overrun"); - return IRQ_HANDLED; - } + /* PXA25x_SSP has no timeout, read trailing bytes */ + if (drv_data->ssp_type == PXA25x_SSP) { + while ((read_SSSR(reg) & SSSR_BSY) && limit--) + drv_data->read(drv_data); - if (irq_status & SSSR_TINT) { - write_SSSR(SSSR_TINT, reg); - if (drv_data->read(drv_data)) { - int_transfer_complete(drv_data); - return IRQ_HANDLED; + if (limit == 0) + dev_err(&drv_data->pdev->dev, + "interrupt_transfer: " + "trailing byte read failed\n"); + } } - } - /* Drain rx fifo, Fill tx fifo and prevent overruns */ - do { - if (drv_data->read(drv_data)) { - int_transfer_complete(drv_data); - return IRQ_HANDLED; - } - } while (drv_data->write(drv_data)); + if ((irq_status & SSSR_TINT) + || (drv_data->rx == drv_data->rx_end)) { - if (drv_data->read(drv_data)) { - int_transfer_complete(drv_data); - return IRQ_HANDLED; - } + /* Clear timeout */ + write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); + if (drv_data->ssp_type != PXA25x_SSP) + write_SSTO(0, reg); + write_SSSR(drv_data->clear_sr, reg); - if (drv_data->tx == drv_data->tx_end) { - write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); - /* PXA25x_SSP has no timeout, read trailing bytes */ - if (drv_data->ssp_type == PXA25x_SSP) { - if (!wait_ssp_rx_stall(reg)) - { - int_error_stop(drv_data, "interrupt_transfer: " - "rx stall failed"); - return IRQ_HANDLED; - } - if (!drv_data->read(drv_data)) - { - int_error_stop(drv_data, - "interrupt_transfer: " - "trailing byte read failed"); - return IRQ_HANDLED; - } - int_transfer_complete(drv_data); + /* Update total byte transfered */ + msg->actual_length += drv_data->len; + + /* Release chip select if requested, transfer delays are + * handled in pump_transfers */ + if (drv_data->cs_change) + drv_data->cs_control(PXA2XX_CS_DEASSERT); + + /* Move to next transfer */ + msg->state = next_transfer(drv_data); + + /* Schedule transfer tasklet */ + tasklet_schedule(&drv_data->pump_transfers); } } @@ -674,7 +681,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id) write_SSSR(drv_data->clear_sr, reg); dev_err(&drv_data->pdev->dev, "bad message state " - "in interrupt handler\n"); + "in interrupt handler"); /* Never fail */ return IRQ_HANDLED; @@ -683,102 +690,6 @@ static irqreturn_t ssp_int(int irq, void *dev_id) return drv_data->transfer_handler(drv_data); } -int set_dma_burst_and_threshold(struct chip_data *chip, struct spi_device *spi, - u8 bits_per_word, u32 *burst_code, - u32 *threshold) -{ - struct pxa2xx_spi_chip *chip_info = - (struct pxa2xx_spi_chip *)spi->controller_data; - int bytes_per_word; - int burst_bytes; - int thresh_words; - int req_burst_size; - int retval = 0; - - /* Set the threshold (in registers) to equal the same amount of data - * as represented by burst size (in bytes). The computation below - * is (burst_size rounded up to nearest 8 byte, word or long word) - * divided by (bytes/register); the tx threshold is the inverse of - * the rx, so that there will always be enough data in the rx fifo - * to satisfy a burst, and there will always be enough space in the - * tx fifo to accept a burst (a tx burst will overwrite the fifo if - * there is not enough space), there must always remain enough empty - * space in the rx fifo for any data loaded to the tx fifo. - * Whenever burst_size (in bytes) equals bits/word, the fifo threshold - * will be 8, or half the fifo; - * The threshold can only be set to 2, 4 or 8, but not 16, because - * to burst 16 to the tx fifo, the fifo would have to be empty; - * however, the minimum fifo trigger level is 1, and the tx will - * request service when the fifo is at this level, with only 15 spaces. - */ - - /* find bytes/word */ - if (bits_per_word <= 8) - bytes_per_word = 1; - else if (bits_per_word <= 16) - bytes_per_word = 2; - else - bytes_per_word = 4; - - /* use struct pxa2xx_spi_chip->dma_burst_size if available */ - if (chip_info) - req_burst_size = chip_info->dma_burst_size; - else { - switch (chip->dma_burst_size) { - default: - /* if the default burst size is not set, - * do it now */ - chip->dma_burst_size = DCMD_BURST8; - case DCMD_BURST8: - req_burst_size = 8; - break; - case DCMD_BURST16: - req_burst_size = 16; - break; - case DCMD_BURST32: - req_burst_size = 32; - break; - } - } - if (req_burst_size <= 8) { - *burst_code = DCMD_BURST8; - burst_bytes = 8; - } else if (req_burst_size <= 16) { - if (bytes_per_word == 1) { - /* don't burst more than 1/2 the fifo */ - *burst_code = DCMD_BURST8; - burst_bytes = 8; - retval = 1; - } else { - *burst_code = DCMD_BURST16; - burst_bytes = 16; - } - } else { - if (bytes_per_word == 1) { - /* don't burst more than 1/2 the fifo */ - *burst_code = DCMD_BURST8; - burst_bytes = 8; - retval = 1; - } else if (bytes_per_word == 2) { - /* don't burst more than 1/2 the fifo */ - *burst_code = DCMD_BURST16; - burst_bytes = 16; - retval = 1; - } else { - *burst_code = DCMD_BURST32; - burst_bytes = 32; - } - } - - thresh_words = burst_bytes / bytes_per_word; - - /* thresh_words will be between 2 and 8 */ - *threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT) - | (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT); - - return retval; -} - static void pump_transfers(unsigned long data) { struct driver_data *drv_data = (struct driver_data *)data; @@ -791,9 +702,6 @@ static void pump_transfers(unsigned long data) u8 bits = 0; u32 speed = 0; u32 cr0; - u32 cr1; - u32 dma_thresh = drv_data->cur_chip->dma_threshold; - u32 dma_burst = drv_data->cur_chip->dma_burst_size; /* Get current state information */ message = drv_data->cur_msg; @@ -823,16 +731,6 @@ static void pump_transfers(unsigned long data) udelay(previous->delay_usecs); } - /* Check transfer length */ - if (transfer->len > 8191) - { - dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer " - "length greater than 8191\n"); - message->status = -EINVAL; - giveback(drv_data); - return; - } - /* Setup the transfer state based on the type of transfer */ if (flush(drv_data) == 0) { dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); @@ -849,15 +747,17 @@ static void pump_transfers(unsigned long data) drv_data->rx_end = drv_data->rx + transfer->len; drv_data->rx_dma = transfer->rx_dma; drv_data->tx_dma = transfer->tx_dma; - drv_data->len = transfer->len & DCMD_LENGTH; + drv_data->len = transfer->len; drv_data->write = drv_data->tx ? chip->write : null_writer; drv_data->read = drv_data->rx ? chip->read : null_reader; drv_data->cs_change = transfer->cs_change; /* Change speed and bit per word on a per transfer */ - cr0 = chip->cr0; if (transfer->speed_hz || transfer->bits_per_word) { + /* Disable clock */ + write_SSCR0(chip->cr0 & ~SSCR0_SSE, reg); + cr0 = chip->cr0; bits = chip->bits_per_word; speed = chip->speed_hz; @@ -896,24 +796,15 @@ static void pump_transfers(unsigned long data) drv_data->write = drv_data->write != null_writer ? u32_writer : null_writer; } - /* if bits/word is changed in dma mode, then must check the - * thresholds and burst also */ - if (chip->enable_dma) { - if (set_dma_burst_and_threshold(chip, message->spi, - bits, &dma_burst, - &dma_thresh)) - if (printk_ratelimit()) - dev_warn(&message->spi->dev, - "pump_transfer: " - "DMA burst size reduced to " - "match bits_per_word\n"); - } cr0 = clk_div | SSCR0_Motorola | SSCR0_DataSize(bits > 16 ? bits - 16 : bits) | SSCR0_SSE | (bits > 16 ? SSCR0_EDSS : 0); + + /* Start it back up */ + write_SSCR0(cr0, reg); } message->state = RUNNING_STATE; @@ -932,13 +823,13 @@ static void pump_transfers(unsigned long data) /* No target address increment */ DCMD(drv_data->rx_channel) = DCMD_FLOWSRC | drv_data->dma_width - | dma_burst + | chip->dma_burst_size | drv_data->len; else DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR | DCMD_FLOWSRC | drv_data->dma_width - | dma_burst + | chip->dma_burst_size | drv_data->len; /* Setup tx DMA Channel */ @@ -949,13 +840,13 @@ static void pump_transfers(unsigned long data) /* No source address increment */ DCMD(drv_data->tx_channel) = DCMD_FLOWTRG | drv_data->dma_width - | dma_burst + | chip->dma_burst_size | drv_data->len; else DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR | DCMD_FLOWTRG | drv_data->dma_width - | dma_burst + | chip->dma_burst_size | drv_data->len; /* Enable dma end irqs on SSP to detect end of transfer */ @@ -965,11 +856,16 @@ static void pump_transfers(unsigned long data) /* Fix me, need to handle cs polarity */ drv_data->cs_control(PXA2XX_CS_ASSERT); - /* Clear status and start DMA engine */ - cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1; + /* Go baby, go */ write_SSSR(drv_data->clear_sr, reg); DCSR(drv_data->rx_channel) |= DCSR_RUN; DCSR(drv_data->tx_channel) |= DCSR_RUN; + if (drv_data->ssp_type != PXA25x_SSP) + write_SSTO(chip->timeout, reg); + write_SSCR1(chip->cr1 + | chip->dma_threshold + | drv_data->dma_cr1, + reg); } else { /* Ensure we have the correct interrupt handler */ drv_data->transfer_handler = interrupt_transfer; @@ -977,25 +873,14 @@ static void pump_transfers(unsigned long data) /* Fix me, need to handle cs polarity */ drv_data->cs_control(PXA2XX_CS_ASSERT); - /* Clear status */ - cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1; + /* Go baby, go */ write_SSSR(drv_data->clear_sr, reg); - } - - /* see if we need to reload the config registers */ - if ((read_SSCR0(reg) != cr0) - || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) != - (cr1 & SSCR1_CHANGE_MASK)) { - - write_SSCR0(cr0 & ~SSCR0_SSE, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(chip->timeout, reg); - write_SSCR1(cr1, reg); - write_SSCR0(cr0, reg); - } else { - if (drv_data->ssp_type != PXA25x_SSP) - write_SSTO(chip->timeout, reg); - write_SSCR1(cr1, reg); + write_SSCR1(chip->cr1 + | chip->threshold + | drv_data->int_cr1, + reg); } } @@ -1030,9 +915,9 @@ static void pump_messages(struct work_struct *work) struct spi_transfer, transfer_list); - /* prepare to setup the SSP, in pump_transfers, using the per - * chip configuration */ + /* Setup the SSP using the per chip configuration */ drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); + restore_state(drv_data); /* Mark as busy and launch transfers */ tasklet_schedule(&drv_data->pump_transfers); @@ -1078,77 +963,63 @@ static int setup(struct spi_device *spi) spi->bits_per_word = 8; if (drv_data->ssp_type != PXA25x_SSP - && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) { - dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " - "b/w not 4-32 for type non-PXA25x_SSP\n", - drv_data->ssp_type, spi->bits_per_word); + && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) return -EINVAL; - } - else if (drv_data->ssp_type == PXA25x_SSP - && (spi->bits_per_word < 4 - || spi->bits_per_word > 16)) { - dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " - "b/w not 4-16 for type PXA25x_SSP\n", - drv_data->ssp_type, spi->bits_per_word); + else if (spi->bits_per_word < 4 || spi->bits_per_word > 16) return -EINVAL; - } - /* Only alloc on first setup */ + /* Only alloc (or use chip_info) on first setup */ chip = spi_get_ctldata(spi); - if (!chip) { + if (chip == NULL) { chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); - if (!chip) { - dev_err(&spi->dev, - "failed setup: can't allocate chip data\n"); + if (!chip) return -ENOMEM; - } chip->cs_control = null_cs_control; chip->enable_dma = 0; - chip->timeout = 1000; + chip->timeout = SSP_TIMEOUT(1000); chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1); chip->dma_burst_size = drv_data->master_info->enable_dma ? DCMD_BURST8 : 0; - } - /* protocol drivers may change the chip settings, so... - * if chip_info exists, use it */ - chip_info = spi->controller_data; + chip_info = spi->controller_data; + } /* chip_info isn't always needed */ - chip->cr1 = 0; if (chip_info) { if (chip_info->cs_control) chip->cs_control = chip_info->cs_control; - chip->timeout = chip_info->timeout; + chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs); - chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) & - SSCR1_RFT) | - (SSCR1_TxTresh(chip_info->tx_threshold) & - SSCR1_TFT); + chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold) + | SSCR1_TxTresh(chip_info->tx_threshold); chip->enable_dma = chip_info->dma_burst_size != 0 && drv_data->master_info->enable_dma; chip->dma_threshold = 0; + if (chip->enable_dma) { + if (chip_info->dma_burst_size <= 8) { + chip->dma_threshold = SSCR1_RxTresh(8) + | SSCR1_TxTresh(8); + chip->dma_burst_size = DCMD_BURST8; + } else if (chip_info->dma_burst_size <= 16) { + chip->dma_threshold = SSCR1_RxTresh(16) + | SSCR1_TxTresh(16); + chip->dma_burst_size = DCMD_BURST16; + } else { + chip->dma_threshold = SSCR1_RxTresh(32) + | SSCR1_TxTresh(32); + chip->dma_burst_size = DCMD_BURST32; + } + } + + if (chip_info->enable_loopback) chip->cr1 = SSCR1_LBM; } - /* set dma burst and threshold outside of chip_info path so that if - * chip_info goes away after setting chip->enable_dma, the - * burst and threshold can still respond to changes in bits_per_word */ - if (chip->enable_dma) { - /* set up legal burst and threshold for dma */ - if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word, - &chip->dma_burst_size, - &chip->dma_threshold)) { - dev_warn(&spi->dev, "in setup: DMA burst size reduced " - "to match bits_per_word\n"); - } - } - if (drv_data->ioaddr == SSP1_VIRT) clk_div = SSP1_SerClkDiv(spi->max_speed_hz); else if (drv_data->ioaddr == SSP2_VIRT) @@ -1156,11 +1027,7 @@ static int setup(struct spi_device *spi) else if (drv_data->ioaddr == SSP3_VIRT) clk_div = SSP3_SerClkDiv(spi->max_speed_hz); else - { - dev_err(&spi->dev, "failed setup: unknown IO address=0x%p\n", - drv_data->ioaddr); return -ENODEV; - } chip->speed_hz = spi->max_speed_hz; chip->cr0 = clk_div @@ -1204,6 +1071,7 @@ static int setup(struct spi_device *spi) chip->write = u32_writer; } else { dev_err(&spi->dev, "invalid wordsize\n"); + kfree(chip); return -ENODEV; } chip->bits_per_word = spi->bits_per_word; @@ -1294,12 +1162,6 @@ static int destroy_queue(struct driver_data *drv_data) int status; status = stop_queue(drv_data); - /* we are unloading the module or failing to load (only two calls - * to this routine), and neither call can handle a return value. - * However, destroy_workqueue calls flush_workqueue, and that will - * block until all work is done. If the reason that stop_queue - * timed out is that the work will never finish, then it does no - * good to call destroy_workqueue, so return anyway. */ if (status != 0) return status; @@ -1498,16 +1360,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) /* Remove the queue */ status = destroy_queue(drv_data); if (status != 0) - /* the kernel does not check the return status of this - * this routine (mod->exit, within the kernel). Therefore - * nothing is gained by returning from here, the module is - * going away regardless, and we should not leave any more - * resources allocated than necessary. We cannot free the - * message memory in drv_data->queue, but we can release the - * resources below. I think the kernel should honor -EBUSY - * returns but... */ - dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not " - "complete, message memory not freed\n"); + return status; /* Disable the SSP at the peripheral and SOC level */ write_SSCR0(0, drv_data->ioaddr); diff --git a/trunk/drivers/usb/gadget/at91_udc.c b/trunk/drivers/usb/gadget/at91_udc.c index 3e0abbb49fe1..72f3db99ff94 100644 --- a/trunk/drivers/usb/gadget/at91_udc.c +++ b/trunk/drivers/usb/gadget/at91_udc.c @@ -598,7 +598,7 @@ at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags) { struct at91_request *req; - req = kzalloc(sizeof (struct at91_request), gfp_flags); + req = kcalloc(1, sizeof (struct at91_request), gfp_flags); if (!req) return NULL; diff --git a/trunk/drivers/usb/gadget/serial.c b/trunk/drivers/usb/gadget/serial.c index 2d12bf9f19d6..5516c59ed5ec 100644 --- a/trunk/drivers/usb/gadget/serial.c +++ b/trunk/drivers/usb/gadget/serial.c @@ -2195,7 +2195,7 @@ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags) if (size == 0) return NULL; - gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags); + gb = (struct gs_buf *)kmalloc(sizeof(struct gs_buf), kmalloc_flags); if (gb == NULL) return NULL; diff --git a/trunk/drivers/usb/host/hc_crisv10.c b/trunk/drivers/usb/host/hc_crisv10.c index 282d82efc0b0..9325e46a68c0 100644 --- a/trunk/drivers/usb/host/hc_crisv10.c +++ b/trunk/drivers/usb/host/hc_crisv10.c @@ -365,7 +365,7 @@ static inline struct urb *urb_list_first(int epid) /* Adds an urb_entry last in the list for this epid. */ static inline void urb_list_add(struct urb *urb, int epid) { - urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG); + urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG); assert(urb_entry); urb_entry->urb = urb; diff --git a/trunk/drivers/usb/misc/auerswald.c b/trunk/drivers/usb/misc/auerswald.c index 6c7f3efb1d40..c703f73e1655 100644 --- a/trunk/drivers/usb/misc/auerswald.c +++ b/trunk/drivers/usb/misc/auerswald.c @@ -766,7 +766,7 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned bep->bufp = kmalloc (bufsize, GFP_KERNEL); if (!bep->bufp) goto bl_fail; - bep->dr = kmalloc(sizeof (struct usb_ctrlrequest), GFP_KERNEL); + bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL); if (!bep->dr) goto bl_fail; bep->urbp = usb_alloc_urb (0, GFP_KERNEL); @@ -1969,7 +1969,7 @@ static int auerswald_probe (struct usb_interface *intf, info("device is a %s", cp->dev_desc); /* get the maximum allowed control transfer length */ - pbuf = kmalloc(2, GFP_KERNEL); /* use an allocated buffer because of urb target */ + pbuf = (__le16 *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */ if (!pbuf) { err( "out of memory"); goto pfail; diff --git a/trunk/drivers/usb/misc/uss720.c b/trunk/drivers/usb/misc/uss720.c index 70250252ae2a..7e8a0acd52ee 100644 --- a/trunk/drivers/usb/misc/uss720.c +++ b/trunk/drivers/usb/misc/uss720.c @@ -705,7 +705,7 @@ static int uss720_probe(struct usb_interface *intf, /* * Allocate parport interface */ - if (!(priv = kzalloc(sizeof(struct parport_uss720_private), GFP_KERNEL))) { + if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) { usb_put_dev(usbdev); return -ENOMEM; } diff --git a/trunk/drivers/usb/net/rndis_host.c b/trunk/drivers/usb/net/rndis_host.c index ea5f44de3de2..99f26b3e502f 100644 --- a/trunk/drivers/usb/net/rndis_host.c +++ b/trunk/drivers/usb/net/rndis_host.c @@ -469,7 +469,7 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) struct rndis_halt *halt; /* try to clear any rndis state/activity (no i/o from stack!) */ - halt = kzalloc(sizeof *halt, GFP_KERNEL); + halt = kcalloc(1, sizeof *halt, GFP_KERNEL); if (halt) { halt->msg_type = RNDIS_MSG_HALT; halt->msg_len = ccpu2(sizeof *halt); diff --git a/trunk/drivers/usb/serial/cypress_m8.c b/trunk/drivers/usb/serial/cypress_m8.c index 45cdf9bc43b2..a1fdb85b8c0a 100644 --- a/trunk/drivers/usb/serial/cypress_m8.c +++ b/trunk/drivers/usb/serial/cypress_m8.c @@ -1493,7 +1493,7 @@ static struct cypress_buf *cypress_buf_alloc(unsigned int size) if (size == 0) return NULL; - cb = kmalloc(sizeof(struct cypress_buf), GFP_KERNEL); + cb = (struct cypress_buf *)kmalloc(sizeof(struct cypress_buf), GFP_KERNEL); if (cb == NULL) return NULL; diff --git a/trunk/drivers/usb/serial/digi_acceleport.c b/trunk/drivers/usb/serial/digi_acceleport.c index efd9ce3f931f..9d9ea874639c 100644 --- a/trunk/drivers/usb/serial/digi_acceleport.c +++ b/trunk/drivers/usb/serial/digi_acceleport.c @@ -1681,7 +1681,7 @@ dbg( "digi_startup: TOP" ); for( i=0; itype->num_ports+1; i++ ) { /* allocate port private structure */ - priv = kmalloc( sizeof(struct digi_port), + priv = (struct digi_port *)kmalloc( sizeof(struct digi_port), GFP_KERNEL ); if( priv == (struct digi_port *)0 ) { while( --i >= 0 ) @@ -1714,7 +1714,7 @@ dbg( "digi_startup: TOP" ); } /* allocate serial private structure */ - serial_priv = kmalloc( sizeof(struct digi_serial), + serial_priv = (struct digi_serial *)kmalloc( sizeof(struct digi_serial), GFP_KERNEL ); if( serial_priv == (struct digi_serial *)0 ) { for( i=0; itype->num_ports+1; i++ ) diff --git a/trunk/drivers/usb/serial/io_ti.c b/trunk/drivers/usb/serial/io_ti.c index 980285c0233a..2da2684e0809 100644 --- a/trunk/drivers/usb/serial/io_ti.c +++ b/trunk/drivers/usb/serial/io_ti.c @@ -2811,7 +2811,7 @@ static struct edge_buf *edge_buf_alloc(unsigned int size) if (size == 0) return NULL; - eb = kmalloc(sizeof(struct edge_buf), GFP_KERNEL); + eb = (struct edge_buf *)kmalloc(sizeof(struct edge_buf), GFP_KERNEL); if (eb == NULL) return NULL; diff --git a/trunk/drivers/usb/serial/ipaq.c b/trunk/drivers/usb/serial/ipaq.c index 42f757a5b876..d72cf8bc7f76 100644 --- a/trunk/drivers/usb/serial/ipaq.c +++ b/trunk/drivers/usb/serial/ipaq.c @@ -595,7 +595,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) bytes_in = 0; bytes_out = 0; - priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL); + priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL); if (priv == NULL) { err("%s - Out of memory", __FUNCTION__); return -ENOMEM; diff --git a/trunk/drivers/usb/serial/kobil_sct.c b/trunk/drivers/usb/serial/kobil_sct.c index 62bea0c923bd..e284d6c0fd35 100644 --- a/trunk/drivers/usb/serial/kobil_sct.c +++ b/trunk/drivers/usb/serial/kobil_sct.c @@ -269,7 +269,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) } // allocate memory for write_urb transfer buffer - port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); + port->write_urb->transfer_buffer = (unsigned char *) kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); if (! port->write_urb->transfer_buffer) { kfree(transfer_buffer); usb_free_urb(port->write_urb); @@ -696,7 +696,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, return 0; case TCFLSH: // 0x540B - transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL); + transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); if (! transfer_buffer) { return -ENOBUFS; } diff --git a/trunk/drivers/usb/serial/pl2303.c b/trunk/drivers/usb/serial/pl2303.c index 5dc2ac9afa90..d124d780e42e 100644 --- a/trunk/drivers/usb/serial/pl2303.c +++ b/trunk/drivers/usb/serial/pl2303.c @@ -159,7 +159,7 @@ static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) if (size == 0) return NULL; - pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); + pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); if (pb == NULL) return NULL; diff --git a/trunk/drivers/usb/serial/ti_usb_3410_5052.c b/trunk/drivers/usb/serial/ti_usb_3410_5052.c index 83189005c6fb..f42eb9ea6405 100644 --- a/trunk/drivers/usb/serial/ti_usb_3410_5052.c +++ b/trunk/drivers/usb/serial/ti_usb_3410_5052.c @@ -1710,7 +1710,7 @@ static struct circ_buf *ti_buf_alloc(void) { struct circ_buf *cb; - cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL); + cb = (struct circ_buf *)kmalloc(sizeof(struct circ_buf), GFP_KERNEL); if (cb == NULL) return NULL; diff --git a/trunk/drivers/usb/serial/whiteheat.c b/trunk/drivers/usb/serial/whiteheat.c index 5483d8564c1b..dc45e58e2b8c 100644 --- a/trunk/drivers/usb/serial/whiteheat.c +++ b/trunk/drivers/usb/serial/whiteheat.c @@ -416,7 +416,7 @@ static int whiteheat_attach (struct usb_serial *serial) for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; - info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); + info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); if (info == NULL) { err("%s: Out of memory for port structures\n", serial->type->description); goto no_private; @@ -487,7 +487,7 @@ static int whiteheat_attach (struct usb_serial *serial) usb_set_serial_port_data(port, info); } - command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); + command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); if (command_info == NULL) { err("%s: Out of memory for port structures\n", serial->type->description); goto no_command_private; diff --git a/trunk/drivers/usb/storage/sddr09.c b/trunk/drivers/usb/storage/sddr09.c index e3528eca29a5..fb8bacaae27c 100644 --- a/trunk/drivers/usb/storage/sddr09.c +++ b/trunk/drivers/usb/storage/sddr09.c @@ -646,7 +646,7 @@ sddr09_read_sg_test_only(struct us_data *us) { return result; } - buf = kmalloc(bulklen, GFP_NOIO); + buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO); if (!buf) return -ENOMEM; diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 4e83f01e894e..ab1daecfeac6 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -1615,16 +1615,6 @@ config FB_PNX4008_DUM_RGB ---help--- Say Y here to enable support for PNX4008 RGB Framebuffer -config FB_IBM_GXT4500 - tristate "Framebuffer support for IBM GXT4500P adaptor" - depends on PPC - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Say Y here to enable support for the IBM GXT4500P display - adaptor, found on some IBM System P (pSeries) machines. - config FB_VIRTUAL tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" depends on FB diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index 309a26dd164a..a6980e9a2481 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -99,7 +99,6 @@ obj-$(CONFIG_FB_IMX) += imxfb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ -obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o # Platform or fallback drivers go here obj-$(CONFIG_FB_VESA) += vesafb.o diff --git a/trunk/drivers/video/amba-clcd.c b/trunk/drivers/video/amba-clcd.c index 6c9dc2e69c82..6761b68c35e9 100644 --- a/trunk/drivers/video/amba-clcd.c +++ b/trunk/drivers/video/amba-clcd.c @@ -447,7 +447,7 @@ static int clcdfb_probe(struct amba_device *dev, void *id) goto out; } - fb = kmalloc(sizeof(struct clcd_fb), GFP_KERNEL); + fb = (struct clcd_fb *) kmalloc(sizeof(struct clcd_fb), GFP_KERNEL); if (!fb) { printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n"); ret = -ENOMEM; diff --git a/trunk/drivers/video/amifb.c b/trunk/drivers/video/amifb.c index 1a849b870bcc..88a47845c4f7 100644 --- a/trunk/drivers/video/amifb.c +++ b/trunk/drivers/video/amifb.c @@ -2906,6 +2906,14 @@ static int ami_decode_var(struct fb_var_screeninfo *var, par->crsr.spot_x = par->crsr.spot_y = 0; par->crsr.height = par->crsr.width = 0; +#if 0 /* fbmon not done. uncomment for 2.5.x -brad */ + if (!fbmon_valid_timings(pixclock[clk_shift], htotal, vtotal, + &fb_info)) { + DPRINTK("mode doesn't fit for monitor\n"); + return -EINVAL; + } +#endif + return 0; } diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index 09684d7a7ce9..176f9b85cdbe 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -1488,6 +1488,10 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) else info->var.accel_flags = 0; +#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */ + if (!fbmon_valid_timings(pixclock, htotal, vtotal, info)) + return -EINVAL; +#endif aty_crtc_to_var(&crtc, var); var->pixclock = par->pll_ops->pll_to_var(info, &pll); return 0; diff --git a/trunk/drivers/video/aty/radeon_i2c.c b/trunk/drivers/video/aty/radeon_i2c.c index e7c5b219ad1b..869725a13c21 100644 --- a/trunk/drivers/video/aty/radeon_i2c.c +++ b/trunk/drivers/video/aty/radeon_i2c.c @@ -120,19 +120,19 @@ void radeon_create_i2c_busses(struct radeonfb_info *rinfo) void radeon_delete_i2c_busses(struct radeonfb_info *rinfo) { if (rinfo->i2c[0].rinfo) - i2c_del_adapter(&rinfo->i2c[0].adapter); + i2c_bit_del_bus(&rinfo->i2c[0].adapter); rinfo->i2c[0].rinfo = NULL; if (rinfo->i2c[1].rinfo) - i2c_del_adapter(&rinfo->i2c[1].adapter); + i2c_bit_del_bus(&rinfo->i2c[1].adapter); rinfo->i2c[1].rinfo = NULL; if (rinfo->i2c[2].rinfo) - i2c_del_adapter(&rinfo->i2c[2].adapter); + i2c_bit_del_bus(&rinfo->i2c[2].adapter); rinfo->i2c[2].rinfo = NULL; if (rinfo->i2c[3].rinfo) - i2c_del_adapter(&rinfo->i2c[3].adapter); + i2c_bit_del_bus(&rinfo->i2c[3].adapter); rinfo->i2c[3].rinfo = NULL; } diff --git a/trunk/drivers/video/gxt4500.c b/trunk/drivers/video/gxt4500.c deleted file mode 100644 index 3adf6ab0768f..000000000000 --- a/trunk/drivers/video/gxt4500.c +++ /dev/null @@ -1,741 +0,0 @@ -/* - * Frame buffer device for IBM GXT4500P display adaptor - * - * Copyright (C) 2006 Paul Mackerras, IBM Corp. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define PCI_DEVICE_ID_IBM_GXT4500P 0x21c - -/* GXT4500P registers */ - -/* Registers in PCI config space */ -#define CFG_ENDIAN0 0x40 - -/* Misc control/status registers */ -#define STATUS 0x1000 -#define CTRL_REG0 0x1004 -#define CR0_HALT_DMA 0x4 -#define CR0_RASTER_RESET 0x8 -#define CR0_GEOM_RESET 0x10 -#define CR0_MEM_CTRLER_RESET 0x20 - -/* Framebuffer control registers */ -#define FB_AB_CTRL 0x1100 -#define FB_CD_CTRL 0x1104 -#define FB_WID_CTRL 0x1108 -#define FB_Z_CTRL 0x110c -#define FB_VGA_CTRL 0x1110 -#define REFRESH_AB_CTRL 0x1114 -#define REFRESH_CD_CTRL 0x1118 -#define FB_OVL_CTRL 0x111c -#define FB_CTRL_TYPE 0x80000000 -#define FB_CTRL_WIDTH_MASK 0x007f0000 -#define FB_CTRL_WIDTH_SHIFT 16 -#define FB_CTRL_START_SEG_MASK 0x00003fff - -#define REFRESH_START 0x1098 -#define REFRESH_SIZE 0x109c - -/* "Direct" framebuffer access registers */ -#define DFA_FB_A 0x11e0 -#define DFA_FB_B 0x11e4 -#define DFA_FB_C 0x11e8 -#define DFA_FB_D 0x11ec -#define DFA_FB_ENABLE 0x80000000 -#define DFA_FB_BASE_MASK 0x03f00000 -#define DFA_FB_STRIDE_1k 0x00000000 -#define DFA_FB_STRIDE_2k 0x00000010 -#define DFA_FB_STRIDE_4k 0x00000020 -#define DFA_PIX_8BIT 0x00000000 -#define DFA_PIX_16BIT_565 0x00000001 -#define DFA_PIX_16BIT_1555 0x00000002 -#define DFA_PIX_24BIT 0x00000004 -#define DFA_PIX_32BIT 0x00000005 - -/* maps DFA_PIX_* to pixel size in bytes */ -static const unsigned char pixsize[] = { - 1, 2, 2, 2, 4, 4 -}; - -/* Display timing generator registers */ -#define DTG_CONTROL 0x1900 -#define DTG_CTL_SCREEN_REFRESH 2 -#define DTG_CTL_ENABLE 1 -#define DTG_HORIZ_EXTENT 0x1904 -#define DTG_HORIZ_DISPLAY 0x1908 -#define DTG_HSYNC_START 0x190c -#define DTG_HSYNC_END 0x1910 -#define DTG_HSYNC_END_COMP 0x1914 -#define DTG_VERT_EXTENT 0x1918 -#define DTG_VERT_DISPLAY 0x191c -#define DTG_VSYNC_START 0x1920 -#define DTG_VSYNC_END 0x1924 -#define DTG_VERT_SHORT 0x1928 - -/* PLL/RAMDAC registers */ -#define DISP_CTL 0x402c -#define DISP_CTL_OFF 2 -#define SYNC_CTL 0x4034 -#define SYNC_CTL_SYNC_ON_RGB 1 -#define SYNC_CTL_SYNC_OFF 2 -#define SYNC_CTL_HSYNC_INV 8 -#define SYNC_CTL_VSYNC_INV 0x10 -#define SYNC_CTL_HSYNC_OFF 0x20 -#define SYNC_CTL_VSYNC_OFF 0x40 - -#define PLL_M 0x4040 -#define PLL_N 0x4044 -#define PLL_POSTDIV 0x4048 - -/* Hardware cursor */ -#define CURSOR_X 0x4078 -#define CURSOR_Y 0x407c -#define CURSOR_HOTSPOT 0x4080 -#define CURSOR_MODE 0x4084 -#define CURSOR_MODE_OFF 0 -#define CURSOR_MODE_4BPP 1 -#define CURSOR_PIXMAP 0x5000 -#define CURSOR_CMAP 0x7400 - -/* Window attribute table */ -#define WAT_FMT 0x4100 -#define WAT_FMT_24BIT 0 -#define WAT_FMT_16BIT_565 1 -#define WAT_FMT_16BIT_1555 2 -#define WAT_FMT_32BIT 3 /* 0 vs. 3 is a guess */ -#define WAT_FMT_8BIT_332 9 -#define WAT_FMT_8BIT 0xa -#define WAT_FMT_NO_CMAP 4 /* ORd in to other values */ -#define WAT_CMAP_OFFSET 0x4104 /* 4-bit value gets << 6 */ -#define WAT_CTRL 0x4108 -#define WAT_CTRL_SEL_B 1 /* select B buffer if 1 */ -#define WAT_CTRL_NO_INC 2 -#define WAT_GAMMA_CTRL 0x410c -#define WAT_GAMMA_DISABLE 1 /* disables gamma cmap */ -#define WAT_OVL_CTRL 0x430c /* controls overlay */ - -/* Indexed by DFA_PIX_* values */ -static const unsigned char watfmt[] = { - WAT_FMT_8BIT, WAT_FMT_16BIT_565, WAT_FMT_16BIT_1555, 0, - WAT_FMT_24BIT, WAT_FMT_32BIT -}; - -/* Colormap array; 1k entries of 4 bytes each */ -#define CMAP 0x6000 - -#define readreg(par, reg) readl((par)->regs + (reg)) -#define writereg(par, reg, val) writel((val), (par)->regs + (reg)) - -struct gxt4500_par { - void __iomem *regs; - - int pixfmt; /* pixel format, see DFA_PIX_* values */ - - /* PLL parameters */ - int pll_m; /* ref clock divisor */ - int pll_n; /* VCO divisor */ - int pll_pd1; /* first post-divisor */ - int pll_pd2; /* second post-divisor */ - - u32 pseudo_palette[16]; /* used in color blits */ -}; - -/* mode requested by user */ -static char *mode_option; - -/* default mode: 1280x1024 @ 60 Hz, 8 bpp */ -static const struct fb_videomode defaultmode __devinitdata = { - .refresh = 60, - .xres = 1280, - .yres = 1024, - .pixclock = 9295, - .left_margin = 248, - .right_margin = 48, - .upper_margin = 38, - .lower_margin = 1, - .hsync_len = 112, - .vsync_len = 3, - .vmode = FB_VMODE_NONINTERLACED -}; - -/* - * The refclk and VCO dividers appear to use a linear feedback shift - * register, which gets reloaded when it reaches a terminal value, at - * which point the divider output is toggled. Thus one can obtain - * whatever divisor is required by putting the appropriate value into - * the reload register. For a divisor of N, one puts the value from - * the LFSR sequence that comes N-1 places before the terminal value - * into the reload register. - */ - -static const unsigned char mdivtab[] = { -/* 1 */ 0x3f, 0x00, 0x20, 0x10, 0x28, 0x14, 0x2a, 0x15, 0x0a, -/* 10 */ 0x25, 0x32, 0x19, 0x0c, 0x26, 0x13, 0x09, 0x04, 0x22, 0x11, -/* 20 */ 0x08, 0x24, 0x12, 0x29, 0x34, 0x1a, 0x2d, 0x36, 0x1b, 0x0d, -/* 30 */ 0x06, 0x23, 0x31, 0x38, 0x1c, 0x2e, 0x17, 0x0b, 0x05, 0x02, -/* 40 */ 0x21, 0x30, 0x18, 0x2c, 0x16, 0x2b, 0x35, 0x3a, 0x1d, 0x0e, -/* 50 */ 0x27, 0x33, 0x39, 0x3c, 0x1e, 0x2f, 0x37, 0x3b, 0x3d, 0x3e, -/* 60 */ 0x1f, 0x0f, 0x07, 0x03, 0x01, -}; - -static const unsigned char ndivtab[] = { -/* 2 */ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0xbc, 0x5e, -/* 10 */ 0x2f, 0x17, 0x0b, 0x85, 0xc2, 0xe1, 0x70, 0x38, 0x9c, 0x4e, -/* 20 */ 0xa7, 0xd3, 0xe9, 0xf4, 0xfa, 0xfd, 0xfe, 0x7f, 0xbf, 0xdf, -/* 30 */ 0xef, 0x77, 0x3b, 0x1d, 0x8e, 0xc7, 0xe3, 0x71, 0xb8, 0xdc, -/* 40 */ 0x6e, 0xb7, 0x5b, 0x2d, 0x16, 0x8b, 0xc5, 0xe2, 0xf1, 0xf8, -/* 50 */ 0xfc, 0x7e, 0x3f, 0x9f, 0xcf, 0x67, 0xb3, 0xd9, 0x6c, 0xb6, -/* 60 */ 0xdb, 0x6d, 0x36, 0x9b, 0x4d, 0x26, 0x13, 0x89, 0xc4, 0x62, -/* 70 */ 0xb1, 0xd8, 0xec, 0xf6, 0xfb, 0x7d, 0xbe, 0x5f, 0xaf, 0x57, -/* 80 */ 0x2b, 0x95, 0x4a, 0x25, 0x92, 0x49, 0xa4, 0x52, 0x29, 0x94, -/* 90 */ 0xca, 0x65, 0xb2, 0x59, 0x2c, 0x96, 0xcb, 0xe5, 0xf2, 0x79, -/* 100 */ 0x3c, 0x1e, 0x0f, 0x07, 0x83, 0x41, 0x20, 0x90, 0x48, 0x24, -/* 110 */ 0x12, 0x09, 0x84, 0x42, 0xa1, 0x50, 0x28, 0x14, 0x8a, 0x45, -/* 120 */ 0xa2, 0xd1, 0xe8, 0x74, 0xba, 0xdd, 0xee, 0xf7, 0x7b, 0x3d, -/* 130 */ 0x9e, 0x4f, 0x27, 0x93, 0xc9, 0xe4, 0x72, 0x39, 0x1c, 0x0e, -/* 140 */ 0x87, 0xc3, 0x61, 0x30, 0x18, 0x8c, 0xc6, 0x63, 0x31, 0x98, -/* 150 */ 0xcc, 0xe6, 0x73, 0xb9, 0x5c, 0x2e, 0x97, 0x4b, 0xa5, 0xd2, -/* 160 */ 0x69, 0xb4, 0xda, 0xed, 0x76, 0xbb, 0x5d, 0xae, 0xd7, 0x6b, -/* 170 */ 0xb5, 0x5a, 0xad, 0x56, 0xab, 0xd5, 0x6a, 0x35, 0x1a, 0x8d, -/* 180 */ 0x46, 0x23, 0x11, 0x88, 0x44, 0x22, 0x91, 0xc8, 0x64, 0x32, -/* 190 */ 0x19, 0x0c, 0x86, 0x43, 0x21, 0x10, 0x08, 0x04, 0x02, 0x81, -/* 200 */ 0x40, 0xa0, 0xd0, 0x68, 0x34, 0x9a, 0xcd, 0x66, 0x33, 0x99, -/* 210 */ 0x4c, 0xa6, 0x53, 0xa9, 0xd4, 0xea, 0x75, 0x3a, 0x9d, 0xce, -/* 220 */ 0xe7, 0xf3, 0xf9, 0x7c, 0x3e, 0x1f, 0x8f, 0x47, 0xa3, 0x51, -/* 230 */ 0xa8, 0x54, 0xaa, 0x55, 0x2a, 0x15, 0x0a, 0x05, 0x82, 0xc1, -/* 240 */ 0x60, 0xb0, 0x58, 0xac, 0xd6, 0xeb, 0xf5, 0x7a, 0xbd, 0xde, -/* 250 */ 0x6f, 0x37, 0x1b, 0x0d, 0x06, 0x03, 0x01, -}; - -#define REF_PERIOD_PS 9259 /* period of reference clock in ps */ - -static int calc_pll(int period_ps, struct gxt4500_par *par) -{ - int m, n, pdiv1, pdiv2, postdiv; - int pll_period, best_error, t; - - /* only deal with range 1MHz - 400MHz */ - if (period_ps < 2500 || period_ps > 1000000) - return -1; - - best_error = 1000000; - for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) { - for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) { - postdiv = pdiv1 * pdiv2; - pll_period = (period_ps + postdiv - 1) / postdiv; - /* keep pll in range 500..1250 MHz */ - if (pll_period < 800 || pll_period > 2000) - continue; - for (m = 3; m <= 40; ++m) { - n = REF_PERIOD_PS * m * postdiv / period_ps; - if (n < 5 || n > 256) - continue; - t = REF_PERIOD_PS * m * postdiv / n; - t -= period_ps; - if (t >= 0 && t < best_error) { - par->pll_m = m; - par->pll_n = n; - par->pll_pd1 = pdiv1; - par->pll_pd2 = pdiv2; - best_error = t; - } - } - } - } - if (best_error == 1000000) - return -1; - return 0; -} - -static int calc_pixclock(struct gxt4500_par *par) -{ - return REF_PERIOD_PS * par->pll_m * par->pll_pd1 * par->pll_pd2 - / par->pll_n; -} - -static int gxt4500_var_to_par(struct fb_var_screeninfo *var, - struct gxt4500_par *par) -{ - if (var->xres + var->xoffset > var->xres_virtual || - var->yres + var->yoffset > var->yres_virtual || - var->xres_virtual > 4096) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (calc_pll(var->pixclock, par) < 0) - return -EINVAL; - - switch (var->bits_per_pixel) { - case 32: - if (var->transp.length) - par->pixfmt = DFA_PIX_32BIT; - else - par->pixfmt = DFA_PIX_24BIT; - break; - case 24: - par->pixfmt = DFA_PIX_24BIT; - break; - case 16: - if (var->green.length == 5) - par->pixfmt = DFA_PIX_16BIT_1555; - else - par->pixfmt = DFA_PIX_16BIT_565; - break; - case 8: - par->pixfmt = DFA_PIX_8BIT; - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct fb_bitfield eightbits = {0, 8}; -static const struct fb_bitfield nobits = {0, 0}; - -static void gxt4500_unpack_pixfmt(struct fb_var_screeninfo *var, - int pixfmt) -{ - var->bits_per_pixel = pixsize[pixfmt] * 8; - var->red = eightbits; - var->green = eightbits; - var->blue = eightbits; - var->transp = nobits; - - switch (pixfmt) { - case DFA_PIX_16BIT_565: - var->red.length = 5; - var->green.length = 6; - var->blue.length = 5; - break; - case DFA_PIX_16BIT_1555: - var->red.length = 5; - var->green.length = 5; - var->blue.length = 5; - var->transp.length = 1; - break; - case DFA_PIX_32BIT: - var->transp.length = 8; - break; - } - if (pixfmt != DFA_PIX_8BIT) { - var->green.offset = var->red.length; - var->blue.offset = var->green.offset + var->green.length; - if (var->transp.length) - var->transp.offset = - var->blue.offset + var->blue.length; - } -} - -static int gxt4500_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - struct gxt4500_par par; - int err; - - par = *(struct gxt4500_par *)info->par; - err = gxt4500_var_to_par(var, &par); - if (!err) { - var->pixclock = calc_pixclock(&par); - gxt4500_unpack_pixfmt(var, par.pixfmt); - } - return err; -} - -static int gxt4500_set_par(struct fb_info *info) -{ - struct gxt4500_par *par = info->par; - struct fb_var_screeninfo *var = &info->var; - int err; - u32 ctrlreg; - unsigned int dfa_ctl, pixfmt, stride; - unsigned int wid_tiles, i; - unsigned int prefetch_pix, htot; - struct gxt4500_par save_par; - - save_par = *par; - err = gxt4500_var_to_par(var, par); - if (err) { - *par = save_par; - return err; - } - - /* turn off DTG for now */ - ctrlreg = readreg(par, DTG_CONTROL); - ctrlreg &= ~(DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH); - writereg(par, DTG_CONTROL, ctrlreg); - - /* set PLL registers */ - writereg(par, PLL_M, mdivtab[par->pll_m - 1]); - writereg(par, PLL_N, ndivtab[par->pll_n - 2]); - writereg(par, PLL_POSTDIV, - ((8 - par->pll_pd1) << 3) | (8 - par->pll_pd2)); - msleep(20); - - /* turn off hardware cursor */ - writereg(par, CURSOR_MODE, CURSOR_MODE_OFF); - - /* reset raster engine */ - writereg(par, CTRL_REG0, CR0_RASTER_RESET | (CR0_RASTER_RESET << 16)); - udelay(10); - writereg(par, CTRL_REG0, CR0_RASTER_RESET << 16); - - /* set display timing generator registers */ - htot = var->xres + var->left_margin + var->right_margin + - var->hsync_len; - writereg(par, DTG_HORIZ_EXTENT, htot - 1); - writereg(par, DTG_HORIZ_DISPLAY, var->xres - 1); - writereg(par, DTG_HSYNC_START, var->xres + var->right_margin - 1); - writereg(par, DTG_HSYNC_END, - var->xres + var->right_margin + var->hsync_len - 1); - writereg(par, DTG_HSYNC_END_COMP, - var->xres + var->right_margin + var->hsync_len - 1); - writereg(par, DTG_VERT_EXTENT, - var->yres + var->upper_margin + var->lower_margin + - var->vsync_len - 1); - writereg(par, DTG_VERT_DISPLAY, var->yres - 1); - writereg(par, DTG_VSYNC_START, var->yres + var->lower_margin - 1); - writereg(par, DTG_VSYNC_END, - var->yres + var->lower_margin + var->vsync_len - 1); - prefetch_pix = 3300000 / var->pixclock; - if (prefetch_pix >= htot) - prefetch_pix = htot - 1; - writereg(par, DTG_VERT_SHORT, htot - prefetch_pix - 1); - ctrlreg |= DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH; - writereg(par, DTG_CONTROL, ctrlreg); - - /* calculate stride in DFA aperture */ - if (var->xres_virtual > 2048) { - stride = 4096; - dfa_ctl = DFA_FB_STRIDE_4k; - } else if (var->xres_virtual > 1024) { - stride = 2048; - dfa_ctl = DFA_FB_STRIDE_2k; - } else { - stride = 1024; - dfa_ctl = DFA_FB_STRIDE_1k; - } - - /* Set up framebuffer definition */ - wid_tiles = (var->xres_virtual + 63) >> 6; - - /* XXX add proper FB allocation here someday */ - writereg(par, FB_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); - writereg(par, REFRESH_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); - writereg(par, FB_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); - writereg(par, REFRESH_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); - writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); - writereg(par, REFRESH_SIZE, (var->xres << 16) | var->yres); - - /* Set up framebuffer access by CPU */ - - pixfmt = par->pixfmt; - dfa_ctl |= DFA_FB_ENABLE | pixfmt; - writereg(par, DFA_FB_A, dfa_ctl); - - /* - * Set up window attribute table. - * We set all WAT entries the same so it doesn't matter what the - * window ID (WID) plane contains. - */ - for (i = 0; i < 32; ++i) { - writereg(par, WAT_FMT + (i << 4), watfmt[pixfmt]); - writereg(par, WAT_CMAP_OFFSET + (i << 4), 0); - writereg(par, WAT_CTRL + (i << 4), 0); - writereg(par, WAT_GAMMA_CTRL + (i << 4), WAT_GAMMA_DISABLE); - } - - /* Set sync polarity etc. */ - ctrlreg = readreg(par, SYNC_CTL) & - ~(SYNC_CTL_SYNC_ON_RGB | SYNC_CTL_HSYNC_INV | - SYNC_CTL_VSYNC_INV); - if (var->sync & FB_SYNC_ON_GREEN) - ctrlreg |= SYNC_CTL_SYNC_ON_RGB; - if (!(var->sync & FB_SYNC_HOR_HIGH_ACT)) - ctrlreg |= SYNC_CTL_HSYNC_INV; - if (!(var->sync & FB_SYNC_VERT_HIGH_ACT)) - ctrlreg |= SYNC_CTL_VSYNC_INV; - writereg(par, SYNC_CTL, ctrlreg); - - info->fix.line_length = stride * pixsize[pixfmt]; - info->fix.visual = (pixfmt == DFA_PIX_8BIT)? FB_VISUAL_PSEUDOCOLOR: - FB_VISUAL_DIRECTCOLOR; - - return 0; -} - -static int gxt4500_setcolreg(unsigned int reg, unsigned int red, - unsigned int green, unsigned int blue, - unsigned int transp, struct fb_info *info) -{ - u32 cmap_entry; - struct gxt4500_par *par = info->par; - - if (reg > 1023) - return 1; - cmap_entry = ((transp & 0xff00) << 16) | ((blue & 0xff00) << 8) | - (green & 0xff00) | (red >> 8); - writereg(par, CMAP + reg * 4, cmap_entry); - - if (reg < 16 && par->pixfmt != DFA_PIX_8BIT) { - u32 *pal = info->pseudo_palette; - u32 val = reg; - switch (par->pixfmt) { - case DFA_PIX_16BIT_565: - val |= (reg << 11) | (reg << 6); - break; - case DFA_PIX_16BIT_1555: - val |= (reg << 10) | (reg << 5); - break; - case DFA_PIX_32BIT: - val |= (reg << 24); - /* fall through */ - case DFA_PIX_24BIT: - val |= (reg << 16) | (reg << 8); - break; - } - pal[reg] = val; - } - - return 0; -} - -static int gxt4500_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - struct gxt4500_par *par = info->par; - - if (var->xoffset & 7) - return -EINVAL; - if (var->xoffset + var->xres > var->xres_virtual || - var->yoffset + var->yres > var->yres_virtual) - return -EINVAL; - - writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); - return 0; -} - -static int gxt4500_blank(int blank, struct fb_info *info) -{ - struct gxt4500_par *par = info->par; - int ctrl, dctl; - - ctrl = readreg(par, SYNC_CTL); - ctrl &= ~(SYNC_CTL_SYNC_OFF | SYNC_CTL_HSYNC_OFF | SYNC_CTL_VSYNC_OFF); - dctl = readreg(par, DISP_CTL); - dctl |= DISP_CTL_OFF; - switch (blank) { - case FB_BLANK_UNBLANK: - dctl &= ~DISP_CTL_OFF; - break; - case FB_BLANK_POWERDOWN: - ctrl |= SYNC_CTL_SYNC_OFF; - break; - case FB_BLANK_HSYNC_SUSPEND: - ctrl |= SYNC_CTL_HSYNC_OFF; - break; - case FB_BLANK_VSYNC_SUSPEND: - ctrl |= SYNC_CTL_VSYNC_OFF; - break; - default: ; - } - writereg(par, SYNC_CTL, ctrl); - writereg(par, DISP_CTL, dctl); - - return 0; -} - -static const struct fb_fix_screeninfo gxt4500_fix __devinitdata = { - .id = "IBM GXT4500P", - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_PSEUDOCOLOR, - .xpanstep = 8, - .ypanstep = 1, - .mmio_len = 0x20000, -}; - -static struct fb_ops gxt4500_ops = { - .owner = THIS_MODULE, - .fb_check_var = gxt4500_check_var, - .fb_set_par = gxt4500_set_par, - .fb_setcolreg = gxt4500_setcolreg, - .fb_pan_display = gxt4500_pan_display, - .fb_blank = gxt4500_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, -}; - -/* PCI functions */ -static int __devinit gxt4500_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int err; - unsigned long reg_phys, fb_phys; - struct gxt4500_par *par; - struct fb_info *info; - struct fb_var_screeninfo var; - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n", - err); - return err; - } - - reg_phys = pci_resource_start(pdev, 0); - if (!request_mem_region(reg_phys, pci_resource_len(pdev, 0), - "gxt4500 regs")) { - dev_err(&pdev->dev, "gxt4500: cannot get registers\n"); - goto err_nodev; - } - - fb_phys = pci_resource_start(pdev, 1); - if (!request_mem_region(fb_phys, pci_resource_len(pdev, 1), - "gxt4500 FB")) { - dev_err(&pdev->dev, "gxt4500: cannot get framebuffer\n"); - goto err_free_regs; - } - - info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev); - if (!info) { - dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record"); - goto err_free_fb; - } - par = info->par; - info->fix = gxt4500_fix; - info->pseudo_palette = par->pseudo_palette; - - info->fix.mmio_start = reg_phys; - par->regs = ioremap(reg_phys, pci_resource_len(pdev, 0)); - if (!par->regs) { - dev_err(&pdev->dev, "gxt4500: cannot map registers\n"); - goto err_free_all; - } - - info->fix.smem_start = fb_phys; - info->fix.smem_len = pci_resource_len(pdev, 1); - info->screen_base = ioremap(fb_phys, pci_resource_len(pdev, 1)); - if (!info->screen_base) { - dev_err(&pdev->dev, "gxt4500: cannot map framebuffer\n"); - goto err_unmap_regs; - } - - pci_set_drvdata(pdev, info); - - /* Set byte-swapping for DFA aperture for all pixel sizes */ - pci_write_config_dword(pdev, CFG_ENDIAN0, 0x333300); - - info->fbops = &gxt4500_ops; - info->flags = FBINFO_FLAG_DEFAULT; - - err = fb_alloc_cmap(&info->cmap, 256, 0); - if (err) { - dev_err(&pdev->dev, "gxt4500: cannot allocate cmap\n"); - goto err_unmap_all; - } - - gxt4500_blank(FB_BLANK_UNBLANK, info); - - if (!fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8)) { - dev_err(&pdev->dev, "gxt4500: cannot find valid video mode\n"); - goto err_free_cmap; - } - info->var = var; - if (gxt4500_set_par(info)) { - printk(KERN_ERR "gxt4500: cannot set video mode\n"); - goto err_free_cmap; - } - - if (register_framebuffer(info) < 0) { - dev_err(&pdev->dev, "gxt4500: cannot register framebuffer\n"); - goto err_free_cmap; - } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); - - return 0; - - err_free_cmap: - fb_dealloc_cmap(&info->cmap); - err_unmap_all: - iounmap(info->screen_base); - err_unmap_regs: - iounmap(par->regs); - err_free_all: - framebuffer_release(info); - err_free_fb: - release_mem_region(fb_phys, pci_resource_len(pdev, 1)); - err_free_regs: - release_mem_region(reg_phys, pci_resource_len(pdev, 0)); - err_nodev: - return -ENODEV; -} - -static void __devexit gxt4500_remove(struct pci_dev *pdev) -{ - struct fb_info *info = pci_get_drvdata(pdev); - struct gxt4500_par *par; - - if (!info) - return; - par = info->par; - unregister_framebuffer(info); - fb_dealloc_cmap(&info->cmap); - iounmap(par->regs); - iounmap(info->screen_base); - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - framebuffer_release(info); -} - -/* supported chipsets */ -static const struct pci_device_id gxt4500_pci_tbl[] = { - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4500P, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, gxt4500_pci_tbl); - -static struct pci_driver gxt4500_driver = { - .name = "gxt4500", - .id_table = gxt4500_pci_tbl, - .probe = gxt4500_probe, - .remove = __devexit_p(gxt4500_remove), -}; - -static int __devinit gxt4500_init(void) -{ -#ifndef MODULE - if (fb_get_options("gxt4500", &mode_option)) - return -ENODEV; -#endif - - return pci_register_driver(&gxt4500_driver); -} -module_init(gxt4500_init); - -static void __exit gxt4500_exit(void) -{ - pci_unregister_driver(&gxt4500_driver); -} -module_exit(gxt4500_exit); - -MODULE_AUTHOR("Paul Mackerras "); -MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P"); -MODULE_LICENSE("GPL"); -module_param(mode_option, charp, 0); -MODULE_PARM_DESC(mode_option, "Specify resolution as \"x[-][@]\""); diff --git a/trunk/drivers/video/i810/i810-i2c.c b/trunk/drivers/video/i810/i810-i2c.c index 961f4d404467..b952e4504abe 100644 --- a/trunk/drivers/video/i810/i810-i2c.c +++ b/trunk/drivers/video/i810/i810-i2c.c @@ -137,15 +137,15 @@ void i810_create_i2c_busses(struct i810fb_par *par) void i810_delete_i2c_busses(struct i810fb_par *par) { if (par->chan[0].par) - i2c_del_adapter(&par->chan[0].adapter); + i2c_bit_del_bus(&par->chan[0].adapter); par->chan[0].par = NULL; if (par->chan[1].par) - i2c_del_adapter(&par->chan[1].adapter); + i2c_bit_del_bus(&par->chan[1].adapter); par->chan[1].par = NULL; if (par->chan[2].par) - i2c_del_adapter(&par->chan[2].adapter); + i2c_bit_del_bus(&par->chan[2].adapter); par->chan[2].par = NULL; } diff --git a/trunk/drivers/video/intelfb/intelfb_i2c.c b/trunk/drivers/video/intelfb/intelfb_i2c.c index 33bc41f50540..5686e2164e39 100644 --- a/trunk/drivers/video/intelfb/intelfb_i2c.c +++ b/trunk/drivers/video/intelfb/intelfb_i2c.c @@ -188,11 +188,11 @@ void intelfb_delete_i2c_busses(struct intelfb_info *dinfo) for (i = 0; i < MAX_OUTPUTS; i++) { if (dinfo->output[i].i2c_bus.dinfo) { - i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter); + i2c_bit_del_bus(&dinfo->output[i].i2c_bus.adapter); dinfo->output[i].i2c_bus.dinfo = NULL; } if (dinfo->output[i].ddc_bus.dinfo) { - i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter); + i2c_bit_del_bus(&dinfo->output[i].ddc_bus.adapter); dinfo->output[i].ddc_bus.dinfo = NULL; } } diff --git a/trunk/drivers/video/matrox/i2c-matroxfb.c b/trunk/drivers/video/matrox/i2c-matroxfb.c index fe28848e7b52..795c1a99a680 100644 --- a/trunk/drivers/video/matrox/i2c-matroxfb.c +++ b/trunk/drivers/video/matrox/i2c-matroxfb.c @@ -124,7 +124,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, static void i2c_bit_bus_del(struct i2c_bit_adapter* b) { if (b->initialized) { - i2c_del_adapter(&b->adapter); + i2c_bit_del_bus(&b->adapter); b->initialized = 0; } } @@ -146,7 +146,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) { unsigned long flags; struct matroxfb_dh_maven_info* m2info; - m2info = kmalloc(sizeof(*m2info), GFP_KERNEL); + m2info = (struct matroxfb_dh_maven_info*)kmalloc(sizeof(*m2info), GFP_KERNEL); if (!m2info) return NULL; diff --git a/trunk/drivers/video/matrox/matroxfb_base.c b/trunk/drivers/video/matrox/matroxfb_base.c index cb2aa402ddfd..e9b4115fcad0 100644 --- a/trunk/drivers/video/matrox/matroxfb_base.c +++ b/trunk/drivers/video/matrox/matroxfb_base.c @@ -2028,7 +2028,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm } #ifdef CONFIG_FB_MATROX_MULTIHEAD - minfo = kmalloc(sizeof(*minfo), GFP_KERNEL); + minfo = (struct matrox_fb_info*)kmalloc(sizeof(*minfo), GFP_KERNEL); if (!minfo) return -1; #else diff --git a/trunk/drivers/video/matrox/matroxfb_crtc2.c b/trunk/drivers/video/matrox/matroxfb_crtc2.c index 2c9801090fae..27eb4bb4f89f 100644 --- a/trunk/drivers/video/matrox/matroxfb_crtc2.c +++ b/trunk/drivers/video/matrox/matroxfb_crtc2.c @@ -694,7 +694,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) { /* hardware is CRTC2 incapable... */ if (!ACCESS_FBINFO(devflags.crtc2)) return NULL; - m2info = kmalloc(sizeof(*m2info), GFP_KERNEL); + m2info = (struct matroxfb_dh_fb_info*)kmalloc(sizeof(*m2info), GFP_KERNEL); if (!m2info) { printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n"); return NULL; diff --git a/trunk/drivers/video/nvidia/nv_i2c.c b/trunk/drivers/video/nvidia/nv_i2c.c index 8454adf2d178..442e85328341 100644 --- a/trunk/drivers/video/nvidia/nv_i2c.c +++ b/trunk/drivers/video/nvidia/nv_i2c.c @@ -147,15 +147,15 @@ void nvidia_create_i2c_busses(struct nvidia_par *par) void nvidia_delete_i2c_busses(struct nvidia_par *par) { if (par->chan[0].par) - i2c_del_adapter(&par->chan[0].adapter); + i2c_bit_del_bus(&par->chan[0].adapter); par->chan[0].par = NULL; if (par->chan[1].par) - i2c_del_adapter(&par->chan[1].adapter); + i2c_bit_del_bus(&par->chan[1].adapter); par->chan[1].par = NULL; if (par->chan[2].par) - i2c_del_adapter(&par->chan[2].adapter); + i2c_bit_del_bus(&par->chan[2].adapter); par->chan[2].par = NULL; } diff --git a/trunk/drivers/video/riva/rivafb-i2c.c b/trunk/drivers/video/riva/rivafb-i2c.c index 01b85e3b0ae1..c15b259af644 100644 --- a/trunk/drivers/video/riva/rivafb-i2c.c +++ b/trunk/drivers/video/riva/rivafb-i2c.c @@ -144,15 +144,15 @@ void riva_create_i2c_busses(struct riva_par *par) void riva_delete_i2c_busses(struct riva_par *par) { if (par->chan[0].par) - i2c_del_adapter(&par->chan[0].adapter); + i2c_bit_del_bus(&par->chan[0].adapter); par->chan[0].par = NULL; if (par->chan[1].par) - i2c_del_adapter(&par->chan[1].adapter); + i2c_bit_del_bus(&par->chan[1].adapter); par->chan[1].par = NULL; if (par->chan[2].par) - i2c_del_adapter(&par->chan[2].adapter); + i2c_bit_del_bus(&par->chan[2].adapter); par->chan[2].par = NULL; } diff --git a/trunk/drivers/video/savage/savagefb-i2c.c b/trunk/drivers/video/savage/savagefb-i2c.c index 1411f3b6a009..cef5bf591cdf 100644 --- a/trunk/drivers/video/savage/savagefb-i2c.c +++ b/trunk/drivers/video/savage/savagefb-i2c.c @@ -208,7 +208,7 @@ void savagefb_delete_i2c_busses(struct fb_info *info) struct savagefb_par *par = info->par; if (par->chan.par) - i2c_del_adapter(&par->chan.adapter); + i2c_bit_del_bus(&par->chan.adapter); par->chan.par = NULL; } diff --git a/trunk/drivers/video/sstfb.c b/trunk/drivers/video/sstfb.c index 59cd1e750f30..711cb11d6eb3 100644 --- a/trunk/drivers/video/sstfb.c +++ b/trunk/drivers/video/sstfb.c @@ -21,11 +21,6 @@ * Remove never finished and bogus 24/32bit support * Clean up macro abuse * Minor tidying for format. - * 12/2006 Helge Deller - * add /sys/class/graphics/fbX/vgapass sysfs-interface - * add module option "mode_option" to set initial screen mode - * use fbdev default videomode database - * remove debug functions from ioctl */ /* @@ -70,10 +65,19 @@ * * sstfb specific ioctls: * toggle vga (0x46db) : toggle vga_pass_through + * fill fb (0x46dc) : fills fb + * test disp (0x46de) : draws a test image */ #undef SST_DEBUG +/* + Default video mode . + 0 800x600@60 took from glide + 1 640x480@75 took from glide + 2 1024x768@76 std fb.mode + 3 640x480@60 glide default */ +#define DEFAULT_MODE 3 /* * Includes @@ -88,24 +92,20 @@ #include #include #include +#include #include #include